Skip to content

Commit 618aa5e

Browse files
nilslicekalzoo
andauthored
chore: convert terminate_working_block macro to fn (#79)
* chore: convert terminate_working_block macro to fn * chore: clippy fixes * chore: fix mutability on fn param to remove regression * chore: update readme to document testing instructions * chore: use early return instead of if/else and document fn * chore: remove needless assignment * chore: update docs Co-authored-by: Kalan <[email protected]> Co-authored-by: kalzoo <[email protected]>
1 parent 9f60bc2 commit 618aa5e

File tree

2 files changed

+80
-62
lines changed

2 files changed

+80
-62
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,12 @@ It serves three purposes:
99
3. Construct a dependency graph among program instructions
1010

1111
It should be considered unstable until the release of v1.0.
12+
13+
14+
## Testing
15+
16+
When testing this crate, you should run with the `--all-features` flag to ensure all tests are executed.
17+
18+
```sh
19+
cargo test --all-features
20+
```

src/program/graph.rs

+71-62
Original file line numberDiff line numberDiff line change
@@ -452,33 +452,44 @@ pub struct ScheduledProgram {
452452
pub blocks: IndexMap<String, InstructionBlock>,
453453
}
454454

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(())
482493
}
483494

484495
impl ScheduledProgram {
@@ -536,80 +547,78 @@ impl ScheduledProgram {
536547
Ok(())
537548
}
538549
Instruction::Label(Label(value)) => {
539-
terminate_working_block!(
550+
terminate_working_block(
540551
None as Option<BlockTerminator>,
541-
working_instructions,
542-
blocks,
543-
working_label,
552+
&mut working_instructions,
553+
&mut blocks,
554+
&mut working_label,
544555
program,
545-
instruction_index
556+
instruction_index,
546557
)?;
547558

548559
working_label = Some(value.clone());
549560
Ok(())
550561
}
551562
Instruction::Jump(Jump { target }) => {
552-
terminate_working_block!(
563+
terminate_working_block(
553564
Some(BlockTerminator::Unconditional {
554565
target: target.clone(),
555566
}),
556-
working_instructions,
557-
blocks,
558-
working_label,
567+
&mut working_instructions,
568+
&mut blocks,
569+
&mut working_label,
559570
program,
560-
instruction_index
571+
instruction_index,
561572
)?;
562573
Ok(())
563574
}
564575
Instruction::JumpWhen(JumpWhen { target, condition }) => {
565-
terminate_working_block!(
576+
terminate_working_block(
566577
Some(BlockTerminator::Conditional {
567578
target: target.clone(),
568579
condition: condition.clone(),
569580
jump_if_condition_true: true,
570581
}),
571-
working_instructions,
572-
blocks,
573-
working_label,
582+
&mut working_instructions,
583+
&mut blocks,
584+
&mut working_label,
574585
program,
575-
instruction_index
586+
instruction_index,
576587
)?;
577588
Ok(())
578589
}
579590
Instruction::JumpUnless(JumpUnless { target, condition }) => {
580-
terminate_working_block!(
591+
terminate_working_block(
581592
Some(BlockTerminator::Conditional {
582593
target: target.clone(),
583594
condition: condition.clone(),
584595
jump_if_condition_true: false,
585596
}),
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,
599600
program,
600-
instruction_index
601+
instruction_index,
601602
)
602603
}
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+
),
603612
}?;
604613
}
605614

606-
terminate_working_block!(
615+
terminate_working_block(
607616
None as Option<BlockTerminator>,
608-
working_instructions,
609-
blocks,
610-
working_label,
617+
&mut working_instructions,
618+
&mut blocks,
619+
&mut working_label,
611620
program,
612-
None
621+
None,
613622
)?;
614623

615624
Ok(ScheduledProgram { blocks })

0 commit comments

Comments
 (0)