...

Source file src/go/ast/scope.go

Documentation: go/ast

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

View as plain text