@@ -4,12 +4,61 @@ import (
44 "go/types"
55)
66
7+ // Iter is a iterator over instructions
8+ type Iter interface {
9+ // Instr returns the current instruction
10+ Instr () * Instr
11+
12+ // InstrIndex returns the index of the current instruction in the Block
13+ InstrIndex () int
14+
15+ // Block returns the current block
16+ Block () * Block
17+
18+ // BlockIndex returns the index of the Block within the Func
19+ BlockIndex () int
20+
21+ // HasNext returns whether Next() will succeed
22+ HasNext () bool
23+
24+ // Next increments the position and returns whether that was successful
25+ Next () bool
26+
27+ // HasPrev returns whether Prev() will succeed
28+ HasPrev () bool
29+
30+ // Prev decrements the position and returns whether that was successful
31+ Prev () bool
32+
33+ // Insert inserts an instruction at the cursor position and increments the position
34+ Insert (op Op , typ types.Type , args ... interface {}) * Instr
35+
36+ // Remove will remove the instruction at the current position and decrement the position,
37+ // returning the removed instruction.
38+ // NOTE: this only removes the instruction from the Block, it does not Unlink() it from
39+ // any uses.
40+ Remove () * Instr
41+
42+ // Update updates the instruction at the cursor position
43+ Update (op Op , typ types.Type , args ... interface {}) * Instr
44+
45+ // HasChanged returns true if `Changed()` was called, or one of the mutation methods
46+ HasChanged () bool
47+
48+ // Changed forces `HasChanged()` to return true
49+ Changed ()
50+ }
51+
52+ var _ Iter = & BlockIter {}
53+ var _ Iter = & CrossBlockIter {}
54+
755/// in-block iterator
856
957// BlockIter is an iterator that iterates over instructions in a Block
1058type BlockIter struct {
11- blk * Block
12- insIdx int
59+ blk * Block
60+ insIdx int
61+ changed bool
1362}
1463
1564// InstrIter will return an Iter which iterates over every
@@ -74,13 +123,25 @@ func (it *BlockIter) HasPrev() bool {
74123 return it .insIdx >= 0 // todo: there is a bug here
75124}
76125
126+ // HasChanged returns true if `Changed()` was called, or one of the mutation methods
127+ func (it * BlockIter ) HasChanged () bool {
128+ return it .changed
129+ }
130+
131+ // Changed forces `HasChanged()` to return true
132+ func (it * BlockIter ) Changed () {
133+ it .changed = true
134+ }
135+
77136// Insert inserts an instruction at the cursor position and increments the position
78137func (it * BlockIter ) Insert (op Op , typ types.Type , args ... interface {}) * Instr {
79138 instr := it .blk .fn .NewInstr (op , typ , args ... )
80139
81140 it .blk .InsertInstr (it .insIdx , instr )
82141 it .Next ()
83142
143+ it .changed = true
144+
84145 return instr
85146}
86147
@@ -95,6 +156,8 @@ func (it *BlockIter) Remove() *Instr {
95156 it .blk .RemoveInstr (instr )
96157 it .Prev ()
97158
159+ it .changed = true
160+
98161 return instr
99162}
100163
@@ -104,6 +167,8 @@ func (it *BlockIter) Update(op Op, typ types.Type, args ...interface{}) *Instr {
104167
105168 instr .Update (op , typ , args ... )
106169
170+ it .changed = true
171+
107172 return instr
108173}
109174
@@ -128,24 +193,25 @@ func (fn *Func) InstrIter() *CrossBlockIter {
128193
129194// HasNext returns whether Next() will succeed
130195func (it * CrossBlockIter ) HasNext () bool {
131- return it .insIdx < len (it .blk .instrs ) && it .blkIdx < len (it .fn .blocks )
196+ return ( it .insIdx + 1 ) < len (it .blk .instrs ) || ( it .blkIdx + 1 ) < len (it .fn .blocks )
132197}
133198
134199// Next increments the position and returns whether that was successful
135200func (it * CrossBlockIter ) Next () bool {
136- if it .insIdx >= len (it .blk .instrs ) {
137- if (it .blkIdx + 1 ) >= len (it .fn .blocks ) {
138- return false
139- }
201+ if ! it .HasNext () {
202+ return false
203+ }
204+
205+ it .insIdx ++
140206
207+ if it .insIdx >= len (it .blk .instrs ) {
141208 it .blkIdx ++
142209 it .insIdx = 0
143210 it .blk = it .fn .blocks [it .blkIdx ]
144211 return true
145212 }
146213
147- it .insIdx ++
148- return it .insIdx < len (it .blk .instrs )
214+ return true
149215}
150216
151217// HasPrev returns whether Prev() will succeed
0 commit comments