The Go Programming Language

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, or LabeledStmt; 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		}
   129		return token.NoPos
   130	}
   131	
   132	// ObKind describes what an object represents.
   133	type ObjKind int
   134	
   135	// The list of possible Object kinds.
   136	const (
   137		Bad ObjKind = iota // for error handling
   138		Pkg                // package
   139		Con                // constant
   140		Typ                // type
   141		Var                // variable
   142		Fun                // function or method
   143		Lbl                // label
   144	)
   145	
   146	var objKindStrings = [...]string{
   147		Bad: "bad",
   148		Pkg: "package",
   149		Con: "const",
   150		Typ: "type",
   151		Var: "var",
   152		Fun: "func",
   153		Lbl: "label",
   154	}
   155	
   156	func (kind ObjKind) String() string { return objKindStrings[kind] }

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.