1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "fmt"
12 "io"
13 "sort"
14 "strings"
15 "sync"
16 )
17
18
19
20
21
22 type Scope struct {
23 parent *Scope
24 children []*Scope
25 number int
26 elems map[string]Object
27 pos, end syntax.Pos
28 comment string
29 isFunc bool
30 }
31
32
33
34 func NewScope(parent *Scope, pos, end syntax.Pos, comment string) *Scope {
35 s := &Scope{parent, nil, 0, nil, pos, end, comment, false}
36
37 if parent != nil && parent != Universe {
38 parent.children = append(parent.children, s)
39 s.number = len(parent.children)
40 }
41 return s
42 }
43
44
45 func (s *Scope) Parent() *Scope { return s.parent }
46
47
48 func (s *Scope) Len() int { return len(s.elems) }
49
50
51 func (s *Scope) Names() []string {
52 names := make([]string, len(s.elems))
53 i := 0
54 for name := range s.elems {
55 names[i] = name
56 i++
57 }
58 sort.Strings(names)
59 return names
60 }
61
62
63 func (s *Scope) NumChildren() int { return len(s.children) }
64
65
66 func (s *Scope) Child(i int) *Scope { return s.children[i] }
67
68
69
70 func (s *Scope) Lookup(name string) Object {
71 obj := resolve(name, s.elems[name])
72
73
74
75
76
77
78
79
80 if obj == universeAnyAlias && !aliasAny() {
81 return universeAnyNoAlias
82 }
83 return obj
84 }
85
86
87
88
89
90
91
92
93
94
95
96 func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) {
97 for ; s != nil; s = s.parent {
98 if obj := s.Lookup(name); obj != nil && (!pos.IsKnown() || cmpPos(obj.scopePos(), pos) <= 0) {
99 return s, obj
100 }
101 }
102 return nil, nil
103 }
104
105
106
107
108
109
110 func (s *Scope) Insert(obj Object) Object {
111 name := obj.Name()
112 if alt := s.Lookup(name); alt != nil {
113 return alt
114 }
115 s.insert(name, obj)
116 if obj.Parent() == nil {
117 obj.setParent(s)
118 }
119 return nil
120 }
121
122
123
124
125
126
127
128
129 func (s *Scope) InsertLazy(name string, resolve func() Object) bool {
130 if s.elems[name] != nil {
131 return false
132 }
133 s.insert(name, &lazyObject{parent: s, resolve: resolve})
134 return true
135 }
136
137 func (s *Scope) insert(name string, obj Object) {
138 if s.elems == nil {
139 s.elems = make(map[string]Object)
140 }
141 s.elems[name] = obj
142 }
143
144
145
146
147
148
149
150 func (s *Scope) Squash(err func(obj, alt Object)) {
151 p := s.parent
152 assert(p != nil)
153 for name, obj := range s.elems {
154 obj = resolve(name, obj)
155 obj.setParent(nil)
156 if alt := p.Insert(obj); alt != nil {
157 err(obj, alt)
158 }
159 }
160
161 j := -1
162 for i, ch := range p.children {
163 if ch == s {
164 j = i
165 break
166 }
167 }
168 assert(j >= 0)
169 k := len(p.children) - 1
170 p.children[j] = p.children[k]
171 p.children = p.children[:k]
172
173 p.children = append(p.children, s.children...)
174
175 s.children = nil
176 s.elems = nil
177 }
178
179
180
181
182
183 func (s *Scope) Pos() syntax.Pos { return s.pos }
184 func (s *Scope) End() syntax.Pos { return s.end }
185
186
187
188
189 func (s *Scope) Contains(pos syntax.Pos) bool {
190 return cmpPos(s.pos, pos) <= 0 && cmpPos(pos, s.end) < 0
191 }
192
193
194
195
196
197
198 func (s *Scope) Innermost(pos syntax.Pos) *Scope {
199
200
201 if s.parent == Universe {
202 for _, s := range s.children {
203 if inner := s.Innermost(pos); inner != nil {
204 return inner
205 }
206 }
207 }
208
209 if s.Contains(pos) {
210 for _, s := range s.children {
211 if s.Contains(pos) {
212 return s.Innermost(pos)
213 }
214 }
215 return s
216 }
217 return nil
218 }
219
220
221
222
223
224
225 func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
226 const ind = ". "
227 indn := strings.Repeat(ind, n)
228
229 fmt.Fprintf(w, "%s%s scope %p {\n", indn, s.comment, s)
230
231 indn1 := indn + ind
232 for _, name := range s.Names() {
233 fmt.Fprintf(w, "%s%s\n", indn1, s.Lookup(name))
234 }
235
236 if recurse {
237 for _, s := range s.children {
238 s.WriteTo(w, n+1, recurse)
239 }
240 }
241
242 fmt.Fprintf(w, "%s}\n", indn)
243 }
244
245
246 func (s *Scope) String() string {
247 var buf strings.Builder
248 s.WriteTo(&buf, 0, false)
249 return buf.String()
250 }
251
252
253
254 type lazyObject struct {
255 parent *Scope
256 resolve func() Object
257 obj Object
258 once sync.Once
259 }
260
261
262
263 func resolve(name string, obj Object) Object {
264 if lazy, ok := obj.(*lazyObject); ok {
265 lazy.once.Do(func() {
266 obj := lazy.resolve()
267
268 if _, ok := obj.(*lazyObject); ok {
269 panic("recursive lazy object")
270 }
271 if obj.Name() != name {
272 panic("lazy object has unexpected name")
273 }
274
275 if obj.Parent() == nil {
276 obj.setParent(lazy.parent)
277 }
278 lazy.obj = obj
279 })
280
281 obj = lazy.obj
282 }
283 return obj
284 }
285
286
287
288 func (*lazyObject) Parent() *Scope { panic("unreachable") }
289 func (*lazyObject) Pos() syntax.Pos { panic("unreachable") }
290 func (*lazyObject) Pkg() *Package { panic("unreachable") }
291 func (*lazyObject) Name() string { panic("unreachable") }
292 func (*lazyObject) Type() Type { panic("unreachable") }
293 func (*lazyObject) Exported() bool { panic("unreachable") }
294 func (*lazyObject) Id() string { panic("unreachable") }
295 func (*lazyObject) String() string { panic("unreachable") }
296 func (*lazyObject) order() uint32 { panic("unreachable") }
297 func (*lazyObject) color() color { panic("unreachable") }
298 func (*lazyObject) setType(Type) { panic("unreachable") }
299 func (*lazyObject) setOrder(uint32) { panic("unreachable") }
300 func (*lazyObject) setColor(color color) { panic("unreachable") }
301 func (*lazyObject) setParent(*Scope) { panic("unreachable") }
302 func (*lazyObject) sameId(*Package, string, bool) bool { panic("unreachable") }
303 func (*lazyObject) scopePos() syntax.Pos { panic("unreachable") }
304 func (*lazyObject) setScopePos(syntax.Pos) { panic("unreachable") }
305
View as plain text