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