1
0
mirror of https://github.com/golang/go synced 2024-11-26 19:41:19 -07:00

cmd/compile/internal/types2: review of pos.go and move into syntax package

This moves the two helper functions startPos and endPos into
the syntax package where they belong. Export the functions and
adjust dependent code.

Change-Id: I8170faeadd7cfa8f53009f81fcffd50ec0fc6a98
Reviewed-on: https://go-review.googlesource.com/c/go/+/305578
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-03-29 15:15:56 -07:00
parent d57189e92b
commit 93466cc1b6
9 changed files with 128 additions and 132 deletions

View File

@ -1,16 +1,13 @@
// UNREVIEWED // Copyright 2020 The Go Authors. All rights reserved.
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This file implements helper functions for scope position computations. // This file implements helper functions for scope position computations.
package types2 package syntax
import "cmd/compile/internal/syntax" // StartPos returns the start position of n.
func StartPos(n Node) Pos {
// startPos returns the start position of n.
func startPos(n syntax.Node) syntax.Pos {
// Cases for nodes which don't need a correction are commented out. // Cases for nodes which don't need a correction are commented out.
for m := n; ; { for m := n; ; {
switch n := m.(type) { switch n := m.(type) {
@ -18,95 +15,95 @@ func startPos(n syntax.Node) syntax.Pos {
panic("internal error: nil") panic("internal error: nil")
// packages // packages
case *syntax.File: case *File:
// file block starts at the beginning of the file // file block starts at the beginning of the file
return syntax.MakePos(n.Pos().Base(), 1, 1) return MakePos(n.Pos().Base(), 1, 1)
// declarations // declarations
// case *syntax.ImportDecl: // case *ImportDecl:
// case *syntax.ConstDecl: // case *ConstDecl:
// case *syntax.TypeDecl: // case *TypeDecl:
// case *syntax.VarDecl: // case *VarDecl:
// case *syntax.FuncDecl: // case *FuncDecl:
// expressions // expressions
// case *syntax.BadExpr: // case *BadExpr:
// case *syntax.Name: // case *Name:
// case *syntax.BasicLit: // case *BasicLit:
case *syntax.CompositeLit: case *CompositeLit:
if n.Type != nil { if n.Type != nil {
m = n.Type m = n.Type
continue continue
} }
return n.Pos() return n.Pos()
// case *syntax.KeyValueExpr: // case *KeyValueExpr:
// case *syntax.FuncLit: // case *FuncLit:
// case *syntax.ParenExpr: // case *ParenExpr:
case *syntax.SelectorExpr: case *SelectorExpr:
m = n.X m = n.X
case *syntax.IndexExpr: case *IndexExpr:
m = n.X m = n.X
// case *syntax.SliceExpr: // case *SliceExpr:
case *syntax.AssertExpr: case *AssertExpr:
m = n.X m = n.X
case *syntax.TypeSwitchGuard: case *TypeSwitchGuard:
if n.Lhs != nil { if n.Lhs != nil {
m = n.Lhs m = n.Lhs
continue continue
} }
m = n.X m = n.X
case *syntax.Operation: case *Operation:
if n.Y != nil { if n.Y != nil {
m = n.X m = n.X
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.CallExpr: case *CallExpr:
m = n.Fun m = n.Fun
case *syntax.ListExpr: case *ListExpr:
if len(n.ElemList) > 0 { if len(n.ElemList) > 0 {
m = n.ElemList[0] m = n.ElemList[0]
continue continue
} }
return n.Pos() return n.Pos()
// types // types
// case *syntax.ArrayType: // case *ArrayType:
// case *syntax.SliceType: // case *SliceType:
// case *syntax.DotsType: // case *DotsType:
// case *syntax.StructType: // case *StructType:
// case *syntax.Field: // case *Field:
// case *syntax.InterfaceType: // case *InterfaceType:
// case *syntax.FuncType: // case *FuncType:
// case *syntax.MapType: // case *MapType:
// case *syntax.ChanType: // case *ChanType:
// statements // statements
// case *syntax.EmptyStmt: // case *EmptyStmt:
// case *syntax.LabeledStmt: // case *LabeledStmt:
// case *syntax.BlockStmt: // case *BlockStmt:
// case *syntax.ExprStmt: // case *ExprStmt:
case *syntax.SendStmt: case *SendStmt:
m = n.Chan m = n.Chan
// case *syntax.DeclStmt: // case *DeclStmt:
case *syntax.AssignStmt: case *AssignStmt:
m = n.Lhs m = n.Lhs
// case *syntax.BranchStmt: // case *BranchStmt:
// case *syntax.CallStmt: // case *CallStmt:
// case *syntax.ReturnStmt: // case *ReturnStmt:
// case *syntax.IfStmt: // case *IfStmt:
// case *syntax.ForStmt: // case *ForStmt:
// case *syntax.SwitchStmt: // case *SwitchStmt:
// case *syntax.SelectStmt: // case *SelectStmt:
// helper nodes // helper nodes
case *syntax.RangeClause: case *RangeClause:
if n.Lhs != nil { if n.Lhs != nil {
m = n.Lhs m = n.Lhs
continue continue
} }
m = n.X m = n.X
// case *syntax.CaseClause: // case *CaseClause:
// case *syntax.CommClause: // case *CommClause:
default: default:
return n.Pos() return n.Pos()
@ -114,30 +111,29 @@ func startPos(n syntax.Node) syntax.Pos {
} }
} }
// endPos returns the approximate end position of n in the source. // EndPos returns the approximate end position of n in the source.
// For some nodes (*syntax.Name, *syntax.BasicLit) it returns // For some nodes (*Name, *BasicLit) it returns the position immediately
// the position immediately following the node; for others // following the node; for others (*BlockStmt, *SwitchStmt, etc.) it
// (*syntax.BlockStmt, *syntax.SwitchStmt, etc.) it returns // returns the position of the closing '}'; and for some (*ParenExpr)
// the position of the closing '}'; and for some (*syntax.ParenExpr)
// the returned position is the end position of the last enclosed // the returned position is the end position of the last enclosed
// expression. // expression.
// Thus, endPos should not be used for exact demarcation of the // Thus, EndPos should not be used for exact demarcation of the
// end of a node in the source; it is mostly useful to determine // end of a node in the source; it is mostly useful to determine
// scope ranges where there is some leeway. // scope ranges where there is some leeway.
func endPos(n syntax.Node) syntax.Pos { func EndPos(n Node) Pos {
for m := n; ; { for m := n; ; {
switch n := m.(type) { switch n := m.(type) {
case nil: case nil:
panic("internal error: nil") panic("internal error: nil")
// packages // packages
case *syntax.File: case *File:
return n.EOF return n.EOF
// declarations // declarations
case *syntax.ImportDecl: case *ImportDecl:
m = n.Path m = n.Path
case *syntax.ConstDecl: case *ConstDecl:
if n.Values != nil { if n.Values != nil {
m = n.Values m = n.Values
continue continue
@ -151,9 +147,9 @@ func endPos(n syntax.Node) syntax.Pos {
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.TypeDecl: case *TypeDecl:
m = n.Type m = n.Type
case *syntax.VarDecl: case *VarDecl:
if n.Values != nil { if n.Values != nil {
m = n.Values m = n.Values
continue continue
@ -167,7 +163,7 @@ func endPos(n syntax.Node) syntax.Pos {
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.FuncDecl: case *FuncDecl:
if n.Body != nil { if n.Body != nil {
m = n.Body m = n.Body
continue continue
@ -175,27 +171,27 @@ func endPos(n syntax.Node) syntax.Pos {
m = n.Type m = n.Type
// expressions // expressions
case *syntax.BadExpr: case *BadExpr:
return n.Pos() return n.Pos()
case *syntax.Name: case *Name:
p := n.Pos() p := n.Pos()
return syntax.MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value))) return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value)))
case *syntax.BasicLit: case *BasicLit:
p := n.Pos() p := n.Pos()
return syntax.MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value))) return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value)))
case *syntax.CompositeLit: case *CompositeLit:
return n.Rbrace return n.Rbrace
case *syntax.KeyValueExpr: case *KeyValueExpr:
m = n.Value m = n.Value
case *syntax.FuncLit: case *FuncLit:
m = n.Body m = n.Body
case *syntax.ParenExpr: case *ParenExpr:
m = n.X m = n.X
case *syntax.SelectorExpr: case *SelectorExpr:
m = n.Sel m = n.Sel
case *syntax.IndexExpr: case *IndexExpr:
m = n.Index m = n.Index
case *syntax.SliceExpr: case *SliceExpr:
for i := len(n.Index) - 1; i >= 0; i-- { for i := len(n.Index) - 1; i >= 0; i-- {
if x := n.Index[i]; x != nil { if x := n.Index[i]; x != nil {
m = x m = x
@ -203,23 +199,23 @@ func endPos(n syntax.Node) syntax.Pos {
} }
} }
m = n.X m = n.X
case *syntax.AssertExpr: case *AssertExpr:
m = n.Type m = n.Type
case *syntax.TypeSwitchGuard: case *TypeSwitchGuard:
m = n.X m = n.X
case *syntax.Operation: case *Operation:
if n.Y != nil { if n.Y != nil {
m = n.Y m = n.Y
continue continue
} }
m = n.X m = n.X
case *syntax.CallExpr: case *CallExpr:
if l := lastExpr(n.ArgList); l != nil { if l := lastExpr(n.ArgList); l != nil {
m = l m = l
continue continue
} }
m = n.Fun m = n.Fun
case *syntax.ListExpr: case *ListExpr:
if l := lastExpr(n.ElemList); l != nil { if l := lastExpr(n.ElemList); l != nil {
m = l m = l
continue continue
@ -227,32 +223,32 @@ func endPos(n syntax.Node) syntax.Pos {
return n.Pos() return n.Pos()
// types // types
case *syntax.ArrayType: case *ArrayType:
m = n.Elem m = n.Elem
case *syntax.SliceType: case *SliceType:
m = n.Elem m = n.Elem
case *syntax.DotsType: case *DotsType:
m = n.Elem m = n.Elem
case *syntax.StructType: case *StructType:
if l := lastField(n.FieldList); l != nil { if l := lastField(n.FieldList); l != nil {
m = l m = l
continue continue
} }
return n.Pos() return n.Pos()
// TODO(gri) need to take TagList into account // TODO(gri) need to take TagList into account
case *syntax.Field: case *Field:
if n.Type != nil { if n.Type != nil {
m = n.Type m = n.Type
continue continue
} }
m = n.Name m = n.Name
case *syntax.InterfaceType: case *InterfaceType:
if l := lastField(n.MethodList); l != nil { if l := lastField(n.MethodList); l != nil {
m = l m = l
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.FuncType: case *FuncType:
if l := lastField(n.ResultList); l != nil { if l := lastField(n.ResultList); l != nil {
m = l m = l
continue continue
@ -262,71 +258,71 @@ func endPos(n syntax.Node) syntax.Pos {
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.MapType: case *MapType:
m = n.Value m = n.Value
case *syntax.ChanType: case *ChanType:
m = n.Elem m = n.Elem
// statements // statements
case *syntax.EmptyStmt: case *EmptyStmt:
return n.Pos() return n.Pos()
case *syntax.LabeledStmt: case *LabeledStmt:
m = n.Stmt m = n.Stmt
case *syntax.BlockStmt: case *BlockStmt:
return n.Rbrace return n.Rbrace
case *syntax.ExprStmt: case *ExprStmt:
m = n.X m = n.X
case *syntax.SendStmt: case *SendStmt:
m = n.Value m = n.Value
case *syntax.DeclStmt: case *DeclStmt:
if l := lastDecl(n.DeclList); l != nil { if l := lastDecl(n.DeclList); l != nil {
m = l m = l
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.AssignStmt: case *AssignStmt:
m = n.Rhs m = n.Rhs
if m == nil { if m == nil {
p := endPos(n.Lhs) p := EndPos(n.Lhs)
return syntax.MakePos(p.Base(), p.Line(), p.Col()+2) return MakePos(p.Base(), p.Line(), p.Col()+2)
} }
case *syntax.BranchStmt: case *BranchStmt:
if n.Label != nil { if n.Label != nil {
m = n.Label m = n.Label
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.CallStmt: case *CallStmt:
m = n.Call m = n.Call
case *syntax.ReturnStmt: case *ReturnStmt:
if n.Results != nil { if n.Results != nil {
m = n.Results m = n.Results
continue continue
} }
return n.Pos() return n.Pos()
case *syntax.IfStmt: case *IfStmt:
if n.Else != nil { if n.Else != nil {
m = n.Else m = n.Else
continue continue
} }
m = n.Then m = n.Then
case *syntax.ForStmt: case *ForStmt:
m = n.Body m = n.Body
case *syntax.SwitchStmt: case *SwitchStmt:
return n.Rbrace return n.Rbrace
case *syntax.SelectStmt: case *SelectStmt:
return n.Rbrace return n.Rbrace
// helper nodes // helper nodes
case *syntax.RangeClause: case *RangeClause:
m = n.X m = n.X
case *syntax.CaseClause: case *CaseClause:
if l := lastStmt(n.Body); l != nil { if l := lastStmt(n.Body); l != nil {
m = l m = l
continue continue
} }
return n.Colon return n.Colon
case *syntax.CommClause: case *CommClause:
if l := lastStmt(n.Body); l != nil { if l := lastStmt(n.Body); l != nil {
m = l m = l
continue continue
@ -339,28 +335,28 @@ func endPos(n syntax.Node) syntax.Pos {
} }
} }
func lastDecl(list []syntax.Decl) syntax.Decl { func lastDecl(list []Decl) Decl {
if l := len(list); l > 0 { if l := len(list); l > 0 {
return list[l-1] return list[l-1]
} }
return nil return nil
} }
func lastExpr(list []syntax.Expr) syntax.Expr { func lastExpr(list []Expr) Expr {
if l := len(list); l > 0 { if l := len(list); l > 0 {
return list[l-1] return list[l-1]
} }
return nil return nil
} }
func lastStmt(list []syntax.Stmt) syntax.Stmt { func lastStmt(list []Stmt) Stmt {
if l := len(list); l > 0 { if l := len(list); l > 0 {
return list[l-1] return list[l-1]
} }
return nil return nil
} }
func lastField(list []*syntax.Field) *syntax.Field { func lastField(list []*Field) *Field {
if l := len(list); l > 0 { if l := len(list); l > 0 {
return list[l-1] return list[l-1]
} }

View File

@ -377,7 +377,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
// for short variable declarations) and ends at the end of the innermost // for short variable declarations) and ends at the end of the innermost
// containing block." // containing block."
scopePos := endPos(rhs[len(rhs)-1]) scopePos := syntax.EndPos(rhs[len(rhs)-1])
for _, obj := range newVars { for _, obj := range newVars {
check.declare(scope, nil, obj, scopePos) // recordObject already called check.declare(scope, nil, obj, scopePos) // recordObject already called
} }

View File

@ -901,7 +901,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
// inside a function begins at the end of the ConstSpec or VarSpec // inside a function begins at the end of the ConstSpec or VarSpec
// (ShortVarDecl for short variable declarations) and ends at the // (ShortVarDecl for short variable declarations) and ends at the
// end of the innermost containing block." // end of the innermost containing block."
scopePos := endPos(s) scopePos := syntax.EndPos(s)
for i, name := range s.NameList { for i, name := range s.NameList {
check.declare(check.scope, name, lhs[i], scopePos) check.declare(check.scope, name, lhs[i], scopePos)
} }
@ -958,7 +958,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
// declare all variables // declare all variables
// (only at this point are the variable scopes (parents) set) // (only at this point are the variable scopes (parents) set)
scopePos := endPos(s) // see constant declarations scopePos := syntax.EndPos(s) // see constant declarations
for i, name := range s.NameList { for i, name := range s.NameList {
// see constant declarations // see constant declarations
check.declare(check.scope, name, lhs0[i], scopePos) check.declare(check.scope, name, lhs0[i], scopePos)

View File

@ -207,10 +207,10 @@ func posFor(at poser) syntax.Pos {
switch x := at.(type) { switch x := at.(type) {
case *operand: case *operand:
if x.expr != nil { if x.expr != nil {
return startPos(x.expr) return syntax.StartPos(x.expr)
} }
case syntax.Node: case syntax.Node:
return startPos(x) return syntax.StartPos(x)
} }
return at.Pos() return at.Pos()
} }

View File

@ -96,7 +96,7 @@ func (check *Checker) overflow(x *operand) {
// If the corresponding expression is an operation, use the // If the corresponding expression is an operation, use the
// operator position rather than the start of the expression // operator position rather than the start of the expression
// as error position. // as error position.
pos := startPos(x.expr) pos := syntax.StartPos(x.expr)
what := "" // operator description, if any what := "" // operator description, if any
if op, _ := x.expr.(*syntax.Operation); op != nil { if op, _ := x.expr.(*syntax.Operation); op != nil {
pos = op.Pos() pos = op.Pos()

View File

@ -11,7 +11,7 @@ import (
// labels checks correct label use in body. // labels checks correct label use in body.
func (check *Checker) labels(body *syntax.BlockStmt) { func (check *Checker) labels(body *syntax.BlockStmt) {
// set of all labels in this body // set of all labels in this body
all := NewScope(nil, body.Pos(), endPos(body), "label") all := NewScope(nil, body.Pos(), syntax.EndPos(body), "label")
fwdJumps := check.blockBranches(all, nil, nil, body.List) fwdJumps := check.blockBranches(all, nil, nil, body.List)

View File

@ -216,7 +216,7 @@ func (check *Checker) collectObjects() {
// but there is no corresponding package object. // but there is no corresponding package object.
check.recordDef(file.PkgName, nil) check.recordDef(file.PkgName, nil)
fileScope := NewScope(check.pkg.scope, startPos(file), endPos(file), check.filename(fileNo)) fileScope := NewScope(check.pkg.scope, syntax.StartPos(file), syntax.EndPos(file), check.filename(fileNo))
fileScopes = append(fileScopes, fileScope) fileScopes = append(fileScopes, fileScope)
check.recordScope(file, fileScope) check.recordScope(file, fileScope)

View File

@ -16,13 +16,13 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
if check.conf.Trace { if check.conf.Trace {
check.trace(body.Pos(), "--- %s: %s", name, sig) check.trace(body.Pos(), "--- %s: %s", name, sig)
defer func() { defer func() {
check.trace(endPos(body), "--- <end>") check.trace(syntax.EndPos(body), "--- <end>")
}() }()
} }
// set function scope extent // set function scope extent
sig.scope.pos = body.Pos() sig.scope.pos = body.Pos()
sig.scope.end = endPos(body) sig.scope.end = syntax.EndPos(body)
// save/restore current context and setup function context // save/restore current context and setup function context
// (and use 0 indentation at function start) // (and use 0 indentation at function start)
@ -154,7 +154,7 @@ func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
} }
func (check *Checker) openScope(node syntax.Node, comment string) { func (check *Checker) openScope(node syntax.Node, comment string) {
check.openScopeUntil(node, endPos(node), comment) check.openScopeUntil(node, syntax.EndPos(node), comment)
} }
func (check *Checker) openScopeUntil(node syntax.Node, end syntax.Pos, comment string) { func (check *Checker) openScopeUntil(node syntax.Node, end syntax.Pos, comment string) {
@ -723,7 +723,7 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
// "at the end of the TypeSwitchCase" in #16794 instead? // "at the end of the TypeSwitchCase" in #16794 instead?
scopePos := clause.Pos() // for default clause (len(List) == 0) scopePos := clause.Pos() // for default clause (len(List) == 0)
if n := len(cases); n > 0 { if n := len(cases); n > 0 {
scopePos = endPos(cases[n-1]) scopePos = syntax.EndPos(cases[n-1])
} }
check.declare(check.scope, nil, obj, scopePos) check.declare(check.scope, nil, obj, scopePos)
check.recordImplicit(clause, obj) check.recordImplicit(clause, obj)
@ -840,7 +840,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// declare variables // declare variables
if len(vars) > 0 { if len(vars) > 0 {
scopePos := endPos(rclause.X) // TODO(gri) should this just be s.Body.Pos (spec clarification)? scopePos := syntax.EndPos(rclause.X) // TODO(gri) should this just be s.Body.Pos (spec clarification)?
for _, obj := range vars { for _, obj := range vars {
// spec: "The scope of a constant or variable identifier declared inside // spec: "The scope of a constant or variable identifier declared inside
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl // a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl

View File

@ -131,7 +131,7 @@ func (check *Checker) typ(e syntax.Expr) Type {
// (see ordinaryType). // (see ordinaryType).
func (check *Checker) varType(e syntax.Expr) Type { func (check *Checker) varType(e syntax.Expr) Type {
typ := check.definedType(e, nil) typ := check.definedType(e, nil)
check.ordinaryType(startPos(e), typ) check.ordinaryType(syntax.StartPos(e), typ)
return typ return typ
} }
@ -1154,7 +1154,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
// spec: "An embedded type must be specified as a type name T or as a // spec: "An embedded type must be specified as a type name T or as a
// pointer to a non-interface type name *T, and T itself may not be a // pointer to a non-interface type name *T, and T itself may not be a
// pointer type." // pointer type."
pos := startPos(f.Type) pos := syntax.StartPos(f.Type)
name := embeddedFieldIdent(f.Type) name := embeddedFieldIdent(f.Type)
if name == nil { if name == nil {
check.errorf(pos, "invalid embedded field type %s", f.Type) check.errorf(pos, "invalid embedded field type %s", f.Type)