github.com/bir3/gocompiler@v0.9.2202/src/go/parser/resolver.go (about)

     1  // Copyright 2021 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  package parser
     6  
     7  import (
     8  	"fmt"
     9  	"github.com/bir3/gocompiler/src/go/ast"
    10  	"github.com/bir3/gocompiler/src/go/token"
    11  	"strings"
    12  )
    13  
    14  const debugResolve = false
    15  
    16  // resolveFile walks the given file to resolve identifiers within the file
    17  // scope, updating ast.Ident.Obj fields with declaration information.
    18  //
    19  // If declErr is non-nil, it is used to report declaration errors during
    20  // resolution. tok is used to format position in error messages.
    21  func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) {
    22  	pkgScope := ast.NewScope(nil)
    23  	r := &resolver{
    24  		handle:		handle,
    25  		declErr:	declErr,
    26  		topScope:	pkgScope,
    27  		pkgScope:	pkgScope,
    28  		depth:		1,
    29  	}
    30  
    31  	for _, decl := range file.Decls {
    32  		ast.Walk(r, decl)
    33  	}
    34  
    35  	r.closeScope()
    36  	assert(r.topScope == nil, "unbalanced scopes")
    37  	assert(r.labelScope == nil, "unbalanced label scopes")
    38  
    39  	// resolve global identifiers within the same file
    40  	i := 0
    41  	for _, ident := range r.unresolved {
    42  		// i <= index for current ident
    43  		assert(ident.Obj == unresolved, "object already resolved")
    44  		ident.Obj = r.pkgScope.Lookup(ident.Name)	// also removes unresolved sentinel
    45  		if ident.Obj == nil {
    46  			r.unresolved[i] = ident
    47  			i++
    48  		} else if debugResolve {
    49  			pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()
    50  			r.trace("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
    51  		}
    52  	}
    53  	file.Scope = r.pkgScope
    54  	file.Unresolved = r.unresolved[0:i]
    55  }
    56  
    57  const maxScopeDepth int = 1e3
    58  
    59  type resolver struct {
    60  	handle	*token.File
    61  	declErr	func(token.Pos, string)
    62  
    63  	// Ordinary identifier scopes
    64  	pkgScope	*ast.Scope	// pkgScope.Outer == nil
    65  	topScope	*ast.Scope	// top-most scope; may be pkgScope
    66  	unresolved	[]*ast.Ident	// unresolved identifiers
    67  	depth		int		// scope depth
    68  
    69  	// Label scopes
    70  	// (maintained by open/close LabelScope)
    71  	labelScope	*ast.Scope	// label scope for current function
    72  	targetStack	[][]*ast.Ident	// stack of unresolved labels
    73  }
    74  
    75  func (r *resolver) trace(format string, args ...any) {
    76  	fmt.Println(strings.Repeat(". ", r.depth) + r.sprintf(format, args...))
    77  }
    78  
    79  func (r *resolver) sprintf(format string, args ...any) string {
    80  	for i, arg := range args {
    81  		switch arg := arg.(type) {
    82  		case token.Pos:
    83  			args[i] = r.handle.Position(arg)
    84  		}
    85  	}
    86  	return fmt.Sprintf(format, args...)
    87  }
    88  
    89  func (r *resolver) openScope(pos token.Pos) {
    90  	r.depth++
    91  	if r.depth > maxScopeDepth {
    92  		panic(bailout{pos: pos, msg: "exceeded max scope depth during object resolution"})
    93  	}
    94  	if debugResolve {
    95  		r.trace("opening scope @%v", pos)
    96  	}
    97  	r.topScope = ast.NewScope(r.topScope)
    98  }
    99  
   100  func (r *resolver) closeScope() {
   101  	r.depth--
   102  	if debugResolve {
   103  		r.trace("closing scope")
   104  	}
   105  	r.topScope = r.topScope.Outer
   106  }
   107  
   108  func (r *resolver) openLabelScope() {
   109  	r.labelScope = ast.NewScope(r.labelScope)
   110  	r.targetStack = append(r.targetStack, nil)
   111  }
   112  
   113  func (r *resolver) closeLabelScope() {
   114  	// resolve labels
   115  	n := len(r.targetStack) - 1
   116  	scope := r.labelScope
   117  	for _, ident := range r.targetStack[n] {
   118  		ident.Obj = scope.Lookup(ident.Name)
   119  		if ident.Obj == nil && r.declErr != nil {
   120  			r.declErr(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
   121  		}
   122  	}
   123  	// pop label scope
   124  	r.targetStack = r.targetStack[0:n]
   125  	r.labelScope = r.labelScope.Outer
   126  }
   127  
   128  func (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
   129  	for _, ident := range idents {
   130  		if ident.Obj != nil {
   131  			panic(fmt.Sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
   132  		}
   133  		obj := ast.NewObj(kind, ident.Name)
   134  		// remember the corresponding declaration for redeclaration
   135  		// errors and global variable resolution/typechecking phase
   136  		obj.Decl = decl
   137  		obj.Data = data
   138  		// Identifiers (for receiver type parameters) are written to the scope, but
   139  		// never set as the resolved object. See go.dev/issue/50956.
   140  		if _, ok := decl.(*ast.Ident); !ok {
   141  			ident.Obj = obj
   142  		}
   143  		if ident.Name != "_" {
   144  			if debugResolve {
   145  				r.trace("declaring %s@%v", ident.Name, ident.Pos())
   146  			}
   147  			if alt := scope.Insert(obj); alt != nil && r.declErr != nil {
   148  				prevDecl := ""
   149  				if pos := alt.Pos(); pos.IsValid() {
   150  					prevDecl = r.sprintf("\n\tprevious declaration at %v", pos)
   151  				}
   152  				r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
   153  			}
   154  		}
   155  	}
   156  }
   157  
   158  func (r *resolver) shortVarDecl(decl *ast.AssignStmt) {
   159  	// Go spec: A short variable declaration may redeclare variables
   160  	// provided they were originally declared in the same block with
   161  	// the same type, and at least one of the non-blank variables is new.
   162  	n := 0	// number of new variables
   163  	for _, x := range decl.Lhs {
   164  		if ident, isIdent := x.(*ast.Ident); isIdent {
   165  			assert(ident.Obj == nil, "identifier already declared or resolved")
   166  			obj := ast.NewObj(ast.Var, ident.Name)
   167  			// remember corresponding assignment for other tools
   168  			obj.Decl = decl
   169  			ident.Obj = obj
   170  			if ident.Name != "_" {
   171  				if debugResolve {
   172  					r.trace("declaring %s@%v", ident.Name, ident.Pos())
   173  				}
   174  				if alt := r.topScope.Insert(obj); alt != nil {
   175  					ident.Obj = alt	// redeclaration
   176  				} else {
   177  					n++	// new declaration
   178  				}
   179  			}
   180  		}
   181  	}
   182  	if n == 0 && r.declErr != nil {
   183  		r.declErr(decl.Lhs[0].Pos(), "no new variables on left side of :=")
   184  	}
   185  }
   186  
   187  // The unresolved object is a sentinel to mark identifiers that have been added
   188  // to the list of unresolved identifiers. The sentinel is only used for verifying
   189  // internal consistency.
   190  var unresolved = new(ast.Object)
   191  
   192  // If x is an identifier, resolve attempts to resolve x by looking up
   193  // the object it denotes. If no object is found and collectUnresolved is
   194  // set, x is marked as unresolved and collected in the list of unresolved
   195  // identifiers.
   196  func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {
   197  	if ident.Obj != nil {
   198  		panic(r.sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
   199  	}
   200  	// '_' should never refer to existing declarations, because it has special
   201  	// handling in the spec.
   202  	if ident.Name == "_" {
   203  		return
   204  	}
   205  	for s := r.topScope; s != nil; s = s.Outer {
   206  		if obj := s.Lookup(ident.Name); obj != nil {
   207  			if debugResolve {
   208  				r.trace("resolved %v:%s to %v", ident.Pos(), ident.Name, obj)
   209  			}
   210  			assert(obj.Name != "", "obj with no name")
   211  			// Identifiers (for receiver type parameters) are written to the scope,
   212  			// but never set as the resolved object. See go.dev/issue/50956.
   213  			if _, ok := obj.Decl.(*ast.Ident); !ok {
   214  				ident.Obj = obj
   215  			}
   216  			return
   217  		}
   218  	}
   219  	// all local scopes are known, so any unresolved identifier
   220  	// must be found either in the file scope, package scope
   221  	// (perhaps in another file), or universe scope --- collect
   222  	// them so that they can be resolved later
   223  	if collectUnresolved {
   224  		ident.Obj = unresolved
   225  		r.unresolved = append(r.unresolved, ident)
   226  	}
   227  }
   228  
   229  func (r *resolver) walkExprs(list []ast.Expr) {
   230  	for _, node := range list {
   231  		ast.Walk(r, node)
   232  	}
   233  }
   234  
   235  func (r *resolver) walkLHS(list []ast.Expr) {
   236  	for _, expr := range list {
   237  		expr := ast.Unparen(expr)
   238  		if _, ok := expr.(*ast.Ident); !ok && expr != nil {
   239  			ast.Walk(r, expr)
   240  		}
   241  	}
   242  }
   243  
   244  func (r *resolver) walkStmts(list []ast.Stmt) {
   245  	for _, stmt := range list {
   246  		ast.Walk(r, stmt)
   247  	}
   248  }
   249  
   250  func (r *resolver) Visit(node ast.Node) ast.Visitor {
   251  	if debugResolve && node != nil {
   252  		r.trace("node %T@%v", node, node.Pos())
   253  	}
   254  
   255  	switch n := node.(type) {
   256  
   257  	// Expressions.
   258  	case *ast.Ident:
   259  		r.resolve(n, true)
   260  
   261  	case *ast.FuncLit:
   262  		r.openScope(n.Pos())
   263  		defer r.closeScope()
   264  		r.walkFuncType(n.Type)
   265  		r.walkBody(n.Body)
   266  
   267  	case *ast.SelectorExpr:
   268  		ast.Walk(r, n.X)
   269  		// Note: don't try to resolve n.Sel, as we don't support qualified
   270  		// resolution.
   271  
   272  	case *ast.StructType:
   273  		r.openScope(n.Pos())
   274  		defer r.closeScope()
   275  		r.walkFieldList(n.Fields, ast.Var)
   276  
   277  	case *ast.FuncType:
   278  		r.openScope(n.Pos())
   279  		defer r.closeScope()
   280  		r.walkFuncType(n)
   281  
   282  	case *ast.CompositeLit:
   283  		if n.Type != nil {
   284  			ast.Walk(r, n.Type)
   285  		}
   286  		for _, e := range n.Elts {
   287  			if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
   288  				// See go.dev/issue/45160: try to resolve composite lit keys, but don't
   289  				// collect them as unresolved if resolution failed. This replicates
   290  				// existing behavior when resolving during parsing.
   291  				if ident, _ := kv.Key.(*ast.Ident); ident != nil {
   292  					r.resolve(ident, false)
   293  				} else {
   294  					ast.Walk(r, kv.Key)
   295  				}
   296  				ast.Walk(r, kv.Value)
   297  			} else {
   298  				ast.Walk(r, e)
   299  			}
   300  		}
   301  
   302  	case *ast.InterfaceType:
   303  		r.openScope(n.Pos())
   304  		defer r.closeScope()
   305  		r.walkFieldList(n.Methods, ast.Fun)
   306  
   307  	// Statements
   308  	case *ast.LabeledStmt:
   309  		r.declare(n, nil, r.labelScope, ast.Lbl, n.Label)
   310  		ast.Walk(r, n.Stmt)
   311  
   312  	case *ast.AssignStmt:
   313  		r.walkExprs(n.Rhs)
   314  		if n.Tok == token.DEFINE {
   315  			r.shortVarDecl(n)
   316  		} else {
   317  			r.walkExprs(n.Lhs)
   318  		}
   319  
   320  	case *ast.BranchStmt:
   321  		// add to list of unresolved targets
   322  		if n.Tok != token.FALLTHROUGH && n.Label != nil {
   323  			depth := len(r.targetStack) - 1
   324  			r.targetStack[depth] = append(r.targetStack[depth], n.Label)
   325  		}
   326  
   327  	case *ast.BlockStmt:
   328  		r.openScope(n.Pos())
   329  		defer r.closeScope()
   330  		r.walkStmts(n.List)
   331  
   332  	case *ast.IfStmt:
   333  		r.openScope(n.Pos())
   334  		defer r.closeScope()
   335  		if n.Init != nil {
   336  			ast.Walk(r, n.Init)
   337  		}
   338  		ast.Walk(r, n.Cond)
   339  		ast.Walk(r, n.Body)
   340  		if n.Else != nil {
   341  			ast.Walk(r, n.Else)
   342  		}
   343  
   344  	case *ast.CaseClause:
   345  		r.walkExprs(n.List)
   346  		r.openScope(n.Pos())
   347  		defer r.closeScope()
   348  		r.walkStmts(n.Body)
   349  
   350  	case *ast.SwitchStmt:
   351  		r.openScope(n.Pos())
   352  		defer r.closeScope()
   353  		if n.Init != nil {
   354  			ast.Walk(r, n.Init)
   355  		}
   356  		if n.Tag != nil {
   357  			// The scope below reproduces some unnecessary behavior of the parser,
   358  			// opening an extra scope in case this is a type switch. It's not needed
   359  			// for expression switches.
   360  			// TODO: remove this once we've matched the parser resolution exactly.
   361  			if n.Init != nil {
   362  				r.openScope(n.Tag.Pos())
   363  				defer r.closeScope()
   364  			}
   365  			ast.Walk(r, n.Tag)
   366  		}
   367  		if n.Body != nil {
   368  			r.walkStmts(n.Body.List)
   369  		}
   370  
   371  	case *ast.TypeSwitchStmt:
   372  		if n.Init != nil {
   373  			r.openScope(n.Pos())
   374  			defer r.closeScope()
   375  			ast.Walk(r, n.Init)
   376  		}
   377  		r.openScope(n.Assign.Pos())
   378  		defer r.closeScope()
   379  		ast.Walk(r, n.Assign)
   380  		// s.Body consists only of case clauses, so does not get its own
   381  		// scope.
   382  		if n.Body != nil {
   383  			r.walkStmts(n.Body.List)
   384  		}
   385  
   386  	case *ast.CommClause:
   387  		r.openScope(n.Pos())
   388  		defer r.closeScope()
   389  		if n.Comm != nil {
   390  			ast.Walk(r, n.Comm)
   391  		}
   392  		r.walkStmts(n.Body)
   393  
   394  	case *ast.SelectStmt:
   395  		// as for switch statements, select statement bodies don't get their own
   396  		// scope.
   397  		if n.Body != nil {
   398  			r.walkStmts(n.Body.List)
   399  		}
   400  
   401  	case *ast.ForStmt:
   402  		r.openScope(n.Pos())
   403  		defer r.closeScope()
   404  		if n.Init != nil {
   405  			ast.Walk(r, n.Init)
   406  		}
   407  		if n.Cond != nil {
   408  			ast.Walk(r, n.Cond)
   409  		}
   410  		if n.Post != nil {
   411  			ast.Walk(r, n.Post)
   412  		}
   413  		ast.Walk(r, n.Body)
   414  
   415  	case *ast.RangeStmt:
   416  		r.openScope(n.Pos())
   417  		defer r.closeScope()
   418  		ast.Walk(r, n.X)
   419  		var lhs []ast.Expr
   420  		if n.Key != nil {
   421  			lhs = append(lhs, n.Key)
   422  		}
   423  		if n.Value != nil {
   424  			lhs = append(lhs, n.Value)
   425  		}
   426  		if len(lhs) > 0 {
   427  			if n.Tok == token.DEFINE {
   428  				// Note: we can't exactly match the behavior of object resolution
   429  				// during the parsing pass here, as it uses the position of the RANGE
   430  				// token for the RHS OpPos. That information is not contained within
   431  				// the AST.
   432  				as := &ast.AssignStmt{
   433  					Lhs:	lhs,
   434  					Tok:	token.DEFINE,
   435  					TokPos:	n.TokPos,
   436  					Rhs:	[]ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}},
   437  				}
   438  				// TODO(rFindley): this walkLHS reproduced the parser resolution, but
   439  				// is it necessary? By comparison, for a normal AssignStmt we don't
   440  				// walk the LHS in case there is an invalid identifier list.
   441  				r.walkLHS(lhs)
   442  				r.shortVarDecl(as)
   443  			} else {
   444  				r.walkExprs(lhs)
   445  			}
   446  		}
   447  		ast.Walk(r, n.Body)
   448  
   449  	// Declarations
   450  	case *ast.GenDecl:
   451  		switch n.Tok {
   452  		case token.CONST, token.VAR:
   453  			for i, spec := range n.Specs {
   454  				spec := spec.(*ast.ValueSpec)
   455  				kind := ast.Con
   456  				if n.Tok == token.VAR {
   457  					kind = ast.Var
   458  				}
   459  				r.walkExprs(spec.Values)
   460  				if spec.Type != nil {
   461  					ast.Walk(r, spec.Type)
   462  				}
   463  				r.declare(spec, i, r.topScope, kind, spec.Names...)
   464  			}
   465  		case token.TYPE:
   466  			for _, spec := range n.Specs {
   467  				spec := spec.(*ast.TypeSpec)
   468  				// Go spec: The scope of a type identifier declared inside a function begins
   469  				// at the identifier in the TypeSpec and ends at the end of the innermost
   470  				// containing block.
   471  				r.declare(spec, nil, r.topScope, ast.Typ, spec.Name)
   472  				if spec.TypeParams != nil {
   473  					r.openScope(spec.Pos())
   474  					defer r.closeScope()
   475  					r.walkTParams(spec.TypeParams)
   476  				}
   477  				ast.Walk(r, spec.Type)
   478  			}
   479  		}
   480  
   481  	case *ast.FuncDecl:
   482  		// Open the function scope.
   483  		r.openScope(n.Pos())
   484  		defer r.closeScope()
   485  
   486  		r.walkRecv(n.Recv)
   487  
   488  		// Type parameters are walked normally: they can reference each other, and
   489  		// can be referenced by normal parameters.
   490  		if n.Type.TypeParams != nil {
   491  			r.walkTParams(n.Type.TypeParams)
   492  			// TODO(rFindley): need to address receiver type parameters.
   493  		}
   494  
   495  		// Resolve and declare parameters in a specific order to get duplicate
   496  		// declaration errors in the correct location.
   497  		r.resolveList(n.Type.Params)
   498  		r.resolveList(n.Type.Results)
   499  		r.declareList(n.Recv, ast.Var)
   500  		r.declareList(n.Type.Params, ast.Var)
   501  		r.declareList(n.Type.Results, ast.Var)
   502  
   503  		r.walkBody(n.Body)
   504  		if n.Recv == nil && n.Name.Name != "init" {
   505  			r.declare(n, nil, r.pkgScope, ast.Fun, n.Name)
   506  		}
   507  
   508  	default:
   509  		return r
   510  	}
   511  
   512  	return nil
   513  }
   514  
   515  func (r *resolver) walkFuncType(typ *ast.FuncType) {
   516  	// typ.TypeParams must be walked separately for FuncDecls.
   517  	r.resolveList(typ.Params)
   518  	r.resolveList(typ.Results)
   519  	r.declareList(typ.Params, ast.Var)
   520  	r.declareList(typ.Results, ast.Var)
   521  }
   522  
   523  func (r *resolver) resolveList(list *ast.FieldList) {
   524  	if list == nil {
   525  		return
   526  	}
   527  	for _, f := range list.List {
   528  		if f.Type != nil {
   529  			ast.Walk(r, f.Type)
   530  		}
   531  	}
   532  }
   533  
   534  func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) {
   535  	if list == nil {
   536  		return
   537  	}
   538  	for _, f := range list.List {
   539  		r.declare(f, nil, r.topScope, kind, f.Names...)
   540  	}
   541  }
   542  
   543  func (r *resolver) walkRecv(recv *ast.FieldList) {
   544  	// If our receiver has receiver type parameters, we must declare them before
   545  	// trying to resolve the rest of the receiver, and avoid re-resolving the
   546  	// type parameter identifiers.
   547  	if recv == nil || len(recv.List) == 0 {
   548  		return	// nothing to do
   549  	}
   550  	typ := recv.List[0].Type
   551  	if ptr, ok := typ.(*ast.StarExpr); ok {
   552  		typ = ptr.X
   553  	}
   554  
   555  	var declareExprs []ast.Expr	// exprs to declare
   556  	var resolveExprs []ast.Expr	// exprs to resolve
   557  	switch typ := typ.(type) {
   558  	case *ast.IndexExpr:
   559  		declareExprs = []ast.Expr{typ.Index}
   560  		resolveExprs = append(resolveExprs, typ.X)
   561  	case *ast.IndexListExpr:
   562  		declareExprs = typ.Indices
   563  		resolveExprs = append(resolveExprs, typ.X)
   564  	default:
   565  		resolveExprs = append(resolveExprs, typ)
   566  	}
   567  	for _, expr := range declareExprs {
   568  		if id, _ := expr.(*ast.Ident); id != nil {
   569  			r.declare(expr, nil, r.topScope, ast.Typ, id)
   570  		} else {
   571  			// The receiver type parameter expression is invalid, but try to resolve
   572  			// it anyway for consistency.
   573  			resolveExprs = append(resolveExprs, expr)
   574  		}
   575  	}
   576  	for _, expr := range resolveExprs {
   577  		if expr != nil {
   578  			ast.Walk(r, expr)
   579  		}
   580  	}
   581  	// The receiver is invalid, but try to resolve it anyway for consistency.
   582  	for _, f := range recv.List[1:] {
   583  		if f.Type != nil {
   584  			ast.Walk(r, f.Type)
   585  		}
   586  	}
   587  }
   588  
   589  func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {
   590  	if list == nil {
   591  		return
   592  	}
   593  	r.resolveList(list)
   594  	r.declareList(list, kind)
   595  }
   596  
   597  // walkTParams is like walkFieldList, but declares type parameters eagerly so
   598  // that they may be resolved in the constraint expressions held in the field
   599  // Type.
   600  func (r *resolver) walkTParams(list *ast.FieldList) {
   601  	r.declareList(list, ast.Typ)
   602  	r.resolveList(list)
   603  }
   604  
   605  func (r *resolver) walkBody(body *ast.BlockStmt) {
   606  	if body == nil {
   607  		return
   608  	}
   609  	r.openLabelScope()
   610  	defer r.closeLabelScope()
   611  	r.walkStmts(body.List)
   612  }