-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction.go
More file actions
85 lines (66 loc) · 1.71 KB
/
Copy pathfunction.go
File metadata and controls
85 lines (66 loc) · 1.71 KB
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main
type Function struct {
decl *FunDecl
closure *Environment
isInitializer bool
}
func (f *Function) Bind(instance *Instance) *Function {
env := NewEnvironment(f.closure)
env.Set("this", instance)
return &Function{f.decl, env, f.isInitializer}
}
func (f *Function) Call(interpreter *Interpreter, arguments []any) any {
localEnv := NewEnvironment(f.closure)
localEnv.Set(f.decl.name.lexeme, f) // Define function in its own scope so recursion works properly
for i := 0; i < len(f.decl.params); i++ {
localEnv.Set(f.decl.params[i].lexeme, arguments[i])
}
body, ok := f.decl.body.(*Block)
if !ok {
panic("Unreachable.")
}
err := interpreter.execBlock(body, localEnv)
if ret, ok := err.(Return); ok {
if f.isInitializer {
return f.closure.GetAt(0, "this")
}
return ret.value
} else if err != nil {
return err
}
if f.isInitializer {
return f.closure.GetAt(0, "this")
}
return nil
}
func (f *Function) Arity() int {
return len(f.decl.params)
}
func (f *Function) String() string {
return "<fn " + f.decl.name.lexeme + ">"
}
type AnonFunction struct {
expr *FunExpr
closure *Environment
}
func (f *AnonFunction) Call(interpreter *Interpreter, arguments []any) any {
localEnv := NewEnvironment(f.closure)
for i := 0; i < len(f.expr.params); i++ {
localEnv.Set(f.expr.params[i].lexeme, arguments[i])
}
body, ok := f.expr.body.(*Block)
if !ok {
panic("Unreachable.")
}
err := interpreter.execBlock(body, localEnv)
if ret, ok := err.(Return); ok {
return ret.value
}
return err // Either nil or an error we want to handle
}
func (f *AnonFunction) Arity() int {
return len(f.expr.params)
}
func (f *AnonFunction) String() string {
return f.expr.String()
}