github.com/masahide/goansible@v0.0.0-20160116054156-01eac649e9f2/lisp/scope.go (about) 1 package lisp 2 3 var scope *Scope 4 5 func init() { 6 scope = NewScope() 7 scope.AddEnv() 8 } 9 10 type ScopedVars interface { 11 Get(key string) (Value, bool) 12 Set(key string, val Value) Value 13 Create(key string, val Value) Value 14 } 15 16 type Env map[string]Value 17 18 type Scope struct { 19 parent *Scope 20 envs []*Env 21 } 22 23 func NewScope() *Scope { 24 scope := &Scope{} 25 scope.envs = make([]*Env, 0) 26 return scope 27 } 28 29 func NewNestedScope(parent *Scope) *Scope { 30 scope := &Scope{} 31 scope.parent = parent 32 scope.envs = make([]*Env, 0) 33 return scope 34 } 35 36 func (s *Scope) Dup() *Scope { 37 scope := &Scope{} 38 scope.envs = make([]*Env, len(s.envs)) 39 copy(scope.envs, s.envs) 40 return scope 41 } 42 43 func (s *Scope) Env() *Env { 44 if len(s.envs) > 0 { 45 return s.envs[len(s.envs)-1] 46 } 47 return nil 48 } 49 50 func (s *Scope) AddEnv() *Env { 51 env := make(Env) 52 s.envs = append(s.envs, &env) 53 return &env 54 } 55 56 func (s *Scope) DropEnv() *Env { 57 s.envs[len(s.envs)-1] = nil 58 s.envs = s.envs[:len(s.envs)-1] 59 return s.Env() 60 } 61 62 func (s *Scope) Create(key string, value Value) Value { 63 env := *s.Env() 64 env[key] = value 65 return value 66 } 67 68 func (s *Scope) Set(key string, value Value) Value { 69 t := s 70 71 for t != nil { 72 for i := len(s.envs) - 1; i >= 0; i-- { 73 env := *s.envs[i] 74 if _, ok := env[key]; ok { 75 env[key] = value 76 return value 77 } 78 } 79 80 t = t.parent 81 } 82 83 return s.Create(key, value) 84 } 85 86 func (s *Scope) Get(key string) (val Value, ok bool) { 87 t := s 88 89 for t != nil { 90 for i := len(s.envs) - 1; i >= 0; i-- { 91 env := *s.envs[i] 92 if val, ok = env[key]; ok { 93 return 94 } 95 } 96 97 t = t.parent 98 } 99 100 return 101 }