mirror of
https://github.com/golang/go
synced 2024-11-26 08:07:57 -07:00
go/types: : generate assignments.go from types2 source
This CL reduces the amount of code that needs to be maintained manually by about 600 LOC. Change-Id: I7107c8050075281bf6840a9f5234d70e09734ce6 Reviewed-on: https://go-review.googlesource.com/c/go/+/565836 Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
638b9023e3
commit
55bb3d1c10
@ -24,7 +24,10 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
switch x.mode {
|
||||
case invalid:
|
||||
return // error reported before
|
||||
case constant_, variable, mapindex, value, nilvalue, commaok, commaerr:
|
||||
case nilvalue:
|
||||
assert(isTypes2)
|
||||
// ok
|
||||
case constant_, variable, mapindex, value, commaok, commaerr:
|
||||
// ok
|
||||
default:
|
||||
// we may get here because of other problems (go.dev/issue/39634, crash 12)
|
||||
@ -41,14 +44,25 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
// bool, rune, int, float64, complex128 or string respectively, depending
|
||||
// on whether the value is a boolean, rune, integer, floating-point,
|
||||
// complex, or string constant."
|
||||
if x.isNil() {
|
||||
if T == nil {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
if isTypes2 {
|
||||
if x.isNil() {
|
||||
if T == nil {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
} else if T == nil || isNonTypeParamInterface(T) {
|
||||
target = Default(x.typ)
|
||||
}
|
||||
} else { // go/types
|
||||
if T == nil || isNonTypeParamInterface(T) {
|
||||
if T == nil && x.typ == Typ[UntypedNil] {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
target = Default(x.typ)
|
||||
}
|
||||
} else if T == nil || isNonTypeParamInterface(T) {
|
||||
target = Default(x.typ)
|
||||
}
|
||||
newType, val, code := check.implicitTypeAndValue(x, target)
|
||||
if code != 0 {
|
||||
@ -245,7 +259,7 @@ func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand, context string
|
||||
|
||||
if x == nil {
|
||||
var target *target
|
||||
// avoid calling syntax.String if not needed
|
||||
// avoid calling ExprString if not needed
|
||||
if T != nil {
|
||||
if _, ok := under(T).(*Signature); ok {
|
||||
target = newTarget(T, ExprString(lhs))
|
||||
@ -493,7 +507,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
|
||||
// orig_rhs[0] was already evaluated
|
||||
}
|
||||
|
||||
func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
||||
func (check *Checker) shortVarDecl(pos poser, lhs, rhs []syntax.Expr) {
|
||||
top := len(check.delayed)
|
||||
scope := check.scope
|
||||
|
||||
@ -506,6 +520,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
||||
ident, _ := lhs.(*syntax.Name)
|
||||
if ident == nil {
|
||||
check.useLHS(lhs)
|
||||
// TODO(gri) This is redundant with a go/parser error. Consider omitting in go/types?
|
||||
check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
|
||||
hasErr = true
|
||||
continue
|
||||
@ -568,7 +583,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
||||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
// for short variable declarations) and ends at the end of the innermost
|
||||
// containing block."
|
||||
scopePos := syntax.EndPos(rhs[len(rhs)-1])
|
||||
scopePos := endPos(rhs[len(rhs)-1])
|
||||
for _, obj := range newVars {
|
||||
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ const (
|
||||
variable // operand is an addressable variable
|
||||
mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
|
||||
value // operand is a computed value
|
||||
nilvalue // operand is the nil value
|
||||
nilvalue // operand is the nil value - only used by types2
|
||||
commaok // like value, but operand may be used in a comma,ok expression
|
||||
commaerr // like commaok, but second value is error, not boolean
|
||||
cgofunc // operand is a cgo function
|
||||
@ -42,7 +42,7 @@ var operandModeString = [...]string{
|
||||
variable: "variable",
|
||||
mapindex: "map index expression",
|
||||
value: "value",
|
||||
nilvalue: "nil",
|
||||
nilvalue: "nil", // only used by types2
|
||||
commaok: "comma, ok expression",
|
||||
commaerr: "comma, error expression",
|
||||
cgofunc: "cgo function",
|
||||
|
@ -33,9 +33,10 @@ func dddErrPos(call *syntax.CallExpr) *syntax.CallExpr {
|
||||
}
|
||||
|
||||
// argErrPos returns the node (poser) for reportign an invalid argument count.
|
||||
func argErrPos(call *syntax.CallExpr) *syntax.CallExpr {
|
||||
return call
|
||||
}
|
||||
func argErrPos(call *syntax.CallExpr) *syntax.CallExpr { return call }
|
||||
|
||||
// ExprString returns a string representation of x.
|
||||
func ExprString(x syntax.Node) string { return syntax.String(x) }
|
||||
|
||||
// endPos returns the position of the first character immediately after node n.
|
||||
func endPos(n syntax.Node) syntax.Pos { return syntax.EndPos(n) }
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
|
||||
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
@ -24,6 +26,9 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
switch x.mode {
|
||||
case invalid:
|
||||
return // error reported before
|
||||
case nilvalue:
|
||||
assert(isTypes2)
|
||||
// ok
|
||||
case constant_, variable, mapindex, value, commaok, commaerr:
|
||||
// ok
|
||||
default:
|
||||
@ -41,13 +46,25 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
// bool, rune, int, float64, complex128 or string respectively, depending
|
||||
// on whether the value is a boolean, rune, integer, floating-point,
|
||||
// complex, or string constant."
|
||||
if T == nil || isNonTypeParamInterface(T) {
|
||||
if T == nil && x.typ == Typ[UntypedNil] {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
if isTypes2 {
|
||||
if x.isNil() {
|
||||
if T == nil {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
} else if T == nil || isNonTypeParamInterface(T) {
|
||||
target = Default(x.typ)
|
||||
}
|
||||
} else { // go/types
|
||||
if T == nil || isNonTypeParamInterface(T) {
|
||||
if T == nil && x.typ == Typ[UntypedNil] {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
target = Default(x.typ)
|
||||
}
|
||||
target = Default(x.typ)
|
||||
}
|
||||
newType, val, code := check.implicitTypeAndValue(x, target)
|
||||
if code != 0 {
|
||||
@ -505,7 +522,7 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
|
||||
ident, _ := lhs.(*ast.Ident)
|
||||
if ident == nil {
|
||||
check.useLHS(lhs)
|
||||
// TODO(rFindley) this is redundant with a parser error. Consider omitting?
|
||||
// TODO(gri) This is redundant with a go/parser error. Consider omitting in go/types?
|
||||
check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
|
||||
hasErr = true
|
||||
continue
|
||||
@ -568,7 +585,7 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
|
||||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
// for short variable declarations) and ends at the end of the innermost
|
||||
// containing block."
|
||||
scopePos := rhs[len(rhs)-1].End()
|
||||
scopePos := endPos(rhs[len(rhs)-1])
|
||||
for _, obj := range newVars {
|
||||
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
||||
}
|
||||
|
@ -95,7 +95,12 @@ func generate(t *testing.T, filename string, write bool) {
|
||||
type action func(in *ast.File)
|
||||
|
||||
var filemap = map[string]action{
|
||||
"alias.go": nil,
|
||||
"alias.go": nil,
|
||||
"assignments.go": func(f *ast.File) {
|
||||
renameImportPath(f, `"cmd/compile/internal/syntax"->"go/ast"`)
|
||||
renameSelectorExprs(f, "syntax.Name->ast.Ident", "ident.Value->ident.Name", "ast.Pos->token.Pos") // must happen before renaming identifiers
|
||||
renameIdents(f, "syntax->ast", "poser->positioner", "nopos->noposn")
|
||||
},
|
||||
"array.go": nil,
|
||||
"api_predicates.go": nil,
|
||||
"basic.go": nil,
|
||||
|
@ -26,6 +26,7 @@ const (
|
||||
variable // operand is an addressable variable
|
||||
mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
|
||||
value // operand is a computed value
|
||||
nilvalue // operand is the nil value - only used by types2
|
||||
commaok // like value, but operand may be used in a comma,ok expression
|
||||
commaerr // like commaok, but second value is error, not boolean
|
||||
cgofunc // operand is a cgo function
|
||||
@ -40,6 +41,7 @@ var operandModeString = [...]string{
|
||||
variable: "variable",
|
||||
mapindex: "map index expression",
|
||||
value: "value",
|
||||
nilvalue: "nil", // only used by types2
|
||||
commaok: "comma, ok expression",
|
||||
commaerr: "comma, error expression",
|
||||
cgofunc: "cgo function",
|
||||
|
@ -30,11 +30,10 @@ func cmpPos(p, q token.Pos) int { return int(p - q) }
|
||||
func hasDots(call *ast.CallExpr) bool { return call.Ellipsis.IsValid() }
|
||||
|
||||
// dddErrPos returns the positioner for reporting an invalid ... use in a call.
|
||||
func dddErrPos(call *ast.CallExpr) positioner {
|
||||
return atPos(call.Ellipsis)
|
||||
}
|
||||
func dddErrPos(call *ast.CallExpr) positioner { return atPos(call.Ellipsis) }
|
||||
|
||||
// argErrPos returns positioner for reportign an invalid argument count.
|
||||
func argErrPos(call *ast.CallExpr) positioner {
|
||||
return inNode(call, call.Rparen)
|
||||
}
|
||||
func argErrPos(call *ast.CallExpr) positioner { return inNode(call, call.Rparen) }
|
||||
|
||||
// endPos returns the position of the first character immediately after node n.
|
||||
func endPos(n ast.Node) token.Pos { return n.End() }
|
||||
|
Loading…
Reference in New Issue
Block a user