github.com/AndrienkoAleksandr/go@v0.0.19/src/go/ast/scope.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements scopes and the objects they contain. 6 7 package ast 8 9 import ( 10 "fmt" 11 "go/token" 12 "strings" 13 ) 14 15 // A Scope maintains the set of named language entities declared 16 // in the scope and a link to the immediately surrounding (outer) 17 // scope. 18 type Scope struct { 19 Outer *Scope 20 Objects map[string]*Object 21 } 22 23 // NewScope creates a new scope nested in the outer scope. 24 func NewScope(outer *Scope) *Scope { 25 const n = 4 // initial scope capacity 26 return &Scope{outer, make(map[string]*Object, n)} 27 } 28 29 // Lookup returns the object with the given name if it is 30 // found in scope s, otherwise it returns nil. Outer scopes 31 // are ignored. 32 func (s *Scope) Lookup(name string) *Object { 33 return s.Objects[name] 34 } 35 36 // Insert attempts to insert a named object obj into the scope s. 37 // If the scope already contains an object alt with the same name, 38 // Insert leaves the scope unchanged and returns alt. Otherwise 39 // it inserts obj and returns nil. 40 func (s *Scope) Insert(obj *Object) (alt *Object) { 41 if alt = s.Objects[obj.Name]; alt == nil { 42 s.Objects[obj.Name] = obj 43 } 44 return 45 } 46 47 // Debugging support 48 func (s *Scope) String() string { 49 var buf strings.Builder 50 fmt.Fprintf(&buf, "scope %p {", s) 51 if s != nil && len(s.Objects) > 0 { 52 fmt.Fprintln(&buf) 53 for _, obj := range s.Objects { 54 fmt.Fprintf(&buf, "\t%s %s\n", obj.Kind, obj.Name) 55 } 56 } 57 fmt.Fprintf(&buf, "}\n") 58 return buf.String() 59 } 60 61 // ---------------------------------------------------------------------------- 62 // Objects 63 64 // An Object describes a named language entity such as a package, 65 // constant, type, variable, function (incl. methods), or label. 66 // 67 // The Data fields contains object-specific data: 68 // 69 // Kind Data type Data value 70 // Pkg *Scope package scope 71 // Con int iota for the respective declaration 72 type Object struct { 73 Kind ObjKind 74 Name string // declared name 75 Decl any // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil 76 Data any // object-specific data; or nil 77 Type any // placeholder for type information; may be nil 78 } 79 80 // NewObj creates a new object of a given kind and name. 81 func NewObj(kind ObjKind, name string) *Object { 82 return &Object{Kind: kind, Name: name} 83 } 84 85 // Pos computes the source position of the declaration of an object name. 86 // The result may be an invalid position if it cannot be computed 87 // (obj.Decl may be nil or not correct). 88 func (obj *Object) Pos() token.Pos { 89 name := obj.Name 90 switch d := obj.Decl.(type) { 91 case *Field: 92 for _, n := range d.Names { 93 if n.Name == name { 94 return n.Pos() 95 } 96 } 97 case *ImportSpec: 98 if d.Name != nil && d.Name.Name == name { 99 return d.Name.Pos() 100 } 101 return d.Path.Pos() 102 case *ValueSpec: 103 for _, n := range d.Names { 104 if n.Name == name { 105 return n.Pos() 106 } 107 } 108 case *TypeSpec: 109 if d.Name.Name == name { 110 return d.Name.Pos() 111 } 112 case *FuncDecl: 113 if d.Name.Name == name { 114 return d.Name.Pos() 115 } 116 case *LabeledStmt: 117 if d.Label.Name == name { 118 return d.Label.Pos() 119 } 120 case *AssignStmt: 121 for _, x := range d.Lhs { 122 if ident, isIdent := x.(*Ident); isIdent && ident.Name == name { 123 return ident.Pos() 124 } 125 } 126 case *Scope: 127 // predeclared object - nothing to do for now 128 } 129 return token.NoPos 130 } 131 132 // ObjKind describes what an object represents. 133 type ObjKind int 134 135 // The list of possible Object kinds. 136 const ( 137 Bad ObjKind = iota // for error handling 138 Pkg // package 139 Con // constant 140 Typ // type 141 Var // variable 142 Fun // function or method 143 Lbl // label 144 ) 145 146 var objKindStrings = [...]string{ 147 Bad: "bad", 148 Pkg: "package", 149 Con: "const", 150 Typ: "type", 151 Var: "var", 152 Fun: "func", 153 Lbl: "label", 154 } 155 156 func (kind ObjKind) String() string { return objKindStrings[kind] }