Skip to content

Commit 32db3f2

Browse files
committed
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 <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 28ed2b0 commit 32db3f2

File tree

7 files changed

+144
-39
lines changed

7 files changed

+144
-39
lines changed

src/cmd/compile/internal/gc/noder.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
6060
case *syntax.ImportDecl:
6161
p.importDecl(decl)
6262

63+
case *syntax.AliasDecl:
64+
yyerror("alias declarations not yet implemented")
65+
6366
case *syntax.VarDecl:
6467
l = append(l, p.varDecl(decl)...)
6568

@@ -87,6 +90,10 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
8790
lastConstGroup = decl.Group
8891

8992
case *syntax.TypeDecl:
93+
if decl.Alias {
94+
yyerror("alias declarations not yet implemented")
95+
break
96+
}
9097
l = append(l, p.typeDecl(decl))
9198

9299
case *syntax.FuncDecl:

src/cmd/compile/internal/syntax/nodes.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,21 @@ func (n *node) Line() uint32 {
2525
return n.line
2626
}
2727

28+
// TODO(gri) clean up init/initFrom once we have a good file pos story
2829
func (n *node) init(p *parser) {
2930
n.pos = uint32(p.pos)
3031
n.line = uint32(p.line)
3132
}
3233

34+
func (n *node) initFrom(a *node) {
35+
n.pos = a.pos
36+
n.line = a.line
37+
}
38+
3339
// ----------------------------------------------------------------------------
3440
// Files
3541

42+
// package PkgName; DeclList[0], DeclList[1], ...
3643
type File struct {
3744
PkgName *Name
3845
DeclList []Decl
@@ -49,13 +56,27 @@ type (
4956
aDecl()
5057
}
5158

59+
// Path
60+
// LocalPkgName Path
5261
ImportDecl struct {
5362
LocalPkgName *Name // including "."; nil means no rename present
5463
Path *BasicLit
5564
Group *Group // nil means not part of a group
5665
decl
5766
}
5867

68+
// Name => Orig
69+
AliasDecl struct {
70+
Tok token // Const, Type, Var, or Func
71+
Name *Name
72+
Orig Expr
73+
Group *Group // nil means not part of a group
74+
decl
75+
}
76+
77+
// NameList
78+
// NameList = Values
79+
// NameList Type = Values
5980
ConstDecl struct {
6081
NameList []*Name
6182
Type Expr // nil means no type
@@ -64,13 +85,18 @@ type (
6485
decl
6586
}
6687

88+
// Name Type
6789
TypeDecl struct {
6890
Name *Name
6991
Type Expr
92+
Alias bool
7093
Group *Group // nil means not part of a group
7194
decl
7295
}
7396

97+
// NameList Type
98+
// NameList Type = Values
99+
// NameList = Values
74100
VarDecl struct {
75101
NameList []*Name
76102
Type Expr // nil means no type
@@ -79,6 +105,10 @@ type (
79105
decl
80106
}
81107

108+
// func Name Type { Body }
109+
// func Name Type
110+
// func Receiver Name Type { Body }
111+
// func Receiver Name Type
82112
FuncDecl struct {
83113
Attr map[string]bool // go:attr map
84114
Recv *Field // nil means regular function
@@ -418,6 +448,8 @@ func (simpleStmt) aSimpleStmt() {}
418448
// ----------------------------------------------------------------------------
419449
// Comments
420450

451+
// TODO(gri) Consider renaming to CommentPos, CommentPlacement, etc.
452+
// Kind = Above doesn't make much sense.
421453
type CommentKind uint
422454

423455
const (

src/cmd/compile/internal/syntax/parser.go

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -315,16 +315,37 @@ func (p *parser) importDecl(group *Group) Decl {
315315
return d
316316
}
317317

318-
// ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
318+
// AliasSpec = identifier "=>" [ PackageName "." ] identifier .
319+
func (p *parser) aliasDecl(tok token, name *Name, group *Group) Decl {
320+
// no tracing since this is already called from a const/type/var/funcDecl
321+
322+
d := new(AliasDecl)
323+
d.initFrom(&name.node)
324+
325+
p.want(_Rarrow)
326+
d.Tok = tok
327+
d.Name = name
328+
d.Orig = p.dotname(p.name())
329+
d.Group = group
330+
331+
return d
332+
}
333+
334+
// ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] | AliasSpec .
319335
func (p *parser) constDecl(group *Group) Decl {
320336
if trace {
321337
defer p.trace("constDecl")()
322338
}
323339

340+
name := p.name()
341+
if p.tok == _Rarrow {
342+
return p.aliasDecl(Const, name, group)
343+
}
344+
324345
d := new(ConstDecl)
325-
d.init(p)
346+
d.initFrom(&name.node)
326347

327-
d.NameList = p.nameList(p.name())
348+
d.NameList = p.nameList(name)
328349
if p.tok != _EOF && p.tok != _Semi && p.tok != _Rparen {
329350
d.Type = p.tryType()
330351
if p.got(_Assign) {
@@ -336,16 +357,24 @@ func (p *parser) constDecl(group *Group) Decl {
336357
return d
337358
}
338359

339-
// TypeSpec = identifier Type .
360+
// TypeSpec = identifier Type | AliasSpec .
340361
func (p *parser) typeDecl(group *Group) Decl {
341362
if trace {
342363
defer p.trace("typeDecl")()
343364
}
344365

366+
name := p.name()
367+
if p.tok == _Rarrow {
368+
return p.aliasDecl(Type, name, group)
369+
}
370+
345371
d := new(TypeDecl)
346-
d.init(p)
372+
d.initFrom(&name.node)
347373

348-
d.Name = p.name()
374+
d.Name = name
375+
// accept "type T = p.T" for now so we can experiment
376+
// with a type-alias only approach as well
377+
d.Alias = p.got(_Assign)
349378
d.Type = p.tryType()
350379
if d.Type == nil {
351380
p.syntax_error("in type declaration")
@@ -356,16 +385,21 @@ func (p *parser) typeDecl(group *Group) Decl {
356385
return d
357386
}
358387

359-
// VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
388+
// VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) | AliasSpec .
360389
func (p *parser) varDecl(group *Group) Decl {
361390
if trace {
362391
defer p.trace("varDecl")()
363392
}
364393

394+
name := p.name()
395+
if p.tok == _Rarrow {
396+
return p.aliasDecl(Var, name, group)
397+
}
398+
365399
d := new(VarDecl)
366-
d.init(p)
400+
d.initFrom(&name.node)
367401

368-
d.NameList = p.nameList(p.name())
402+
d.NameList = p.nameList(name)
369403
if p.got(_Assign) {
370404
d.Values = p.exprList()
371405
} else {
@@ -382,31 +416,28 @@ func (p *parser) varDecl(group *Group) Decl {
382416
return d
383417
}
384418

385-
// FunctionDecl = "func" FunctionName ( Function | Signature ) .
419+
var badRecv = new(Field) // to signal invalid receiver in funcDecl
420+
421+
// FunctionDecl = "func" FunctionName ( Function | Signature ) | "func" AliasSpec .
386422
// FunctionName = identifier .
387423
// Function = Signature FunctionBody .
388424
// MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
389425
// Receiver = Parameters .
390-
func (p *parser) funcDecl() *FuncDecl {
426+
func (p *parser) funcDecl() Decl {
391427
if trace {
392428
defer p.trace("funcDecl")()
393429
}
394430

395-
f := new(FuncDecl)
396-
f.init(p)
397-
398-
badRecv := false
431+
var recv *Field
399432
if p.tok == _Lparen {
400-
rcvr := p.paramList()
401-
switch len(rcvr) {
433+
recv = badRecv
434+
switch list := p.paramList(); len(list) {
402435
case 0:
403436
p.error("method has no receiver")
404-
badRecv = true
405437
case 1:
406-
f.Recv = rcvr[0]
438+
recv = list[0]
407439
default:
408440
p.error("method has multiple receivers")
409-
badRecv = true
410441
}
411442
}
412443

@@ -416,6 +447,11 @@ func (p *parser) funcDecl() *FuncDecl {
416447
return nil
417448
}
418449

450+
name := p.name()
451+
if recv == nil && p.tok == _Rarrow {
452+
return p.aliasDecl(Func, name, nil)
453+
}
454+
419455
// TODO(gri) check for regular functions only
420456
// if name.Sym.Name == "init" {
421457
// name = renameinit()
@@ -430,7 +466,11 @@ func (p *parser) funcDecl() *FuncDecl {
430466
// }
431467
// }
432468

433-
f.Name = p.name()
469+
f := new(FuncDecl)
470+
f.initFrom(&name.node) // TODO(gri) is this the correct position for methods?
471+
472+
f.Recv = recv
473+
f.Name = name
434474
f.Type = p.funcType()
435475
if gcCompat {
436476
f.node = f.Type.node
@@ -445,7 +485,7 @@ func (p *parser) funcDecl() *FuncDecl {
445485
// p.error("can only use //go:noescape with external func implementations")
446486
// }
447487

448-
if badRecv {
488+
if recv == badRecv {
449489
return nil // TODO(gri) better solution
450490
}
451491
return f
@@ -514,7 +554,7 @@ func (p *parser) unaryExpr() Expr {
514554
return x
515555
}
516556

517-
case _Arrow:
557+
case _Larrow:
518558
// receive op (<-x) or receive-only channel (<-chan E)
519559
p.next()
520560

@@ -928,7 +968,7 @@ func (p *parser) tryType() Expr {
928968
p.next()
929969
return indirect(p.type_())
930970

931-
case _Arrow:
971+
case _Larrow:
932972
// recvchantype
933973
p.next()
934974
p.want(_Chan)
@@ -974,7 +1014,7 @@ func (p *parser) tryType() Expr {
9741014
p.next()
9751015
t := new(ChanType)
9761016
t.init(p)
977-
if p.got(_Arrow) {
1017+
if p.got(_Larrow) {
9781018
t.Dir = SendOnly
9791019
}
9801020
t.Elem = p.chanElem()
@@ -1317,7 +1357,7 @@ func (p *parser) paramDecl() *Field {
13171357
case _Name:
13181358
f.Name = p.name()
13191359
switch p.tok {
1320-
case _Name, _Star, _Arrow, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
1360+
case _Name, _Star, _Larrow, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
13211361
// sym name_or_type
13221362
f.Type = p.type_()
13231363

@@ -1332,7 +1372,7 @@ func (p *parser) paramDecl() *Field {
13321372
f.Name = nil
13331373
}
13341374

1335-
case _Arrow, _Star, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
1375+
case _Larrow, _Star, _Func, _Lbrack, _Chan, _Map, _Struct, _Interface, _Lparen:
13361376
// name_or_type
13371377
f.Type = p.type_()
13381378

@@ -1466,7 +1506,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
14661506
p.next()
14671507
return p.newAssignStmt(op, lhs, ImplicitOne)
14681508

1469-
case _Arrow:
1509+
case _Larrow:
14701510
// lhs <- rhs
14711511
p.next()
14721512
s := new(SendStmt)
@@ -1819,7 +1859,7 @@ func (p *parser) commClause() *CommClause {
18191859
p.next()
18201860
lhs := p.exprList()
18211861

1822-
if _, ok := lhs.(*ListExpr); !ok && p.tok == _Arrow {
1862+
if _, ok := lhs.(*ListExpr); !ok && p.tok == _Larrow {
18231863
// lhs <- x
18241864
} else {
18251865
// lhs
@@ -1899,7 +1939,7 @@ func (p *parser) stmt() Stmt {
18991939

19001940
case _Literal, _Func, _Lparen, // operands
19011941
_Lbrack, _Struct, _Map, _Chan, _Interface, // composite types
1902-
_Arrow: // receive operator
1942+
_Larrow: // receive operator
19031943
return p.simpleStmt(nil, false)
19041944

19051945
case _For:

0 commit comments

Comments
 (0)