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
aDecl()
}
+ // Path
+ // LocalPkgName Path
ImportDecl struct {
LocalPkgName *Name // including "."; nil means no rename present
Path *BasicLit
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
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
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
// ----------------------------------------------------------------------------
// Comments
+// TODO(gri) Consider renaming to CommentPos, CommentPlacement, etc.
+// Kind = Above doesn't make much sense.
type CommentKind uint
const (
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) {
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")
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 {
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
}
}
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()
// }
// }
- 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
// p.error("can only use //go:noescape with external func implementations")
// }
- if badRecv {
+ if recv == badRecv {
return nil // TODO(gri) better solution
}
return f
return x
}
- case _Arrow:
+ case _Larrow:
// receive op (<-x) or receive-only channel (<-chan E)
p.next()
p.next()
return indirect(p.type_())
- case _Arrow:
+ case _Larrow:
// recvchantype
p.next()
p.want(_Chan)
p.next()
t := new(ChanType)
t.init(p)
- if p.got(_Arrow) {
+ if p.got(_Larrow) {
t.Dir = SendOnly
}
t.Elem = p.chanElem()
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_()
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_()
p.next()
return p.newAssignStmt(op, lhs, ImplicitOne)
- case _Arrow:
+ case _Larrow:
// lhs <- rhs
p.next()
s := new(SendStmt)
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
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: