github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 "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 // An Object describes a named language entity such as a package, 68 // constant, type, variable, function (incl. methods), or label. 69 // 70 // The Data fields contains object-specific data: 71 // 72 // Kind Data type Data value 73 // Pkg *types.Package package scope 74 // Con int iota for the respective declaration 75 // Con != nil constant value 76 // Typ *Scope (used as method scope during type checking - transient) 77 // 78 type Object struct { 79 Kind ObjKind 80 Name string // declared name 81 Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil 82 Data interface{} // object-specific data; or nil 83 Type interface{} // place holder for type information; may be nil 84 } 85 86 // NewObj creates a new object of a given kind and name. 87 func NewObj(kind ObjKind, name string) *Object { 88 return &Object{Kind: kind, Name: name} 89 } 90 91 // Pos computes the source position of the declaration of an object name. 92 // The result may be an invalid position if it cannot be computed 93 // (obj.Decl may be nil or not correct). 94 func (obj *Object) Pos() token.Pos { 95 name := obj.Name 96 switch d := obj.Decl.(type) { 97 case *Field: 98 for _, n := range d.Names { 99 if n.Name == name { 100 return n.Pos() 101 } 102 } 103 case *ImportSpec: 104 if d.Name != nil && d.Name.Name == name { 105 return d.Name.Pos() 106 } 107 return d.Path.Pos() 108 case *ValueSpec: 109 for _, n := range d.Names { 110 if n.Name == name { 111 return n.Pos() 112 } 113 } 114 case *TypeSpec: 115 if d.Name.Name == name { 116 return d.Name.Pos() 117 } 118 case *FuncDecl: 119 if d.Name.Name == name { 120 return d.Name.Pos() 121 } 122 case *LabeledStmt: 123 if d.Label.Name == name { 124 return d.Label.Pos() 125 } 126 case *AssignStmt: 127 for _, x := range d.Lhs { 128 if ident, isIdent := x.(*Ident); isIdent && ident.Name == name { 129 return ident.Pos() 130 } 131 } 132 case *Scope: 133 // predeclared object - nothing to do for now 134 } 135 return token.NoPos 136 } 137 138 // ObjKind describes what an object represents. 139 type ObjKind int 140 141 // The list of possible Object kinds. 142 const ( 143 Bad ObjKind = iota // for error handling 144 Pkg // package 145 Con // constant 146 Typ // type 147 Var // variable 148 Fun // function or method 149 Lbl // label 150 ) 151 152 var objKindStrings = [...]string{ 153 Bad: "bad", 154 Pkg: "package", 155 Con: "const", 156 Typ: "type", 157 Var: "var", 158 Fun: "func", 159 Lbl: "label", 160 } 161 162 func (kind ObjKind) String() string { return objKindStrings[kind] }