[dev.regabi] cmd/compile: add custom statement Node implementations

These are fairly rote implementations of structs appropriate to
each Op (or group of Ops).

The names of these are unknown except to ir.NodAt for now.
A later, automated change will introduce direct use of the types
throughout package gc.

Passes buildall w/ toolstash -cmp.

Change-Id: Ie9835fcd2b214fda5b2149e187af369d76534487
Reviewed-on: https://go-review.googlesource.com/c/go/+/274108
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-11-29 21:23:47 -05:00
parent 2bc814cd18
commit ffa68716a0
2 changed files with 578 additions and 35 deletions

View file

@ -1029,22 +1029,60 @@ func Nod(op Op, nleft, nright Node) Node {
func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
var n *node
switch op {
case OAS, OSELRECV:
n := NewAssignStmt(pos, nleft, nright)
n.SetOp(op)
return n
case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2:
n := NewAssignListStmt(pos, nil, nil)
n.SetOp(op)
return n
case OASOP:
return NewAssignOpStmt(pos, OXXX, nleft, nright)
case OBLOCK:
return NewBlockStmt(pos, nil)
case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP:
return NewBranchStmt(pos, op, nil)
case OCASE:
return NewCaseStmt(pos, nil, nil)
case ODCL, ODCLCONST, ODCLTYPE:
return NewDecl(pos, op, nleft)
case ODCLFUNC:
return NewFunc(pos)
case ODEFER:
return NewDeferStmt(pos, nleft)
case ODEREF:
return NewStarExpr(pos, nleft)
case OPACK:
return NewPkgName(pos, nil, nil)
case OEMPTY:
return NewEmptyStmt(pos)
case OBREAK, OCONTINUE, OFALL, OGOTO:
return NewBranchStmt(pos, op, nil)
case OFOR:
return NewForStmt(pos, nil, nleft, nright, nil)
case OGO:
return NewGoStmt(pos, nleft)
case OIF:
return NewIfStmt(pos, nleft, nil, nil)
case OINLMARK:
return NewInlineMarkStmt(pos, types.BADWIDTH)
case OLABEL:
return NewLabelStmt(pos, nil)
case OLITERAL, OTYPE, OIOTA:
n := newNameAt(pos, nil)
n.SetOp(op)
return n
case OLABEL:
return NewLabelStmt(pos, nil)
case OPACK:
return NewPkgName(pos, nil, nil)
case ORANGE:
return NewRangeStmt(pos, nil, nright, nil)
case ORETURN:
return NewReturnStmt(pos, nil)
case OSELECT:
return NewSelectStmt(pos, nil)
case OSEND:
return NewSendStmt(pos, nleft, nright)
case OSWITCH:
return NewSwitchStmt(pos, nleft, nil)
case OTYPESW:
return NewTypeSwitchGuard(pos, nleft, nright)
default:
n = new(node)
}
@ -1067,15 +1105,7 @@ var okForNod = [OEND]bool{
OANDNOT: true,
OAPPEND: true,
OARRAYLIT: true,
OAS: true,
OAS2: true,
OAS2DOTTYPE: true,
OAS2FUNC: true,
OAS2MAPR: true,
OAS2RECV: true,
OASOP: true,
OBITNOT: true,
OBLOCK: true,
OBYTES2STR: true,
OBYTES2STRTMP: true,
OCALL: true,
@ -1083,7 +1113,6 @@ var okForNod = [OEND]bool{
OCALLINTER: true,
OCALLMETH: true,
OCAP: true,
OCASE: true,
OCFUNC: true,
OCHECKNIL: true,
OCLOSE: true,
@ -1093,10 +1122,6 @@ var okForNod = [OEND]bool{
OCONVIFACE: true,
OCONVNOP: true,
OCOPY: true,
ODCL: true,
ODCLCONST: true,
ODCLTYPE: true,
ODEFER: true,
ODELETE: true,
ODIV: true,
ODOT: true,
@ -1107,22 +1132,16 @@ var okForNod = [OEND]bool{
ODOTTYPE2: true,
OEFACE: true,
OEQ: true,
OFOR: true,
OFORUNTIL: true,
OGE: true,
OGETG: true,
OGO: true,
OGT: true,
OIDATA: true,
OIF: true,
OIMAG: true,
OINDEX: true,
OINDEXMAP: true,
OINLCALL: true,
OINLMARK: true,
OITAB: true,
OKEY: true,
OLABEL: true,
OLE: true,
OLEN: true,
OLSH: true,
@ -1151,20 +1170,13 @@ var okForNod = [OEND]bool{
OPRINT: true,
OPRINTN: true,
OPTRLIT: true,
ORANGE: true,
OREAL: true,
ORECOVER: true,
ORECV: true,
ORESULT: true,
ORETJMP: true,
ORETURN: true,
ORSH: true,
ORUNES2STR: true,
ORUNESTR: true,
OSELECT: true,
OSELRECV: true,
OSELRECV2: true,
OSEND: true,
OSIZEOF: true,
OSLICE: true,
OSLICE3: true,
@ -1180,8 +1192,6 @@ var okForNod = [OEND]bool{
OSTRUCTKEY: true,
OSTRUCTLIT: true,
OSUB: true,
OSWITCH: true,
OTYPESW: true,
OVARDEF: true,
OVARKILL: true,
OVARLIVE: true,

View file

@ -10,6 +10,31 @@ import (
"fmt"
)
// A Decl is a declaration of a const, type, or var. (A declared func is a Func.)
// (This is not technically a statement but it's not worth its own file.)
type Decl struct {
miniNode
X Node // the thing being declared
}
func NewDecl(pos src.XPos, op Op, x Node) *Decl {
n := &Decl{X: x}
n.pos = pos
switch op {
default:
panic("invalid Decl op " + op.String())
case ODCL, ODCLCONST, ODCLTYPE:
n.op = op
}
return n
}
func (n *Decl) String() string { return fmt.Sprint(n) }
func (n *Decl) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *Decl) RawCopy() Node { c := *n; return &c }
func (n *Decl) Left() Node { return n.X }
func (n *Decl) SetLeft(x Node) { n.X = x }
// A miniStmt is a miniNode with extra fields common to statements.
type miniStmt struct {
miniNode
@ -22,7 +47,148 @@ func (n *miniStmt) PtrInit() *Nodes { return &n.init }
func (n *miniStmt) HasCall() bool { return n.bits&miniHasCall != 0 }
func (n *miniStmt) SetHasCall(b bool) { n.bits.set(miniHasCall, b) }
// An AssignListStmt is an assignment statement with
// more than one item on at least one side: Lhs = Rhs.
// If Def is true, the assignment is a :=.
type AssignListStmt struct {
miniStmt
Lhs Nodes
Def bool
Rhs Nodes
offset int64 // for initorder
}
func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt {
n := &AssignListStmt{}
n.pos = pos
n.op = OAS2
n.Lhs.Set(lhs)
n.Rhs.Set(rhs)
n.offset = types.BADWIDTH
return n
}
func (n *AssignListStmt) String() string { return fmt.Sprint(n) }
func (n *AssignListStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *AssignListStmt) RawCopy() Node { c := *n; return &c }
func (n *AssignListStmt) List() Nodes { return n.Lhs }
func (n *AssignListStmt) PtrList() *Nodes { return &n.Lhs }
func (n *AssignListStmt) SetList(x Nodes) { n.Lhs = x }
func (n *AssignListStmt) Rlist() Nodes { return n.Rhs }
func (n *AssignListStmt) PtrRlist() *Nodes { return &n.Rhs }
func (n *AssignListStmt) SetRlist(x Nodes) { n.Rhs = x }
func (n *AssignListStmt) Colas() bool { return n.Def }
func (n *AssignListStmt) SetColas(x bool) { n.Def = x }
func (n *AssignListStmt) Offset() int64 { return n.offset }
func (n *AssignListStmt) SetOffset(x int64) { n.offset = x }
func (n *AssignListStmt) SetOp(op Op) {
switch op {
default:
panic(n.no("SetOp " + op.String()))
case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2:
n.op = op
}
}
// An AssignStmt is a simple assignment statement: X = Y.
// If Def is true, the assignment is a :=.
type AssignStmt struct {
miniStmt
X Node
Def bool
Y Node
offset int64 // for initorder
}
func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt {
n := &AssignStmt{X: x, Y: y}
n.pos = pos
n.op = OAS
n.offset = types.BADWIDTH
return n
}
func (n *AssignStmt) String() string { return fmt.Sprint(n) }
func (n *AssignStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *AssignStmt) RawCopy() Node { c := *n; return &c }
func (n *AssignStmt) Left() Node { return n.X }
func (n *AssignStmt) SetLeft(x Node) { n.X = x }
func (n *AssignStmt) Right() Node { return n.Y }
func (n *AssignStmt) SetRight(y Node) { n.Y = y }
func (n *AssignStmt) Colas() bool { return n.Def }
func (n *AssignStmt) SetColas(x bool) { n.Def = x }
func (n *AssignStmt) Offset() int64 { return n.offset }
func (n *AssignStmt) SetOffset(x int64) { n.offset = x }
func (n *AssignStmt) SetOp(op Op) {
switch op {
default:
panic(n.no("SetOp " + op.String()))
case OAS, OSELRECV:
n.op = op
}
}
// An AssignOpStmt is an AsOp= assignment statement: X AsOp= Y.
type AssignOpStmt struct {
miniStmt
typ *types.Type
X Node
AsOp Op // OADD etc
Y Node
IncDec bool // actually ++ or --
}
func NewAssignOpStmt(pos src.XPos, op Op, x, y Node) *AssignOpStmt {
n := &AssignOpStmt{AsOp: op, X: x, Y: y}
n.pos = pos
n.op = OASOP
return n
}
func (n *AssignOpStmt) String() string { return fmt.Sprint(n) }
func (n *AssignOpStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *AssignOpStmt) RawCopy() Node { c := *n; return &c }
func (n *AssignOpStmt) Left() Node { return n.X }
func (n *AssignOpStmt) SetLeft(x Node) { n.X = x }
func (n *AssignOpStmt) Right() Node { return n.Y }
func (n *AssignOpStmt) SetRight(y Node) { n.Y = y }
func (n *AssignOpStmt) SubOp() Op { return n.AsOp }
func (n *AssignOpStmt) SetSubOp(x Op) { n.AsOp = x }
func (n *AssignOpStmt) Implicit() bool { return n.IncDec }
func (n *AssignOpStmt) SetImplicit(b bool) { n.IncDec = b }
func (n *AssignOpStmt) Type() *types.Type { return n.typ }
func (n *AssignOpStmt) SetType(x *types.Type) { n.typ = x }
// A BlockStmt is a block: { List }.
type BlockStmt struct {
miniStmt
list Nodes
}
func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt {
n := &BlockStmt{}
n.pos = pos
n.op = OBLOCK
n.list.Set(list)
return n
}
func (n *BlockStmt) String() string { return fmt.Sprint(n) }
func (n *BlockStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *BlockStmt) RawCopy() Node { c := *n; return &c }
func (n *BlockStmt) List() Nodes { return n.list }
func (n *BlockStmt) PtrList() *Nodes { return &n.list }
func (n *BlockStmt) SetList(x Nodes) { n.list = x }
// A BranchStmt is a break, continue, fallthrough, or goto statement.
//
// For back-end code generation, Op may also be RETJMP (return+jump),
// in which case the label names another function entirely.
type BranchStmt struct {
miniStmt
Label *types.Sym // label if present
@ -30,7 +196,7 @@ type BranchStmt struct {
func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt {
switch op {
case OBREAK, OCONTINUE, OFALL, OGOTO:
case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP:
// ok
default:
panic("NewBranch " + op.String())
@ -47,6 +213,59 @@ func (n *BranchStmt) RawCopy() Node { c := *n; return &c }
func (n *BranchStmt) Sym() *types.Sym { return n.Label }
func (n *BranchStmt) SetSym(sym *types.Sym) { n.Label = sym }
// A CaseStmt is a case statement in a switch or select: case List: Body.
type CaseStmt struct {
miniStmt
Vars Nodes // declared variable for this case in type switch
list Nodes // list of expressions for switch, early select
Comm Node // communication case (Exprs[0]) after select is type-checked
body Nodes
}
func NewCaseStmt(pos src.XPos, list, body []Node) *CaseStmt {
n := &CaseStmt{}
n.pos = pos
n.op = OCASE
n.list.Set(list)
n.body.Set(body)
return n
}
func (n *CaseStmt) String() string { return fmt.Sprint(n) }
func (n *CaseStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *CaseStmt) RawCopy() Node { c := *n; return &c }
func (n *CaseStmt) List() Nodes { return n.list }
func (n *CaseStmt) PtrList() *Nodes { return &n.list }
func (n *CaseStmt) SetList(x Nodes) { n.list = x }
func (n *CaseStmt) Body() Nodes { return n.body }
func (n *CaseStmt) PtrBody() *Nodes { return &n.body }
func (n *CaseStmt) SetBody(x Nodes) { n.body = x }
func (n *CaseStmt) Rlist() Nodes { return n.Vars }
func (n *CaseStmt) PtrRlist() *Nodes { return &n.Vars }
func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x }
func (n *CaseStmt) Left() Node { return n.Comm }
func (n *CaseStmt) SetLeft(x Node) { n.Comm = x }
// A DeferStmt is a defer statement: defer Call.
type DeferStmt struct {
miniStmt
Call Node
}
func NewDeferStmt(pos src.XPos, call Node) *DeferStmt {
n := &DeferStmt{Call: call}
n.pos = pos
n.op = ODEFER
return n
}
func (n *DeferStmt) String() string { return fmt.Sprint(n) }
func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *DeferStmt) RawCopy() Node { c := *n; return &c }
func (n *DeferStmt) Left() Node { return n.Call }
func (n *DeferStmt) SetLeft(x Node) { n.Call = x }
// An EmptyStmt is an empty statement
type EmptyStmt struct {
miniStmt
@ -63,6 +282,123 @@ func (n *EmptyStmt) String() string { return fmt.Sprint(n) }
func (n *EmptyStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *EmptyStmt) RawCopy() Node { c := *n; return &c }
// A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
// Op can be OFOR or OFORUNTIL (!Cond).
type ForStmt struct {
miniStmt
Label *types.Sym
Cond Node
Post Node
Late Nodes
body Nodes
hasBreak bool
}
func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt {
n := &ForStmt{Cond: cond, Post: post}
n.pos = pos
n.op = OFOR
n.init.Set(init)
n.body.Set(body)
return n
}
func (n *ForStmt) String() string { return fmt.Sprint(n) }
func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *ForStmt) RawCopy() Node { c := *n; return &c }
func (n *ForStmt) Sym() *types.Sym { return n.Label }
func (n *ForStmt) SetSym(x *types.Sym) { n.Label = x }
func (n *ForStmt) Left() Node { return n.Cond }
func (n *ForStmt) SetLeft(x Node) { n.Cond = x }
func (n *ForStmt) Right() Node { return n.Post }
func (n *ForStmt) SetRight(x Node) { n.Post = x }
func (n *ForStmt) Body() Nodes { return n.body }
func (n *ForStmt) PtrBody() *Nodes { return &n.body }
func (n *ForStmt) SetBody(x Nodes) { n.body = x }
func (n *ForStmt) List() Nodes { return n.Late }
func (n *ForStmt) PtrList() *Nodes { return &n.Late }
func (n *ForStmt) SetList(x Nodes) { n.Late = x }
func (n *ForStmt) HasBreak() bool { return n.hasBreak }
func (n *ForStmt) SetHasBreak(b bool) { n.hasBreak = b }
func (n *ForStmt) SetOp(op Op) {
if op != OFOR && op != OFORUNTIL {
panic(n.no("SetOp " + op.String()))
}
n.op = op
}
// A GoStmt is a go statement: go Call.
type GoStmt struct {
miniStmt
Call Node
}
func NewGoStmt(pos src.XPos, call Node) *GoStmt {
n := &GoStmt{Call: call}
n.pos = pos
n.op = OGO
return n
}
func (n *GoStmt) String() string { return fmt.Sprint(n) }
func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *GoStmt) RawCopy() Node { c := *n; return &c }
func (n *GoStmt) Left() Node { return n.Call }
func (n *GoStmt) SetLeft(x Node) { n.Call = x }
// A IfStmt is a return statement: if Init; Cond { Then } else { Else }.
type IfStmt struct {
miniStmt
Cond Node
body Nodes
Else Nodes
likely bool // code layout hint
}
func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt {
n := &IfStmt{Cond: cond}
n.pos = pos
n.op = OIF
n.body.Set(body)
n.Else.Set(els)
return n
}
func (n *IfStmt) String() string { return fmt.Sprint(n) }
func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *IfStmt) RawCopy() Node { c := *n; return &c }
func (n *IfStmt) Left() Node { return n.Cond }
func (n *IfStmt) SetLeft(x Node) { n.Cond = x }
func (n *IfStmt) Body() Nodes { return n.body }
func (n *IfStmt) PtrBody() *Nodes { return &n.body }
func (n *IfStmt) SetBody(x Nodes) { n.body = x }
func (n *IfStmt) Rlist() Nodes { return n.Else }
func (n *IfStmt) PtrRlist() *Nodes { return &n.Else }
func (n *IfStmt) SetRlist(x Nodes) { n.Else = x }
func (n *IfStmt) Likely() bool { return n.likely }
func (n *IfStmt) SetLikely(x bool) { n.likely = x }
// An InlineMarkStmt is a marker placed just before an inlined body.
type InlineMarkStmt struct {
miniStmt
Index int64
}
func NewInlineMarkStmt(pos src.XPos, index int64) *InlineMarkStmt {
n := &InlineMarkStmt{Index: index}
n.pos = pos
n.op = OINLMARK
return n
}
func (n *InlineMarkStmt) String() string { return fmt.Sprint(n) }
func (n *InlineMarkStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *InlineMarkStmt) RawCopy() Node { c := *n; return &c }
func (n *InlineMarkStmt) Offset() int64 { return n.Index }
func (n *InlineMarkStmt) SetOffset(x int64) { n.Index = x }
// A LabelStmt is a label statement (just the label, not including the statement it labels).
type LabelStmt struct {
miniStmt
@ -81,3 +417,200 @@ func (n *LabelStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *LabelStmt) RawCopy() Node { c := *n; return &c }
func (n *LabelStmt) Sym() *types.Sym { return n.Label }
func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x }
// A RangeStmt is a range loop: for Vars = range X { Stmts }
// Op can be OFOR or OFORUNTIL (!Cond).
type RangeStmt struct {
miniStmt
Label *types.Sym
Vars Nodes // TODO(rsc): Replace with Key, Value Node
Def bool
X Node
body Nodes
hasBreak bool
typ *types.Type // TODO(rsc): Remove - use X.Type() instead
}
func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt {
n := &RangeStmt{X: x}
n.pos = pos
n.op = ORANGE
n.Vars.Set(vars)
n.body.Set(body)
return n
}
func (n *RangeStmt) String() string { return fmt.Sprint(n) }
func (n *RangeStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *RangeStmt) RawCopy() Node { c := *n; return &c }
func (n *RangeStmt) Sym() *types.Sym { return n.Label }
func (n *RangeStmt) SetSym(x *types.Sym) { n.Label = x }
func (n *RangeStmt) Right() Node { return n.X }
func (n *RangeStmt) SetRight(x Node) { n.X = x }
func (n *RangeStmt) Body() Nodes { return n.body }
func (n *RangeStmt) PtrBody() *Nodes { return &n.body }
func (n *RangeStmt) SetBody(x Nodes) { n.body = x }
func (n *RangeStmt) List() Nodes { return n.Vars }
func (n *RangeStmt) PtrList() *Nodes { return &n.Vars }
func (n *RangeStmt) SetList(x Nodes) { n.Vars = x }
func (n *RangeStmt) HasBreak() bool { return n.hasBreak }
func (n *RangeStmt) SetHasBreak(b bool) { n.hasBreak = b }
func (n *RangeStmt) Colas() bool { return n.Def }
func (n *RangeStmt) SetColas(b bool) { n.Def = b }
func (n *RangeStmt) Type() *types.Type { return n.typ }
func (n *RangeStmt) SetType(x *types.Type) { n.typ = x }
// A ReturnStmt is a return statement.
type ReturnStmt struct {
miniStmt
orig Node // for typecheckargs rewrite
Results Nodes // return list
}
func NewReturnStmt(pos src.XPos, results []Node) *ReturnStmt {
n := &ReturnStmt{}
n.pos = pos
n.op = ORETURN
n.orig = n
n.Results.Set(results)
return n
}
func (n *ReturnStmt) String() string { return fmt.Sprint(n) }
func (n *ReturnStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *ReturnStmt) RawCopy() Node { c := *n; return &c }
func (n *ReturnStmt) Orig() Node { return n.orig }
func (n *ReturnStmt) SetOrig(x Node) { n.orig = x }
func (n *ReturnStmt) List() Nodes { return n.Results }
func (n *ReturnStmt) PtrList() *Nodes { return &n.Results }
func (n *ReturnStmt) SetList(x Nodes) { n.Results = x }
func (n *ReturnStmt) IsDDD() bool { return false } // typecheckargs asks
// A SelectStmt is a block: { Cases }.
type SelectStmt struct {
miniStmt
Label *types.Sym
Cases Nodes
hasBreak bool
// TODO(rsc): Instead of recording here, replace with a block?
Compiled Nodes // compiled form, after walkswitch
}
func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt {
n := &SelectStmt{}
n.pos = pos
n.op = OSELECT
n.Cases.Set(cases)
return n
}
func (n *SelectStmt) String() string { return fmt.Sprint(n) }
func (n *SelectStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SelectStmt) RawCopy() Node { c := *n; return &c }
func (n *SelectStmt) List() Nodes { return n.Cases }
func (n *SelectStmt) PtrList() *Nodes { return &n.Cases }
func (n *SelectStmt) SetList(x Nodes) { n.Cases = x }
func (n *SelectStmt) Sym() *types.Sym { return n.Label }
func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x }
func (n *SelectStmt) HasBreak() bool { return n.hasBreak }
func (n *SelectStmt) SetHasBreak(x bool) { n.hasBreak = x }
func (n *SelectStmt) Body() Nodes { return n.Compiled }
func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled }
func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x }
// A SendStmt is a send statement: X <- Y.
type SendStmt struct {
miniStmt
Chan Node
Value Node
}
func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt {
n := &SendStmt{Chan: ch, Value: value}
n.pos = pos
n.op = OSEND
return n
}
func (n *SendStmt) String() string { return fmt.Sprint(n) }
func (n *SendStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SendStmt) RawCopy() Node { c := *n; return &c }
func (n *SendStmt) Left() Node { return n.Chan }
func (n *SendStmt) SetLeft(x Node) { n.Chan = x }
func (n *SendStmt) Right() Node { return n.Value }
func (n *SendStmt) SetRight(y Node) { n.Value = y }
// A SwitchStmt is a switch statement: switch Init; Expr { Cases }.
type SwitchStmt struct {
miniStmt
Tag Node
Cases Nodes // list of *CaseStmt
Label *types.Sym
hasBreak bool
// TODO(rsc): Instead of recording here, replace with a block?
Compiled Nodes // compiled form, after walkswitch
}
func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt {
n := &SwitchStmt{Tag: tag}
n.pos = pos
n.op = OSWITCH
n.Cases.Set(cases)
return n
}
func (n *SwitchStmt) String() string { return fmt.Sprint(n) }
func (n *SwitchStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *SwitchStmt) RawCopy() Node { c := *n; return &c }
func (n *SwitchStmt) Left() Node { return n.Tag }
func (n *SwitchStmt) SetLeft(x Node) { n.Tag = x }
func (n *SwitchStmt) List() Nodes { return n.Cases }
func (n *SwitchStmt) PtrList() *Nodes { return &n.Cases }
func (n *SwitchStmt) SetList(x Nodes) { n.Cases = x }
func (n *SwitchStmt) Body() Nodes { return n.Compiled }
func (n *SwitchStmt) PtrBody() *Nodes { return &n.Compiled }
func (n *SwitchStmt) SetBody(x Nodes) { n.Compiled = x }
func (n *SwitchStmt) Sym() *types.Sym { return n.Label }
func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x }
func (n *SwitchStmt) HasBreak() bool { return n.hasBreak }
func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x }
// A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
type TypeSwitchGuard struct {
miniNode
name *Name
X Node
}
func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard {
n := &TypeSwitchGuard{X: x}
if name != nil {
n.name = name.(*Name)
}
n.pos = pos
n.op = OTYPESW
return n
}
func (n *TypeSwitchGuard) String() string { return fmt.Sprint(n) }
func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *TypeSwitchGuard) RawCopy() Node { c := *n; return &c }
func (n *TypeSwitchGuard) Left() Node {
if n.name == nil {
return nil
}
return n.name
}
func (n *TypeSwitchGuard) SetLeft(x Node) {
if x == nil {
n.name = nil
return
}
n.name = x.(*Name)
}
func (n *TypeSwitchGuard) Right() Node { return n.X }
func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x }