mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] cmd/compile: more incremental typecheck for unified IR
CL 332469 changed the unified IR reader to incrementally typecheck each statement as they're read/constructed. This CL goes further to incrementally typecheck each expression. While here, this CL reorganizes a few things to make this go more smoothly. In particular, it renames expr to expr0 and adds a new expr wrapper that applies typecheck.Expr; gets rid of exprTypeSwitchguard by moving that logic into switchStmt; and splits exprConvert out from exprCall, which simplifies the logic for typechecking the calleee expression somewhat. Change-Id: I6289de9388dc94a947971f4b7213aafeb2faa5dc Reviewed-on: https://go-review.googlesource.com/c/go/+/333730 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
a12ad27119
commit
3c3c1d8d28
3 changed files with 57 additions and 24 deletions
|
|
@ -107,9 +107,7 @@ const (
|
||||||
exprUnaryOp
|
exprUnaryOp
|
||||||
exprBinaryOp
|
exprBinaryOp
|
||||||
exprCall
|
exprCall
|
||||||
|
exprConvert
|
||||||
// TODO(mdempsky): Handle in switchStmt directly instead.
|
|
||||||
exprTypeSwitchGuard
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type codeDecl int
|
type codeDecl int
|
||||||
|
|
|
||||||
|
|
@ -1252,7 +1252,7 @@ func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs[i] = r.expr()
|
lhs[i] = typecheck.AssignExpr(r.expr0())
|
||||||
}
|
}
|
||||||
|
|
||||||
return names, lhs
|
return names, lhs
|
||||||
|
|
@ -1351,7 +1351,21 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node {
|
||||||
r.openScope()
|
r.openScope()
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
init := r.stmt()
|
init := r.stmt()
|
||||||
tag := r.expr()
|
|
||||||
|
var tag ir.Node
|
||||||
|
if r.bool() {
|
||||||
|
pos := r.pos()
|
||||||
|
var ident *ir.Ident
|
||||||
|
if r.bool() {
|
||||||
|
pos := r.pos()
|
||||||
|
sym := typecheck.Lookup(r.string())
|
||||||
|
ident = ir.NewIdent(pos, sym)
|
||||||
|
}
|
||||||
|
x := r.expr()
|
||||||
|
tag = ir.NewTypeSwitchGuard(pos, ident, x)
|
||||||
|
} else {
|
||||||
|
tag = r.expr()
|
||||||
|
}
|
||||||
|
|
||||||
tswitch, ok := tag.(*ir.TypeSwitchGuard)
|
tswitch, ok := tag.(*ir.TypeSwitchGuard)
|
||||||
if ok && tswitch.Tag == nil {
|
if ok && tswitch.Tag == nil {
|
||||||
|
|
@ -1432,7 +1446,19 @@ func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
|
||||||
|
|
||||||
// @@@ Expressions
|
// @@@ Expressions
|
||||||
|
|
||||||
|
// expr reads and returns a typechecked expression.
|
||||||
func (r *reader) expr() ir.Node {
|
func (r *reader) expr() ir.Node {
|
||||||
|
n := r.expr0()
|
||||||
|
if n == nil || n.Op() == ir.OTYPE {
|
||||||
|
// TODO(mdempsky): Push this responsibility up to callers?
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
return typecheck.Expr(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr0 reads and returns an expression, possibly untypechecked.
|
||||||
|
// The caller must typecheck the result as appropriate for its context.
|
||||||
|
func (r *reader) expr0() ir.Node {
|
||||||
switch tag := codeExpr(r.code(syncExpr)); tag {
|
switch tag := codeExpr(r.code(syncExpr)); tag {
|
||||||
default:
|
default:
|
||||||
panic("unhandled expression")
|
panic("unhandled expression")
|
||||||
|
|
@ -1522,22 +1548,17 @@ func (r *reader) expr() ir.Node {
|
||||||
return ir.NewBinaryExpr(pos, op, x, y)
|
return ir.NewBinaryExpr(pos, op, x, y)
|
||||||
|
|
||||||
case exprCall:
|
case exprCall:
|
||||||
fun := r.expr()
|
fun := typecheck.Callee(r.expr0())
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
args := r.exprs()
|
args := r.exprs()
|
||||||
dots := r.bool()
|
dots := r.bool()
|
||||||
return typecheck.Call(pos, fun, args, dots)
|
return typecheck.Call(pos, fun, args, dots)
|
||||||
|
|
||||||
case exprTypeSwitchGuard:
|
case exprConvert:
|
||||||
|
typ := r.typ()
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
var tag *ir.Ident
|
|
||||||
if r.bool() {
|
|
||||||
pos := r.pos()
|
|
||||||
sym := typecheck.Lookup(r.string())
|
|
||||||
tag = ir.NewIdent(pos, sym)
|
|
||||||
}
|
|
||||||
x := r.expr()
|
x := r.expr()
|
||||||
return ir.NewTypeSwitchGuard(pos, tag, x)
|
return ir.NewConvExpr(pos, ir.OCONV, typ, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1033,7 +1033,17 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
|
||||||
w.openScope(stmt.Pos())
|
w.openScope(stmt.Pos())
|
||||||
w.pos(stmt)
|
w.pos(stmt)
|
||||||
w.stmt(stmt.Init)
|
w.stmt(stmt.Init)
|
||||||
w.expr(stmt.Tag)
|
|
||||||
|
if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.bool(ok) {
|
||||||
|
w.pos(guard)
|
||||||
|
if tag := guard.Lhs; w.bool(tag != nil) {
|
||||||
|
w.pos(tag)
|
||||||
|
w.string(tag.Value)
|
||||||
|
}
|
||||||
|
w.expr(guard.X)
|
||||||
|
} else {
|
||||||
|
w.expr(stmt.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
w.len(len(stmt.Body))
|
w.len(len(stmt.Body))
|
||||||
for i, clause := range stmt.Body {
|
for i, clause := range stmt.Body {
|
||||||
|
|
@ -1207,6 +1217,19 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.expr(expr.Y)
|
w.expr(expr.Y)
|
||||||
|
|
||||||
case *syntax.CallExpr:
|
case *syntax.CallExpr:
|
||||||
|
tv, ok := w.p.info.Types[expr.Fun]
|
||||||
|
assert(ok)
|
||||||
|
if tv.IsType() {
|
||||||
|
assert(len(expr.ArgList) == 1)
|
||||||
|
assert(!expr.HasDots)
|
||||||
|
|
||||||
|
w.code(exprConvert)
|
||||||
|
w.typ(tv.Type)
|
||||||
|
w.pos(expr)
|
||||||
|
w.expr(expr.ArgList[0])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
w.code(exprCall)
|
w.code(exprCall)
|
||||||
|
|
||||||
if inf, ok := w.p.info.Inferred[expr]; ok {
|
if inf, ok := w.p.info.Inferred[expr]; ok {
|
||||||
|
|
@ -1223,15 +1246,6 @@ func (w *writer) expr(expr syntax.Expr) {
|
||||||
w.pos(expr)
|
w.pos(expr)
|
||||||
w.exprs(expr.ArgList)
|
w.exprs(expr.ArgList)
|
||||||
w.bool(expr.HasDots)
|
w.bool(expr.HasDots)
|
||||||
|
|
||||||
case *syntax.TypeSwitchGuard:
|
|
||||||
w.code(exprTypeSwitchGuard)
|
|
||||||
w.pos(expr)
|
|
||||||
if tag := expr.Lhs; w.bool(tag != nil) {
|
|
||||||
w.pos(tag)
|
|
||||||
w.string(tag.Value)
|
|
||||||
}
|
|
||||||
w.expr(expr.X)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue