...

Source file src/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	// 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