...
Source file
src/go/types/scope.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "bytes"
11 "fmt"
12 "go/token"
13 "io"
14 "sort"
15 "strings"
16 )
17
18
19
20
21
22 type Scope struct {
23 parent *Scope
24 children []*Scope
25 elems map[string]Object
26 pos, end token.Pos
27 comment string
28 isFunc bool
29 }
30
31
32
33 func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
34 s := &Scope{parent, nil, nil, pos, end, comment, false}
35
36 if parent != nil && parent != Universe {
37 parent.children = append(parent.children, s)
38 }
39 return s
40 }
41
42
43 func (s *Scope) Parent() *Scope { return s.parent }
44
45
46 func (s *Scope) Len() int { return len(s.elems) }
47
48
49 func (s *Scope) Names() []string {
50 names := make([]string, len(s.elems))
51 i := 0
52 for name := range s.elems {
53 names[i] = name
54 i++
55 }
56 sort.Strings(names)
57 return names
58 }
59
60
61 func (s *Scope) NumChildren() int { return len(s.children) }
62
63
64 func (s *Scope) Child(i int) *Scope { return s.children[i] }
65
66
67
68 func (s *Scope) Lookup(name string) Object {
69 return s.elems[name]
70 }
71
72
73
74
75
76
77
78
79
80
81
82 func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) {
83 for ; s != nil; s = s.parent {
84 if obj := s.elems[name]; obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) {
85 return s, obj
86 }
87 }
88 return nil, nil
89 }
90
91
92
93
94
95
96 func (s *Scope) Insert(obj Object) Object {
97 name := obj.Name()
98 if alt := s.elems[name]; alt != nil {
99 return alt
100 }
101 if s.elems == nil {
102 s.elems = make(map[string]Object)
103 }
104 s.elems[name] = obj
105 if obj.Parent() == nil {
106 obj.setParent(s)
107 }
108 return nil
109 }
110
111
112
113
114
115
116
117 func (s *Scope) squash(err func(obj, alt Object)) {
118 p := s.parent
119 assert(p != nil)
120 for _, obj := range s.elems {
121 obj.setParent(nil)
122 if alt := p.Insert(obj); alt != nil {
123 err(obj, alt)
124 }
125 }
126
127 j := -1
128 for i, ch := range p.children {
129 if ch == s {
130 j = i
131 break
132 }
133 }
134 assert(j >= 0)
135 k := len(p.children) - 1
136 p.children[j] = p.children[k]
137 p.children = p.children[:k]
138
139 p.children = append(p.children, s.children...)
140
141 s.children = nil
142 s.elems = nil
143 }
144
145
146
147
148
149 func (s *Scope) Pos() token.Pos { return s.pos }
150 func (s *Scope) End() token.Pos { return s.end }
151
152
153
154
155 func (s *Scope) Contains(pos token.Pos) bool {
156 return s.pos <= pos && pos < s.end
157 }
158
159
160
161
162
163
164 func (s *Scope) Innermost(pos token.Pos) *Scope {
165
166
167 if s.parent == Universe {
168 for _, s := range s.children {
169 if inner := s.Innermost(pos); inner != nil {
170 return inner
171 }
172 }
173 }
174
175 if s.Contains(pos) {
176 for _, s := range s.children {
177 if s.Contains(pos) {
178 return s.Innermost(pos)
179 }
180 }
181 return s
182 }
183 return nil
184 }
185
186
187
188
189
190
191 func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
192 const ind = ". "
193 indn := strings.Repeat(ind, n)
194
195 fmt.Fprintf(w, "%s%s scope %p {\n", indn, s.comment, s)
196
197 indn1 := indn + ind
198 for _, name := range s.Names() {
199 fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name])
200 }
201
202 if recurse {
203 for _, s := range s.children {
204 s.WriteTo(w, n+1, recurse)
205 }
206 }
207
208 fmt.Fprintf(w, "%s}\n", indn)
209 }
210
211
212 func (s *Scope) String() string {
213 var buf bytes.Buffer
214 s.WriteTo(&buf, 0, false)
215 return buf.String()
216 }
217
View as plain text