scope.go raw

   1  package typecheck
   2  
   3  // Scope is a mapping from names to Objects. Scopes are chained:
   4  // a lookup that misses in the current scope walks up to the parent.
   5  type Scope struct {
   6  	parent   *Scope
   7  	children []*Scope
   8  	elems    map[string]Object
   9  }
  10  
  11  func NewScope(parent *Scope) *Scope {
  12  	return &Scope{parent: parent, elems: map[string]Object{}}
  13  }
  14  
  15  func (s *Scope) Parent() *Scope   { return s.parent }
  16  func (s *Scope) Len() int         { return len(s.elems) }
  17  
  18  func (s *Scope) Lookup(name string) Object {
  19  	return s.elems[name]
  20  }
  21  
  22  // LookupParent looks up name starting at s, walking the parent chain.
  23  // Returns the scope where it was found and the object, or nil, nil.
  24  func (s *Scope) LookupParent(name string) (*Scope, Object) {
  25  	for sc := s; sc != nil; sc = sc.parent {
  26  		if obj, ok := sc.elems[name]; ok {
  27  			return sc, obj
  28  		}
  29  	}
  30  	return nil, nil
  31  }
  32  
  33  // Insert inserts obj into s. Returns an existing object with the same name
  34  // if there is one (caller must report the error).
  35  func (s *Scope) Insert(obj Object) Object {
  36  	name := obj.Name()
  37  	if alt, ok := s.elems[name]; ok {
  38  		return alt
  39  	}
  40  	s.elems[name] = obj
  41  	return nil
  42  }
  43  
  44  // Names returns all names in this scope, unsorted.
  45  func (s *Scope) Names() []string {
  46  	names := make([]string, 0, len(s.elems))
  47  	for n := range s.elems {
  48  		names = append(names, n)
  49  	}
  50  	return names
  51  }
  52