/
id.go
130 lines (104 loc) · 2.6 KB
/
id.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
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package gfoo
import (
"fmt"
"io"
)
type Id struct {
FormBase
name string
}
func NewId(name string, pos Pos) *Id {
f := new(Id)
f.FormBase.Init(pos)
f.name = name
return f
}
func (self *Id) Compile(in *Forms, out []Op, scope *Scope) ([]Op, error) {
return self.compileName(self.name, in, out, scope, scope)
}
func (self *Id) Do(action func(Form) error) error {
return action(self)
}
func (self *Id) Dump(out io.Writer) error {
_, err := fmt.Fprintf(out, "%v", self.name)
return err
}
func (self *Id) Quote(in *Forms, scope *Scope, thread *Thread, registers []Val, pos Pos) (Val, error) {
if in != nil {
if next := in.Peek(); next != nil {
g, ok := next.(*Group)
if ok {
in.Pop()
return NewCallForm(self, g, pos).Quote(nil, scope, thread, registers, pos)
}
}
}
return NewVal(&TId, self.name), nil
}
func compileArgs(in *Forms, scope *Scope) ([]Op, error) {
if next := in.Peek(); next != nil {
if _, ok := next.(*Group); ok {
return in.Pop().Compile(nil, nil, scope)
}
}
return nil, nil
}
func (self *Id) compileFunction(f *Function, in *Forms, out []Op, scope *Scope) ([]Op, error) {
if len(f.methods) == 1 {
return self.compileMethod(f.methods[0], in, out, scope)
}
var args []Op
var err error
if args, err = compileArgs(in, scope); err != nil {
return out, err
}
v := NewVal(&TFunction, f)
return append(out, NewCall(self, &v, args)), nil
}
func (self *Id) compileMethod(m *Method, in *Forms, out []Op, scope *Scope) ([]Op, error) {
var args []Op
var err error
if args, err = compileArgs(in, scope); err != nil {
return out, err
}
v := NewVal(&TMethod, m)
return append(out, NewCall(self, &v, args)), nil
}
func (self *Id) compileName(
name string,
in *Forms,
out []Op,
nameScope, scope *Scope) ([]Op, error) {
b := nameScope.Get(name)
if b == nil {
if name[0] == '.' {
return append(out, NewGet(self, name[1:])), nil
}
return out, Error(self.pos, "Unknown identifier: %v", name)
}
if b.val == Undefined {
return append(out, NewLoad(self, name, nameScope.registers[name])), nil
}
v := &b.val
switch (v.dataType) {
case &TFunction:
return self.compileFunction(v.data.(*Function), in, out, scope)
case &TMacro:
return v.data.(*Macro).Expand(self, in, out, scope)
case &TMethod:
return self.compileMethod(v.data.(*Method), in, out, scope)
case &TModule:
if next := in.Peek(); next != nil {
if id, ok := next.(*Id); ok && id.name[0] == '.' {
in.Pop()
return self.compileName(
id.name[1:],
in,
out,
&v.data.(*Module).Scope,
scope)
}
}
}
return append(out, NewPush(self, *v)), nil
}