2020-11-28 01:41:13 -05:00
|
|
|
// Copyright 2020 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package ir
|
|
|
|
|
|
|
|
import (
|
2020-11-29 21:25:47 -05:00
|
|
|
"cmd/compile/internal/base"
|
2020-11-28 01:41:13 -05:00
|
|
|
"cmd/compile/internal/types"
|
2020-11-26 00:47:44 -05:00
|
|
|
"cmd/internal/src"
|
|
|
|
"fmt"
|
2020-12-02 19:26:56 -08:00
|
|
|
"go/constant"
|
2020-11-28 01:41:13 -05:00
|
|
|
)
|
|
|
|
|
2020-12-03 21:02:19 -05:00
|
|
|
func maybeDo(x Node, err error, do func(Node) error) error {
|
|
|
|
if x != nil && err == nil {
|
|
|
|
err = do(x)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func maybeDoList(x Nodes, err error, do func(Node) error) error {
|
|
|
|
if err == nil {
|
|
|
|
err = DoList(x, do)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-12-03 21:29:23 -05:00
|
|
|
func maybeEdit(x Node, edit func(Node) Node) Node {
|
|
|
|
if x == nil {
|
|
|
|
return x
|
|
|
|
}
|
|
|
|
return edit(x)
|
|
|
|
}
|
|
|
|
|
2020-11-28 01:41:13 -05:00
|
|
|
// A miniStmt is a miniNode with extra fields common to expressions.
|
|
|
|
// TODO(rsc): Once we are sure about the contents, compact the bools
|
|
|
|
// into a bit field and leave extra bits available for implementations
|
|
|
|
// embedding miniExpr. Right now there are ~60 unused bits sitting here.
|
|
|
|
type miniExpr struct {
|
|
|
|
miniNode
|
|
|
|
typ *types.Type
|
|
|
|
init Nodes // TODO(rsc): Don't require every Node to have an init
|
|
|
|
opt interface{} // TODO(rsc): Don't require every Node to have an opt?
|
|
|
|
flags bitset8
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
miniExprHasCall = 1 << iota
|
|
|
|
miniExprImplicit
|
|
|
|
miniExprNonNil
|
|
|
|
miniExprTransient
|
|
|
|
miniExprBounded
|
|
|
|
)
|
|
|
|
|
|
|
|
func (n *miniExpr) Type() *types.Type { return n.typ }
|
|
|
|
func (n *miniExpr) SetType(x *types.Type) { n.typ = x }
|
|
|
|
func (n *miniExpr) Opt() interface{} { return n.opt }
|
|
|
|
func (n *miniExpr) SetOpt(x interface{}) { n.opt = x }
|
|
|
|
func (n *miniExpr) HasCall() bool { return n.flags&miniExprHasCall != 0 }
|
|
|
|
func (n *miniExpr) SetHasCall(b bool) { n.flags.set(miniExprHasCall, b) }
|
|
|
|
func (n *miniExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 }
|
|
|
|
func (n *miniExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) }
|
|
|
|
func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 }
|
|
|
|
func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil }
|
|
|
|
func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 }
|
|
|
|
func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) }
|
|
|
|
func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 }
|
|
|
|
func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) }
|
|
|
|
func (n *miniExpr) Init() Nodes { return n.init }
|
|
|
|
func (n *miniExpr) PtrInit() *Nodes { return &n.init }
|
|
|
|
func (n *miniExpr) SetInit(x Nodes) { n.init = x }
|
2020-11-26 00:47:44 -05:00
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
func toNtype(x Node) Ntype {
|
|
|
|
if x == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if _, ok := x.(Ntype); !ok {
|
|
|
|
Dump("not Ntype", x)
|
|
|
|
}
|
|
|
|
return x.(Ntype)
|
|
|
|
}
|
|
|
|
|
|
|
|
// An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1].
|
|
|
|
type AddStringExpr struct {
|
|
|
|
miniExpr
|
|
|
|
list Nodes
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr {
|
|
|
|
n := &AddStringExpr{}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OADDSTR
|
|
|
|
n.list.Set(list)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *AddStringExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *AddStringExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *AddStringExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
c.list = c.list.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *AddStringExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDoList(n.list, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *AddStringExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
editList(n.list, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *AddStringExpr) List() Nodes { return n.list }
|
|
|
|
func (n *AddStringExpr) PtrList() *Nodes { return &n.list }
|
|
|
|
func (n *AddStringExpr) SetList(x Nodes) { n.list = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
// An AddrExpr is an address-of expression &X.
|
|
|
|
// It may end up being a normal address-of or an allocation of a composite literal.
|
|
|
|
type AddrExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
Alloc Node // preallocated storage if any
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewAddrExpr(pos src.XPos, x Node) *AddrExpr {
|
|
|
|
n := &AddrExpr{X: x}
|
|
|
|
n.op = OADDR
|
|
|
|
n.pos = pos
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *AddrExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *AddrExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *AddrExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *AddrExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *AddrExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *AddrExpr) Left() Node { return n.X }
|
|
|
|
func (n *AddrExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *AddrExpr) Right() Node { return n.Alloc }
|
|
|
|
func (n *AddrExpr) SetRight(x Node) { n.Alloc = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *AddrExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OADDR, OPTRLIT:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A BinaryExpr is a binary expression X Op Y,
|
|
|
|
// or Op(X, Y) for builtin functions that do not become calls.
|
|
|
|
type BinaryExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
Y Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr {
|
|
|
|
n := &BinaryExpr{X: x, Y: y}
|
|
|
|
n.pos = pos
|
|
|
|
n.SetOp(op)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *BinaryExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *BinaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *BinaryExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *BinaryExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
err = maybeDo(n.Y, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *BinaryExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
n.Y = maybeEdit(n.Y, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *BinaryExpr) Left() Node { return n.X }
|
|
|
|
func (n *BinaryExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *BinaryExpr) Right() Node { return n.Y }
|
|
|
|
func (n *BinaryExpr) SetRight(y Node) { n.Y = y }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *BinaryExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OADD, OADDSTR, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
|
|
|
|
OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR,
|
|
|
|
OCOPY, OCOMPLEX,
|
|
|
|
OEFACE:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:06:41 -05:00
|
|
|
// A CallUse records how the result of the call is used:
|
|
|
|
type CallUse int
|
|
|
|
|
|
|
|
const (
|
|
|
|
_ CallUse = iota
|
|
|
|
|
|
|
|
CallUseExpr // single expression result is used
|
|
|
|
CallUseList // list of results are used
|
|
|
|
CallUseStmt // results not used - call is a statement
|
|
|
|
)
|
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
// A CallExpr is a function call X(Args).
|
|
|
|
type CallExpr struct {
|
|
|
|
miniExpr
|
|
|
|
orig Node
|
|
|
|
X Node
|
|
|
|
Args Nodes
|
|
|
|
Rargs Nodes // TODO(rsc): Delete.
|
|
|
|
body Nodes // TODO(rsc): Delete.
|
|
|
|
DDD bool
|
2020-12-03 14:06:41 -05:00
|
|
|
Use CallUse
|
2020-11-29 21:25:47 -05:00
|
|
|
noInline bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr {
|
|
|
|
n := &CallExpr{X: fun}
|
|
|
|
n.pos = pos
|
|
|
|
n.orig = n
|
|
|
|
n.op = OCALL
|
|
|
|
n.Args.Set(args)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *CallExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *CallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *CallExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
c.Args = c.Args.Copy()
|
|
|
|
c.Rargs = c.Rargs.Copy()
|
|
|
|
c.body = c.body.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *CallExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
err = maybeDoList(n.Args, err, do)
|
|
|
|
err = maybeDoList(n.Rargs, err, do)
|
|
|
|
err = maybeDoList(n.body, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *CallExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
editList(n.Args, edit)
|
|
|
|
editList(n.Rargs, edit)
|
|
|
|
editList(n.body, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *CallExpr) Orig() Node { return n.orig }
|
|
|
|
func (n *CallExpr) SetOrig(x Node) { n.orig = x }
|
|
|
|
func (n *CallExpr) Left() Node { return n.X }
|
|
|
|
func (n *CallExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *CallExpr) List() Nodes { return n.Args }
|
|
|
|
func (n *CallExpr) PtrList() *Nodes { return &n.Args }
|
|
|
|
func (n *CallExpr) SetList(x Nodes) { n.Args = x }
|
|
|
|
func (n *CallExpr) Rlist() Nodes { return n.Rargs }
|
|
|
|
func (n *CallExpr) PtrRlist() *Nodes { return &n.Rargs }
|
|
|
|
func (n *CallExpr) SetRlist(x Nodes) { n.Rargs = x }
|
|
|
|
func (n *CallExpr) IsDDD() bool { return n.DDD }
|
|
|
|
func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x }
|
|
|
|
func (n *CallExpr) NoInline() bool { return n.noInline }
|
|
|
|
func (n *CallExpr) SetNoInline(x bool) { n.noInline = x }
|
|
|
|
func (n *CallExpr) Body() Nodes { return n.body }
|
|
|
|
func (n *CallExpr) PtrBody() *Nodes { return &n.body }
|
|
|
|
func (n *CallExpr) SetBody(x Nodes) { n.body = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *CallExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
|
|
|
|
OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A CallPartExpr is a method expression X.Method (uncalled).
|
|
|
|
type CallPartExpr struct {
|
|
|
|
miniExpr
|
|
|
|
fn *Func
|
|
|
|
X Node
|
2020-12-02 21:38:20 -08:00
|
|
|
Method *types.Field
|
2020-11-29 21:25:47 -05:00
|
|
|
}
|
|
|
|
|
2020-12-02 21:38:20 -08:00
|
|
|
func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr {
|
2020-11-29 21:25:47 -05:00
|
|
|
n := &CallPartExpr{fn: fn, X: x, Method: method}
|
|
|
|
n.op = OCALLPART
|
|
|
|
n.pos = pos
|
|
|
|
n.typ = fn.Type()
|
|
|
|
n.fn = fn
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *CallPartExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *CallPartExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *CallPartExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *CallPartExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *CallPartExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *CallPartExpr) Func() *Func { return n.fn }
|
|
|
|
func (n *CallPartExpr) Left() Node { return n.X }
|
|
|
|
func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym }
|
|
|
|
func (n *CallPartExpr) SetLeft(x Node) { n.X = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
2020-11-26 00:47:44 -05:00
|
|
|
// A ClosureExpr is a function literal expression.
|
|
|
|
type ClosureExpr struct {
|
|
|
|
miniExpr
|
|
|
|
fn *Func
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
|
|
|
|
n := &ClosureExpr{fn: fn}
|
|
|
|
n.op = OCLOSURE
|
|
|
|
n.pos = pos
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *ClosureExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *ClosureExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *ClosureExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *ClosureExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *ClosureExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *ClosureExpr) Func() *Func { return n.fn }
|
2020-11-26 00:47:44 -05:00
|
|
|
|
|
|
|
// A ClosureRead denotes reading a variable stored within a closure struct.
|
|
|
|
type ClosureRead struct {
|
|
|
|
miniExpr
|
|
|
|
offset int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewClosureRead(typ *types.Type, offset int64) *ClosureRead {
|
|
|
|
n := &ClosureRead{offset: offset}
|
|
|
|
n.typ = typ
|
|
|
|
n.op = OCLOSUREREAD
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *ClosureRead) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *ClosureRead) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *ClosureRead) Type() *types.Type { return n.typ }
|
|
|
|
func (n *ClosureRead) Offset() int64 { return n.offset }
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *ClosureRead) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *ClosureRead) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
}
|
2020-11-26 01:05:39 -05:00
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
// A CompLitExpr is a composite literal Type{Vals}.
|
|
|
|
// Before type-checking, the type is Ntype.
|
|
|
|
type CompLitExpr struct {
|
|
|
|
miniExpr
|
|
|
|
orig Node
|
|
|
|
Ntype Ntype
|
|
|
|
list Nodes // initialized values
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr {
|
|
|
|
n := &CompLitExpr{Ntype: typ}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OCOMPLIT
|
|
|
|
n.list.Set(list)
|
|
|
|
n.orig = n
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *CompLitExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *CompLitExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *CompLitExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
c.list = c.list.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *CompLitExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.Ntype, err, do)
|
|
|
|
err = maybeDoList(n.list, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *CompLitExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.Ntype = toNtype(maybeEdit(n.Ntype, edit))
|
|
|
|
editList(n.list, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *CompLitExpr) Orig() Node { return n.orig }
|
|
|
|
func (n *CompLitExpr) SetOrig(x Node) { n.orig = x }
|
|
|
|
func (n *CompLitExpr) Right() Node { return n.Ntype }
|
|
|
|
func (n *CompLitExpr) SetRight(x Node) { n.Ntype = toNtype(x) }
|
|
|
|
func (n *CompLitExpr) List() Nodes { return n.list }
|
|
|
|
func (n *CompLitExpr) PtrList() *Nodes { return &n.list }
|
|
|
|
func (n *CompLitExpr) SetList(x Nodes) { n.list = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *CompLitExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-02 19:26:56 -08:00
|
|
|
type ConstExpr struct {
|
|
|
|
miniExpr
|
|
|
|
val constant.Value
|
|
|
|
orig Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewConstExpr(val constant.Value, orig Node) Node {
|
|
|
|
n := &ConstExpr{orig: orig, val: val}
|
|
|
|
n.op = OLITERAL
|
|
|
|
n.pos = orig.Pos()
|
|
|
|
n.SetType(orig.Type())
|
|
|
|
n.SetTypecheck(orig.Typecheck())
|
|
|
|
n.SetDiag(orig.Diag())
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *ConstExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *ConstExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
|
|
|
func (n *ConstExpr) copy() Node { c := *n; return &c }
|
|
|
|
func (n *ConstExpr) doChildren(do func(Node) error) error { return nil }
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *ConstExpr) editChildren(edit func(Node) Node) {}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() }
|
|
|
|
func (n *ConstExpr) Orig() Node { return n.orig }
|
|
|
|
func (n *ConstExpr) SetOrig(orig Node) { panic(n.no("SetOrig")) }
|
|
|
|
func (n *ConstExpr) Val() constant.Value { return n.val }
|
2020-12-02 19:26:56 -08:00
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
// A ConvExpr is a conversion Type(X).
|
|
|
|
// It may end up being a value or a type.
|
|
|
|
type ConvExpr struct {
|
|
|
|
miniExpr
|
|
|
|
orig Node
|
|
|
|
X Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr {
|
|
|
|
n := &ConvExpr{X: x}
|
|
|
|
n.pos = pos
|
|
|
|
n.typ = typ
|
|
|
|
n.SetOp(op)
|
|
|
|
n.orig = n
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *ConvExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *ConvExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *ConvExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *ConvExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *ConvExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *ConvExpr) rawCopy() Node { c := *n; return &c }
|
|
|
|
func (n *ConvExpr) Left() Node { return n.X }
|
|
|
|
func (n *ConvExpr) SetLeft(x Node) { n.X = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *ConvExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// An IndexExpr is an index expression X[Y].
|
|
|
|
type IndexExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
Index Node
|
|
|
|
Assigned bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr {
|
|
|
|
n := &IndexExpr{X: x, Index: index}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OINDEX
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *IndexExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *IndexExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *IndexExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *IndexExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
err = maybeDo(n.Index, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *IndexExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
n.Index = maybeEdit(n.Index, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *IndexExpr) Left() Node { return n.X }
|
|
|
|
func (n *IndexExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *IndexExpr) Right() Node { return n.Index }
|
|
|
|
func (n *IndexExpr) SetRight(y Node) { n.Index = y }
|
|
|
|
func (n *IndexExpr) IndexMapLValue() bool { return n.Assigned }
|
|
|
|
func (n *IndexExpr) SetIndexMapLValue(x bool) { n.Assigned = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *IndexExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OINDEX, OINDEXMAP:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A KeyExpr is an X:Y composite literal key.
|
|
|
|
// After type-checking, a key for a struct sets Sym to the field.
|
|
|
|
type KeyExpr struct {
|
|
|
|
miniExpr
|
|
|
|
Key Node
|
|
|
|
sym *types.Sym
|
|
|
|
Value Node
|
|
|
|
offset int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
|
|
|
|
n := &KeyExpr{Key: key, Value: value}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OKEY
|
|
|
|
n.offset = types.BADWIDTH
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *KeyExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *KeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *KeyExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *KeyExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.Key, err, do)
|
|
|
|
err = maybeDo(n.Value, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *KeyExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.Key = maybeEdit(n.Key, edit)
|
|
|
|
n.Value = maybeEdit(n.Value, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *KeyExpr) Left() Node { return n.Key }
|
|
|
|
func (n *KeyExpr) SetLeft(x Node) { n.Key = x }
|
|
|
|
func (n *KeyExpr) Right() Node { return n.Value }
|
|
|
|
func (n *KeyExpr) SetRight(y Node) { n.Value = y }
|
|
|
|
func (n *KeyExpr) Sym() *types.Sym { return n.sym }
|
|
|
|
func (n *KeyExpr) SetSym(x *types.Sym) { n.sym = x }
|
|
|
|
func (n *KeyExpr) Offset() int64 { return n.offset }
|
|
|
|
func (n *KeyExpr) SetOffset(x int64) { n.offset = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *KeyExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OKEY, OSTRUCTKEY:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// An InlinedCallExpr is an inlined function call.
|
|
|
|
type InlinedCallExpr struct {
|
|
|
|
miniExpr
|
|
|
|
body Nodes
|
|
|
|
ReturnVars Nodes
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr {
|
|
|
|
n := &InlinedCallExpr{}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OINLCALL
|
|
|
|
n.body.Set(body)
|
|
|
|
n.ReturnVars.Set(retvars)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *InlinedCallExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *InlinedCallExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *InlinedCallExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
c.body = c.body.Copy()
|
|
|
|
c.ReturnVars = c.ReturnVars.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *InlinedCallExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDoList(n.body, err, do)
|
|
|
|
err = maybeDoList(n.ReturnVars, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *InlinedCallExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
editList(n.body, edit)
|
|
|
|
editList(n.ReturnVars, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *InlinedCallExpr) Body() Nodes { return n.body }
|
|
|
|
func (n *InlinedCallExpr) PtrBody() *Nodes { return &n.body }
|
|
|
|
func (n *InlinedCallExpr) SetBody(x Nodes) { n.body = x }
|
|
|
|
func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars }
|
|
|
|
func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars }
|
|
|
|
func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
// A MakeExpr is a make expression: make(Type[, Len[, Cap]]).
|
|
|
|
// Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY,
|
|
|
|
// but *not* OMAKE (that's a pre-typechecking CallExpr).
|
|
|
|
type MakeExpr struct {
|
|
|
|
miniExpr
|
|
|
|
Len Node
|
|
|
|
Cap Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr {
|
|
|
|
n := &MakeExpr{Len: len, Cap: cap}
|
|
|
|
n.pos = pos
|
|
|
|
n.SetOp(op)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *MakeExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *MakeExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *MakeExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.Len, err, do)
|
|
|
|
err = maybeDo(n.Cap, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *MakeExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.Len = maybeEdit(n.Len, edit)
|
|
|
|
n.Cap = maybeEdit(n.Cap, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *MakeExpr) Left() Node { return n.Len }
|
|
|
|
func (n *MakeExpr) SetLeft(x Node) { n.Len = x }
|
|
|
|
func (n *MakeExpr) Right() Node { return n.Cap }
|
|
|
|
func (n *MakeExpr) SetRight(x Node) { n.Cap = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *MakeExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 21:02:19 -05:00
|
|
|
// A MethodExpr is a method value X.M (where X is an expression, not a type).
|
2020-11-29 21:25:47 -05:00
|
|
|
type MethodExpr struct {
|
2020-11-26 01:05:39 -05:00
|
|
|
miniExpr
|
|
|
|
X Node
|
2020-11-29 21:25:47 -05:00
|
|
|
M Node
|
|
|
|
sym *types.Sym
|
|
|
|
offset int64
|
|
|
|
class Class
|
2020-12-02 21:38:20 -08:00
|
|
|
Method *types.Field
|
2020-11-26 01:05:39 -05:00
|
|
|
}
|
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr {
|
|
|
|
n := &MethodExpr{X: x, M: m}
|
2020-11-26 01:05:39 -05:00
|
|
|
n.pos = pos
|
2020-11-29 21:25:47 -05:00
|
|
|
n.op = OMETHEXPR
|
|
|
|
n.offset = types.BADWIDTH
|
2020-11-26 01:05:39 -05:00
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
func (n *MethodExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *MethodExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *MethodExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *MethodExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
err = maybeDo(n.M, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *MethodExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
n.M = maybeEdit(n.M, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *MethodExpr) Left() Node { return n.X }
|
|
|
|
func (n *MethodExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *MethodExpr) Right() Node { return n.M }
|
|
|
|
func (n *MethodExpr) SetRight(y Node) { n.M = y }
|
|
|
|
func (n *MethodExpr) Sym() *types.Sym { return n.sym }
|
|
|
|
func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x }
|
|
|
|
func (n *MethodExpr) Offset() int64 { return n.offset }
|
|
|
|
func (n *MethodExpr) SetOffset(x int64) { n.offset = x }
|
|
|
|
func (n *MethodExpr) Class() Class { return n.class }
|
|
|
|
func (n *MethodExpr) SetClass(x Class) { n.class = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
// A NilExpr represents the predefined untyped constant nil.
|
|
|
|
// (It may be copied and assigned a type, though.)
|
|
|
|
type NilExpr struct {
|
|
|
|
miniExpr
|
|
|
|
sym *types.Sym // TODO: Remove
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewNilExpr(pos src.XPos) *NilExpr {
|
|
|
|
n := &NilExpr{}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = ONIL
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *NilExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *NilExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *NilExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *NilExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *NilExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *NilExpr) Sym() *types.Sym { return n.sym }
|
|
|
|
func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
// A ParenExpr is a parenthesized expression (X).
|
|
|
|
// It may end up being a value or a type.
|
|
|
|
type ParenExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewParenExpr(pos src.XPos, x Node) *ParenExpr {
|
|
|
|
n := &ParenExpr{X: x}
|
|
|
|
n.op = OPAREN
|
|
|
|
n.pos = pos
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *ParenExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *ParenExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *ParenExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *ParenExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *ParenExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *ParenExpr) Left() Node { return n.X }
|
|
|
|
func (n *ParenExpr) SetLeft(x Node) { n.X = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (*ParenExpr) CanBeNtype() {}
|
|
|
|
|
|
|
|
// SetOTYPE changes n to be an OTYPE node returning t,
|
|
|
|
// like all the type nodes in type.go.
|
|
|
|
func (n *ParenExpr) SetOTYPE(t *types.Type) {
|
|
|
|
n.op = OTYPE
|
|
|
|
n.typ = t
|
2020-12-01 01:42:47 -08:00
|
|
|
t.SetNod(n)
|
2020-11-29 21:25:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// A ResultExpr represents a direct access to a result slot on the stack frame.
|
|
|
|
type ResultExpr struct {
|
|
|
|
miniExpr
|
|
|
|
offset int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr {
|
|
|
|
n := &ResultExpr{offset: offset}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = ORESULT
|
|
|
|
n.typ = typ
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *ResultExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *ResultExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *ResultExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *ResultExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *ResultExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *ResultExpr) Offset() int64 { return n.offset }
|
|
|
|
func (n *ResultExpr) SetOffset(x int64) { n.offset = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
// A SelectorExpr is a selector expression X.Sym.
|
|
|
|
type SelectorExpr struct {
|
|
|
|
miniExpr
|
2020-12-02 21:38:20 -08:00
|
|
|
X Node
|
|
|
|
Sel *types.Sym
|
|
|
|
offset int64
|
|
|
|
Selection *types.Field
|
2020-11-29 21:25:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr {
|
|
|
|
n := &SelectorExpr{X: x, Sel: sel}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OXDOT
|
|
|
|
n.offset = types.BADWIDTH
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *SelectorExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *SelectorExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *SelectorExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *SelectorExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *SelectorExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *SelectorExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *SelectorExpr) Left() Node { return n.X }
|
|
|
|
func (n *SelectorExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *SelectorExpr) Sym() *types.Sym { return n.Sel }
|
|
|
|
func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x }
|
|
|
|
func (n *SelectorExpr) Offset() int64 { return n.offset }
|
|
|
|
func (n *SelectorExpr) SetOffset(x int64) { n.offset = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
// Before type-checking, bytes.Buffer is a SelectorExpr.
|
|
|
|
// After type-checking it becomes a Name.
|
|
|
|
func (*SelectorExpr) CanBeNtype() {}
|
|
|
|
|
|
|
|
// A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
|
|
|
|
type SliceExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
list Nodes // TODO(rsc): Use separate Nodes
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSliceExpr(pos src.XPos, op Op, x Node) *SliceExpr {
|
|
|
|
n := &SliceExpr{X: x}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = op
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *SliceExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *SliceExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *SliceExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
c.list = c.list.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *SliceExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
err = maybeDoList(n.list, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *SliceExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
editList(n.list, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *SliceExpr) Left() Node { return n.X }
|
|
|
|
func (n *SliceExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *SliceExpr) List() Nodes { return n.list }
|
|
|
|
func (n *SliceExpr) PtrList() *Nodes { return &n.list }
|
|
|
|
func (n *SliceExpr) SetList(x Nodes) { n.list = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *SliceExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max].
|
|
|
|
// n must be a slice expression. max is nil if n is a simple slice expression.
|
|
|
|
func (n *SliceExpr) SliceBounds() (low, high, max Node) {
|
|
|
|
if n.list.Len() == 0 {
|
|
|
|
return nil, nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
switch n.Op() {
|
|
|
|
case OSLICE, OSLICEARR, OSLICESTR:
|
|
|
|
s := n.list.Slice()
|
|
|
|
return s[0], s[1], nil
|
|
|
|
case OSLICE3, OSLICE3ARR:
|
|
|
|
s := n.list.Slice()
|
|
|
|
return s[0], s[1], s[2]
|
|
|
|
}
|
|
|
|
base.Fatalf("SliceBounds op %v: %v", n.Op(), n)
|
|
|
|
return nil, nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetSliceBounds sets n's slice bounds, where n is a slice expression.
|
|
|
|
// n must be a slice expression. If max is non-nil, n must be a full slice expression.
|
|
|
|
func (n *SliceExpr) SetSliceBounds(low, high, max Node) {
|
|
|
|
switch n.Op() {
|
|
|
|
case OSLICE, OSLICEARR, OSLICESTR:
|
|
|
|
if max != nil {
|
|
|
|
base.Fatalf("SetSliceBounds %v given three bounds", n.Op())
|
|
|
|
}
|
|
|
|
s := n.list.Slice()
|
|
|
|
if s == nil {
|
|
|
|
if low == nil && high == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
n.list.Set2(low, high)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
s[0] = low
|
|
|
|
s[1] = high
|
|
|
|
return
|
|
|
|
case OSLICE3, OSLICE3ARR:
|
|
|
|
s := n.list.Slice()
|
|
|
|
if s == nil {
|
|
|
|
if low == nil && high == nil && max == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
n.list.Set3(low, high, max)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
s[0] = low
|
|
|
|
s[1] = high
|
|
|
|
s[2] = max
|
|
|
|
return
|
|
|
|
}
|
|
|
|
base.Fatalf("SetSliceBounds op %v: %v", n.Op(), n)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR).
|
|
|
|
// o must be a slicing op.
|
|
|
|
func (o Op) IsSlice3() bool {
|
|
|
|
switch o {
|
|
|
|
case OSLICE, OSLICEARR, OSLICESTR:
|
|
|
|
return false
|
|
|
|
case OSLICE3, OSLICE3ARR:
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
base.Fatalf("IsSlice3 op %v", o)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// A SliceHeader expression constructs a slice header from its parts.
|
|
|
|
type SliceHeaderExpr struct {
|
|
|
|
miniExpr
|
|
|
|
Ptr Node
|
|
|
|
lenCap Nodes // TODO(rsc): Split into two Node fields
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr {
|
|
|
|
n := &SliceHeaderExpr{Ptr: ptr}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = OSLICEHEADER
|
|
|
|
n.typ = typ
|
|
|
|
n.lenCap.Set2(len, cap)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *SliceHeaderExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *SliceHeaderExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *SliceHeaderExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *SliceHeaderExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.Ptr, err, do)
|
|
|
|
err = maybeDoList(n.lenCap, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *SliceHeaderExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.Ptr = maybeEdit(n.Ptr, edit)
|
|
|
|
editList(n.lenCap, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *SliceHeaderExpr) Left() Node { return n.Ptr }
|
|
|
|
func (n *SliceHeaderExpr) SetLeft(x Node) { n.Ptr = x }
|
|
|
|
func (n *SliceHeaderExpr) List() Nodes { return n.lenCap }
|
|
|
|
func (n *SliceHeaderExpr) PtrList() *Nodes { return &n.lenCap }
|
|
|
|
func (n *SliceHeaderExpr) SetList(x Nodes) { n.lenCap = x }
|
2020-11-26 07:02:13 -05:00
|
|
|
|
|
|
|
// A StarExpr is a dereference expression *X.
|
|
|
|
// It may end up being a value or a type.
|
|
|
|
type StarExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewStarExpr(pos src.XPos, x Node) *StarExpr {
|
|
|
|
n := &StarExpr{X: x}
|
|
|
|
n.op = ODEREF
|
|
|
|
n.pos = pos
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *StarExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *StarExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *StarExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *StarExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *StarExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *StarExpr) Left() Node { return n.X }
|
|
|
|
func (n *StarExpr) SetLeft(x Node) { n.X = x }
|
2020-11-26 07:02:13 -05:00
|
|
|
|
|
|
|
func (*StarExpr) CanBeNtype() {}
|
|
|
|
|
|
|
|
// SetOTYPE changes n to be an OTYPE node returning t,
|
|
|
|
// like all the type nodes in type.go.
|
|
|
|
func (n *StarExpr) SetOTYPE(t *types.Type) {
|
|
|
|
n.op = OTYPE
|
|
|
|
n.X = nil
|
|
|
|
n.typ = t
|
2020-12-01 01:42:47 -08:00
|
|
|
t.SetNod(n)
|
2020-11-26 07:02:13 -05:00
|
|
|
}
|
|
|
|
|
2020-11-29 21:25:47 -05:00
|
|
|
// A TypeAssertionExpr is a selector expression X.(Type).
|
|
|
|
// Before type-checking, the type is Ntype.
|
|
|
|
type TypeAssertExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
Ntype Node // TODO: Should be Ntype, but reused as address of type structure
|
|
|
|
Itab Nodes // Itab[0] is itab
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
|
|
|
|
n := &TypeAssertExpr{X: x, Ntype: typ}
|
|
|
|
n.pos = pos
|
|
|
|
n.op = ODOTTYPE
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *TypeAssertExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *TypeAssertExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *TypeAssertExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
c.Itab = c.Itab.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *TypeAssertExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
err = maybeDo(n.Ntype, err, do)
|
|
|
|
err = maybeDoList(n.Itab, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *TypeAssertExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
n.Ntype = maybeEdit(n.Ntype, edit)
|
|
|
|
editList(n.Itab, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *TypeAssertExpr) Left() Node { return n.X }
|
|
|
|
func (n *TypeAssertExpr) SetLeft(x Node) { n.X = x }
|
|
|
|
func (n *TypeAssertExpr) Right() Node { return n.Ntype }
|
|
|
|
func (n *TypeAssertExpr) SetRight(x Node) { n.Ntype = x } // TODO: toNtype(x)
|
|
|
|
func (n *TypeAssertExpr) List() Nodes { return n.Itab }
|
|
|
|
func (n *TypeAssertExpr) PtrList() *Nodes { return &n.Itab }
|
|
|
|
func (n *TypeAssertExpr) SetList(x Nodes) { n.Itab = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *TypeAssertExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case ODOTTYPE, ODOTTYPE2:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A UnaryExpr is a unary expression Op X,
|
|
|
|
// or Op(X) for a builtin function that does not end up being a call.
|
|
|
|
type UnaryExpr struct {
|
|
|
|
miniExpr
|
|
|
|
X Node
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr {
|
|
|
|
n := &UnaryExpr{X: x}
|
|
|
|
n.pos = pos
|
|
|
|
n.SetOp(op)
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *UnaryExpr) String() string { return fmt.Sprint(n) }
|
|
|
|
func (n *UnaryExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
|
2020-12-03 18:43:18 -05:00
|
|
|
func (n *UnaryExpr) copy() Node {
|
|
|
|
c := *n
|
|
|
|
c.init = c.init.Copy()
|
|
|
|
return &c
|
|
|
|
}
|
2020-12-03 21:02:19 -05:00
|
|
|
func (n *UnaryExpr) doChildren(do func(Node) error) error {
|
|
|
|
var err error
|
|
|
|
err = maybeDoList(n.init, err, do)
|
|
|
|
err = maybeDo(n.X, err, do)
|
|
|
|
return err
|
|
|
|
}
|
2020-12-03 21:29:23 -05:00
|
|
|
func (n *UnaryExpr) editChildren(edit func(Node) Node) {
|
|
|
|
editList(n.init, edit)
|
|
|
|
n.X = maybeEdit(n.X, edit)
|
|
|
|
}
|
2020-12-03 18:43:18 -05:00
|
|
|
|
|
|
|
func (n *UnaryExpr) Left() Node { return n.X }
|
|
|
|
func (n *UnaryExpr) SetLeft(x Node) { n.X = x }
|
2020-11-29 21:25:47 -05:00
|
|
|
|
|
|
|
func (n *UnaryExpr) SetOp(op Op) {
|
|
|
|
switch op {
|
|
|
|
default:
|
|
|
|
panic(n.no("SetOp " + op.String()))
|
|
|
|
case OBITNOT, ONEG, ONOT, OPLUS, ORECV,
|
|
|
|
OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW,
|
|
|
|
OOFFSETOF, OPANIC, OREAL, OSIZEOF,
|
|
|
|
OCHECKNIL, OCFUNC, OIDATA, OITAB, ONEWOBJ, OSPTR, OVARDEF, OVARKILL, OVARLIVE:
|
|
|
|
n.op = op
|
|
|
|
}
|
|
|
|
}
|