From 0d8ac5ecf1c6be4d81214b11579a7fd1cf7a4514 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 9 Jun 2016 14:55:56 -0700 Subject: cmd/compile/internal/syntax: cleanup TypeSwitchGuard handling Fixes typeswitch3.go and at least recognizes the error in typesw.go (albeit wrong line number and non-pretty-printed syntax.Expr output). Change-Id: I38b8e923265b0e7b3c301aea2f4a901bbabc24b5 --- src/cmd/compile/internal/syntax/nodes.go | 2 +- src/cmd/compile/internal/syntax/parser.go | 59 ++++++++++++------------------- 2 files changed, 23 insertions(+), 38 deletions(-) diff --git a/src/cmd/compile/internal/syntax/nodes.go b/src/cmd/compile/internal/syntax/nodes.go index de677a847a..087d7acafe 100644 --- a/src/cmd/compile/internal/syntax/nodes.go +++ b/src/cmd/compile/internal/syntax/nodes.go @@ -171,7 +171,7 @@ type ( AssertExpr struct { X Expr // TODO(gri) consider using Name{"..."} instead of nil (permits attaching of comments) - Type Expr // nil means x.(type) (for use in type switch) + Type Expr expr } diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 903a89c2ff..39e7347849 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -689,14 +689,19 @@ loop: case _Lparen: p.next() - t := new(AssertExpr) - t.init(p) - t.X = x - if !p.got(_Type) { + if p.got(_Type) { + t := new(TypeSwitchGuard) + t.init(p) + t.X = x + x = t + } else { + t := new(AssertExpr) + t.init(p) + t.X = x t.Type = p.expr() + x = t } p.want(_Rparen) - x = t default: p.syntax_error("expecting name or (") @@ -1446,16 +1451,17 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { // expr_list ':=' expr_list rhs := p.exprList() - if x, ok := rhs.(*AssertExpr); ok && x.Type == nil { - // x.(type) - // if len(rhs) > 1 { - // p.error("expr.(type) must be alone on ths") - // } - // if len(lhs) > 1 { - // p.error("argument count mismatch: %d = %d", len(lhs), 1) - // } else if x, ok := lhs[0].(*Name); !ok { - // p.error("invalid variable name %s in type switch", x) - // } + if x, ok := rhs.(*TypeSwitchGuard); ok { + switch lhs := lhs.(type) { + case *Name: + x.Lhs = lhs + case *ListExpr: + p.error(fmt.Sprintf("argument count mismatch: %d = %d", len(lhs.ElemList), 1)) + default: + // TODO(mdempsky): Have Expr types implement Stringer? + p.error(fmt.Sprintf("invalid variable name %s in type switch", lhs)) + } + return &ExprStmt{X: x} } return p.newAssignStmt(Def, lhs, rhs) @@ -1598,12 +1604,7 @@ func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleSt case nil: // nothing to do case *ExprStmt: - cond = p.unpackCond(nil, s.X) - case *AssignStmt: - // TODO(gri) allow := and = - if name, ok := s.Lhs.(*Name); ok && s.Op == Def { - cond = p.unpackCond(name, s.Rhs) - } + cond = s.X default: p.error("invalid condition, tag, or type switch guard") } @@ -1612,22 +1613,6 @@ func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleSt return } -func (p *parser) unpackCond(lhs *Name, x Expr) Expr { - if x, ok := x.(*AssertExpr); ok && x.Type == nil { - g := new(TypeSwitchGuard) - g.init(p) // TODO(gri) use correct position info - g.Lhs = lhs - g.X = x.X - return g - } - - if lhs != nil { - p.error("invalid type switch guard") - } - - return x -} - func (p *parser) ifStmt() *IfStmt { if trace { defer p.trace("ifStmt")() -- cgit v1.2.3-54-g00ecf