]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/syntax: support for alias declarations
authorRobert Griesemer <gri@golang.org>
Fri, 16 Sep 2016 00:40:26 +0000 (17:40 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 16 Sep 2016 20:58:20 +0000 (20:58 +0000)
Permits parsing of alias declarations with -newparser

const/type/var/func T => p.T

but the compiler will reject it with an error. For now this
also accepts

type T = p.T

so we can experiment with a type-alias only scenario.

- renamed _Arrow token to _Larrow (<-)
- introduced _Rarrow token (=>)
- introduced AliasDecl node
- extended scanner to accept _Rarrow
- extended parser and printer to handle alias declarations

Change-Id: I0170d10a87df8255db9186d466b6fd405228c38e
Reviewed-on: https://go-review.googlesource.com/29355
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/syntax/nodes.go
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/printer.go
src/cmd/compile/internal/syntax/scanner.go
src/cmd/compile/internal/syntax/scanner_test.go
src/cmd/compile/internal/syntax/tokens.go

index 13429ba816d26565161cc0a8a8312a3960596d10..4d97b48bce68a64a04f8104ae44c7c485c13a327 100644 (file)
@@ -60,6 +60,9 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
                case *syntax.ImportDecl:
                        p.importDecl(decl)
 
+               case *syntax.AliasDecl:
+                       yyerror("alias declarations not yet implemented")
+
                case *syntax.VarDecl:
                        l = append(l, p.varDecl(decl)...)
 
@@ -87,6 +90,10 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
                        lastConstGroup = decl.Group
 
                case *syntax.TypeDecl:
+                       if decl.Alias {
+                               yyerror("alias declarations not yet implemented")
+                               break
+                       }
                        l = append(l, p.typeDecl(decl))
 
                case *syntax.FuncDecl:
index 280a2e8f694fc62ad6dbd5706d6ae22920d7dca1..9555a4b9a8dde6c5c08e543735ee8e9fe81008c1 100644 (file)
@@ -25,14 +25,21 @@ func (n *node) Line() uint32 {
        return n.line
 }
 
+// TODO(gri) clean up init/initFrom once we have a good file pos story
 func (n *node) init(p *parser) {
        n.pos = uint32(p.pos)
        n.line = uint32(p.line)
 }
 
+func (n *node) initFrom(a *node) {
+       n.pos = a.pos
+       n.line = a.line
+}
+
 // ----------------------------------------------------------------------------
 // Files
 
+// package PkgName; DeclList[0], DeclList[1], ...
 type File struct {
        PkgName  *Name
        DeclList []Decl
@@ -49,6 +56,8 @@ type (
                aDecl()
        }
 
+       //              Path
+       // LocalPkgName Path
        ImportDecl struct {
                LocalPkgName *Name // including "."; nil means no rename present
                Path         *BasicLit
@@ -56,6 +65,18 @@ type (
                decl
        }
 
+       // Name => Orig
+       AliasDecl struct {
+               Tok   token // Const, Type, Var, or Func
+               Name  *Name
+               Orig  Expr
+               Group *Group // nil means not part of a group
+               decl
+       }
+
+       // NameList
+       // NameList      = Values
+       // NameList Type = Values
        ConstDecl struct {
                NameList []*Name
                Type     Expr   // nil means no type
@@ -64,13 +85,18 @@ type (
                decl
        }
 
+       // Name Type
        TypeDecl struct {
                Name  *Name
                Type  Expr
+               Alias bool
                Group *Group // nil means not part of a group
                decl
        }
 
+       // NameList Type
+       // NameList Type = Values
+       // NameList      = Values
        VarDecl struct {
                NameList []*Name
                Type     Expr   // nil means no type
@@ -79,6 +105,10 @@ type (
                decl
        }
 
+       // func          Name Type { Body }
+       // func          Name Type
+       // func Receiver Name Type { Body }
+       // func Receiver Name Type
        FuncDecl struct {
                Attr    map[string]bool // go:attr map
                Recv    *Field          // nil means regular function
@@ -418,6 +448,8 @@ func (simpleStmt) aSimpleStmt() {}
 // ----------------------------------------------------------------------------
 // Comments
 
+// TODO(gri) Consider renaming to CommentPos, CommentPlacement, etc.
+//           Kind = Above doesn't make much sense.
 type CommentKind uint
 
 const (
index 369f3ffccdd4904ac51a9a20450961403340e127..6cf899dd9147f97be859df17449b45384da05bf5 100644 (file)
@@ -315,16 +315,37 @@ func (p *parser) importDecl(group *Group) Decl {
        return d
 }
 
-// ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
+// AliasSpec = identifier "=>" [ PackageName "." ] identifier .
+func (p *parser) aliasDecl(tok token, name *Name, group *Group) Decl {
+       // no tracing since this is already called from a const/type/var/funcDecl
+
+       d := new(AliasDecl)
+       d.initFrom(&name.node)
+
+       p.want(_Rarrow)
+       d.Tok = tok
+       d.Name = name
+       d.Orig = p.dotname(p.name())
+       d.Group = group
+
+       return d
+}
+
+// ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] | AliasSpec .
 func (p *parser) constDecl(group *Group) Decl {
        if trace {
                defer p.trace("constDecl")()
        }
 
+       name := p.name()
+       if p.tok == _Rarrow {
+               return p.aliasDecl(Const, name, group)
+       }
+
        d := new(ConstDecl)
-       d.init(p)
+       d.initFrom(&name.node)
 
-       d.NameList = p.nameList(p.name())
+       d.NameList = p.nameList(name)
        if p.tok != _EOF && p.tok != _Semi && p.tok != _Rparen {
                d.Type = p.tryType()
                if p.got(_Assign) {
@@ -336,16 +357,24 @@ func (p *parser) constDecl(group *Group) Decl {
        return d
 }
 
-// TypeSpec = identifier Type .
+// TypeSpec = identifier Type | AliasSpec .
 func (p *parser) typeDecl(group *Group) Decl {
        if trace {
                defer p.trace("typeDecl")()
        }
 
+       name := p.name()
+       if p.tok == _Rarrow {
+               return p.aliasDecl(Type, name, group)
+       }
+
        d := new(TypeDecl)
-       d.init(p)
+       d.initFrom(&name.node)
 
-       d.Name = p.name()
+       d.Name = name
+       // accept "type T = p.T" for now so we can experiment
+       // with a type-alias only approach as well
+       d.Alias = p.got(_Assign)
        d.Type = p.tryType()
        if d.Type == nil {
                p.syntax_error("in type declaration")
@@ -356,16 +385,21 @@ func (p *parser) typeDecl(group *Group) Decl {
        return d
 }
 
-// VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
+// VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) | AliasSpec .
 func (p *parser) varDecl(group *Group) Decl {
        if trace {
                defer p.trace("varDecl")()
        }
 
+       name := p.name()
+       if p.tok == _Rarrow {
+               return p.aliasDecl(Var, name, group)
+       }
+
        d := new(VarDecl)
-       d.init(p)
+       d.initFrom(&name.node)
 
-       d.NameList = p.nameList(p.name())
+       d.NameList = p.nameList(name)
        if p.got(_Assign) {
                d.Values = p.exprList()
        } else {
@@ -382,31 +416,28 @@ func (p *parser) varDecl(group *Group) Decl {
        return d
 }
 
-// FunctionDecl = "func" FunctionName ( Function | Signature ) .
+var badRecv = new(Field) // to signal invalid receiver in funcDecl
+
+// FunctionDecl = "func" FunctionName ( Function | Signature ) | "func" AliasSpec .
 // FunctionName = identifier .
 // Function     = Signature FunctionBody .
 // MethodDecl   = "func" Receiver MethodName ( Function | Signature ) .
 // Receiver     = Parameters .
-func (p *parser) funcDecl() *FuncDecl {
+func (p *parser) funcDecl() Decl {
        if trace {
                defer p.trace("funcDecl")()
        }
 
-       f := new(FuncDecl)
-       f.init(p)
-
-       badRecv := false
+       var recv *Field
        if p.tok == _Lparen {
-               rcvr := p.paramList()
-               switch len(rcvr) {
+               recv = badRecv
+               switch list := p.paramList(); len(list) {
                case 0:
                        p.error("method has no receiver")
-                       badRecv = true
                case 1:
-                       f.Recv = rcvr[0]
+                       recv = list[0]
                default:
                        p.error("method has multiple receivers")
-                       badRecv = true
                }
        }
 
@@ -416,6 +447,11 @@ func (p *parser) funcDecl() *FuncDecl {
                return nil
        }
 
+       name := p.name()
+       if recv == nil && p.tok == _Rarrow {
+               return p.aliasDecl(Func, name, nil)
+       }
+
        // TODO(gri) check for regular functions only
        // if name.Sym.Name == "init" {
        //      name = renameinit()
@@ -430,7 +466,11 @@ func (p *parser) funcDecl() *FuncDecl {
        //      }
        // }
 
-       f.Name = p.name()
+       f := new(FuncDecl)
+       f.initFrom(&name.node) // TODO(gri) is this the correct position for methods?
+
+       f.Recv = recv
+       f.Name = name
        f.Type = p.funcType()
        if gcCompat {
                f.node = f.Type.node
@@ -445,7 +485,7 @@ func (p *parser) funcDecl() *FuncDecl {
        //      p.error("can only use //go:noescape with external func implementations")
        // }
 
-       if badRecv {
+       if recv == badRecv {
                return nil // TODO(gri) better solution
        }
        return f
@@ -514,7 +554,7 @@ func (p *parser) unaryExpr() Expr {
                        return x
                }
 
-       case _Arrow:
+       case _Larrow:
                // receive op (<-x) or receive-only channel (<-chan E)
                p.next()
 
@@ -928,7 +968,7 @@ func (p *parser) tryType() Expr {
                p.next()
                return indirect(p.type_())
 
-       case _Arrow:
+       case _Larrow:
                // recvchantype
                p.next()
                p.want(_Chan)
@@ -974,7 +1014,7 @@ func (p *parser) tryType() Expr {
                p.next()
                t := new(ChanType)
                t.init(p)
-               if p.got(_Arrow) {
+               if p.got(_Larrow) {
                        t.Dir = SendOnly
                }
                t.Elem = p.chanElem()
@@ -1317,7 +1357,7 @@ func (p *parser) paramDecl() *Field {
        case _Name:
                f.Name = p.name()
                switch p.tok {
-               case _Name, _Star, _Arrow, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
+               case _Name, _Star, _Larrow, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
                        // sym name_or_type
                        f.Type = p.type_()
 
@@ -1332,7 +1372,7 @@ func (p *parser) paramDecl() *Field {
                        f.Name = nil
                }
 
-       case _Arrow, _Star, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
+       case _Larrow, _Star, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
                // name_or_type
                f.Type = p.type_()
 
@@ -1466,7 +1506,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
                        p.next()
                        return p.newAssignStmt(op, lhs, ImplicitOne)
 
-               case _Arrow:
+               case _Larrow:
                        // lhs <- rhs
                        p.next()
                        s := new(SendStmt)
@@ -1819,7 +1859,7 @@ func (p *parser) commClause() *CommClause {
                p.next()
                lhs := p.exprList()
 
-               if _, ok := lhs.(*ListExpr); !ok && p.tok == _Arrow {
+               if _, ok := lhs.(*ListExpr); !ok && p.tok == _Larrow {
                        // lhs <- x
                } else {
                        // lhs
@@ -1899,7 +1939,7 @@ func (p *parser) stmt() Stmt {
 
        case _Literal, _Func, _Lparen, // operands
                _Lbrack, _Struct, _Map, _Chan, _Interface, // composite types
-               _Arrow: // receive operator
+               _Larrow: // receive operator
                return p.simpleStmt(nil, false)
 
        case _For:
index 0cacf1e5d496015cade1116ba0b50918ab2cf868..de2afe0499c442ea408c523a2dfc8355ab2bae68 100644 (file)
@@ -473,11 +473,11 @@ func (p *printer) printRawNode(n Node) {
 
        case *ChanType:
                if n.Dir == RecvOnly {
-                       p.print(_Arrow)
+                       p.print(_Larrow)
                }
                p.print(_Chan)
                if n.Dir == SendOnly {
-                       p.print(_Arrow)
+                       p.print(_Larrow)
                }
                p.print(blank, n.Elem)
 
@@ -495,7 +495,7 @@ func (p *printer) printRawNode(n Node) {
                p.print(n.X)
 
        case *SendStmt:
-               p.print(n.Chan, blank, _Arrow, blank, n.Value)
+               p.print(n.Chan, blank, _Larrow, blank, n.Value)
 
        case *AssignStmt:
                p.print(n.Lhs)
@@ -603,6 +603,12 @@ func (p *printer) printRawNode(n Node) {
                }
                p.print(n.Path)
 
+       case *AliasDecl:
+               if n.Group == nil {
+                       p.print(n.Tok, blank)
+               }
+               p.print(n.Name, blank, _Rarrow, blank, n.Orig)
+
        case *ConstDecl:
                if n.Group == nil {
                        p.print(_Const, blank)
@@ -619,7 +625,11 @@ func (p *printer) printRawNode(n Node) {
                if n.Group == nil {
                        p.print(_Type, blank)
                }
-               p.print(n.Name, blank, n.Type)
+               p.print(n.Name, blank)
+               if n.Alias {
+                       p.print(_Assign, blank)
+               }
+               p.print(n.Type)
 
        case *VarDecl:
                if n.Group == nil {
@@ -757,6 +767,8 @@ func groupFor(d Decl) (token, *Group) {
        switch d := d.(type) {
        case *ImportDecl:
                return _Import, d.Group
+       case *AliasDecl:
+               return d.Tok, d.Group
        case *ConstDecl:
                return _Const, d.Group
        case *TypeDecl:
index b84fcc5fd16d8ad27369f752f89b2b6a91314ad1..bd38943c30721416ae0ba758c1831296f55a1ced 100644 (file)
@@ -229,7 +229,7 @@ redo:
                        goto assignop
                }
                if c == '-' {
-                       s.tok = _Arrow
+                       s.tok = _Larrow
                        break
                }
                s.ungetr()
@@ -253,11 +253,16 @@ redo:
                s.tok = _Operator
 
        case '=':
-               if s.getr() == '=' {
+               c = s.getr()
+               if c == '=' {
                        s.op, s.prec = Eql, precCmp
                        s.tok = _Operator
                        break
                }
+               if c == '>' {
+                       s.tok = _Rarrow
+                       break
+               }
                s.ungetr()
                s.tok = _Assign
 
index 38a7e0da4c6209282313e3e9a082fbd9484e7ef4..0e0ff1b172ec4d021bb0ebbebd01aff478c0fa4f 100644 (file)
@@ -210,7 +210,8 @@ var sampleTokens = [...]struct {
        {_IncOp, "--", Sub, precAdd},
        {_Assign, "=", 0, 0},
        {_Define, ":=", 0, 0},
-       {_Arrow, "<-", 0, 0},
+       {_Larrow, "<-", 0, 0},
+       {_Rarrow, "=>", 0, 0},
 
        // delimiters
        {_Lparen, "(", 0, 0},
index bd0118a141e7bd05374657440ae89faed0752f14..4a02c0ce3b3c66454bbece51bc058a042ee0f0b5 100644 (file)
@@ -22,7 +22,8 @@ const (
        _IncOp
        _Assign
        _Define
-       _Arrow
+       _Larrow
+       _Rarrow
        _Star
 
        // delimitors
@@ -69,6 +70,12 @@ const (
 )
 
 const (
+       // for AliasDecl
+       Const = _Const
+       Type  = _Type
+       Var   = _Var
+       Func  = _Func
+
        // for BranchStmt
        Break       = _Break
        Continue    = _Continue
@@ -94,7 +101,8 @@ var tokstrings = [...]string{
        _IncOp:    "opop",
        _Assign:   "=",
        _Define:   ":=",
-       _Arrow:    "<-",
+       _Larrow:   "<-",
+       _Rarrow:   "=>",
        _Star:     "*",
 
        // delimitors