@@ -452,33 +452,44 @@ pub struct ScheduledProgram {
452
452
pub blocks : IndexMap < String , InstructionBlock > ,
453
453
}
454
454
455
- macro_rules! terminate_working_block {
456
- ( $terminator: expr, $working_instructions: ident, $blocks: ident, $working_label: ident, $program: ident, $instruction_index: ident) => { {
457
- // If this "block" has no instructions and no terminator, it's not worth storing - skip it
458
- if $working_instructions. is_empty( ) && $terminator. is_none( ) && $working_label. is_none( ) {
459
- $working_label = None
460
- } else {
461
- let block = InstructionBlock :: build(
462
- $working_instructions. iter( ) . map( |el| el. clone( ) ) . collect( ) ,
463
- $terminator,
464
- $program,
465
- ) ?;
466
- let label =
467
- $working_label. unwrap_or_else( || Self :: generate_autoincremented_label( & $blocks) ) ;
468
-
469
- match $blocks. insert( label. clone( ) , block) {
470
- Some ( _) => Err ( ScheduleError {
471
- instruction_index: $instruction_index,
472
- instruction: Instruction :: Label ( Label ( label. clone( ) ) ) ,
473
- variant: ScheduleErrorVariant :: DuplicateLabel ,
474
- } ) , // Duplicate label
475
- None => Ok ( ( ) ) ,
476
- } ?;
477
- $working_instructions = vec![ ] ;
478
- $working_label = None
479
- }
480
- Ok ( ( ) )
481
- } } ;
455
+ /// Builds an [`InstructionBlock`] from provided instructions, terminator, and program, then tracks
456
+ /// the block and its label, and resets the instruction list and label for a future block to use.
457
+ ///
458
+ /// The "working block" is that being traversed within the program, accumulating instructions located
459
+ /// between control instructions (such as `LABEL` and 'JUMP`). When such a control instruction is reached,
460
+ /// this function performs the work to close out and store the instructions in the current "working block"
461
+ /// and then reset the state to prepare for the next block.
462
+ fn terminate_working_block (
463
+ terminator : Option < BlockTerminator > ,
464
+ working_instructions : & mut Vec < Instruction > ,
465
+ blocks : & mut IndexMap < String , InstructionBlock > ,
466
+ working_label : & mut Option < String > ,
467
+ program : & Program ,
468
+ instruction_index : Option < usize > ,
469
+ ) -> ScheduleResult < ( ) > {
470
+ // If this "block" has no instructions and no terminator, it's not worth storing - skip it
471
+ if working_instructions. is_empty ( ) && terminator. is_none ( ) && working_label. is_none ( ) {
472
+ return Ok ( ( ) ) ;
473
+ }
474
+
475
+ let block = InstructionBlock :: build ( working_instructions. to_vec ( ) , terminator, program) ?;
476
+ let label = working_label
477
+ . clone ( )
478
+ . unwrap_or_else ( || ScheduledProgram :: generate_autoincremented_label ( blocks) ) ;
479
+
480
+ match blocks. insert ( label. clone ( ) , block) {
481
+ Some ( _) => Err ( ScheduleError {
482
+ instruction_index,
483
+ instruction : Instruction :: Label ( Label ( label) ) ,
484
+ variant : ScheduleErrorVariant :: DuplicateLabel ,
485
+ } ) ,
486
+ None => Ok ( ( ) ) ,
487
+ } ?;
488
+
489
+ working_instructions. drain ( ..) ;
490
+ * working_label = None ;
491
+
492
+ Ok ( ( ) )
482
493
}
483
494
484
495
impl ScheduledProgram {
@@ -536,80 +547,78 @@ impl ScheduledProgram {
536
547
Ok ( ( ) )
537
548
}
538
549
Instruction :: Label ( Label ( value) ) => {
539
- terminate_working_block ! (
550
+ terminate_working_block (
540
551
None as Option < BlockTerminator > ,
541
- working_instructions,
542
- blocks,
543
- working_label,
552
+ & mut working_instructions,
553
+ & mut blocks,
554
+ & mut working_label,
544
555
program,
545
- instruction_index
556
+ instruction_index,
546
557
) ?;
547
558
548
559
working_label = Some ( value. clone ( ) ) ;
549
560
Ok ( ( ) )
550
561
}
551
562
Instruction :: Jump ( Jump { target } ) => {
552
- terminate_working_block ! (
563
+ terminate_working_block (
553
564
Some ( BlockTerminator :: Unconditional {
554
565
target : target. clone ( ) ,
555
566
} ) ,
556
- working_instructions,
557
- blocks,
558
- working_label,
567
+ & mut working_instructions,
568
+ & mut blocks,
569
+ & mut working_label,
559
570
program,
560
- instruction_index
571
+ instruction_index,
561
572
) ?;
562
573
Ok ( ( ) )
563
574
}
564
575
Instruction :: JumpWhen ( JumpWhen { target, condition } ) => {
565
- terminate_working_block ! (
576
+ terminate_working_block (
566
577
Some ( BlockTerminator :: Conditional {
567
578
target : target. clone ( ) ,
568
579
condition : condition. clone ( ) ,
569
580
jump_if_condition_true : true ,
570
581
} ) ,
571
- working_instructions,
572
- blocks,
573
- working_label,
582
+ & mut working_instructions,
583
+ & mut blocks,
584
+ & mut working_label,
574
585
program,
575
- instruction_index
586
+ instruction_index,
576
587
) ?;
577
588
Ok ( ( ) )
578
589
}
579
590
Instruction :: JumpUnless ( JumpUnless { target, condition } ) => {
580
- terminate_working_block ! (
591
+ terminate_working_block (
581
592
Some ( BlockTerminator :: Conditional {
582
593
target : target. clone ( ) ,
583
594
condition : condition. clone ( ) ,
584
595
jump_if_condition_true : false ,
585
596
} ) ,
586
- working_instructions,
587
- blocks,
588
- working_label,
589
- program,
590
- instruction_index
591
- )
592
- }
593
- Instruction :: Halt => {
594
- terminate_working_block ! (
595
- Some ( BlockTerminator :: Halt ) ,
596
- working_instructions,
597
- blocks,
598
- working_label,
597
+ & mut working_instructions,
598
+ & mut blocks,
599
+ & mut working_label,
599
600
program,
600
- instruction_index
601
+ instruction_index,
601
602
)
602
603
}
604
+ Instruction :: Halt => terminate_working_block (
605
+ Some ( BlockTerminator :: Halt ) ,
606
+ & mut working_instructions,
607
+ & mut blocks,
608
+ & mut working_label,
609
+ program,
610
+ instruction_index,
611
+ ) ,
603
612
} ?;
604
613
}
605
614
606
- terminate_working_block ! (
615
+ terminate_working_block (
607
616
None as Option < BlockTerminator > ,
608
- working_instructions,
609
- blocks,
610
- working_label,
617
+ & mut working_instructions,
618
+ & mut blocks,
619
+ & mut working_label,
611
620
program,
612
- None
621
+ None ,
613
622
) ?;
614
623
615
624
Ok ( ScheduledProgram { blocks } )
0 commit comments