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  }