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