mirror of
https://github.com/golang/go
synced 2024-11-19 07:14:45 -07:00
cmd/compile: factor parameter parsing
Step 1 of streamlining parameter parsing. Change-Id: If9fd38295ccc08aafc7f1d26188d0926dd73058b Reviewed-on: https://go-review.googlesource.com/20747 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
c8b148e7a5
commit
9f301643bd
@ -1662,6 +1662,30 @@ func (p *parser) ntype() *Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
// signature parses a function signature and returns an OTFUNC node.
|
||||
//
|
||||
// Signature = Parameters [ Result ] .
|
||||
func (p *parser) signature(recv *Node) *Node {
|
||||
if trace && Debug['x'] != 0 {
|
||||
defer p.trace("signature")()
|
||||
}
|
||||
|
||||
params := p.param_list(true)
|
||||
|
||||
var result []*Node
|
||||
if p.tok == '(' {
|
||||
result = p.param_list(false)
|
||||
} else if t := p.try_ntype(); t != nil {
|
||||
result = []*Node{Nod(ODCLFIELD, nil, t)}
|
||||
}
|
||||
|
||||
typ := Nod(OTFUNC, recv, nil)
|
||||
typ.List.Set(params)
|
||||
typ.Rlist.Set(result)
|
||||
|
||||
return typ
|
||||
}
|
||||
|
||||
// try_ntype is like ntype but it returns nil if there was no type
|
||||
// instead of reporting an error.
|
||||
//
|
||||
@ -1686,13 +1710,7 @@ func (p *parser) try_ntype() *Node {
|
||||
case LFUNC:
|
||||
// fntype
|
||||
p.next()
|
||||
params := p.param_list()
|
||||
result := p.fnres()
|
||||
params = checkarglist(params, 1)
|
||||
t := Nod(OTFUNC, nil, nil)
|
||||
t.List.Set(params)
|
||||
t.Rlist.Set(result)
|
||||
return t
|
||||
return p.signature(nil)
|
||||
|
||||
case '[':
|
||||
// '[' oexpr ']' ntype
|
||||
@ -1882,30 +1900,23 @@ func (p *parser) fndcl(nointerface bool) *Node {
|
||||
|
||||
switch p.tok {
|
||||
case LNAME, '@', '?':
|
||||
// sym '(' oarg_type_list_ocomma ')' fnres
|
||||
// FunctionName Signature
|
||||
name := p.sym()
|
||||
params := p.param_list()
|
||||
result := p.fnres()
|
||||
|
||||
params = checkarglist(params, 1)
|
||||
t := p.signature(nil)
|
||||
|
||||
if name.Name == "init" {
|
||||
name = renameinit()
|
||||
if len(params) != 0 || len(result) != 0 {
|
||||
if t.List.Len() > 0 || t.Rlist.Len() > 0 {
|
||||
Yyerror("func init must have no arguments and no return values")
|
||||
}
|
||||
}
|
||||
|
||||
if localpkg.Name == "main" && name.Name == "main" {
|
||||
if len(params) != 0 || len(result) != 0 {
|
||||
if t.List.Len() > 0 || t.Rlist.Len() > 0 {
|
||||
Yyerror("func main must have no arguments and no return values")
|
||||
}
|
||||
}
|
||||
|
||||
t := Nod(OTFUNC, nil, nil)
|
||||
t.List.Set(params)
|
||||
t.Rlist.Set(result)
|
||||
|
||||
f := Nod(ODCLFUNC, nil, nil)
|
||||
f.Func.Nname = newfuncname(name)
|
||||
f.Func.Nname.Name.Defn = f
|
||||
@ -1916,16 +1927,17 @@ func (p *parser) fndcl(nointerface bool) *Node {
|
||||
return f
|
||||
|
||||
case '(':
|
||||
// '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
|
||||
rparam := p.param_list()
|
||||
// Receiver MethodName Signature
|
||||
rparam := p.param_list(false)
|
||||
var recv *Node
|
||||
if len(rparam) > 0 {
|
||||
recv = rparam[0]
|
||||
}
|
||||
name := p.sym()
|
||||
params := p.param_list()
|
||||
result := p.fnres()
|
||||
t := p.signature(recv)
|
||||
|
||||
rparam = checkarglist(rparam, 0)
|
||||
params = checkarglist(params, 1)
|
||||
|
||||
if len(rparam) == 0 {
|
||||
// check after parsing header for fault-tolerance
|
||||
if recv == nil {
|
||||
Yyerror("method has no receiver")
|
||||
return nil
|
||||
}
|
||||
@ -1935,19 +1947,14 @@ func (p *parser) fndcl(nointerface bool) *Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
rcvr := rparam[0]
|
||||
if rcvr.Op != ODCLFIELD {
|
||||
if recv.Op != ODCLFIELD {
|
||||
Yyerror("bad receiver in method")
|
||||
return nil
|
||||
}
|
||||
|
||||
t := Nod(OTFUNC, rcvr, nil)
|
||||
t.List.Set(params)
|
||||
t.Rlist.Set(result)
|
||||
|
||||
f := Nod(ODCLFUNC, nil, nil)
|
||||
f.Func.Shortname = newfuncname(name)
|
||||
f.Func.Nname = methodname1(f.Func.Shortname, rcvr.Right)
|
||||
f.Func.Nname = methodname1(f.Func.Shortname, recv.Right)
|
||||
f.Func.Nname.Name.Defn = f
|
||||
f.Func.Nname.Name.Param.Ntype = t
|
||||
f.Func.Nname.Nointerface = nointerface
|
||||
@ -2043,24 +2050,6 @@ func (p *parser) fnbody() []*Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Result = Parameters | Type .
|
||||
func (p *parser) fnres() []*Node {
|
||||
if trace && Debug['x'] != 0 {
|
||||
defer p.trace("fnres")()
|
||||
}
|
||||
|
||||
if p.tok == '(' {
|
||||
result := p.param_list()
|
||||
return checkarglist(result, 0)
|
||||
}
|
||||
|
||||
if result := p.try_ntype(); result != nil {
|
||||
return []*Node{Nod(ODCLFIELD, nil, result)}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Declaration = ConstDecl | TypeDecl | VarDecl .
|
||||
// TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
|
||||
func (p *parser) xdcl_list() (l []*Node) {
|
||||
@ -2302,16 +2291,17 @@ func (p *parser) interfacedcl() *Node {
|
||||
return Nod(ODCLFIELD, nil, oldname(pname))
|
||||
}
|
||||
|
||||
// newname indcl
|
||||
// MethodName Signature
|
||||
mname := newname(sym)
|
||||
sig := p.indcl()
|
||||
sig := p.signature(fakethis())
|
||||
|
||||
meth := Nod(ODCLFIELD, mname, sig)
|
||||
ifacedcl(meth)
|
||||
return meth
|
||||
|
||||
case '@', '?':
|
||||
// newname indcl
|
||||
// MethodName Signature
|
||||
//
|
||||
// We arrive here when parsing an interface type declared inside
|
||||
// an exported and inlineable function and the interface declares
|
||||
// unexported methods (which are then package-qualified).
|
||||
@ -2322,7 +2312,7 @@ func (p *parser) interfacedcl() *Node {
|
||||
//
|
||||
// See also issue 14164.
|
||||
mname := newname(p.sym())
|
||||
sig := p.indcl()
|
||||
sig := p.signature(fakethis())
|
||||
|
||||
meth := Nod(ODCLFIELD, mname, sig)
|
||||
ifacedcl(meth)
|
||||
@ -2343,29 +2333,10 @@ func (p *parser) interfacedcl() *Node {
|
||||
}
|
||||
}
|
||||
|
||||
// MethodSpec = MethodName Signature .
|
||||
// MethodName = identifier .
|
||||
func (p *parser) indcl() *Node {
|
||||
// [ParameterName] Type
|
||||
func (p *parser) par_type() *Node {
|
||||
if trace && Debug['x'] != 0 {
|
||||
defer p.trace("indcl")()
|
||||
}
|
||||
|
||||
params := p.param_list()
|
||||
result := p.fnres()
|
||||
|
||||
// without func keyword
|
||||
params = checkarglist(params, 1)
|
||||
t := Nod(OTFUNC, fakethis(), nil)
|
||||
t.List.Set(params)
|
||||
t.Rlist.Set(result)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// ParameterDecl = [ IdentifierList ] [ "..." ] Type .
|
||||
func (p *parser) arg_type() *Node {
|
||||
if trace && Debug['x'] != 0 {
|
||||
defer p.trace("arg_type")()
|
||||
defer p.trace("par_type")()
|
||||
}
|
||||
|
||||
switch p.tok {
|
||||
@ -2413,22 +2384,28 @@ func (p *parser) arg_type() *Node {
|
||||
|
||||
// Parameters = "(" [ ParameterList [ "," ] ] ")" .
|
||||
// ParameterList = ParameterDecl { "," ParameterDecl } .
|
||||
func (p *parser) param_list() (l []*Node) {
|
||||
// ParameterDecl = [ IdentifierList ] [ "..." ] Type .
|
||||
func (p *parser) param_list(dddOk bool) []*Node {
|
||||
if trace && Debug['x'] != 0 {
|
||||
defer p.trace("param_list")()
|
||||
}
|
||||
|
||||
p.want('(')
|
||||
|
||||
var l []*Node
|
||||
for p.tok != EOF && p.tok != ')' {
|
||||
l = append(l, p.arg_type())
|
||||
l = append(l, p.par_type())
|
||||
if !p.ocomma(')') {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
p.want(')')
|
||||
return
|
||||
|
||||
// TODO(gri) remove this with next commit
|
||||
input := 0
|
||||
if dddOk {
|
||||
input = 1
|
||||
}
|
||||
return checkarglist(l, input)
|
||||
}
|
||||
|
||||
var missing_stmt = Nod(OXXX, nil, nil)
|
||||
|
Loading…
Reference in New Issue
Block a user