// Maybe a top-level declaration will come along later to
// define s. resolve will check s.Def again once all input
// source has been processed.
- return ir.NewDeclNameAt(base.Pos, s)
+ return ir.NewIdent(base.Pos, s)
}
if Curfn != nil && n.Op() == ir.ONAME && n.Name().Curfn != nil && n.Name().Curfn != Curfn {
return ir.TypeNode(r.typ())
case ir.OTYPESW:
- n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil)
+ pos := r.pos()
+ var tag *ir.Ident
if s := r.ident(); s != nil {
- n.SetLeft(ir.NewDeclNameAt(n.Pos(), s))
+ tag = ir.NewIdent(pos, s)
}
- right, _ := r.exprsOrNil()
- n.SetRight(right)
- return n
+ expr, _ := r.exprsOrNil()
+ return ir.NewTypeSwitchGuard(pos, tag, expr)
// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
// unreachable - should have been resolved by typechecking
p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
case *syntax.TypeSwitchGuard:
- n := p.nod(expr, ir.OTYPESW, nil, p.expr(expr.X))
+ var tag *ir.Ident
if expr.Lhs != nil {
- n.SetLeft(p.declName(expr.Lhs))
- if ir.IsBlank(n.Left()) {
- base.Errorf("invalid variable name %v in type switch", n.Left())
+ tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
+ if ir.IsBlank(tag) {
+ base.Errorf("invalid variable name %v in type switch", tag)
}
}
- return n
+ return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
}
panic("unhandled Expr")
}
defer tracePrint("resolve", n)(&res)
}
- if n.Sym().Pkg != types.LocalPkg {
+ // Stub ir.Name left for us by iimport.
+ if n, ok := n.(*ir.Name); ok {
+ if n.Sym().Pkg == types.LocalPkg {
+ base.Fatalf("unexpected Name: %+v", n)
+ }
if inimport {
base.Fatalf("recursive inimport")
}
inimport = true
- expandDecl(n.(*ir.Name))
+ expandDecl(n)
inimport = false
return n
}
// Propagate the used flag for typeswitch variables up to the NONAME in its definition.
for _, ln := range fn.Dcl {
if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Defn != nil && ln.Defn.Op() == ir.OTYPESW && ln.Used() {
- ln.Defn.Left().Name().SetUsed(true)
+ ln.Defn.(*ir.TypeSwitchGuard).Used = true
}
}
if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Used() {
continue
}
- if defn := ln.Defn; defn != nil && defn.Op() == ir.OTYPESW {
- if defn.Left().Name().Used() {
+ if defn, ok := ln.Defn.(*ir.TypeSwitchGuard); ok {
+ if defn.Used {
continue
}
- base.ErrorfAt(defn.Left().Pos(), "%v declared but not used", ln.Sym())
- defn.Left().Name().SetUsed(true) // suppress repeats
+ base.ErrorfAt(defn.Tag.Pos(), "%v declared but not used", ln.Sym())
+ defn.Used = true // suppress repeats
} else {
base.ErrorfAt(ln.Pos(), "%v declared but not used", ln.Sym())
}
nodesType := lookup("Nodes")
ptrFieldType := types.NewPointer(lookup("Field"))
slicePtrFieldType := types.NewSlice(ptrFieldType)
- ptrNameType := types.NewPointer(lookup("Name"))
+ ptrIdentType := types.NewPointer(lookup("Ident"))
var buf bytes.Buffer
fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.")
fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) error) error { var err error\n", name)
forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
switch {
- case is(ptrNameType):
+ case is(ptrIdentType):
fmt.Fprintf(&buf, "if n.%s != nil { err = maybeDo(n.%s, err, do) }\n", name, name)
case is(nodeType), is(ntypeType):
fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name)
fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
switch {
- case is(ptrNameType):
- fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Name) }\n", name, name, name)
+ case is(ptrIdentType):
+ fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Ident) }\n", name, name, name)
case is(nodeType):
fmt.Fprintf(&buf, "n.%s = maybeEdit(n.%s, edit)\n", name, name)
case is(ntypeType):
"go/constant"
)
+// An Ident is an identifier, possibly qualified.
+type Ident struct {
+ miniExpr
+ sym *types.Sym
+ Used bool
+}
+
+func NewIdent(pos src.XPos, sym *types.Sym) *Ident {
+ n := new(Ident)
+ n.op = ONONAME
+ n.pos = pos
+ n.sym = sym
+ return n
+}
+
+func (n *Ident) Sym() *types.Sym { return n.sym }
+
+func (*Ident) CanBeNtype() {}
+
// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
type Name struct {
miniExpr
return NewSliceHeaderExpr(pos, nil, nleft, nil, nil)
case OSWITCH:
return NewSwitchStmt(pos, nleft, nil)
- case OTYPESW:
- return NewTypeSwitchGuard(pos, nleft, nright)
case OINLCALL:
return NewInlinedCallExpr(pos, nil, nil)
}
n.Call = maybeEdit(n.Call, edit)
}
+func (n *Ident) String() string { return fmt.Sprint(n) }
+func (n *Ident) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Ident) copy() Node {
+ c := *n
+ c.init = c.init.Copy()
+ return &c
+}
+func (n *Ident) doChildren(do func(Node) error) error {
+ var err error
+ err = maybeDoList(n.init, err, do)
+ return err
+}
+func (n *Ident) editChildren(edit func(Node) Node) {
+ editList(n.init, edit)
+}
+
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) copy() Node {
}
func (n *TypeSwitchGuard) doChildren(do func(Node) error) error {
var err error
- if n.Name_ != nil {
- err = maybeDo(n.Name_, err, do)
+ if n.Tag != nil {
+ err = maybeDo(n.Tag, err, do)
}
err = maybeDo(n.X, err, do)
return err
}
func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) {
- if n.Name_ != nil {
- n.Name_ = edit(n.Name_).(*Name)
+ if n.Tag != nil {
+ n.Tag = edit(n.Tag).(*Ident)
}
n.X = maybeEdit(n.X, edit)
}
// A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
type TypeSwitchGuard struct {
miniNode
- Name_ *Name
- X Node
+ Tag *Ident
+ X Node
+ Used bool
}
-func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard {
- n := &TypeSwitchGuard{X: x}
- if name != nil {
- n.Name_ = name.(*Name)
- }
+func NewTypeSwitchGuard(pos src.XPos, tag *Ident, x Node) *TypeSwitchGuard {
+ n := &TypeSwitchGuard{Tag: tag, X: x}
n.pos = pos
n.op = OTYPESW
return n
}
func (n *TypeSwitchGuard) Left() Node {
- if n.Name_ == nil {
+ if n.Tag == nil {
return nil
}
- return n.Name_
+ return n.Tag
}
func (n *TypeSwitchGuard) SetLeft(x Node) {
if x == nil {
- n.Name_ = nil
+ n.Tag = nil
return
}
- n.Name_ = x.(*Name)
+ n.Tag = x.(*Ident)
}
func (n *TypeSwitchGuard) Right() Node { return n.X }
func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x }