-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlox_class.go
55 lines (41 loc) · 1.45 KB
/
lox_class.go
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
package glox
import "errors"
var ErrMethodNotFound = errors.New("method not found with the given name")
type LoxClass struct {
Name string
Superclass *LoxClass
methods map[string]LoxFunction
}
func NewLoxClass(name string, superclass *LoxClass, methods map[string]LoxFunction) *LoxClass {
return &LoxClass{Name: name, Superclass: superclass, methods: methods}
}
func (lc *LoxClass) Call(ip *Interpreter, arguments []interface{}) (interface{}, error) {
instance := NewLoxInstance(lc)
// When a class is called, and the lox instance is created, we look for an "init" method,
// If we find it, we immediately bind and invoke it just like normal method call. The
// argument list is forwarded along.
initializer, err := lc.findMethod("init")
if err == nil {
initializer.Bind(instance).Call(ip, arguments)
}
return instance, nil
}
// Arity returns the arity of the class. If there is an initializer, that method's arity determines
// how many arguments users must pass to call the class. But the initializer is not required though,
// in that case the arity is zero.
func (lc *LoxClass) Arity() int {
initializer, err := lc.findMethod("init")
if err == nil {
return initializer.Arity()
}
return 0
}
func (lc *LoxClass) findMethod(name string) (LoxFunction, error) {
if method, ok := lc.methods[name]; ok {
return method, nil
}
if lc.Superclass != nil {
return lc.Superclass.findMethod(name)
}
return LoxFunction{}, ErrMethodNotFound
}