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