1// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
2// Source: ../../cmd/compile/internal/types2/scope.go
3
4// Copyright 2013 The Go Authors. All rights reserved.
5// Use of this source code is governed by a BSD-style
6// license that can be found in the LICENSE file.
7
8// This file implements Scopes.
9
10package types
11
12import (
13	"fmt"
14	"go/token"
15	"io"
16	"sort"
17	"strings"
18	"sync"
19)
20
21// A Scope maintains a set of objects and links to its containing
22// (parent) and contained (children) scopes. Objects may be inserted
23// and looked up by name. The zero value for Scope is a ready-to-use
24// empty scope.
25type Scope struct {
26	parent   *Scope
27	children []*Scope
28	number   int               // parent.children[number-1] is this scope; 0 if there is no parent
29	elems    map[string]Object // lazily allocated
30	pos, end token.Pos         // scope extent; may be invalid
31	comment  string            // for debugging only
32	isFunc   bool              // set if this is a function scope (internal use only)
33}
34
35// NewScope returns a new, empty scope contained in the given parent
36// scope, if any. The comment is for debugging only.
37func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
38	s := &Scope{parent, nil, 0, nil, pos, end, comment, false}
39	// don't add children to Universe scope!
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// Parent returns the scope's containing (parent) scope.
48func (s *Scope) Parent() *Scope { return s.parent }
49
50// Len returns the number of scope elements.
51func (s *Scope) Len() int { return len(s.elems) }
52
53// Names returns the scope's element names in sorted order.
54func (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	sort.Strings(names)
62	return names
63}
64
65// NumChildren returns the number of scopes nested in s.
66func (s *Scope) NumChildren() int { return len(s.children) }
67
68// Child returns the i'th child scope for 0 <= i < NumChildren().
69func (s *Scope) Child(i int) *Scope { return s.children[i] }
70
71// Lookup returns the object in scope s with the given name if such an
72// object exists; otherwise the result is nil.
73func (s *Scope) Lookup(name string) Object {
74	obj := resolve(name, s.elems[name])
75	// Hijack Lookup for "any": with gotypesalias=1, we want the Universe to
76	// return an Alias for "any", and with gotypesalias=0 we want to return
77	// the legacy representation of aliases.
78	//
79	// This is rather tricky, but works out after auditing of the usage of
80	// s.elems. The only external API to access scope elements is Lookup.
81	//
82	// TODO: remove this once gotypesalias=0 is no longer supported.
83	if obj == universeAnyAlias && !aliasAny() {
84		return universeAnyNoAlias
85	}
86	return obj
87}
88
89// LookupParent follows the parent chain of scopes starting with s until
90// it finds a scope where Lookup(name) returns a non-nil object, and then
91// returns that scope and object. If a valid position pos is provided,
92// only objects that were declared at or before pos are considered.
93// If no such scope and object exists, the result is (nil, nil).
94//
95// Note that obj.Parent() may be different from the returned scope if the
96// object was inserted into the scope and already had a parent at that
97// time (see Insert). This can only happen for dot-imported objects
98// whose scope is the scope of the package that exported them.
99func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) {
100	for ; s != nil; s = s.parent {
101		if obj := s.Lookup(name); obj != nil && (!pos.IsValid() || cmpPos(obj.scopePos(), pos) <= 0) {
102			return s, obj
103		}
104	}
105	return nil, nil
106}
107
108// Insert attempts to insert an object obj into scope s.
109// If s already contains an alternative object alt with
110// the same name, Insert leaves s unchanged and returns alt.
111// Otherwise it inserts obj, sets the object's parent scope
112// if not already set, and returns nil.
113func (s *Scope) Insert(obj Object) Object {
114	name := obj.Name()
115	if alt := s.Lookup(name); alt != nil {
116		return alt
117	}
118	s.insert(name, obj)
119	if obj.Parent() == nil {
120		obj.setParent(s)
121	}
122	return nil
123}
124
125// InsertLazy is like Insert, but allows deferring construction of the
126// inserted object until it's accessed with Lookup. The Object
127// returned by resolve must have the same name as given to InsertLazy.
128// If s already contains an alternative object with the same name,
129// InsertLazy leaves s unchanged and returns false. Otherwise it
130// records the binding and returns true. The object's parent scope
131// will be set to s after resolve is called.
132func (s *Scope) _InsertLazy(name string, resolve func() Object) bool {
133	if s.elems[name] != nil {
134		return false
135	}
136	s.insert(name, &lazyObject{parent: s, resolve: resolve})
137	return true
138}
139
140func (s *Scope) insert(name string, obj Object) {
141	if s.elems == nil {
142		s.elems = make(map[string]Object)
143	}
144	s.elems[name] = obj
145}
146
147// Squash merges s with its parent scope p by adding all
148// objects of s to p, adding all children of s to the
149// children of p, and removing s from p's children.
150// The function f is called for each object obj in s which
151// has an object alt in p. s should be discarded after
152// having been squashed.
153func (s *Scope) squash(err func(obj, alt Object)) {
154	p := s.parent
155	assert(p != nil)
156	for name, obj := range s.elems {
157		obj = resolve(name, obj)
158		obj.setParent(nil)
159		if alt := p.Insert(obj); alt != nil {
160			err(obj, alt)
161		}
162	}
163
164	j := -1 // index of s in p.children
165	for i, ch := range p.children {
166		if ch == s {
167			j = i
168			break
169		}
170	}
171	assert(j >= 0)
172	k := len(p.children) - 1
173	p.children[j] = p.children[k]
174	p.children = p.children[:k]
175
176	p.children = append(p.children, s.children...)
177
178	s.children = nil
179	s.elems = nil
180}
181
182// Pos and End describe the scope's source code extent [pos, end).
183// The results are guaranteed to be valid only if the type-checked
184// AST has complete position information. The extent is undefined
185// for Universe and package scopes.
186func (s *Scope) Pos() token.Pos { return s.pos }
187func (s *Scope) End() token.Pos { return s.end }
188
189// Contains reports whether pos is within the scope's extent.
190// The result is guaranteed to be valid only if the type-checked
191// AST has complete position information.
192func (s *Scope) Contains(pos token.Pos) bool {
193	return cmpPos(s.pos, pos) <= 0 && cmpPos(pos, s.end) < 0
194}
195
196// Innermost returns the innermost (child) scope containing
197// pos. If pos is not within any scope, the result is nil.
198// The result is also nil for the Universe scope.
199// The result is guaranteed to be valid only if the type-checked
200// AST has complete position information.
201func (s *Scope) Innermost(pos token.Pos) *Scope {
202	// Package scopes do not have extents since they may be
203	// discontiguous, so iterate over the package's files.
204	if s.parent == Universe {
205		for _, s := range s.children {
206			if inner := s.Innermost(pos); inner != nil {
207				return inner
208			}
209		}
210	}
211
212	if s.Contains(pos) {
213		for _, s := range s.children {
214			if s.Contains(pos) {
215				return s.Innermost(pos)
216			}
217		}
218		return s
219	}
220	return nil
221}
222
223// WriteTo writes a string representation of the scope to w,
224// with the scope elements sorted by name.
225// The level of indentation is controlled by n >= 0, with
226// n == 0 for no indentation.
227// If recurse is set, it also writes nested (children) scopes.
228func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
229	const ind = ".  "
230	indn := strings.Repeat(ind, n)
231
232	fmt.Fprintf(w, "%s%s scope %p {\n", indn, s.comment, s)
233
234	indn1 := indn + ind
235	for _, name := range s.Names() {
236		fmt.Fprintf(w, "%s%s\n", indn1, s.Lookup(name))
237	}
238
239	if recurse {
240		for _, s := range s.children {
241			s.WriteTo(w, n+1, recurse)
242		}
243	}
244
245	fmt.Fprintf(w, "%s}\n", indn)
246}
247
248// String returns a string representation of the scope, for debugging.
249func (s *Scope) String() string {
250	var buf strings.Builder
251	s.WriteTo(&buf, 0, false)
252	return buf.String()
253}
254
255// A lazyObject represents an imported Object that has not been fully
256// resolved yet by its importer.
257type lazyObject struct {
258	parent  *Scope
259	resolve func() Object
260	obj     Object
261	once    sync.Once
262}
263
264// resolve returns the Object represented by obj, resolving lazy
265// objects as appropriate.
266func resolve(name string, obj Object) Object {
267	if lazy, ok := obj.(*lazyObject); ok {
268		lazy.once.Do(func() {
269			obj := lazy.resolve()
270
271			if _, ok := obj.(*lazyObject); ok {
272				panic("recursive lazy object")
273			}
274			if obj.Name() != name {
275				panic("lazy object has unexpected name")
276			}
277
278			if obj.Parent() == nil {
279				obj.setParent(lazy.parent)
280			}
281			lazy.obj = obj
282		})
283
284		obj = lazy.obj
285	}
286	return obj
287}
288
289// stub implementations so *lazyObject implements Object and we can
290// store them directly into Scope.elems.
291func (*lazyObject) Parent() *Scope                     { panic("unreachable") }
292func (*lazyObject) Pos() token.Pos                     { panic("unreachable") }
293func (*lazyObject) Pkg() *Package                      { panic("unreachable") }
294func (*lazyObject) Name() string                       { panic("unreachable") }
295func (*lazyObject) Type() Type                         { panic("unreachable") }
296func (*lazyObject) Exported() bool                     { panic("unreachable") }
297func (*lazyObject) Id() string                         { panic("unreachable") }
298func (*lazyObject) String() string                     { panic("unreachable") }
299func (*lazyObject) order() uint32                      { panic("unreachable") }
300func (*lazyObject) color() color                       { panic("unreachable") }
301func (*lazyObject) setType(Type)                       { panic("unreachable") }
302func (*lazyObject) setOrder(uint32)                    { panic("unreachable") }
303func (*lazyObject) setColor(color color)               { panic("unreachable") }
304func (*lazyObject) setParent(*Scope)                   { panic("unreachable") }
305func (*lazyObject) sameId(*Package, string, bool) bool { panic("unreachable") }
306func (*lazyObject) scopePos() token.Pos                { panic("unreachable") }
307func (*lazyObject) setScopePos(token.Pos)              { panic("unreachable") }
308