Skip to content

Commit f4abbf1

Browse files
authored
revert: multiple epilogues (#68)
1 parent 9a13d13 commit f4abbf1

File tree

3 files changed

+60
-118
lines changed

3 files changed

+60
-118
lines changed

src/pipelines/exec/navi.rs

Lines changed: 43 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use {
2525
pub(crate) struct StepPath(SmallVec<[usize; 8]>);
2626

2727
const PROLOGUE_INDEX: usize = usize::MIN;
28-
const EPILOGUE_START_INDEX: usize = usize::MAX - 1024; // Reserve space for epilogue steps
28+
const EPILOGUE_INDEX: usize = usize::MAX;
2929
const STEP0_INDEX: usize = PROLOGUE_INDEX + 1;
3030

3131
/// Public API
@@ -86,7 +86,7 @@ impl StepPath {
8686

8787
/// Returns `true` if the path is pointing to an epilogue of a pipeline.
8888
pub(crate) fn is_epilogue(&self) -> bool {
89-
self.leaf() >= EPILOGUE_START_INDEX
89+
self.leaf() == EPILOGUE_INDEX
9090
}
9191
}
9292

@@ -232,15 +232,9 @@ impl StepPath {
232232
Self(smallvec![PROLOGUE_INDEX])
233233
}
234234

235-
/// Returns a leaf step path pointing at the first epilogue step.
235+
/// Returns a leaf step path pointing at the epilogue step.
236236
pub(in crate::pipelines) fn epilogue() -> Self {
237-
Self::epilogue_step(0)
238-
}
239-
240-
/// Returns a leaf step path pointing at a specific epilogue step with the
241-
/// given index.
242-
pub(in crate::pipelines) fn epilogue_step(epilogue_index: usize) -> Self {
243-
Self(smallvec![epilogue_index + EPILOGUE_START_INDEX])
237+
Self(smallvec![EPILOGUE_INDEX])
244238
}
245239

246240
/// Returns a new step path that points to the first non-prologue step.
@@ -281,18 +275,14 @@ impl core::fmt::Display for StepPath {
281275
if let Some(&first) = iter.next() {
282276
match first {
283277
PROLOGUE_INDEX => write!(f, "p"),
284-
idx if idx >= EPILOGUE_START_INDEX => {
285-
write!(f, "e{}", idx - EPILOGUE_START_INDEX)
286-
}
278+
EPILOGUE_INDEX => write!(f, "e"),
287279
index => write!(f, "{index}"),
288280
}?;
289281

290282
for &index in iter {
291283
match index {
292284
PROLOGUE_INDEX => write!(f, "_p"),
293-
idx if idx >= EPILOGUE_START_INDEX => {
294-
write!(f, "_e{}", idx - EPILOGUE_START_INDEX)
295-
}
285+
EPILOGUE_INDEX => write!(f, "_e"),
296286
index => write!(f, "_{index}"),
297287
}?;
298288
}
@@ -328,7 +318,7 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
328318
/// In pipelines with a prologue, this will point to the prologue step.
329319
/// In pipelines without a prologue, this will point to the first step.
330320
/// In pipelines with no steps, but with an epilogue, this will point to the
331-
/// first epilogue step.
321+
/// epilogue step.
332322
///
333323
/// If the first item in the pipeline is a nested pipeline, this will dig
334324
/// deeper into the nested pipeline to find the first executable item.
@@ -346,10 +336,9 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
346336

347337
// pipeline has no prologue
348338
if pipeline.steps().is_empty() {
349-
// If there are no steps, but there is an epilogue, return the first
350-
// epilogue step.
351-
if !pipeline.epilogue().is_empty() {
352-
return Self(StepPath::epilogue(), vec![pipeline]).enter();
339+
// If there are no steps, but there is an epilogue, return it.
340+
if pipeline.epilogue().is_some() {
341+
return Some(Self(StepPath::epilogue(), vec![pipeline]));
353342
}
354343

355344
// this is an empty pipeline, there is nothing executable.
@@ -373,20 +362,11 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
373362
} else if self.is_epilogue() {
374363
enclosing_pipeline
375364
.epilogue()
376-
.get(
377-
step_index
378-
.checked_sub(EPILOGUE_START_INDEX)
379-
.expect("step index should be >= epilogue start index"),
380-
)
381365
.expect("Step path points to a non-existing epilogue")
382366
} else {
383367
let StepOrPipeline::Step(step) = enclosing_pipeline
384368
.steps()
385-
.get(
386-
step_index
387-
.checked_sub(STEP0_INDEX)
388-
.expect("step index should be >= step0 index"),
389-
)
369+
.get(step_index - STEP0_INDEX)
390370
.expect("Step path points to a non-existing step")
391371
else {
392372
unreachable!(
@@ -420,19 +400,7 @@ impl<'a, P: Platform> StepNavigator<'a, P> {
420400
/// Returns `None` if there are no more steps to execute in the pipeline.
421401
pub(crate) fn next_ok(self) -> Option<Self> {
422402
if self.is_epilogue() {
423-
// we are in an epilogue step, check if there are more epilogue steps
424-
let enclosing_pipeline = self.pipeline();
425-
let epilogue_index = self
426-
.0
427-
.leaf()
428-
.checked_sub(EPILOGUE_START_INDEX)
429-
.expect("invalid epilogue step index in the step path");
430-
431-
if epilogue_index + 1 < enclosing_pipeline.epilogue().len() {
432-
// there are more epilogue steps, go to the next one
433-
return Self(self.0.increment_leaf(), self.1.clone()).enter();
434-
}
435-
// this is the last epilogue step, we are done with this pipeline
403+
// the loop is over.
436404
return self.next_in_parent();
437405
}
438406

@@ -551,56 +519,45 @@ impl<P: Platform> StepNavigator<'_, P> {
551519
"StepNavigator should always have at least one enclosing pipeline",
552520
);
553521

554-
if path.is_prologue() {
522+
if path.is_prologue() || path.is_epilogue() {
555523
assert!(
556-
enclosing_pipeline.prologue().is_some(),
557-
"path is prologue, but the enclosing pipeline has none",
524+
enclosing_pipeline.prologue().is_some()
525+
|| enclosing_pipeline.epilogue().is_some(),
526+
"path is prologue or epilogue, but enclosing pipeline has none",
558527
);
559-
// if we are in a prologue, we can just return ourselves.
528+
// if we are in a prologue or epilogue, we can just return ourselves.
560529
return Some(Self(path, ancestors));
561530
}
562531

563-
if path.is_epilogue() {
564-
assert!(
565-
!enclosing_pipeline.epilogue().is_empty(),
566-
"path is epilogue, but the enclosing pipeline has none",
567-
);
568-
Some(Self(path, ancestors))
569-
} else {
570-
let step_index = path
571-
.leaf()
572-
.checked_sub(STEP0_INDEX)
573-
.expect("path is not prologue or epilogue");
574-
575-
match enclosing_pipeline.steps().get(step_index)? {
576-
StepOrPipeline::Step(_) => {
577-
// if we are pointing at a step, we can just return ourselves.
578-
Some(Self(path, ancestors))
579-
}
580-
StepOrPipeline::Pipeline(_, nested) => {
581-
// if we are pointing at a pipeline, we need to dig into its
582-
// entrypoint.
583-
Some(StepNavigator(path, ancestors).join(Self::entrypoint(nested)?))
584-
}
532+
let step_index = path
533+
.leaf()
534+
.checked_sub(STEP0_INDEX)
535+
.expect("path is not prologue or epilogue");
536+
537+
match enclosing_pipeline.steps().get(step_index)? {
538+
StepOrPipeline::Step(_) => {
539+
// if we are pointing at a step, we can just return ourselves.
540+
Some(Self(path, ancestors))
541+
}
542+
StepOrPipeline::Pipeline(_, nested) => {
543+
// if we are pointing at a pipeline, we need to dig into its
544+
// entrypoint.
545+
Some(StepNavigator(path, ancestors).join(Self::entrypoint(nested)?))
585546
}
586547
}
587548
}
588549

589550
/// Finds the next step to run when a loop is finished.
590551
///
591-
/// The next step could be either the first epilogue step of the current
552+
/// The next step could be either the epilogue step of the current
592553
/// pipeline or the next step in the parent pipeline.
593554
fn after_loop(self) -> Option<Self> {
594-
if self.pipeline().epilogue().is_empty() {
595-
self.next_in_parent()
555+
if self.pipeline().epilogue().is_some() {
556+
// we've reached the epilogue of this pipeline, regardless of the
557+
// looping behavior, we should go to the next step in the parent pipeline.
558+
Some(Self(self.0.replace_leaf(EPILOGUE_INDEX), self.1.clone()))
596559
} else {
597-
// we've reached the epilogue of this pipeline, go to the first epilogue
598-
// step
599-
Some(Self(
600-
self.0.replace_leaf(EPILOGUE_START_INDEX),
601-
self.1.clone(),
602-
))
603-
.and_then(|nav| nav.enter())
560+
self.next_in_parent()
604561
}
605562
}
606563

@@ -667,9 +624,7 @@ mod test {
667624

668625
fake_step!(Epilogue1);
669626
fake_step!(Epilogue2);
670-
671-
fake_step!(EpilogueStep1);
672-
fake_step!(EpilogueStep2);
627+
fake_step!(Epilogue3);
673628

674629
fake_step!(Prologue1);
675630
fake_step!(Prologue2);
@@ -711,8 +666,7 @@ mod test {
711666
Once,
712667
(StepI, StepII, StepIII)
713668
.with_name("nested1.2")
714-
.with_epilogue(EpilogueStep1)
715-
.with_epilogue(EpilogueStep2),
669+
.with_epilogue(Epilogue3),
716670
)
717671
})
718672
.with_step(Step4)
@@ -728,10 +682,6 @@ mod test {
728682
self.concat(StepPath::epilogue())
729683
}
730684

731-
fn append_epilogue_step(self, step_index: usize) -> Self {
732-
self.concat(StepPath::epilogue_step(step_index))
733-
}
734-
735685
fn append_step(self, step_index: usize) -> Self {
736686
self.concat(StepPath::step(step_index))
737687
}
@@ -755,7 +705,7 @@ mod test {
755705
}};
756706
}
757707

758-
// one step
708+
// one step with no prologue
759709
assert_entrypoint!(
760710
Pipeline::<Ethereum>::default().with_step(Step1),
761711
StepPath::step0(),
@@ -772,7 +722,7 @@ mod test {
772722
vec!["one"]
773723
);
774724

775-
// no steps, but with a one-step epilogue
725+
// no steps, but with epilogue
776726
assert_entrypoint!(
777727
Pipeline::<Ethereum>::named("one").with_epilogue(Epilogue1),
778728
StepPath::epilogue(),
@@ -797,7 +747,7 @@ mod test {
797747
vec!["one", "two"]
798748
);
799749

800-
// one nested pipeline with no steps, but with a one-step epilogue
750+
// one nested pipeline with no steps, but with an epilogue
801751
assert_entrypoint!(
802752
Pipeline::<Ethereum>::named("one")
803753
.with_pipeline(Loop, Pipeline::named("two").with_epilogue(Epilogue1)),
@@ -935,13 +885,7 @@ mod test {
935885
assert_eq!(cursor.0, StepPath::step(2).append_step(3).append_step(1));
936886

937887
let cursor = cursor.next_break().unwrap();
938-
assert_eq!(
939-
cursor.0,
940-
StepPath::step(2).append_step(3).append_epilogue_step(0)
941-
);
942-
943-
let cursor = cursor.next_ok().unwrap();
944-
StepPath::step(2).append_step(3).append_epilogue_step(1);
888+
assert_eq!(cursor.0, StepPath::step(2).append_step(3).append_epilogue());
945889

946890
let cursor = cursor.next_ok().unwrap();
947891
assert_eq!(cursor.0, StepPath::step(2).append_step(0));

src/pipelines/iter.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct Frame<'a, P: Platform> {
1111
path: StepPath,
1212
next_ix: usize,
1313
yielded_prologue: bool,
14-
epilogue_ix: usize,
14+
yielded_epilogue: bool,
1515
}
1616

1717
impl<'a, P: Platform> StepPathIter<'a, P> {
@@ -22,7 +22,7 @@ impl<'a, P: Platform> StepPathIter<'a, P> {
2222
next_ix: 0,
2323
path: StepPath::empty(),
2424
yielded_prologue: false,
25-
epilogue_ix: 0,
25+
yielded_epilogue: false,
2626
}],
2727
}
2828
}
@@ -56,18 +56,17 @@ impl<P: Platform> Iterator for StepPathIter<'_, P> {
5656
path: next_path,
5757
next_ix: 0,
5858
yielded_prologue: false,
59-
epilogue_ix: 0,
59+
yielded_epilogue: false,
6060
});
6161
continue;
6262
}
6363
}
6464
}
6565

66-
// Walk epilogue steps/pipelines; descend into nested pipelines.
67-
if frame.epilogue_ix < frame.pipeline.epilogue.len() {
68-
let ix = frame.epilogue_ix;
69-
frame.epilogue_ix += 1;
70-
return Some(frame.path.clone().concat(StepPath::epilogue_step(ix)));
66+
// Yield epilogue once, if present.
67+
if !frame.yielded_epilogue && frame.pipeline.epilogue.is_some() {
68+
frame.yielded_epilogue = true;
69+
return Some(frame.path.clone().concat(StepPath::epilogue()));
7170
}
7271

7372
// Done with this frame; pop and continue with parent.
@@ -103,7 +102,7 @@ mod tests {
103102
.with_step(Step3)
104103
.with_epilogue(EpilogueOne);
105104

106-
let expected = vec!["p", "1", "2", "3", "e0"];
105+
let expected = vec!["p", "1", "2", "3", "e"];
107106
let actual = pipeline
108107
.iter_steps()
109108
.map(|step| step.to_string())
@@ -126,7 +125,7 @@ mod tests {
126125
.with_epilogue(EpilogueOne);
127126

128127
let expected = vec![
129-
"p", "1_p", "1_1", "1_2_1", "1_2_2", "1_2_3", "1_2_e0", "1_3", "e0",
128+
"p", "1_p", "1_1", "1_2_1", "1_2_2", "1_2_3", "1_2_e", "1_3", "e",
130129
];
131130

132131
let actual = pipeline

0 commit comments

Comments
 (0)