mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: convert subr, swt, typecheck to nodeSeq
Passes toolstash -cmp. Update #14473. Change-Id: I836197810405cde72cbb49fef7e163a517601f9c Reviewed-on: https://go-review.googlesource.com/20242 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
3da1a26fba
commit
65c4b55aba
5 changed files with 254 additions and 278 deletions
|
|
@ -297,19 +297,19 @@ func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
|
||||||
lastconst = cl
|
lastconst = cl
|
||||||
lasttype = t
|
lasttype = t
|
||||||
}
|
}
|
||||||
cl = listtreecopy(cl, lno)
|
clcopy := listtreecopy(cl, lno)
|
||||||
|
|
||||||
var v *Node
|
var v *Node
|
||||||
var c *Node
|
var c *Node
|
||||||
var vv *NodeList
|
var vv *NodeList
|
||||||
for ; vl != nil; vl = vl.Next {
|
for ; vl != nil; vl = vl.Next {
|
||||||
if cl == nil {
|
if len(clcopy) == 0 {
|
||||||
Yyerror("missing value in const declaration")
|
Yyerror("missing value in const declaration")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
c = cl.N
|
c = clcopy[0]
|
||||||
cl = cl.Next
|
clcopy = clcopy[1:]
|
||||||
|
|
||||||
v = vl.N
|
v = vl.N
|
||||||
v.Op = OLITERAL
|
v.Op = OLITERAL
|
||||||
|
|
@ -321,7 +321,7 @@ func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
|
||||||
vv = list(vv, Nod(ODCLCONST, v, nil))
|
vv = list(vv, Nod(ODCLCONST, v, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
if cl != nil {
|
if len(clcopy) != 0 {
|
||||||
Yyerror("extra expression in const declaration")
|
Yyerror("extra expression in const declaration")
|
||||||
}
|
}
|
||||||
iota_ += 1
|
iota_ += 1
|
||||||
|
|
|
||||||
|
|
@ -536,7 +536,7 @@ func treecopy(n *Node, lineno int32) *Node {
|
||||||
m.Orig = m
|
m.Orig = m
|
||||||
m.Left = treecopy(n.Left, lineno)
|
m.Left = treecopy(n.Left, lineno)
|
||||||
m.Right = treecopy(n.Right, lineno)
|
m.Right = treecopy(n.Right, lineno)
|
||||||
m.List = listtreecopy(n.List, lineno)
|
setNodeSeq(&m.List, listtreecopy(n.List, lineno))
|
||||||
if lineno != 0 {
|
if lineno != 0 {
|
||||||
m.Lineno = lineno
|
m.Lineno = lineno
|
||||||
}
|
}
|
||||||
|
|
@ -1393,7 +1393,7 @@ func ullmancalc(n *Node) {
|
||||||
|
|
||||||
var ul int
|
var ul int
|
||||||
var ur int
|
var ur int
|
||||||
if n.Ninit != nil {
|
if nodeSeqLen(n.Ninit) != 0 {
|
||||||
ul = UINF
|
ul = UINF
|
||||||
goto out
|
goto out
|
||||||
}
|
}
|
||||||
|
|
@ -2014,13 +2014,13 @@ func expandmeth(t *Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given funarg struct list, return list of ODCLFIELD Node fn args.
|
// Given funarg struct list, return list of ODCLFIELD Node fn args.
|
||||||
func structargs(tl **Type, mustname int) *NodeList {
|
func structargs(tl **Type, mustname int) []*Node {
|
||||||
var savet Iter
|
var savet Iter
|
||||||
var a *Node
|
var a *Node
|
||||||
var n *Node
|
var n *Node
|
||||||
var buf string
|
var buf string
|
||||||
|
|
||||||
var args *NodeList
|
var args []*Node
|
||||||
gen := 0
|
gen := 0
|
||||||
for t := Structfirst(&savet, tl); t != nil; t = structnext(&savet) {
|
for t := Structfirst(&savet, tl); t != nil; t = structnext(&savet) {
|
||||||
n = nil
|
n = nil
|
||||||
|
|
@ -2038,7 +2038,7 @@ func structargs(tl **Type, mustname int) *NodeList {
|
||||||
if n != nil {
|
if n != nil {
|
||||||
n.Isddd = t.Isddd
|
n.Isddd = t.Isddd
|
||||||
}
|
}
|
||||||
args = list(args, a)
|
args = append(args, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
@ -2091,7 +2091,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
||||||
out := structargs(Getoutarg(method.Type), 0)
|
out := structargs(Getoutarg(method.Type), 0)
|
||||||
|
|
||||||
t := Nod(OTFUNC, nil, nil)
|
t := Nod(OTFUNC, nil, nil)
|
||||||
l := list1(this)
|
l := []*Node{this}
|
||||||
if iface != 0 && rcvr.Width < Types[Tptr].Width {
|
if iface != 0 && rcvr.Width < Types[Tptr].Width {
|
||||||
// Building method for interface table and receiver
|
// Building method for interface table and receiver
|
||||||
// is smaller than the single pointer-sized word
|
// is smaller than the single pointer-sized word
|
||||||
|
|
@ -2103,11 +2103,11 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
||||||
tpad.Type = Types[TUINT8]
|
tpad.Type = Types[TUINT8]
|
||||||
tpad.Bound = Types[Tptr].Width - rcvr.Width
|
tpad.Bound = Types[Tptr].Width - rcvr.Width
|
||||||
pad := Nod(ODCLFIELD, newname(Lookup(".pad")), typenod(tpad))
|
pad := Nod(ODCLFIELD, newname(Lookup(".pad")), typenod(tpad))
|
||||||
l = list(l, pad)
|
l = append(l, pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.List = concat(l, in)
|
setNodeSeq(&t.List, append(l, in...))
|
||||||
t.Rlist = out
|
setNodeSeq(&t.Rlist, out)
|
||||||
|
|
||||||
fn := Nod(ODCLFUNC, nil, nil)
|
fn := Nod(ODCLFUNC, nil, nil)
|
||||||
fn.Func.Nname = newname(newnam)
|
fn.Func.Nname = newname(newnam)
|
||||||
|
|
@ -2117,12 +2117,12 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
||||||
funchdr(fn)
|
funchdr(fn)
|
||||||
|
|
||||||
// arg list
|
// arg list
|
||||||
var args *NodeList
|
var args []*Node
|
||||||
|
|
||||||
isddd := false
|
isddd := false
|
||||||
for l := in; l != nil; l = l.Next {
|
for _, n := range in {
|
||||||
args = list(args, l.N.Left)
|
args = append(args, n.Left)
|
||||||
isddd = l.N.Left.Isddd
|
isddd = n.Left.Isddd
|
||||||
}
|
}
|
||||||
|
|
||||||
methodrcvr := getthisx(method.Type).Type.Type
|
methodrcvr := getthisx(method.Type).Type.Type
|
||||||
|
|
@ -2136,17 +2136,17 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
||||||
|
|
||||||
// these strings are already in the reflect tables,
|
// these strings are already in the reflect tables,
|
||||||
// so no space cost to use them here.
|
// so no space cost to use them here.
|
||||||
var l *NodeList
|
var l []*Node
|
||||||
|
|
||||||
var v Val
|
var v Val
|
||||||
v.U = rcvr.Type.Sym.Pkg.Name // package name
|
v.U = rcvr.Type.Sym.Pkg.Name // package name
|
||||||
l = list(l, nodlit(v))
|
l = append(l, nodlit(v))
|
||||||
v.U = rcvr.Type.Sym.Name // type name
|
v.U = rcvr.Type.Sym.Name // type name
|
||||||
l = list(l, nodlit(v))
|
l = append(l, nodlit(v))
|
||||||
v.U = method.Sym.Name
|
v.U = method.Sym.Name
|
||||||
l = list(l, nodlit(v)) // method name
|
l = append(l, nodlit(v)) // method name
|
||||||
call := Nod(OCALL, syslook("panicwrap"), nil)
|
call := Nod(OCALL, syslook("panicwrap"), nil)
|
||||||
call.List = l
|
setNodeSeq(&call.List, l)
|
||||||
n.Nbody.Set([]*Node{call})
|
n.Nbody.Set([]*Node{call})
|
||||||
fn.Nbody.Append(n)
|
fn.Nbody.Append(n)
|
||||||
}
|
}
|
||||||
|
|
@ -2169,11 +2169,11 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
|
||||||
} else {
|
} else {
|
||||||
fn.Func.Wrapper = true // ignore frame for panic+recover matching
|
fn.Func.Wrapper = true // ignore frame for panic+recover matching
|
||||||
call := Nod(OCALL, dot, nil)
|
call := Nod(OCALL, dot, nil)
|
||||||
call.List = args
|
setNodeSeq(&call.List, args)
|
||||||
call.Isddd = isddd
|
call.Isddd = isddd
|
||||||
if method.Type.Outtuple > 0 {
|
if method.Type.Outtuple > 0 {
|
||||||
n := Nod(ORETURN, nil, nil)
|
n := Nod(ORETURN, nil, nil)
|
||||||
n.List = list1(call)
|
setNodeSeq(&n.List, []*Node{call})
|
||||||
call = n
|
call = n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2207,10 +2207,10 @@ func hashmem(t *Type) *Node {
|
||||||
n := newname(sym)
|
n := newname(sym)
|
||||||
n.Class = PFUNC
|
n.Class = PFUNC
|
||||||
tfn := Nod(OTFUNC, nil, nil)
|
tfn := Nod(OTFUNC, nil, nil)
|
||||||
tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
|
appendNodeSeqNode(&tfn.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
|
||||||
tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
appendNodeSeqNode(&tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||||
tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
appendNodeSeqNode(&tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||||
tfn.Rlist = list(tfn.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
appendNodeSeqNode(&tfn.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
|
||||||
typecheck(&tfn, Etype)
|
typecheck(&tfn, Etype)
|
||||||
n.Type = tfn.Type
|
n.Type = tfn.Type
|
||||||
return n
|
return n
|
||||||
|
|
@ -2354,10 +2354,10 @@ func Simsimtype(t *Type) EType {
|
||||||
return et
|
return et
|
||||||
}
|
}
|
||||||
|
|
||||||
func listtreecopy(l *NodeList, lineno int32) *NodeList {
|
func listtreecopy(l nodesOrNodeList, lineno int32) []*Node {
|
||||||
var out *NodeList
|
var out []*Node
|
||||||
for ; l != nil; l = l.Next {
|
for it := nodeSeqIterate(l); !it.Done(); it.Next() {
|
||||||
out = list(out, treecopy(l.N, lineno))
|
out = append(out, treecopy(it.N(), lineno))
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,11 +105,10 @@ func typecheckswitch(n *Node) {
|
||||||
n.Type = t
|
n.Type = t
|
||||||
|
|
||||||
var def *Node
|
var def *Node
|
||||||
var ll *NodeList
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
for l := n.List; l != nil; l = l.Next {
|
ncase := it.N()
|
||||||
ncase := l.N
|
|
||||||
setlineno(n)
|
setlineno(n)
|
||||||
if ncase.List == nil {
|
if nodeSeqLen(ncase.List) == 0 {
|
||||||
// default
|
// default
|
||||||
if def != nil {
|
if def != nil {
|
||||||
Yyerror("multiple defaults in switch (first at %v)", def.Line())
|
Yyerror("multiple defaults in switch (first at %v)", def.Line())
|
||||||
|
|
@ -117,30 +116,30 @@ func typecheckswitch(n *Node) {
|
||||||
def = ncase
|
def = ncase
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for ll = ncase.List; ll != nil; ll = ll.Next {
|
for it2 := nodeSeqIterate(ncase.List); !it2.Done(); it2.Next() {
|
||||||
setlineno(ll.N)
|
setlineno(it2.N())
|
||||||
typecheck(&ll.N, Erv|Etype)
|
typecheck(it2.P(), Erv|Etype)
|
||||||
if ll.N.Type == nil || t == nil {
|
if it2.N().Type == nil || t == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
setlineno(ncase)
|
setlineno(ncase)
|
||||||
switch top {
|
switch top {
|
||||||
// expression switch
|
// expression switch
|
||||||
case Erv:
|
case Erv:
|
||||||
defaultlit(&ll.N, t)
|
defaultlit(it2.P(), t)
|
||||||
switch {
|
switch {
|
||||||
case ll.N.Op == OTYPE:
|
case it2.N().Op == OTYPE:
|
||||||
Yyerror("type %v is not an expression", ll.N.Type)
|
Yyerror("type %v is not an expression", it2.N().Type)
|
||||||
case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
|
case it2.N().Type != nil && assignop(it2.N().Type, t, nil) == 0 && assignop(t, it2.N().Type, nil) == 0:
|
||||||
if n.Left != nil {
|
if n.Left != nil {
|
||||||
Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t)
|
Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", it2.N(), n.Left, it2.N().Type, t)
|
||||||
} else {
|
} else {
|
||||||
Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
|
Yyerror("invalid case %v in switch (mismatched types %v and bool)", it2.N(), it2.N().Type)
|
||||||
}
|
}
|
||||||
case nilonly != "" && !isnil(ll.N):
|
case nilonly != "" && !isnil(it2.N()):
|
||||||
Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left)
|
Yyerror("invalid case %v in switch (can only compare %s %v to nil)", it2.N(), nilonly, n.Left)
|
||||||
case Isinter(t) && !Isinter(ll.N.Type) && algtype1(ll.N.Type, nil) == ANOEQ:
|
case Isinter(t) && !Isinter(it2.N().Type) && algtype1(it2.N().Type, nil) == ANOEQ:
|
||||||
Yyerror("invalid case %v in switch (incomparable type)", Nconv(ll.N, obj.FmtLong))
|
Yyerror("invalid case %v in switch (incomparable type)", Nconv(it2.N(), obj.FmtLong))
|
||||||
}
|
}
|
||||||
|
|
||||||
// type switch
|
// type switch
|
||||||
|
|
@ -148,16 +147,16 @@ func typecheckswitch(n *Node) {
|
||||||
var missing, have *Type
|
var missing, have *Type
|
||||||
var ptr int
|
var ptr int
|
||||||
switch {
|
switch {
|
||||||
case ll.N.Op == OLITERAL && Istype(ll.N.Type, TNIL):
|
case it2.N().Op == OLITERAL && Istype(it2.N().Type, TNIL):
|
||||||
case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
|
case it2.N().Op != OTYPE && it2.N().Type != nil: // should this be ||?
|
||||||
Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
|
Yyerror("%v is not a type", Nconv(it2.N(), obj.FmtLong))
|
||||||
// reset to original type
|
// reset to original type
|
||||||
ll.N = n.Left.Right
|
*it2.P() = n.Left.Right
|
||||||
case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
|
case it2.N().Type.Etype != TINTER && t.Etype == TINTER && !implements(it2.N().Type, t, &missing, &have, &ptr):
|
||||||
if have != nil && !missing.Broke && !have.Broke {
|
if have != nil && !missing.Broke && !have.Broke {
|
||||||
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
|
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), it2.N().Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
|
||||||
} else if !missing.Broke {
|
} else if !missing.Broke {
|
||||||
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym)
|
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), it2.N().Type, missing.Sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,19 +164,20 @@ func typecheckswitch(n *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if top == Etype && n.Type != nil {
|
if top == Etype && n.Type != nil {
|
||||||
ll = ncase.List
|
ll := ncase.List
|
||||||
if ncase.Rlist != nil {
|
if nodeSeqLen(ncase.Rlist) != 0 {
|
||||||
nvar := ncase.Rlist.N
|
nvar := nodeSeqFirst(ncase.Rlist)
|
||||||
if ll != nil && ll.Next == nil && ll.N.Type != nil && !Istype(ll.N.Type, TNIL) {
|
if nodeSeqLen(ll) == 1 && nodeSeqFirst(ll).Type != nil && !Istype(nodeSeqFirst(ll).Type, TNIL) {
|
||||||
// single entry type switch
|
// single entry type switch
|
||||||
nvar.Name.Param.Ntype = typenod(ll.N.Type)
|
nvar.Name.Param.Ntype = typenod(nodeSeqFirst(ll).Type)
|
||||||
} else {
|
} else {
|
||||||
// multiple entry type switch or default
|
// multiple entry type switch or default
|
||||||
nvar.Name.Param.Ntype = typenod(n.Type)
|
nvar.Name.Param.Ntype = typenod(n.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
typecheck(&nvar, Erv|Easgn)
|
typecheck(&nvar, Erv|Easgn)
|
||||||
ncase.Rlist.N = nvar
|
rit := nodeSeqIterate(ncase.Rlist)
|
||||||
|
*rit.P() = nvar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,7 +244,7 @@ func (s *exprSwitch) walk(sw *Node) {
|
||||||
|
|
||||||
// enumerate the cases, and lop off the default case
|
// enumerate the cases, and lop off the default case
|
||||||
cc := caseClauses(sw, s.kind)
|
cc := caseClauses(sw, s.kind)
|
||||||
sw.List = nil
|
setNodeSeq(&sw.List, nil)
|
||||||
var def *Node
|
var def *Node
|
||||||
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
||||||
def = cc[0].node.Right
|
def = cc[0].node.Right
|
||||||
|
|
@ -326,7 +326,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
|
||||||
}
|
}
|
||||||
typecheck(&a.Left, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
|
a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
|
||||||
a.Rlist = list1(s.walkCases(cc[half:]))
|
setNodeSeq(&a.Rlist, []*Node{s.walkCases(cc[half:])})
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -334,28 +334,28 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
|
||||||
// It makes labels between cases and statements
|
// It makes labels between cases and statements
|
||||||
// and deals with fallthrough, break, and unreachable statements.
|
// and deals with fallthrough, break, and unreachable statements.
|
||||||
func casebody(sw *Node, typeswvar *Node) {
|
func casebody(sw *Node, typeswvar *Node) {
|
||||||
if sw.List == nil {
|
if nodeSeqLen(sw.List) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lno := setlineno(sw)
|
lno := setlineno(sw)
|
||||||
|
|
||||||
var cas *NodeList // cases
|
var cas []*Node // cases
|
||||||
var stat []*Node // statements
|
var stat []*Node // statements
|
||||||
var def *Node // defaults
|
var def *Node // defaults
|
||||||
br := Nod(OBREAK, nil, nil)
|
br := Nod(OBREAK, nil, nil)
|
||||||
|
|
||||||
for l := sw.List; l != nil; l = l.Next {
|
for it := nodeSeqIterate(sw.List); !it.Done(); it.Next() {
|
||||||
n := l.N
|
n := it.N()
|
||||||
setlineno(n)
|
setlineno(n)
|
||||||
if n.Op != OXCASE {
|
if n.Op != OXCASE {
|
||||||
Fatalf("casebody %v", Oconv(int(n.Op), 0))
|
Fatalf("casebody %v", Oconv(int(n.Op), 0))
|
||||||
}
|
}
|
||||||
n.Op = OCASE
|
n.Op = OCASE
|
||||||
needvar := count(n.List) != 1 || n.List.N.Op == OLITERAL
|
needvar := nodeSeqLen(n.List) != 1 || nodeSeqFirst(n.List).Op == OLITERAL
|
||||||
|
|
||||||
jmp := Nod(OGOTO, newCaseLabel(), nil)
|
jmp := Nod(OGOTO, newCaseLabel(), nil)
|
||||||
if n.List == nil {
|
if nodeSeqLen(n.List) == 0 {
|
||||||
if def != nil {
|
if def != nil {
|
||||||
Yyerror("more than one default case")
|
Yyerror("more than one default case")
|
||||||
}
|
}
|
||||||
|
|
@ -364,24 +364,24 @@ func casebody(sw *Node, typeswvar *Node) {
|
||||||
def = n
|
def = n
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.List != nil && n.List.Next == nil {
|
if nodeSeqLen(n.List) == 1 {
|
||||||
// one case -- reuse OCASE node
|
// one case -- reuse OCASE node
|
||||||
n.Left = n.List.N
|
n.Left = nodeSeqFirst(n.List)
|
||||||
n.Right = jmp
|
n.Right = jmp
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
cas = list(cas, n)
|
cas = append(cas, n)
|
||||||
} else {
|
} else {
|
||||||
// expand multi-valued cases
|
// expand multi-valued cases
|
||||||
for lc := n.List; lc != nil; lc = lc.Next {
|
for lcit := nodeSeqIterate(n.List); !lcit.Done(); lcit.Next() {
|
||||||
cas = list(cas, Nod(OCASE, lc.N, jmp))
|
cas = append(cas, Nod(OCASE, lcit.N(), jmp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stat = append(stat, Nod(OLABEL, jmp.Left, nil))
|
stat = append(stat, Nod(OLABEL, jmp.Left, nil))
|
||||||
if typeswvar != nil && needvar && n.Rlist != nil {
|
if typeswvar != nil && needvar && nodeSeqLen(n.Rlist) != 0 {
|
||||||
l := []*Node{
|
l := []*Node{
|
||||||
Nod(ODCL, n.Rlist.N, nil),
|
Nod(ODCL, nodeSeqFirst(n.Rlist), nil),
|
||||||
Nod(OAS, n.Rlist.N, typeswvar),
|
Nod(OAS, nodeSeqFirst(n.Rlist), typeswvar),
|
||||||
}
|
}
|
||||||
typecheckslice(l, Etop)
|
typecheckslice(l, Etop)
|
||||||
stat = append(stat, l...)
|
stat = append(stat, l...)
|
||||||
|
|
@ -396,7 +396,7 @@ func casebody(sw *Node, typeswvar *Node) {
|
||||||
Yyerror("cannot fallthrough in type switch")
|
Yyerror("cannot fallthrough in type switch")
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.Next == nil {
|
if it.Len() <= 1 {
|
||||||
setlineno(last)
|
setlineno(last)
|
||||||
Yyerror("cannot fallthrough final case in switch")
|
Yyerror("cannot fallthrough final case in switch")
|
||||||
}
|
}
|
||||||
|
|
@ -409,10 +409,10 @@ func casebody(sw *Node, typeswvar *Node) {
|
||||||
|
|
||||||
stat = append(stat, br)
|
stat = append(stat, br)
|
||||||
if def != nil {
|
if def != nil {
|
||||||
cas = list(cas, def)
|
cas = append(cas, def)
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.List = cas
|
setNodeSeq(&sw.List, cas)
|
||||||
sw.Nbody.Set(stat)
|
sw.Nbody.Set(stat)
|
||||||
lineno = lno
|
lineno = lno
|
||||||
}
|
}
|
||||||
|
|
@ -432,8 +432,8 @@ func newCaseLabel() *Node {
|
||||||
// Kind is the kind of switch statement.
|
// Kind is the kind of switch statement.
|
||||||
func caseClauses(sw *Node, kind int) []*caseClause {
|
func caseClauses(sw *Node, kind int) []*caseClause {
|
||||||
var cc []*caseClause
|
var cc []*caseClause
|
||||||
for l := sw.List; l != nil; l = l.Next {
|
for it := nodeSeqIterate(sw.List); !it.Done(); it.Next() {
|
||||||
n := l.N
|
n := it.N()
|
||||||
c := new(caseClause)
|
c := new(caseClause)
|
||||||
cc = append(cc, c)
|
cc = append(cc, c)
|
||||||
c.ordinal = len(cc)
|
c.ordinal = len(cc)
|
||||||
|
|
@ -518,7 +518,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
sw.Left = nil
|
sw.Left = nil
|
||||||
|
|
||||||
if cond == nil {
|
if cond == nil {
|
||||||
sw.List = nil
|
setNodeSeq(&sw.List, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if cond.Right == nil {
|
if cond.Right == nil {
|
||||||
|
|
@ -552,7 +552,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
casebody(sw, s.facename)
|
casebody(sw, s.facename)
|
||||||
|
|
||||||
cc := caseClauses(sw, switchKindType)
|
cc := caseClauses(sw, switchKindType)
|
||||||
sw.List = nil
|
setNodeSeq(&sw.List, nil)
|
||||||
var def *Node
|
var def *Node
|
||||||
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
if len(cc) > 0 && cc[0].typ == caseKindDefault {
|
||||||
def = cc[0].node.Right
|
def = cc[0].node.Right
|
||||||
|
|
@ -588,7 +588,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
i.Nbody.Set([]*Node{Nod(OGOTO, lbl, nil)})
|
i.Nbody.Set([]*Node{Nod(OGOTO, lbl, nil)})
|
||||||
// Wrap default case with label.
|
// Wrap default case with label.
|
||||||
blk := Nod(OBLOCK, nil, nil)
|
blk := Nod(OBLOCK, nil, nil)
|
||||||
blk.List = list(list1(Nod(OLABEL, lbl, nil)), def)
|
setNodeSeq(&blk.List, []*Node{Nod(OLABEL, lbl, nil), def})
|
||||||
def = blk
|
def = blk
|
||||||
}
|
}
|
||||||
typecheck(&i.Left, Erv)
|
typecheck(&i.Left, Erv)
|
||||||
|
|
@ -669,7 +669,7 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
if nerrors == 0 {
|
if nerrors == 0 {
|
||||||
cas = append(cas, def)
|
cas = append(cas, def)
|
||||||
sw.Nbody.Set(append(cas, sw.Nbody.Slice()...))
|
sw.Nbody.Set(append(cas, sw.Nbody.Slice()...))
|
||||||
sw.List = nil
|
setNodeSeq(&sw.List, nil)
|
||||||
walkstmtlist(sw.Nbody)
|
walkstmtlist(sw.Nbody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -679,11 +679,11 @@ func (s *typeSwitch) walk(sw *Node) {
|
||||||
func (s *typeSwitch) typeone(t *Node) *Node {
|
func (s *typeSwitch) typeone(t *Node) *Node {
|
||||||
var name *Node
|
var name *Node
|
||||||
var init *NodeList
|
var init *NodeList
|
||||||
if t.Rlist == nil {
|
if nodeSeqLen(t.Rlist) == 0 {
|
||||||
name = nblank
|
name = nblank
|
||||||
typecheck(&nblank, Erv|Easgn)
|
typecheck(&nblank, Erv|Easgn)
|
||||||
} else {
|
} else {
|
||||||
name = t.Rlist.N
|
name = nodeSeqFirst(t.Rlist)
|
||||||
init = list1(Nod(ODCL, name, nil))
|
init = list1(Nod(ODCL, name, nil))
|
||||||
a := Nod(OAS, name, nil)
|
a := Nod(OAS, name, nil)
|
||||||
typecheck(&a, Etop)
|
typecheck(&a, Etop)
|
||||||
|
|
@ -691,10 +691,10 @@ func (s *typeSwitch) typeone(t *Node) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
a := Nod(OAS2, nil, nil)
|
a := Nod(OAS2, nil, nil)
|
||||||
a.List = list(list1(name), s.okname) // name, ok =
|
setNodeSeq(&a.List, []*Node{name, s.okname}) // name, ok =
|
||||||
b := Nod(ODOTTYPE, s.facename, nil)
|
b := Nod(ODOTTYPE, s.facename, nil)
|
||||||
b.Type = t.Left.Type // interface.(type)
|
b.Type = t.Left.Type // interface.(type)
|
||||||
a.Rlist = list1(b)
|
setNodeSeq(&a.Rlist, []*Node{b})
|
||||||
typecheck(&a, Etop)
|
typecheck(&a, Etop)
|
||||||
init = list(init, a)
|
init = list(init, a)
|
||||||
|
|
||||||
|
|
@ -729,7 +729,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
|
||||||
a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
|
a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
|
||||||
typecheck(&a.Left, Erv)
|
typecheck(&a.Left, Erv)
|
||||||
a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
|
a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
|
||||||
a.Rlist = list1(s.walkCases(cc[half:]))
|
setNodeSeq(&a.Rlist, []*Node{s.walkCases(cc[half:])})
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -391,12 +391,12 @@ func list1(n *Node) *NodeList {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if n.Op == OBLOCK && n.Ninit == nil {
|
if n.Op == OBLOCK && nodeSeqLen(n.Ninit) == 0 {
|
||||||
// Flatten list and steal storage.
|
// Flatten list and steal storage.
|
||||||
// Poison pointer to catch errant uses.
|
// Poison pointer to catch errant uses.
|
||||||
l := n.List
|
l := n.List
|
||||||
|
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,21 +217,12 @@ func callrecv(n *Node) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvslice(n.Nbody.Slice()) || callrecvlist(n.List) || callrecvlist(n.Rlist)
|
return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
func callrecvlist(l *NodeList) bool {
|
func callrecvlist(l nodesOrNodeList) bool {
|
||||||
for ; l != nil; l = l.Next {
|
for it := nodeSeqIterate(l); !it.Done(); it.Next() {
|
||||||
if callrecv(l.N) {
|
if callrecv(it.N()) {
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func callrecvslice(l []*Node) bool {
|
|
||||||
for _, n := range l {
|
|
||||||
if callrecv(n) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -440,7 +431,7 @@ OpSwitch:
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
|
|
||||||
case OTINTER:
|
case OTINTER:
|
||||||
ok |= Etype
|
ok |= Etype
|
||||||
|
|
@ -714,14 +705,14 @@ OpSwitch:
|
||||||
n.Op = OADDSTR
|
n.Op = OADDSTR
|
||||||
|
|
||||||
if l.Op == OADDSTR {
|
if l.Op == OADDSTR {
|
||||||
n.List = l.List
|
setNodeSeq(&n.List, l.List)
|
||||||
} else {
|
} else {
|
||||||
n.List = list1(l)
|
setNodeSeq(&n.List, []*Node{l})
|
||||||
}
|
}
|
||||||
if r.Op == OADDSTR {
|
if r.Op == OADDSTR {
|
||||||
n.List = concat(n.List, r.List)
|
appendNodeSeq(&n.List, r.List)
|
||||||
} else {
|
} else {
|
||||||
n.List = list(n.List, r)
|
appendNodeSeqNode(&n.List, r)
|
||||||
}
|
}
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
|
|
@ -1298,8 +1289,9 @@ OpSwitch:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if count(n.List) == 1 && !n.Isddd {
|
if nodeSeqLen(n.List) == 1 && !n.Isddd {
|
||||||
typecheck(&n.List.N, Erv|Efnstruct)
|
it := nodeSeqIterate(n.List)
|
||||||
|
typecheck(it.P(), Erv|Efnstruct)
|
||||||
} else {
|
} else {
|
||||||
typechecklist(n.List, Erv)
|
typechecklist(n.List, Erv)
|
||||||
}
|
}
|
||||||
|
|
@ -1455,22 +1447,22 @@ OpSwitch:
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
var r *Node
|
var r *Node
|
||||||
var l *Node
|
var l *Node
|
||||||
if count(n.List) == 1 {
|
if nodeSeqLen(n.List) == 1 {
|
||||||
typechecklist(n.List, Efnstruct)
|
typechecklist(n.List, Efnstruct)
|
||||||
if n.List.N.Op != OCALLFUNC && n.List.N.Op != OCALLMETH {
|
if nodeSeqFirst(n.List).Op != OCALLFUNC && nodeSeqFirst(n.List).Op != OCALLMETH {
|
||||||
Yyerror("invalid operation: complex expects two arguments")
|
Yyerror("invalid operation: complex expects two arguments")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
t := n.List.N.Left.Type
|
t := nodeSeqFirst(n.List).Left.Type
|
||||||
if t.Outtuple != 2 {
|
if t.Outtuple != 2 {
|
||||||
Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.N, t.Outtuple)
|
Yyerror("invalid operation: complex expects two arguments, %v returns %d results", nodeSeqFirst(n.List), t.Outtuple)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
t = n.List.N.Type.Type
|
t = nodeSeqFirst(n.List).Type.Type
|
||||||
l = t.Nname
|
l = t.Nname
|
||||||
r = t.Down.Nname
|
r = t.Down.Nname
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1557,19 +1549,19 @@ OpSwitch:
|
||||||
|
|
||||||
case ODELETE:
|
case ODELETE:
|
||||||
args := n.List
|
args := n.List
|
||||||
if args == nil {
|
if nodeSeqLen(args) == 0 {
|
||||||
Yyerror("missing arguments to delete")
|
Yyerror("missing arguments to delete")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Next == nil {
|
if nodeSeqLen(args) == 1 {
|
||||||
Yyerror("missing second (key) argument to delete")
|
Yyerror("missing second (key) argument to delete")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Next.Next != nil {
|
if nodeSeqLen(args) != 2 {
|
||||||
Yyerror("too many arguments to delete")
|
Yyerror("too many arguments to delete")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
|
|
@ -1577,33 +1569,36 @@ OpSwitch:
|
||||||
|
|
||||||
ok |= Etop
|
ok |= Etop
|
||||||
typechecklist(args, Erv)
|
typechecklist(args, Erv)
|
||||||
l := args.N
|
l := nodeSeqFirst(args)
|
||||||
r := args.Next.N
|
r := nodeSeqSecond(args)
|
||||||
if l.Type != nil && l.Type.Etype != TMAP {
|
if l.Type != nil && l.Type.Etype != TMAP {
|
||||||
Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, obj.FmtLong))
|
Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, obj.FmtLong))
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args.Next.N = assignconv(r, l.Type.Down, "delete")
|
it := nodeSeqIterate(args)
|
||||||
|
it.Next()
|
||||||
|
*it.P() = assignconv(r, l.Type.Down, "delete")
|
||||||
break OpSwitch
|
break OpSwitch
|
||||||
|
|
||||||
case OAPPEND:
|
case OAPPEND:
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
args := n.List
|
args := n.List
|
||||||
if args == nil {
|
if nodeSeqLen(args) == 0 {
|
||||||
Yyerror("missing arguments to append")
|
Yyerror("missing arguments to append")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if count(args) == 1 && !n.Isddd {
|
if nodeSeqLen(args) == 1 && !n.Isddd {
|
||||||
typecheck(&args.N, Erv|Efnstruct)
|
it := nodeSeqIterate(args)
|
||||||
|
typecheck(it.P(), Erv|Efnstruct)
|
||||||
} else {
|
} else {
|
||||||
typechecklist(args, Erv)
|
typechecklist(args, Erv)
|
||||||
}
|
}
|
||||||
|
|
||||||
t := args.N.Type
|
t := nodeSeqFirst(args).Type
|
||||||
if t == nil {
|
if t == nil {
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
|
|
@ -1618,7 +1613,7 @@ OpSwitch:
|
||||||
|
|
||||||
n.Type = t
|
n.Type = t
|
||||||
if !Isslice(t) {
|
if !Isslice(t) {
|
||||||
if Isconst(args.N, CTNIL) {
|
if Isconst(nodeSeqFirst(args), CTNIL) {
|
||||||
Yyerror("first argument to append must be typed slice; have untyped nil")
|
Yyerror("first argument to append must be typed slice; have untyped nil")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
|
|
@ -1630,24 +1625,28 @@ OpSwitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Isddd {
|
if n.Isddd {
|
||||||
if args.Next == nil {
|
if nodeSeqLen(args) == 1 {
|
||||||
Yyerror("cannot use ... on first argument to append")
|
Yyerror("cannot use ... on first argument to append")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Next.Next != nil {
|
if nodeSeqLen(args) != 2 {
|
||||||
Yyerror("too many arguments to append")
|
Yyerror("too many arguments to append")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Istype(t.Type, TUINT8) && Istype(args.Next.N.Type, TSTRING) {
|
if Istype(t.Type, TUINT8) && Istype(nodeSeqSecond(args).Type, TSTRING) {
|
||||||
defaultlit(&args.Next.N, Types[TSTRING])
|
it := nodeSeqIterate(args)
|
||||||
|
it.Next()
|
||||||
|
defaultlit(it.P(), Types[TSTRING])
|
||||||
break OpSwitch
|
break OpSwitch
|
||||||
}
|
}
|
||||||
|
|
||||||
args.Next.N = assignconv(args.Next.N, t.Orig, "append")
|
it := nodeSeqIterate(args)
|
||||||
|
it.Next()
|
||||||
|
*it.P() = assignconv(nodeSeqSecond(args), t.Orig, "append")
|
||||||
break OpSwitch
|
break OpSwitch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1658,11 +1657,13 @@ OpSwitch:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for args = args.Next; args != nil; args = args.Next {
|
it := nodeSeqIterate(args)
|
||||||
if args.N.Type == nil {
|
it.Next()
|
||||||
|
for ; !it.Done(); it.Next() {
|
||||||
|
if it.N().Type == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
args.N = assignconv(args.N, t.Type, "append")
|
*it.P() = assignconv(it.N(), t.Type, "append")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1671,21 +1672,21 @@ OpSwitch:
|
||||||
case OCOPY:
|
case OCOPY:
|
||||||
ok |= Etop | Erv
|
ok |= Etop | Erv
|
||||||
args := n.List
|
args := n.List
|
||||||
if args == nil || args.Next == nil {
|
if nodeSeqLen(args) == 0 || args.Next == nil {
|
||||||
Yyerror("missing arguments to copy")
|
Yyerror("missing arguments to copy")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Next.Next != nil {
|
if nodeSeqLen(args) > 2 {
|
||||||
Yyerror("too many arguments to copy")
|
Yyerror("too many arguments to copy")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Left = args.N
|
n.Left = nodeSeqFirst(args)
|
||||||
n.Right = args.Next.N
|
n.Right = nodeSeqSecond(args)
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
n.Type = Types[TINT]
|
n.Type = Types[TINT]
|
||||||
typecheck(&n.Left, Erv)
|
typecheck(&n.Left, Erv)
|
||||||
typecheck(&n.Right, Erv)
|
typecheck(&n.Right, Erv)
|
||||||
|
|
@ -1777,16 +1778,16 @@ OpSwitch:
|
||||||
|
|
||||||
case OMAKE:
|
case OMAKE:
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
args := n.List
|
args := nodeSeqIterate(n.List)
|
||||||
if args == nil {
|
if args.Len() == 0 {
|
||||||
Yyerror("missing argument to make")
|
Yyerror("missing argument to make")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
l := args.N
|
l := args.N()
|
||||||
args = args.Next
|
args.Next()
|
||||||
typecheck(&l, Etype)
|
typecheck(&l, Etype)
|
||||||
t := l.Type
|
t := l.Type
|
||||||
if t == nil {
|
if t == nil {
|
||||||
|
|
@ -1807,19 +1808,19 @@ OpSwitch:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if args == nil {
|
if args.Done() {
|
||||||
Yyerror("missing len argument to make(%v)", t)
|
Yyerror("missing len argument to make(%v)", t)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l = args.N
|
l = args.N()
|
||||||
args = args.Next
|
args.Next()
|
||||||
typecheck(&l, Erv)
|
typecheck(&l, Erv)
|
||||||
var r *Node
|
var r *Node
|
||||||
if args != nil {
|
if !args.Done() {
|
||||||
r = args.N
|
r = args.N()
|
||||||
args = args.Next
|
args.Next()
|
||||||
typecheck(&r, Erv)
|
typecheck(&r, Erv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1842,9 +1843,9 @@ OpSwitch:
|
||||||
n.Op = OMAKESLICE
|
n.Op = OMAKESLICE
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
if args != nil {
|
if !args.Done() {
|
||||||
l = args.N
|
l = args.N()
|
||||||
args = args.Next
|
args.Next()
|
||||||
typecheck(&l, Erv)
|
typecheck(&l, Erv)
|
||||||
defaultlit(&l, Types[TINT])
|
defaultlit(&l, Types[TINT])
|
||||||
if l.Type == nil {
|
if l.Type == nil {
|
||||||
|
|
@ -1863,9 +1864,9 @@ OpSwitch:
|
||||||
|
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
l = nil
|
l = nil
|
||||||
if args != nil {
|
if !args.Done() {
|
||||||
l = args.N
|
l = args.N()
|
||||||
args = args.Next
|
args.Next()
|
||||||
typecheck(&l, Erv)
|
typecheck(&l, Erv)
|
||||||
defaultlit(&l, Types[TINT])
|
defaultlit(&l, Types[TINT])
|
||||||
if l.Type == nil {
|
if l.Type == nil {
|
||||||
|
|
@ -1883,7 +1884,7 @@ OpSwitch:
|
||||||
n.Op = OMAKECHAN
|
n.Op = OMAKECHAN
|
||||||
}
|
}
|
||||||
|
|
||||||
if args != nil {
|
if !args.Done() {
|
||||||
Yyerror("too many arguments to make(%v)", t)
|
Yyerror("too many arguments to make(%v)", t)
|
||||||
n.Op = OMAKE
|
n.Op = OMAKE
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
@ -1896,20 +1897,20 @@ OpSwitch:
|
||||||
case ONEW:
|
case ONEW:
|
||||||
ok |= Erv
|
ok |= Erv
|
||||||
args := n.List
|
args := n.List
|
||||||
if args == nil {
|
if nodeSeqLen(args) == 0 {
|
||||||
Yyerror("missing argument to new")
|
Yyerror("missing argument to new")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l := args.N
|
l := nodeSeqFirst(args)
|
||||||
typecheck(&l, Etype)
|
typecheck(&l, Etype)
|
||||||
t := l.Type
|
t := l.Type
|
||||||
if t == nil {
|
if t == nil {
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if args.Next != nil {
|
if nodeSeqLen(args) > 1 {
|
||||||
Yyerror("too many arguments to new(%v)", t)
|
Yyerror("too many arguments to new(%v)", t)
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
|
|
@ -1922,12 +1923,12 @@ OpSwitch:
|
||||||
case OPRINT, OPRINTN:
|
case OPRINT, OPRINTN:
|
||||||
ok |= Etop
|
ok |= Etop
|
||||||
typechecklist(n.List, Erv|Eindir) // Eindir: address does not escape
|
typechecklist(n.List, Erv|Eindir) // Eindir: address does not escape
|
||||||
for args := n.List; args != nil; args = args.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
// Special case for print: int constant is int64, not int.
|
// Special case for print: int constant is int64, not int.
|
||||||
if Isconst(args.N, CTINT) {
|
if Isconst(it.N(), CTINT) {
|
||||||
defaultlit(&args.N, Types[TINT64])
|
defaultlit(it.P(), Types[TINT64])
|
||||||
} else {
|
} else {
|
||||||
defaultlit(&args.N, nil)
|
defaultlit(it.P(), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1949,7 +1950,7 @@ OpSwitch:
|
||||||
|
|
||||||
case ORECOVER:
|
case ORECOVER:
|
||||||
ok |= Erv | Etop
|
ok |= Erv | Etop
|
||||||
if n.List != nil {
|
if nodeSeqLen(n.List) != 0 {
|
||||||
Yyerror("too many arguments to recover")
|
Yyerror("too many arguments to recover")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
return
|
return
|
||||||
|
|
@ -2093,7 +2094,7 @@ OpSwitch:
|
||||||
|
|
||||||
case ORETURN:
|
case ORETURN:
|
||||||
ok |= Etop
|
ok |= Etop
|
||||||
if count(n.List) == 1 {
|
if nodeSeqLen(n.List) == 1 {
|
||||||
typechecklist(n.List, Erv|Efnstruct)
|
typechecklist(n.List, Erv|Efnstruct)
|
||||||
} else {
|
} else {
|
||||||
typechecklist(n.List, Erv)
|
typechecklist(n.List, Erv)
|
||||||
|
|
@ -2104,7 +2105,7 @@ OpSwitch:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Curfn.Type.Outnamed && n.List == nil {
|
if Curfn.Type.Outnamed && nodeSeqLen(n.List) == 0 {
|
||||||
break OpSwitch
|
break OpSwitch
|
||||||
}
|
}
|
||||||
typecheckaste(ORETURN, nil, false, getoutargx(Curfn.Type), n.List, func() string { return "return argument" })
|
typecheckaste(ORETURN, nil, false, getoutargx(Curfn.Type), n.List, func() string { return "return argument" })
|
||||||
|
|
@ -2332,22 +2333,22 @@ func onearg(n *Node, f string, args ...interface{}) bool {
|
||||||
if n.Left != nil {
|
if n.Left != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if n.List == nil {
|
if nodeSeqLen(n.List) == 0 {
|
||||||
p := fmt.Sprintf(f, args...)
|
p := fmt.Sprintf(f, args...)
|
||||||
Yyerror("missing argument to %s: %v", p, n)
|
Yyerror("missing argument to %s: %v", p, n)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.List.Next != nil {
|
if nodeSeqLen(n.List) > 1 {
|
||||||
p := fmt.Sprintf(f, args...)
|
p := fmt.Sprintf(f, args...)
|
||||||
Yyerror("too many arguments to %s: %v", p, n)
|
Yyerror("too many arguments to %s: %v", p, n)
|
||||||
n.Left = n.List.N
|
n.Left = nodeSeqFirst(n.List)
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Left = n.List.N
|
n.Left = nodeSeqFirst(n.List)
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2355,26 +2356,26 @@ func twoarg(n *Node) bool {
|
||||||
if n.Left != nil {
|
if n.Left != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if n.List == nil {
|
if nodeSeqLen(n.List) == 0 {
|
||||||
Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
|
Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Left = n.List.N
|
n.Left = nodeSeqFirst(n.List)
|
||||||
if n.List.Next == nil {
|
if nodeSeqLen(n.List) == 1 {
|
||||||
Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
|
Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.List.Next.Next != nil {
|
if nodeSeqLen(n.List) > 2 {
|
||||||
Yyerror("too many arguments to %v - %v", Oconv(int(n.Op), 0), n)
|
Yyerror("too many arguments to %v - %v", Oconv(int(n.Op), 0), n)
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Right = n.List.Next.N
|
n.Right = nodeSeqSecond(n.List)
|
||||||
n.List = nil
|
setNodeSeq(&n.List, nil)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2915,8 +2916,8 @@ func typecheckcomplit(np **Node) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if n.Right == nil {
|
if n.Right == nil {
|
||||||
if n.List != nil {
|
if nodeSeqLen(n.List) != 0 {
|
||||||
setlineno(n.List.N)
|
setlineno(nodeSeqFirst(n.List))
|
||||||
}
|
}
|
||||||
Yyerror("missing type in composite literal")
|
Yyerror("missing type in composite literal")
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
@ -2966,22 +2967,22 @@ func typecheckcomplit(np **Node) {
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
// Only allocate hash if there are some key/value pairs.
|
// Only allocate hash if there are some key/value pairs.
|
||||||
var hash map[int64]*Node
|
var hash map[int64]*Node
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
if ll.N.Op == OKEY {
|
if it.N().Op == OKEY {
|
||||||
hash = make(map[int64]*Node)
|
hash = make(map[int64]*Node)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
length := int64(0)
|
length := int64(0)
|
||||||
i := 0
|
i := 0
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
l := ll.N
|
l := it.N()
|
||||||
setlineno(l)
|
setlineno(l)
|
||||||
if l.Op != OKEY {
|
if l.Op != OKEY {
|
||||||
l = Nod(OKEY, Nodintconst(int64(i)), l)
|
l = Nod(OKEY, Nodintconst(int64(i)), l)
|
||||||
l.Left.Type = Types[TINT]
|
l.Left.Type = Types[TINT]
|
||||||
l.Left.Typecheck = 1
|
l.Left.Typecheck = 1
|
||||||
ll.N = l
|
*it.P() = l
|
||||||
}
|
}
|
||||||
|
|
||||||
typecheck(&l.Left, Erv)
|
typecheck(&l.Left, Erv)
|
||||||
|
|
@ -3024,11 +3025,11 @@ func typecheckcomplit(np **Node) {
|
||||||
case TMAP:
|
case TMAP:
|
||||||
hash := make(map[uint32][]*Node)
|
hash := make(map[uint32][]*Node)
|
||||||
var l *Node
|
var l *Node
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
l = ll.N
|
l = it.N()
|
||||||
setlineno(l)
|
setlineno(l)
|
||||||
if l.Op != OKEY {
|
if l.Op != OKEY {
|
||||||
typecheck(&ll.N, Erv)
|
typecheck(it.P(), Erv)
|
||||||
Yyerror("missing key in map literal")
|
Yyerror("missing key in map literal")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -3053,14 +3054,14 @@ func typecheckcomplit(np **Node) {
|
||||||
|
|
||||||
case TSTRUCT:
|
case TSTRUCT:
|
||||||
bad := 0
|
bad := 0
|
||||||
if n.List != nil && nokeys(n.List) {
|
if nodeSeqLen(n.List) != 0 && nokeys(n.List) {
|
||||||
// simple list of variables
|
// simple list of variables
|
||||||
f := t.Type
|
f := t.Type
|
||||||
|
|
||||||
var s *Sym
|
var s *Sym
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
setlineno(ll.N)
|
setlineno(it.N())
|
||||||
typecheck(&ll.N, Erv)
|
typecheck(it.P(), Erv)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
if bad == 0 {
|
if bad == 0 {
|
||||||
Yyerror("too many values in struct initializer")
|
Yyerror("too many values in struct initializer")
|
||||||
|
|
@ -3075,11 +3076,11 @@ func typecheckcomplit(np **Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// No pushtype allowed here. Must name fields for that.
|
// No pushtype allowed here. Must name fields for that.
|
||||||
ll.N = assignconv(ll.N, f.Type, "field value")
|
*it.P() = assignconv(it.N(), f.Type, "field value")
|
||||||
|
|
||||||
ll.N = Nod(OKEY, newname(f.Sym), ll.N)
|
*it.P() = Nod(OKEY, newname(f.Sym), it.N())
|
||||||
ll.N.Left.Type = f
|
it.N().Left.Type = f
|
||||||
ll.N.Left.Typecheck = 1
|
it.N().Left.Typecheck = 1
|
||||||
f = f.Down
|
f = f.Down
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3094,15 +3095,15 @@ func typecheckcomplit(np **Node) {
|
||||||
var f *Type
|
var f *Type
|
||||||
var l *Node
|
var l *Node
|
||||||
var s1 *Sym
|
var s1 *Sym
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
l = ll.N
|
l = it.N()
|
||||||
setlineno(l)
|
setlineno(l)
|
||||||
if l.Op != OKEY {
|
if l.Op != OKEY {
|
||||||
if bad == 0 {
|
if bad == 0 {
|
||||||
Yyerror("mixture of field:value and value initializers")
|
Yyerror("mixture of field:value and value initializers")
|
||||||
}
|
}
|
||||||
bad++
|
bad++
|
||||||
typecheck(&ll.N, Erv)
|
typecheck(it.P(), Erv)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3313,19 +3314,20 @@ func checkassignto(src *Type, dst *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckas2(n *Node) {
|
func typecheckas2(n *Node) {
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
// delicate little dance.
|
// delicate little dance.
|
||||||
ll.N = resolve(ll.N)
|
*it.P() = resolve(it.N())
|
||||||
|
|
||||||
if ll.N.Name == nil || ll.N.Name.Defn != n || ll.N.Name.Param.Ntype != nil {
|
if it.N().Name == nil || it.N().Name.Defn != n || it.N().Name.Param.Ntype != nil {
|
||||||
typecheck(&ll.N, Erv|Easgn)
|
typecheck(it.P(), Erv|Easgn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cl := count(n.List)
|
cl := nodeSeqLen(n.List)
|
||||||
cr := count(n.Rlist)
|
cr := nodeSeqLen(n.Rlist)
|
||||||
if cl > 1 && cr == 1 {
|
if cl > 1 && cr == 1 {
|
||||||
typecheck(&n.Rlist.N, Erv|Efnstruct)
|
it := nodeSeqIterate(n.Rlist)
|
||||||
|
typecheck(it.P(), Erv|Efnstruct)
|
||||||
} else {
|
} else {
|
||||||
typechecklist(n.Rlist, Erv)
|
typechecklist(n.Rlist, Erv)
|
||||||
}
|
}
|
||||||
|
|
@ -3335,23 +3337,24 @@ func typecheckas2(n *Node) {
|
||||||
var r *Node
|
var r *Node
|
||||||
if cl == cr {
|
if cl == cr {
|
||||||
// easy
|
// easy
|
||||||
ll := n.List
|
llit := nodeSeqIterate(n.List)
|
||||||
lr := n.Rlist
|
lrit := nodeSeqIterate(n.Rlist)
|
||||||
for ; ll != nil; ll, lr = ll.Next, lr.Next {
|
for llit = nodeSeqIterate(n.List); !llit.Done(); llit.Next() {
|
||||||
if ll.N.Type != nil && lr.N.Type != nil {
|
if llit.N().Type != nil && lrit.N().Type != nil {
|
||||||
lr.N = assignconv(lr.N, ll.N.Type, "assignment")
|
*lrit.P() = assignconv(lrit.N(), llit.N().Type, "assignment")
|
||||||
}
|
}
|
||||||
if ll.N.Name != nil && ll.N.Name.Defn == n && ll.N.Name.Param.Ntype == nil {
|
if llit.N().Name != nil && llit.N().Name.Defn == n && llit.N().Name.Param.Ntype == nil {
|
||||||
defaultlit(&lr.N, nil)
|
defaultlit(lrit.P(), nil)
|
||||||
ll.N.Type = lr.N.Type
|
llit.N().Type = lrit.N().Type
|
||||||
}
|
}
|
||||||
|
lrit.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
goto out
|
goto out
|
||||||
}
|
}
|
||||||
|
|
||||||
l = n.List.N
|
l = nodeSeqFirst(n.List)
|
||||||
r = n.Rlist.N
|
r = nodeSeqFirst(n.Rlist)
|
||||||
|
|
||||||
// x,y,z = f()
|
// x,y,z = f()
|
||||||
if cr == 1 {
|
if cr == 1 {
|
||||||
|
|
@ -3370,12 +3373,12 @@ func typecheckas2(n *Node) {
|
||||||
n.Op = OAS2FUNC
|
n.Op = OAS2FUNC
|
||||||
var s Iter
|
var s Iter
|
||||||
t := Structfirst(&s, &r.Type)
|
t := Structfirst(&s, &r.Type)
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
if t.Type != nil && ll.N.Type != nil {
|
if t.Type != nil && it.N().Type != nil {
|
||||||
checkassignto(t.Type, ll.N)
|
checkassignto(t.Type, it.N())
|
||||||
}
|
}
|
||||||
if ll.N.Name != nil && ll.N.Name.Defn == n && ll.N.Name.Param.Ntype == nil {
|
if it.N().Name != nil && it.N().Name.Defn == n && it.N().Name.Param.Ntype == nil {
|
||||||
ll.N.Type = t.Type
|
it.N().Type = t.Type
|
||||||
}
|
}
|
||||||
t = structnext(&s)
|
t = structnext(&s)
|
||||||
}
|
}
|
||||||
|
|
@ -3409,7 +3412,7 @@ func typecheckas2(n *Node) {
|
||||||
if l.Name != nil && l.Name.Defn == n {
|
if l.Name != nil && l.Name.Defn == n {
|
||||||
l.Type = r.Type
|
l.Type = r.Type
|
||||||
}
|
}
|
||||||
l := n.List.Next.N
|
l := nodeSeqSecond(n.List)
|
||||||
if l.Type != nil && l.Type.Etype != TBOOL {
|
if l.Type != nil && l.Type.Etype != TBOOL {
|
||||||
checkassignto(Types[TBOOL], l)
|
checkassignto(Types[TBOOL], l)
|
||||||
}
|
}
|
||||||
|
|
@ -3427,9 +3430,9 @@ mismatch:
|
||||||
out:
|
out:
|
||||||
n.Typecheck = 1
|
n.Typecheck = 1
|
||||||
|
|
||||||
for ll := n.List; ll != nil; ll = ll.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
if ll.N.Typecheck == 0 {
|
if it.N().Typecheck == 0 {
|
||||||
typecheck(&ll.N, Erv|Easgn)
|
typecheck(it.P(), Erv|Easgn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3462,23 +3465,23 @@ func stringtoarraylit(np **Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := n.Left.Val().U.(string)
|
s := n.Left.Val().U.(string)
|
||||||
var l *NodeList
|
var l []*Node
|
||||||
if n.Type.Type.Etype == TUINT8 {
|
if n.Type.Type.Etype == TUINT8 {
|
||||||
// []byte
|
// []byte
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
l = list(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(s[0]))))
|
l = append(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(s[0]))))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// []rune
|
// []rune
|
||||||
i := 0
|
i := 0
|
||||||
for _, r := range s {
|
for _, r := range s {
|
||||||
l = list(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(r))))
|
l = append(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(r))))
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nn := Nod(OCOMPLIT, nil, typenod(n.Type))
|
nn := Nod(OCOMPLIT, nil, typenod(n.Type))
|
||||||
nn.List = l
|
setNodeSeq(&nn.List, l)
|
||||||
typecheck(&nn, Erv)
|
typecheck(&nn, Erv)
|
||||||
*np = nn
|
*np = nn
|
||||||
}
|
}
|
||||||
|
|
@ -3880,43 +3883,16 @@ func markbreak(n *Node, implicit *Node) {
|
||||||
|
|
||||||
markbreak(n.Right, implicit)
|
markbreak(n.Right, implicit)
|
||||||
markbreaklist(n.Ninit, implicit)
|
markbreaklist(n.Ninit, implicit)
|
||||||
markbreakslice(n.Nbody.Slice(), implicit)
|
markbreaklist(n.Nbody, implicit)
|
||||||
markbreaklist(n.List, implicit)
|
markbreaklist(n.List, implicit)
|
||||||
markbreaklist(n.Rlist, implicit)
|
markbreaklist(n.Rlist, implicit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func markbreaklist(l *NodeList, implicit *Node) {
|
func markbreaklist(l nodesOrNodeList, implicit *Node) {
|
||||||
var n *Node
|
for it := nodeSeqIterate(l); !it.Done(); it.Next() {
|
||||||
var lab *Label
|
n := it.N()
|
||||||
|
if n.Op == OLABEL && it.Len() > 1 && n.Name.Defn == nodeSeqSlice(it.Seq())[1] {
|
||||||
for ; l != nil; l = l.Next {
|
|
||||||
n = l.N
|
|
||||||
if n.Op == OLABEL && l.Next != nil && n.Name.Defn == l.Next.N {
|
|
||||||
switch n.Name.Defn.Op {
|
|
||||||
case OFOR,
|
|
||||||
OSWITCH,
|
|
||||||
OTYPESW,
|
|
||||||
OSELECT,
|
|
||||||
ORANGE:
|
|
||||||
lab = new(Label)
|
|
||||||
lab.Def = n.Name.Defn
|
|
||||||
n.Left.Sym.Label = lab
|
|
||||||
markbreak(n.Name.Defn, n.Name.Defn)
|
|
||||||
n.Left.Sym.Label = nil
|
|
||||||
l = l.Next
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
markbreak(n, implicit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func markbreakslice(l []*Node, implicit *Node) {
|
|
||||||
for i := 0; i < len(l); i++ {
|
|
||||||
n := l[i]
|
|
||||||
if n.Op == OLABEL && i+1 < len(l) && n.Name.Defn == l[i+1] {
|
|
||||||
switch n.Name.Defn.Op {
|
switch n.Name.Defn.Op {
|
||||||
case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE:
|
case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE:
|
||||||
lab := new(Label)
|
lab := new(Label)
|
||||||
|
|
@ -3924,7 +3900,7 @@ func markbreakslice(l []*Node, implicit *Node) {
|
||||||
n.Left.Sym.Label = lab
|
n.Left.Sym.Label = lab
|
||||||
markbreak(n.Name.Defn, n.Name.Defn)
|
markbreak(n.Name.Defn, n.Name.Defn)
|
||||||
n.Left.Sym.Label = nil
|
n.Left.Sym.Label = nil
|
||||||
i++
|
it.Next()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3991,11 +3967,11 @@ func (n *Node) isterminating() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
def := 0
|
def := 0
|
||||||
for l := n.List; l != nil; l = l.Next {
|
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
|
||||||
if !l.N.Nbody.isterminating() {
|
if !it.N().Nbody.isterminating() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if l.N.List == nil { // default
|
if nodeSeqLen(it.N().List) == 0 { // default
|
||||||
def = 1
|
def = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4011,7 +3987,7 @@ func (n *Node) isterminating() bool {
|
||||||
|
|
||||||
func checkreturn(fn *Node) {
|
func checkreturn(fn *Node) {
|
||||||
if fn.Type.Outtuple != 0 && len(fn.Nbody.Slice()) != 0 {
|
if fn.Type.Outtuple != 0 && len(fn.Nbody.Slice()) != 0 {
|
||||||
markbreakslice(fn.Nbody.Slice(), nil)
|
markbreaklist(fn.Nbody, nil)
|
||||||
if !fn.Nbody.isterminating() {
|
if !fn.Nbody.isterminating() {
|
||||||
yyerrorl(fn.Func.Endlineno, "missing return at end of function")
|
yyerrorl(fn.Func.Endlineno, "missing return at end of function")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue