github.com/MontFerret/ferret@v0.18.0/pkg/compiler/scope.go (about) 1 package compiler 2 3 import ( 4 "github.com/MontFerret/ferret/pkg/runtime/core" 5 ) 6 7 type ( 8 globalScope struct { 9 params map[string]struct{} 10 } 11 12 scope struct { 13 global *globalScope 14 parent *scope 15 name string 16 vars map[string]struct{} 17 } 18 ) 19 20 func newGlobalScope() *globalScope { 21 return &globalScope{ 22 params: map[string]struct{}{}, 23 } 24 } 25 26 func newRootScope(global *globalScope) *scope { 27 return &scope{ 28 global: global, 29 vars: make(map[string]struct{}), 30 name: "root", 31 } 32 } 33 34 func newScope(parent *scope, name string) *scope { 35 s := newRootScope(parent.global) 36 s.parent = parent 37 s.name = name 38 39 return s 40 } 41 42 func (s *scope) Name() string { 43 if s.name != "" { 44 return s.name 45 } 46 47 if s.parent != nil { 48 return s.parent.Name() 49 } 50 51 return "" 52 } 53 54 func (s *scope) AddParam(name string) { 55 s.global.params[name] = struct{}{} 56 } 57 58 func (s *scope) HasVariable(name string) bool { 59 _, exists := s.vars[name] 60 61 if exists { 62 return true 63 } 64 65 if s.parent != nil { 66 return s.parent.HasVariable(name) 67 } 68 69 return false 70 } 71 72 func (s *scope) SetVariable(name string) error { 73 if name == core.IgnorableVariable { 74 return nil 75 } 76 77 _, exists := s.vars[name] 78 79 if exists { 80 return core.Error(ErrVariableNotUnique, name) 81 } 82 83 // TODO: add type detection 84 s.vars[name] = struct{}{} 85 86 return nil 87 } 88 89 func (s *scope) RemoveVariable(name string) error { 90 _, exists := s.vars[name] 91 92 if !exists { 93 return core.Error(ErrVariableNotFound, name) 94 } 95 96 delete(s.vars, name) 97 98 return nil 99 } 100 101 func (s *scope) ClearVariables() { 102 s.vars = make(map[string]struct{}) 103 } 104 105 func (s *scope) Fork(name string) *scope { 106 return newScope(s, name) 107 }