diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-07-09 17:47:15 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-07-10 04:02:52 +0000 |
commit | 3c3c1d8d2856e7859f4ba36b19c91f1538546d2a (patch) | |
tree | 65edade5496515baf44379931f48307975a747ae /src/cmd/compile/internal | |
parent | a12ad271195d88ffa8f68ad01547560fb4d2ab49 (diff) | |
download | go-3c3c1d8d2856e7859f4ba36b19c91f1538546d2a.tar.gz go-3c3c1d8d2856e7859f4ba36b19c91f1538546d2a.zip |
[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>
Diffstat (limited to 'src/cmd/compile/internal')
-rw-r--r-- | src/cmd/compile/internal/noder/codes.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 43 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 34 |
3 files changed, 57 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/noder/codes.go b/src/cmd/compile/internal/noder/codes.go index 4a6a4e8307..f8cb7729ac 100644 --- a/src/cmd/compile/internal/noder/codes.go +++ b/src/cmd/compile/internal/noder/codes.go @@ -107,9 +107,7 @@ const ( exprUnaryOp exprBinaryOp exprCall - - // TODO(mdempsky): Handle in switchStmt directly instead. - exprTypeSwitchGuard + exprConvert ) type codeDecl int diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 122bc70f24..19e51d9eba 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1252,7 +1252,7 @@ func (r *reader) assignList() ([]*ir.Name, []ir.Node) { continue } - lhs[i] = r.expr() + lhs[i] = typecheck.AssignExpr(r.expr0()) } return names, lhs @@ -1351,7 +1351,21 @@ func (r *reader) switchStmt(label *types.Sym) ir.Node { r.openScope() pos := r.pos() 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) if ok && tswitch.Tag == nil { @@ -1432,7 +1446,19 @@ func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool { // @@@ Expressions +// expr reads and returns a typechecked expression. 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 { default: panic("unhandled expression") @@ -1522,22 +1548,17 @@ func (r *reader) expr() ir.Node { return ir.NewBinaryExpr(pos, op, x, y) case exprCall: - fun := r.expr() + fun := typecheck.Callee(r.expr0()) pos := r.pos() args := r.exprs() dots := r.bool() return typecheck.Call(pos, fun, args, dots) - case exprTypeSwitchGuard: + case exprConvert: + typ := r.typ() 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() - return ir.NewTypeSwitchGuard(pos, tag, x) + return ir.NewConvExpr(pos, ir.OCONV, typ, x) } } diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 6348a56741..3f9310514a 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1033,7 +1033,17 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { w.openScope(stmt.Pos()) w.pos(stmt) 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)) for i, clause := range stmt.Body { @@ -1207,6 +1217,19 @@ func (w *writer) expr(expr syntax.Expr) { w.expr(expr.Y) 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) if inf, ok := w.p.info.Inferred[expr]; ok { @@ -1223,15 +1246,6 @@ func (w *writer) expr(expr syntax.Expr) { w.pos(expr) w.exprs(expr.ArgList) 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) } } |