@@ -140,12 +140,11 @@ fn test_or() {
140140
141141// 5;
142142//
143- // 0: Constant(0) push `5`
144- // 1: Pop discard value (it's a statement)
145- // 2: Halt
143+ // Pre-peephole: `Constant(0), Pop, Halt`. The peephole pass elides the dead
144+ // `Constant; Pop` pair, leaving just `Halt`.
146145#[ test]
147146fn test_statement ( ) {
148- assert_eq ! ( compile( "5;" ) , [ Constant ( 0 ) , Pop , Halt ] ) ;
147+ assert_eq ! ( compile( "5;" ) , [ Halt ] ) ;
149148}
150149
151150// { 5 }
@@ -159,40 +158,35 @@ fn test_block_with_expression() {
159158
160159// { 5; }
161160//
162- // 0: Constant(0) push `5`
163- // 1: Pop discard (trailing semicolon)
164- // 2: Constant(1) push `()` (block result is unit)
165- // 3: Halt
161+ // Pre-peephole: `Constant(0), Pop, Constant(1), Halt`. The peephole pass
162+ // elides the dead `Constant(0); Pop`, leaving the unit result.
166163#[ test]
167164fn test_block_with_trailing_statement ( ) {
168- assert_eq ! ( compile( "{ 5; }" ) , [ Constant ( 0 ) , Pop , Constant ( 1 ) , Halt ] ) ;
165+ assert_eq ! ( compile( "{ 5; }" ) , [ Constant ( 1 ) , Halt ] ) ;
169166}
170167
171168// { 5; 6 }
172169//
173- // 0: Constant(0) push `5`
174- // 1: Pop discard intermediate statement
175- // 2: Constant(1) push `6` (block result)
176- // 3: Halt
170+ // Pre-peephole: `Constant(0), Pop, Constant(1), Halt`. The peephole elides
171+ // the intermediate `Constant(0); Pop`, leaving just the block result.
177172#[ test]
178173fn test_block_multiple_statements ( ) {
179- assert_eq ! ( compile( "{ 5; 6 }" ) , [ Constant ( 0 ) , Pop , Constant ( 1 ) , Halt ] ) ;
174+ assert_eq ! ( compile( "{ 5; 6 }" ) , [ Constant ( 1 ) , Halt ] ) ;
180175}
181176
182177// if true { 3 } else { 3; }
183178//
184- // true branch returns 3, false branch returns ()
179+ // true branch returns 3, false branch returns (). The peephole pass elides
180+ // the false branch's `Constant; Pop` (pushing `3` only to discard it).
185181//
186182// 0: Constant(0) push `true`
187183// 1: JumpIfFalse(3) jump to false branch (index 5)
188184// 2: Pop pop condition (true path)
189185// 3: Constant(1) push `3`
190- // 4: Jump(4 ) jump to Halt (index 9 )
186+ // 4: Jump(2 ) jump to Halt (index 7 )
191187// 5: Pop pop condition (false path)
192- // 6: Constant(2) push `3` (inner of `3;`)
193- // 7: Pop discard (trailing semicolon)
194- // 8: Constant(3) push `()` (block result)
195- // 9: Halt
188+ // 6: Constant(3) push `()` (block result; constant 2 still in table but unreferenced)
189+ // 7: Halt
196190#[ test]
197191fn test_if_with_statement_else ( ) {
198192 assert_eq ! (
@@ -202,9 +196,7 @@ fn test_if_with_statement_else() {
202196 JumpIfFalse ( JumpTarget :: Offset ( 3 ) ) ,
203197 Pop ,
204198 Constant ( 1 ) ,
205- Jump ( JumpTarget :: Offset ( 4 ) ) ,
206- Pop ,
207- Constant ( 2 ) ,
199+ Jump ( JumpTarget :: Offset ( 2 ) ) ,
208200 Pop ,
209201 Constant ( 3 ) ,
210202 Halt
@@ -214,34 +206,27 @@ fn test_if_with_statement_else() {
214206
215207// if true { 3; } else { 3; }
216208//
217- // Both branches return () — result is unit regardless of condition
209+ // Both branches return () — the peephole elides the `Constant; Pop` in each
210+ // arm (each branch's `3;` becomes nothing).
218211//
219212// 0: Constant(0) push `true`
220- // 1: JumpIfFalse(5 ) jump to false branch (index 7 )
213+ // 1: JumpIfFalse(3 ) jump to false branch (index 5 )
221214// 2: Pop pop condition (true path)
222- // 3: Constant(1) push `3`
223- // 4: Pop discard
224- // 5: Constant(2) push `()`
225- // 6: Jump(4) jump to Halt (index 11)
226- // 7: Pop pop condition (false path)
227- // 8: Constant(3) push `3`
228- // 9: Pop discard
229- // 10: Constant(4) push `()`
230- // 11: Halt
215+ // 3: Constant(2) push `()` (true-branch result; constant 1 unreferenced)
216+ // 4: Jump(2) jump to Halt (index 7)
217+ // 5: Pop pop condition (false path)
218+ // 6: Constant(4) push `()` (false-branch result; constant 3 unreferenced)
219+ // 7: Halt
231220#[ test]
232221fn test_if_with_statement_branches ( ) {
233222 assert_eq ! (
234223 compile( "if true { 3; } else { 3; }" ) ,
235224 [
236225 Constant ( 0 ) ,
237- JumpIfFalse ( JumpTarget :: Offset ( 5 ) ) ,
238- Pop ,
239- Constant ( 1 ) ,
226+ JumpIfFalse ( JumpTarget :: Offset ( 3 ) ) ,
240227 Pop ,
241228 Constant ( 2 ) ,
242- Jump ( JumpTarget :: Offset ( 4 ) ) ,
243- Pop ,
244- Constant ( 3 ) ,
229+ Jump ( JumpTarget :: Offset ( 2 ) ) ,
245230 Pop ,
246231 Constant ( 4 ) ,
247232 Halt
@@ -251,25 +236,24 @@ fn test_if_with_statement_branches() {
251236
252237// while true { 1 }
253238//
239+ // The peephole elides the body's `Constant(1); Pop` (the loop body's value
240+ // is discarded). The backward jump offset shrinks accordingly.
241+ //
254242// 0: Constant(0) push `true` ← loop_start
255- // 1: JumpIfFalse(4 ) if false, jump past body to exit Pop (index 6 )
243+ // 1: JumpIfFalse(2 ) if false, jump past body to exit Pop (index 4 )
256244// 2: Pop pop condition (true path)
257- // 3: Constant(1) body: push `1`
258- // 4: Pop discard body value (loops produce no value)
259- // 5: Jump(-6) jump back to loop_start (index 0)
260- // 6: Pop pop condition (false path, loop exit)
261- // 7: Halt
245+ // 3: Jump(-4) jump back to loop_start (index 0)
246+ // 4: Pop pop condition (false path, loop exit)
247+ // 5: Halt
262248#[ test]
263249fn test_while ( ) {
264250 assert_eq ! (
265251 compile( "while true { 1 }" ) ,
266252 [
267253 Constant ( 0 ) ,
268- JumpIfFalse ( JumpTarget :: Offset ( 4 ) ) ,
269- Pop ,
270- Constant ( 1 ) ,
254+ JumpIfFalse ( JumpTarget :: Offset ( 2 ) ) ,
271255 Pop ,
272- Jump ( JumpTarget :: Offset ( -6 ) ) ,
256+ Jump ( JumpTarget :: Offset ( -4 ) ) ,
273257 Pop ,
274258 Halt
275259 ]
@@ -294,30 +278,21 @@ fn test_declaration() {
294278// let a = 1;
295279// a = 5;
296280//
297- // Declaration stores 1 into pre-allocated slot 0.
298- // Assignment pushes new value, SetLocal overwrites,
299- // push unit as the expression result, Pop discards it.
281+ // Declaration stores 1 into pre-allocated slot 0. Assignment pushes new
282+ // value, SetLocal overwrites. The peephole elides the trailing
283+ // `Constant; Pop` (the assignment expression's unit result, discarded as a
284+ // statement).
300285//
301286// 0: Constant(0) push `1`
302287// 1: SetLocal(0) store in slot 0 (declaration)
303288// 2: Constant(1) push `5`
304289// 3: SetLocal(0) overwrite slot 0 (assignment)
305- // 4: Constant(2) push `()` (assignment result)
306- // 5: Pop discard (statement)
307- // 6: Halt
290+ // 4: Halt
308291#[ test]
309292fn test_assignment ( ) {
310293 assert_eq ! (
311294 compile_with_analysis( "let a = 1;\n a = 5;" ) ,
312- [
313- Constant ( 0 ) ,
314- SetLocal ( 0 ) ,
315- Constant ( 1 ) ,
316- SetLocal ( 0 ) ,
317- Constant ( 2 ) ,
318- Pop ,
319- Halt
320- ]
295+ [ Constant ( 0 ) , SetLocal ( 0 ) , Constant ( 1 ) , SetLocal ( 0 ) , Halt ]
321296 ) ;
322297}
323298
0 commit comments