continue
}
- lhs[i] = r.expr()
+ lhs[i] = typecheck.AssignExpr(r.expr0())
}
return names, lhs
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 {
// @@@ 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")
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)
}
}
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 {
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 {
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)
}
}