Commit 32db3f27 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile/internal/syntax: support for alias declarations

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