// first.
base.ExitIfErrors()
- findInitLoopAndExit(firstLHS(n), new([]ir.Node))
+ findInitLoopAndExit(firstLHS(n), new([]*ir.Name))
base.Fatalf("initialization unfinished, but failed to identify loop")
}
}
// Compute number of variable dependencies and build the
// inverse dependency ("blocking") graph.
for dep := range collectDeps(n, true) {
- defn := dep.Name().Defn
+ defn := dep.Defn
// Skip dependencies on functions (PFUNC) and
// variables already initialized (InitDone).
if dep.Class() != ir.PEXTERN || defn.Initorder() == InitDone {
// path points to a slice used for tracking the sequence of
// variables/functions visited. Using a pointer to a slice allows the
// slice capacity to grow and limit reallocations.
-func findInitLoopAndExit(n ir.Node, path *[]ir.Node) {
+func findInitLoopAndExit(n *ir.Name, path *[]*ir.Name) {
// We implement a simple DFS loop-finding algorithm. This
// could be faster, but initialization cycles are rare.
// There might be multiple loops involving n; by sorting
// references, we deterministically pick the one reported.
- refers := collectDeps(n.Name().Defn, false).Sorted(func(ni, nj ir.Node) bool {
+ refers := collectDeps(n.Name().Defn, false).Sorted(func(ni, nj *ir.Name) bool {
return ni.Pos().Before(nj.Pos())
})
*path = append(*path, n)
for _, ref := range refers {
// Short-circuit variables that were initialized.
- if ref.Class() == ir.PEXTERN && ref.Name().Defn.Initorder() == InitDone {
+ if ref.Class() == ir.PEXTERN && ref.Defn.Initorder() == InitDone {
continue
}
// reportInitLoopAndExit reports and initialization loop as an error
// and exits. However, if l is not actually an initialization loop, it
// simply returns instead.
-func reportInitLoopAndExit(l []ir.Node) {
+func reportInitLoopAndExit(l []*ir.Name) {
// Rotate loop so that the earliest variable declaration is at
// the start.
i := -1
// variables that declaration n depends on. If transitive is true,
// then it also includes the transitive dependencies of any depended
// upon functions (but not variables).
-func collectDeps(n ir.Node, transitive bool) ir.NodeSet {
+func collectDeps(n ir.Node, transitive bool) ir.NameSet {
d := initDeps{transitive: transitive}
switch n.Op() {
case ir.OAS:
type initDeps struct {
transitive bool
- seen ir.NodeSet
+ seen ir.NameSet
}
func (d *initDeps) inspect(n ir.Node) { ir.Inspect(n, d.visit) }
// firstLHS returns the first expression on the left-hand side of
// assignment n.
-func firstLHS(n ir.Node) ir.Node {
+func firstLHS(n ir.Node) *ir.Name {
switch n.Op() {
case ir.OAS:
- return n.Left()
+ return n.Left().Name()
case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2RECV, ir.OAS2MAPR:
- return n.List().First()
+ return n.List().First().Name()
}
base.Fatalf("unexpected Op: %v", n.Op())
return n
}
-// NodeSet is a set of Nodes.
-type NodeSet map[Node]struct{}
+// NameSet is a set of Names.
+type NameSet map[*Name]struct{}
// Has reports whether s contains n.
-func (s NodeSet) Has(n Node) bool {
+func (s NameSet) Has(n *Name) bool {
_, isPresent := s[n]
return isPresent
}
// Add adds n to s.
-func (s *NodeSet) Add(n Node) {
+func (s *NameSet) Add(n *Name) {
if *s == nil {
- *s = make(map[Node]struct{})
+ *s = make(map[*Name]struct{})
}
(*s)[n] = struct{}{}
}
// Sorted returns s sorted according to less.
-func (s NodeSet) Sorted(less func(Node, Node) bool) []Node {
- var res []Node
+func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name {
+ var res []*Name
for n := range s {
res = append(res, n)
}