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  	"fmt"
    11  	"go/token"
    12  	"strings"
    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  // Deprecated: use the type checker [go/types] instead; see [Object].
    20  type Scope struct {
    21  	Outer   *Scope
    22  	Objects map[string]*Object
    23  }
    24  
    25  // NewScope creates a new scope nested in the outer scope.
    26  func NewScope(outer *Scope) *Scope {
    27  	const n = 4 // initial scope capacity
    28  	return &Scope{outer, make(map[string]*Object, n)}
    29  }
    30  
    31  // Lookup returns the object with the given name if it is
    32  // found in scope s, otherwise it returns nil. Outer scopes
    33  // are ignored.
    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  func (s *Scope) Insert(obj *Object) (alt *Object) {
    43  	if alt = s.Objects[obj.Name]; alt == nil {
    44  		s.Objects[obj.Name] = obj
    45  	}
    46  	return
    47  }
    48  
    49  // Debugging support
    50  func (s *Scope) String() string {
    51  	var buf strings.Builder
    52  	fmt.Fprintf(&buf, "scope %p {", s)
    53  	if s != nil && len(s.Objects) > 0 {
    54  		fmt.Fprintln(&buf)
    55  		for _, obj := range s.Objects {
    56  			fmt.Fprintf(&buf, "\t%s %s\n", obj.Kind, obj.Name)
    57  		}
    58  	}
    59  	fmt.Fprintf(&buf, "}\n")
    60  	return buf.String()
    61  }
    62  
    63  // ----------------------------------------------------------------------------
    64  // Objects
    65  
    66  // An Object describes a named language entity such as a package,
    67  // constant, type, variable, function (incl. methods), or label.
    68  //
    69  // The Data fields contains object-specific data:
    70  //
    71  //	Kind    Data type         Data value
    72  //	Pkg     *Scope            package scope
    73  //	Con     int               iota for the respective declaration
    74  //
    75  // Deprecated: The relationship between Idents and Objects cannot be
    76  // correctly computed without type information. For example, the
    77  // expression T{K: 0} may denote a struct, map, slice, or array
    78  // literal, depending on the type of T. If T is a struct, then K
    79  // refers to a field of T, whereas for the other types it refers to a
    80  // value in the environment.
    81  //
    82  // New programs should set the [parser.SkipObjectResolution] parser
    83  // flag to disable syntactic object resolution (which also saves CPU
    84  // and memory), and instead use the type checker [go/types] if object
    85  // resolution is desired. See the Defs, Uses, and Implicits fields of
    86  // the [types.Info] struct for details.
    87  type Object struct {
    88  	Kind ObjKind
    89  	Name string // declared name
    90  	Decl any    // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil
    91  	Data any    // object-specific data; or nil
    92  	Type any    // placeholder for type information; may be nil
    93  }
    94  
    95  // NewObj creates a new object of a given kind and name.
    96  func NewObj(kind ObjKind, name string) *Object {
    97  	return &Object{Kind: kind, Name: name}
    98  }
    99  
   100  // Pos computes the source position of the declaration of an object name.
   101  // The result may be an invalid position if it cannot be computed
   102  // (obj.Decl may be nil or not correct).
   103  func (obj *Object) Pos() token.Pos {
   104  	name := obj.Name
   105  	switch d := obj.Decl.(type) {
   106  	case *Field:
   107  		for _, n := range d.Names {
   108  			if n.Name == name {
   109  				return n.Pos()
   110  			}
   111  		}
   112  	case *ImportSpec:
   113  		if d.Name != nil && d.Name.Name == name {
   114  			return d.Name.Pos()
   115  		}
   116  		return d.Path.Pos()
   117  	case *ValueSpec:
   118  		for _, n := range d.Names {
   119  			if n.Name == name {
   120  				return n.Pos()
   121  			}
   122  		}
   123  	case *TypeSpec:
   124  		if d.Name.Name == name {
   125  			return d.Name.Pos()
   126  		}
   127  	case *FuncDecl:
   128  		if d.Name.Name == name {
   129  			return d.Name.Pos()
   130  		}
   131  	case *LabeledStmt:
   132  		if d.Label.Name == name {
   133  			return d.Label.Pos()
   134  		}
   135  	case *AssignStmt:
   136  		for _, x := range d.Lhs {
   137  			if ident, isIdent := x.(*Ident); isIdent && ident.Name == name {
   138  				return ident.Pos()
   139  			}
   140  		}
   141  	case *Scope:
   142  		// predeclared object - nothing to do for now
   143  	}
   144  	return token.NoPos
   145  }
   146  
   147  // ObjKind describes what an [Object] represents.
   148  type ObjKind int
   149  
   150  // The list of possible [Object] kinds.
   151  const (
   152  	Bad ObjKind = iota // for error handling
   153  	Pkg                // package
   154  	Con                // constant
   155  	Typ                // type
   156  	Var                // variable
   157  	Fun                // function or method
   158  	Lbl                // label
   159  )
   160  
   161  var objKindStrings = [...]string{
   162  	Bad: "bad",
   163  	Pkg: "package",
   164  	Con: "const",
   165  	Typ: "type",
   166  	Var: "var",
   167  	Fun: "func",
   168  	Lbl: "label",
   169  }
   170  
   171  func (kind ObjKind) String() string { return objKindStrings[kind] }
   172  

View as plain text