mirror of
https://github.com/golang/go
synced 2024-11-22 21:40:03 -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 {
|
switch x.mode {
|
||||||
case invalid:
|
case invalid:
|
||||||
return // error reported before
|
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
|
// ok
|
||||||
default:
|
default:
|
||||||
// we may get here because of other problems (go.dev/issue/39634, crash 12)
|
// we may get here because of other problems (go.dev/issue/39634, crash 12)
|
||||||
@ -41,6 +44,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||||||
// bool, rune, int, float64, complex128 or string respectively, depending
|
// bool, rune, int, float64, complex128 or string respectively, depending
|
||||||
// on whether the value is a boolean, rune, integer, floating-point,
|
// on whether the value is a boolean, rune, integer, floating-point,
|
||||||
// complex, or string constant."
|
// complex, or string constant."
|
||||||
|
if isTypes2 {
|
||||||
if x.isNil() {
|
if x.isNil() {
|
||||||
if T == nil {
|
if T == nil {
|
||||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||||
@ -50,6 +54,16 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||||||
} else if T == nil || isNonTypeParamInterface(T) {
|
} else if T == nil || isNonTypeParamInterface(T) {
|
||||||
target = Default(x.typ)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
newType, val, code := check.implicitTypeAndValue(x, target)
|
newType, val, code := check.implicitTypeAndValue(x, target)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
|
msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
|
||||||
@ -245,7 +259,7 @@ func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand, context string
|
|||||||
|
|
||||||
if x == nil {
|
if x == nil {
|
||||||
var target *target
|
var target *target
|
||||||
// avoid calling syntax.String if not needed
|
// avoid calling ExprString if not needed
|
||||||
if T != nil {
|
if T != nil {
|
||||||
if _, ok := under(T).(*Signature); ok {
|
if _, ok := under(T).(*Signature); ok {
|
||||||
target = newTarget(T, ExprString(lhs))
|
target = newTarget(T, ExprString(lhs))
|
||||||
@ -493,7 +507,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
|
|||||||
// orig_rhs[0] was already evaluated
|
// 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)
|
top := len(check.delayed)
|
||||||
scope := check.scope
|
scope := check.scope
|
||||||
|
|
||||||
@ -506,6 +520,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
|||||||
ident, _ := lhs.(*syntax.Name)
|
ident, _ := lhs.(*syntax.Name)
|
||||||
if ident == nil {
|
if ident == nil {
|
||||||
check.useLHS(lhs)
|
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)
|
check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
|
||||||
hasErr = true
|
hasErr = true
|
||||||
continue
|
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
|
// 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 := syntax.EndPos(rhs[len(rhs)-1])
|
scopePos := endPos(rhs[len(rhs)-1])
|
||||||
for _, obj := range newVars {
|
for _, obj := range newVars {
|
||||||
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ const (
|
|||||||
variable // operand is an addressable variable
|
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)
|
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
|
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
|
commaok // like value, but operand may be used in a comma,ok expression
|
||||||
commaerr // like commaok, but second value is error, not boolean
|
commaerr // like commaok, but second value is error, not boolean
|
||||||
cgofunc // operand is a cgo function
|
cgofunc // operand is a cgo function
|
||||||
@ -42,7 +42,7 @@ var operandModeString = [...]string{
|
|||||||
variable: "variable",
|
variable: "variable",
|
||||||
mapindex: "map index expression",
|
mapindex: "map index expression",
|
||||||
value: "value",
|
value: "value",
|
||||||
nilvalue: "nil",
|
nilvalue: "nil", // only used by types2
|
||||||
commaok: "comma, ok expression",
|
commaok: "comma, ok expression",
|
||||||
commaerr: "comma, error expression",
|
commaerr: "comma, error expression",
|
||||||
cgofunc: "cgo function",
|
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.
|
// argErrPos returns the node (poser) for reportign an invalid argument count.
|
||||||
func argErrPos(call *syntax.CallExpr) *syntax.CallExpr {
|
func argErrPos(call *syntax.CallExpr) *syntax.CallExpr { return call }
|
||||||
return call
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExprString returns a string representation of x.
|
// ExprString returns a string representation of x.
|
||||||
func ExprString(x syntax.Node) string { return syntax.String(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.
|
// Copyright 2013 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.
|
||||||
@ -24,6 +26,9 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||||||
switch x.mode {
|
switch x.mode {
|
||||||
case invalid:
|
case invalid:
|
||||||
return // error reported before
|
return // error reported before
|
||||||
|
case nilvalue:
|
||||||
|
assert(isTypes2)
|
||||||
|
// ok
|
||||||
case constant_, variable, mapindex, value, commaok, commaerr:
|
case constant_, variable, mapindex, value, commaok, commaerr:
|
||||||
// ok
|
// ok
|
||||||
default:
|
default:
|
||||||
@ -41,6 +46,17 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||||||
// bool, rune, int, float64, complex128 or string respectively, depending
|
// bool, rune, int, float64, complex128 or string respectively, depending
|
||||||
// on whether the value is a boolean, rune, integer, floating-point,
|
// on whether the value is a boolean, rune, integer, floating-point,
|
||||||
// complex, or string constant."
|
// complex, or string constant."
|
||||||
|
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 || isNonTypeParamInterface(T) {
|
||||||
if T == nil && x.typ == Typ[UntypedNil] {
|
if T == nil && x.typ == Typ[UntypedNil] {
|
||||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||||
@ -49,6 +65,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||||||
}
|
}
|
||||||
target = Default(x.typ)
|
target = Default(x.typ)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
newType, val, code := check.implicitTypeAndValue(x, target)
|
newType, val, code := check.implicitTypeAndValue(x, target)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
|
msg := check.sprintf("cannot use %s as %s value in %s", x, target, context)
|
||||||
@ -505,7 +522,7 @@ func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
|
|||||||
ident, _ := lhs.(*ast.Ident)
|
ident, _ := lhs.(*ast.Ident)
|
||||||
if ident == nil {
|
if ident == nil {
|
||||||
check.useLHS(lhs)
|
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)
|
check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
|
||||||
hasErr = true
|
hasErr = true
|
||||||
continue
|
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
|
// 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 := rhs[len(rhs)-1].End()
|
scopePos := endPos(rhs[len(rhs)-1])
|
||||||
for _, obj := range newVars {
|
for _, obj := range newVars {
|
||||||
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,11 @@ type action func(in *ast.File)
|
|||||||
|
|
||||||
var filemap = map[string]action{
|
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,
|
"array.go": nil,
|
||||||
"api_predicates.go": nil,
|
"api_predicates.go": nil,
|
||||||
"basic.go": nil,
|
"basic.go": nil,
|
||||||
|
@ -26,6 +26,7 @@ const (
|
|||||||
variable // operand is an addressable variable
|
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)
|
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
|
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
|
commaok // like value, but operand may be used in a comma,ok expression
|
||||||
commaerr // like commaok, but second value is error, not boolean
|
commaerr // like commaok, but second value is error, not boolean
|
||||||
cgofunc // operand is a cgo function
|
cgofunc // operand is a cgo function
|
||||||
@ -40,6 +41,7 @@ var operandModeString = [...]string{
|
|||||||
variable: "variable",
|
variable: "variable",
|
||||||
mapindex: "map index expression",
|
mapindex: "map index expression",
|
||||||
value: "value",
|
value: "value",
|
||||||
|
nilvalue: "nil", // only used by types2
|
||||||
commaok: "comma, ok expression",
|
commaok: "comma, ok expression",
|
||||||
commaerr: "comma, error expression",
|
commaerr: "comma, error expression",
|
||||||
cgofunc: "cgo function",
|
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() }
|
func hasDots(call *ast.CallExpr) bool { return call.Ellipsis.IsValid() }
|
||||||
|
|
||||||
// dddErrPos returns the positioner for reporting an invalid ... use in a call.
|
// dddErrPos returns the positioner for reporting an invalid ... use in a call.
|
||||||
func dddErrPos(call *ast.CallExpr) positioner {
|
func dddErrPos(call *ast.CallExpr) positioner { return atPos(call.Ellipsis) }
|
||||||
return atPos(call.Ellipsis)
|
|
||||||
}
|
|
||||||
|
|
||||||
// argErrPos returns positioner for reportign an invalid argument count.
|
// argErrPos returns positioner for reportign an invalid argument count.
|
||||||
func argErrPos(call *ast.CallExpr) positioner {
|
func argErrPos(call *ast.CallExpr) positioner { return inNode(call, call.Rparen) }
|
||||||
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