Home | History | Annotate | Download | only in 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