aboutsummaryrefslogtreecommitdiffstats
path: root/core/invoke.moon
blob: 3b2ddd52ea6cf061c51df33901d6503bbb2debb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import Result, Value from require 'core.value'
import Action from require 'core.base'
import Scope from require 'core.scope'

class op_invoke extends Action
  patch: (head) =>
    return true if head == @head

    @op\destroy! if @op

    def = head\unwrap 'opdef', "cant op-invoke #{@head}"
    @head, @op = head, def!

    true
    
  eval: (scope, tail) =>
    children = L\push -> [L\push expr\eval, scope for expr in *tail]
    @op\setup [result for result in *children], scope

    any_dirty = false
    for input in @op\all_inputs!
      if input\dirty!
        any_dirty = true
        break

    if any_dirty
      @op\tick true

    for input in @op\all_inputs!
      input\finish_setup!

    Result :children, value: @op.out, op: @op

class fn_invoke extends Action
  -- @TODO:
  -- need to :patch() the case where the new head is a new fndef
  -- but corresponds to the last head over time

  patch: (head) =>
    return true if head == @head

    @head = head

    true

  eval: (outer_scope, tail) =>
    { :params, :body, :scope } = @head\unwrap 'fndef', "cant fn-invoke #{@head}"

    assert #params == #tail, "argument count mismatch in #{@head}"

    fn_scope = Scope scope, outer_scope

    children = for i=1,#params
      name = params[i]\unwrap 'sym'
      with L\push tail[i]\eval, outer_scope
        fn_scope\set name, \make_ref!

    body = body\clone @tag
    result = body\eval fn_scope

    table.insert children, result
    Result :children, value: result.value

{
  :op_invoke, :fn_invoke
}