forked from vektra/tachyon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scope.go
101 lines (81 loc) · 1.53 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
package lisp
var scope *Scope
func init() {
scope = NewScope()
scope.AddEnv()
}
type ScopedVars interface {
Get(key string) (Value, bool)
Set(key string, val Value) Value
Create(key string, val Value) Value
}
type Env map[string]Value
type Scope struct {
parent *Scope
envs []*Env
}
func NewScope() *Scope {
scope := &Scope{}
scope.envs = make([]*Env, 0)
return scope
}
func NewNestedScope(parent *Scope) *Scope {
scope := &Scope{}
scope.parent = parent
scope.envs = make([]*Env, 0)
return scope
}
func (s *Scope) Dup() *Scope {
scope := &Scope{}
scope.envs = make([]*Env, len(s.envs))
copy(scope.envs, s.envs)
return scope
}
func (s *Scope) Env() *Env {
if len(s.envs) > 0 {
return s.envs[len(s.envs)-1]
}
return nil
}
func (s *Scope) AddEnv() *Env {
env := make(Env)
s.envs = append(s.envs, &env)
return &env
}
func (s *Scope) DropEnv() *Env {
s.envs[len(s.envs)-1] = nil
s.envs = s.envs[:len(s.envs)-1]
return s.Env()
}
func (s *Scope) Create(key string, value Value) Value {
env := *s.Env()
env[key] = value
return value
}
func (s *Scope) Set(key string, value Value) Value {
t := s
for t != nil {
for i := len(s.envs) - 1; i >= 0; i-- {
env := *s.envs[i]
if _, ok := env[key]; ok {
env[key] = value
return value
}
}
t = t.parent
}
return s.Create(key, value)
}
func (s *Scope) Get(key string) (val Value, ok bool) {
t := s
for t != nil {
for i := len(s.envs) - 1; i >= 0; i-- {
env := *s.envs[i]
if val, ok = env[key]; ok {
return
}
}
t = t.parent
}
return
}