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 return resolve(name, s.elems[name])
72 }
73
74
75
76
77
78
79
80
81
82
83
84 func (s *Scope) LookupParent(name string, pos syntax.Pos) (*Scope, Object) {
85 for ; s != nil; s = s.parent {
86 if obj := s.Lookup(name); obj != nil && (!pos.IsKnown() || cmpPos(obj.scopePos(), pos) <= 0) {
87 return s, obj
88 }
89 }
90 return nil, nil
91 }
92
93
94
95
96
97
98 func (s *Scope) Insert(obj Object) Object {
99 name := obj.Name()
100 if alt := s.Lookup(name); alt != nil {
101 return alt
102 }
103 s.insert(name, obj)
104 if obj.Parent() == nil {
105 obj.setParent(s)
106 }
107 return nil
108 }
109
110
111
112
113
114
115
116
117 func (s *Scope) InsertLazy(name string, resolve func() Object) bool {
118 if s.elems[name] != nil {
119 return false
120 }
121 s.insert(name, &lazyObject{parent: s, resolve: resolve})
122 return true
123 }
124
125 func (s *Scope) insert(name string, obj Object) {
126 if s.elems == nil {
127 s.elems = make(map[string]Object)
128 }
129 s.elems[name] = obj
130 }
131
132
133
134
135
136
137
138 func (s *Scope) Squash(err func(obj, alt Object)) {
139 p := s.parent
140 assert(p != nil)
141 for name, obj := range s.elems {
142 obj = resolve(name, obj)
143 obj.setParent(nil)
144 if alt := p.Insert(obj); alt != nil {
145 err(obj, alt)
146 }
147 }
148
149 j := -1
150 for i, ch := range p.children {
151 if ch == s {
152 j = i
153 break
154 }
155 }
156 assert(j >= 0)
157 k := len(p.children) - 1
158 p.children[j] = p.children[k]
159 p.children = p.children[:k]
160
161 p.children = append(p.children, s.children...)
162
163 s.children = nil
164 s.elems = nil
165 }
166
167
168
169
170
171 func (s *Scope) Pos() syntax.Pos { return s.pos }
172 func (s *Scope) End() syntax.Pos { return s.end }
173
174
175
176
177 func (s *Scope) Contains(pos syntax.Pos) bool {
178 return cmpPos(s.pos, pos) <= 0 && cmpPos(pos, s.end) < 0
179 }
180
181
182
183
184
185
186 func (s *Scope) Innermost(pos syntax.Pos) *Scope {
187
188
189 if s.parent == Universe {
190 for _, s := range s.children {
191 if inner := s.Innermost(pos); inner != nil {
192 return inner
193 }
194 }
195 }
196
197 if s.Contains(pos) {
198 for _, s := range s.children {
199 if s.Contains(pos) {
200 return s.Innermost(pos)
201 }
202 }
203 return s
204 }
205 return nil
206 }
207
208
209
210
211
212
213 func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
214 const ind = ". "
215 indn := strings.Repeat(ind, n)
216
217 fmt.Fprintf(w, "%s%s scope %p {\n", indn, s.comment, s)
218
219 indn1 := indn + ind
220 for _, name := range s.Names() {
221 fmt.Fprintf(w, "%s%s\n", indn1, s.Lookup(name))
222 }
223
224 if recurse {
225 for _, s := range s.children {
226 s.WriteTo(w, n+1, recurse)
227 }
228 }
229
230 fmt.Fprintf(w, "%s}\n", indn)
231 }
232
233
234 func (s *Scope) String() string {
235 var buf strings.Builder
236 s.WriteTo(&buf, 0, false)
237 return buf.String()
238 }
239
240
241
242 type lazyObject struct {
243 parent *Scope
244 resolve func() Object
245 obj Object
246 once sync.Once
247 }
248
249
250
251 func resolve(name string, obj Object) Object {
252 if lazy, ok := obj.(*lazyObject); ok {
253 lazy.once.Do(func() {
254 obj := lazy.resolve()
255
256 if _, ok := obj.(*lazyObject); ok {
257 panic("recursive lazy object")
258 }
259 if obj.Name() != name {
260 panic("lazy object has unexpected name")
261 }
262
263 if obj.Parent() == nil {
264 obj.setParent(lazy.parent)
265 }
266 lazy.obj = obj
267 })
268
269 obj = lazy.obj
270 }
271 return obj
272 }
273
274
275
276 func (*lazyObject) Parent() *Scope { panic("unreachable") }
277 func (*lazyObject) Pos() syntax.Pos { panic("unreachable") }
278 func (*lazyObject) Pkg() *Package { panic("unreachable") }
279 func (*lazyObject) Name() string { panic("unreachable") }
280 func (*lazyObject) Type() Type { panic("unreachable") }
281 func (*lazyObject) Exported() bool { panic("unreachable") }
282 func (*lazyObject) Id() string { panic("unreachable") }
283 func (*lazyObject) String() string { panic("unreachable") }
284 func (*lazyObject) order() uint32 { panic("unreachable") }
285 func (*lazyObject) color() color { panic("unreachable") }
286 func (*lazyObject) setType(Type) { panic("unreachable") }
287 func (*lazyObject) setOrder(uint32) { panic("unreachable") }
288 func (*lazyObject) setColor(color color) { panic("unreachable") }
289 func (*lazyObject) setParent(*Scope) { panic("unreachable") }
290 func (*lazyObject) sameId(pkg *Package, name string) bool { panic("unreachable") }
291 func (*lazyObject) scopePos() syntax.Pos { panic("unreachable") }
292 func (*lazyObject) setScopePos(pos syntax.Pos) { panic("unreachable") }
293
View as plain text