6.4 赋值语句
最后更新于
var x = f(a, b, b) // 记为 AssignA
var a = g() // 记为 AssignB
var b = h() // 记为 AssignCfunc initOrder(l []ir.Node) []ir.Node {
s := staticinit.Schedule{
Plans: make(map[ir.Node]*staticinit.Plan),
Temps: make(map[ir.Node]*ir.Name),
}
o := InitOrder{
blocking: make(map[ir.Node][]ir.Node),
order: make(map[ir.Node]int),
}
// Process all package-level assignment in declaration order.
for _, n := range l {
switch n.Op() {
case ir.OAS, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
o.processAssign(n)
o.flushReady(s.StaticInit)
case ir.ODCLCONST, ir.ODCLFUNC, ir.ODCLTYPE:
// nop
default:
base.Fatalf("unexpected package-level statement: %v", n)
}
}
return s.Out
}
type InitOrder struct {
// blocking list
blocking map[ir.Node][]ir.Node
// ready queue
ready declOrder
order map[ir.Node]int
}func (o *InitOrder) processAssign(n ir.Node) {
if _, ok := o.order[n]; ok {
base.Fatalf("unexpected state: %v, %v", n, o.order[n])
}
o.order[n] = 0
// 通过 collectDeps() 函数解析依赖列表
for dep := range collectDeps(n, true) {
defn := dep.Defn
// Skip dependencies on functions (PFUNC) and
// variables already initialized (InitDone).
if dep.Class != ir.PEXTERN || o.order[defn] == orderDone {
continue
}
// 设置 order 与 blocking 列表
o.order[n]++
o.blocking[defn] = append(o.blocking[defn], n)
}
// 如果该节点没有依赖,则放入 ready queue 中
if o.order[n] == 0 {
heap.Push(&o.ready, n)
}
}func (o *InitOrder) flushReady(initialize func(ir.Node)) {
for o.ready.Len() != 0 {
n := heap.Pop(&o.ready).(ir.Node)
if order, ok := o.order[n]; !ok || order != 0 {
base.Fatalf("unexpected state: %v, %v, %v", n, ok, order)
}
initialize(n) // 使用方法 StaticInit 进行处理
o.order[n] = orderDone
blocked := o.blocking[n]
delete(o.blocking, n)
// 修改 blocking 列表, 并将 order 降为 0 的语句推入 ready queue
for _, m := range blocked {
if o.order[m]--; o.order[m] == 0 {
heap.Push(&o.ready, m)
}
}
}
}type declOrder []ir.Node
func (s declOrder) Len() int { return len(s) }
func (s declOrder) Less(i, j int) bool {
return firstLHS(s[i]).Pos().Before(firstLHS(s[j]).Pos())
}
func (s declOrder) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s *declOrder) Push(x interface{}) { *s = append(*s, x.(ir.Node)) }
func (s *declOrder) Pop() interface{} {
n := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return n
}type Schedule struct {
// 保存需要运行时才能初始化的语句,已排序
Out []ir.Node
Plans map[ir.Node]*Plan
Temps map[ir.Node]*ir.Name
}
func (s *Schedule) append(n ir.Node) {
s.Out = append(s.Out, n)
}
func (s *Schedule) StaticInit(n ir.Node) {
if !s.tryStaticInit(n) {
if base.Flag.Percent != 0 {
ir.Dump("nonstatic", n)
}
s.append(n)
}
}