1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "fmt"
12 "io"
13 "iter"
14 "slices"
15 "strings"
16 "sync"
17 "sync/atomic"
18 )
19
20
21
22
23
24 type Scope struct {
25 parent *Scope
26 children []*Scope
27 number int
28 objects map[string]Object
29 pos, end syntax.Pos
30 comment string
31 isFunc bool
32 sortedNames atomic.Pointer[[]string]
33 }
34
35
36
37 func NewScope(parent *Scope, pos, end syntax.Pos, comment string) *Scope {
38 s := &Scope{parent: parent, pos: pos, end: end, comment: comment}
39
40 if parent != nil && parent != Universe {
41 parent.children = append(parent.children, s)
42 s.number = len(parent.children)
43 }
44 return s
45 }
46
47
48 func (s *Scope) Parent() *Scope { return s.parent }
49
50
51 func (s *Scope) Len() int { return len(s.objects) }
52
53
54
55 func (s *Scope) Names() []string {
56
57
58 ptr := s.sortedNames.Load()
59 if ptr == nil {
60
61 names := make([]string, len(s.objects))
62 i := 0
63 for name := range s.objects {
64 names[i] = name
65 i++
66 }
67 slices.Sort(names)
68 ptr = &names
69
70
71 s.sortedNames.CompareAndSwap(nil, &names)
72 }
73 return *ptr
74 }
75
76
77 func (s *Scope) NumChildren() int { return len(s.children) }
78
79
80 func (s *Scope) Child(i int) *Scope { return s.children[i] }
81
82
83
84 func (s *Scope) Lookup(name string) Object { return resolve(name, s.objects[name]) }
85
86
87
88
89
90
91
92
93 func (s *Scope) Objects() iter.Seq[Object] {
94 return func(yield func(obj Object) bool) {
95 names := s.Names()
96 for _, name := range names {
97 if !yield(s.Lookup(name)) {
98 break
99 }
100 }
101 }
102 }
103
104
105
106
107 func (s *Scope) lookupIgnoringCase(name string, exported bool) []Object {
108 var matches []Object
109 for _, n := range s.Names() {
110 if (!exported || isExported(n)) && strings.EqualFold(n, name) {
111 matches = append(matches, s.Lookup(n))
112 }
113 }
114 return matches
115 }
116
117
118
119
120
121
122 func (s *Scope) Insert(obj Object) Object {
123 name := obj.Name()
124 if alt := s.Lookup(name); alt != nil {
125 return alt
126 }
127 s.insert(name, obj)
128
129
130
131
132
133 if obj.Parent() == nil {
134 obj.setParent(s)
135 }
136 return nil
137 }
138
139
140
141
142
143
144
145
146 func (s *Scope) InsertLazy(name string, resolve func() Object) bool {
147 if s.objects[name] != nil {
148 return false
149 }
150 s.insert(name, &lazyObject{parent: s, resolve: resolve})
151 return true
152 }
153
154 func (s *Scope) insert(name string, obj Object) {
155 if s.objects == nil {
156 s.objects = make(map[string]Object)
157 }
158 s.sortedNames.Store(nil)
159 s.objects[name] = obj
160 }
161
162
163
164
165
166
167 func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
168 const ind = ". "
169 indn := strings.Repeat(ind, n)
170
171 fmt.Fprintf(w, "%s%s scope %p {\n", indn, s.comment, s)
172
173 indn1 := indn + ind
174 for _, name := range s.Names() {
175 fmt.Fprintf(w, "%s%s\n", indn1, s.Lookup(name))
176 }
177
178 if recurse {
179 for _, s := range s.children {
180 s.WriteTo(w, n+1, recurse)
181 }
182 }
183
184 fmt.Fprintf(w, "%s}\n", indn)
185 }
186
187
188 func (s *Scope) String() string {
189 var buf strings.Builder
190 s.WriteTo(&buf, 0, false)
191 return buf.String()
192 }
193
194
195
196 type lazyObject struct {
197 parent *Scope
198 resolve func() Object
199 obj Object
200 once sync.Once
201 }
202
203
204
205 func resolve(name string, obj Object) Object {
206 if lazy, ok := obj.(*lazyObject); ok {
207 lazy.once.Do(func() {
208 obj := lazy.resolve()
209
210 if _, ok := obj.(*lazyObject); ok {
211 panic("recursive lazy object")
212 }
213 if obj.Name() != name {
214 panic("lazy object has unexpected name")
215 }
216
217 if obj.Parent() == nil {
218 obj.setParent(lazy.parent)
219 }
220 lazy.obj = obj
221 })
222
223 obj = lazy.obj
224 }
225 return obj
226 }
227
228
229
230 func (*lazyObject) Parent() *Scope { panic("unreachable") }
231 func (*lazyObject) Pos() syntax.Pos { panic("unreachable") }
232 func (*lazyObject) Pkg() *Package { panic("unreachable") }
233 func (*lazyObject) Name() string { panic("unreachable") }
234 func (*lazyObject) Type() Type { panic("unreachable") }
235 func (*lazyObject) Exported() bool { panic("unreachable") }
236 func (*lazyObject) Id() string { panic("unreachable") }
237 func (*lazyObject) String() string { panic("unreachable") }
238 func (*lazyObject) order() uint32 { panic("unreachable") }
239 func (*lazyObject) setType(Type) { panic("unreachable") }
240 func (*lazyObject) setOrder(uint32) { panic("unreachable") }
241 func (*lazyObject) setParent(*Scope) { panic("unreachable") }
242 func (*lazyObject) sameId(*Package, string, bool) bool { panic("unreachable") }
243 func (*lazyObject) scopePos() syntax.Pos { panic("unreachable") }
244 func (*lazyObject) setScopePos(syntax.Pos) { panic("unreachable") }
245
View as plain text