-
Notifications
You must be signed in to change notification settings - Fork 0
/
scope.go
173 lines (156 loc) · 3.26 KB
/
scope.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package ego
import (
"sync"
"github.com/bobg/ego/refl"
)
type deferral struct {
fun *refl.Value
args []*refl.Value
}
type Scope struct {
mu sync.RWMutex // protects objs and deferrals
parent *Scope
objs map[string]interface{}
deferrals *[]deferral // nil pointer means not a function scope
}
type uninitialized ast.Expr
type builtin int
const (
builtinBool builtin = 1 + iota
builtinByte
builtinComplex64
builtinComplex128
builtinError
builtinFloat32
builtinFloat64
builtinInt
builtinInt8
builtinInt16
builtinInt32
builtinInt64
builtinRune
builtinString
builtinUint
builtinUint8
builtinUint16
builtinUint32
builtinUint64
builtinUintptr
builtinTrue
builtinFalse
builtinIota
builtinNil
builtinAppend
builtinCap
builtinClose
builtinComplex
builtinCopy
builtinDelete
builtinImag
builtinLen
builtinMake
builtinNew
builtinPanic
builtinPrint
builtinPrintln
builtinReal
builtinRecover
)
var universe = &Scope{
objs: map[string]interface{}{
"bool": builtinBool,
"byte": builtinByte,
"complex64": builtinComplex64,
"complex128": builtinComplex128,
"error": builtinError,
"float32": builtinFloat32,
"float64": builtinFloat64,
"int": builtinInt,
"int8": builtinInt8,
"int16": builtinInt16,
"int32": builtinInt32,
"int64": builtinInt64,
"rune": builtinRune,
"string": builtinString,
"uint": builtinUint,
"uint8": builtinUint8,
"uint16": builtinUint16,
"uint32": builtinUint32,
"uint64": builtinUint64,
"uintptr": builtinUintptr,
"true": builtinTrue,
"false": builtinFalse,
"iota": builtinIota,
"nil": builtinNil,
"append": builtinAppend,
"cap": builtinCap,
"close": builtinClose,
"complex": builtinComplex,
"copy": builtinCopy,
"delete": builtinDelete,
"imag": builtinImag,
"len": builtinLen,
"make": builtinMake,
"new": builtinNew,
"panic": builtinPanic,
"print": builtinPrint,
"println": builtinPrintln,
"real": builtinReal,
"recover": builtinRecover,
},
}
func NewScope(parent *Scope) *Scope {
if parent == nil {
parent = universe
}
return &Scope{
parent: parent,
objs: make(map[string]interface{}),
}
}
func (s *Scope) addDefer(f *refl.Value, args []*refl.Value) {
s.mu.Lock()
defer s.mu.Unlock()
if s.deferrals != nil {
(*s.deferrals) = append((*s.deferrals), deferral{f, args})
} else if s.parent != nil {
s.mu.Unlock()
s.parent.addDefer(f, args)
}
}
// xxx check first that name is undefined?
func (s *Scope) Add(name string, val interface{}) {
s.mu.Lock()
s[name] = val
s.mu.Unlock()
}
func (s *Scope) Set(name string, val interface{}) error {
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s[name]; ok {
s[name] = val
return nil
}
if s.parent == nil || s.parent.isUniverse() {
// xxx err
}
s.mu.Unlock()
return s.parent.Set(name, val)
}
func (s *Scope) Lookup(name) interface{} {
s.mu.RLock()
defer s.mu.RUnlock()
if val, ok := s[name]; ok {
return val
}
if s.parent == nil {
return nil
}
s.mu.RUnlock()
return s.parent.Lookup(name)
}
func (s *Scope) LookupValue(name) *refl.Value {
l := s.Lookup(name)
val, _ := l.(*refl.Value)
return val
}