Skip to main content

sim_lib_control/
backtrack.rs

1use sim_kernel::Ref;
2
3/// Result of advancing a [`Backtracker`]: the next alternative, or failure.
4#[derive(Clone, Debug, PartialEq, Eq)]
5pub enum BacktrackStep {
6    /// The next untried alternative to commit to.
7    Choice(Ref),
8    /// No alternatives remain; the search has exhausted this point.
9    Failed,
10}
11
12/// A linear backtracking choice point over a fixed list of alternatives.
13///
14/// Models the choose/fail surface of non-deterministic control: each
15/// [`Backtracker::choose`] or [`Backtracker::fail`] commits to the next
16/// alternative, yielding [`BacktrackStep::Failed`] once they run out.
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct Backtracker {
19    alternatives: Vec<Ref>,
20    index: usize,
21}
22
23impl Backtracker {
24    /// Builds a backtracker that walks `alternatives` in order.
25    pub fn new(alternatives: Vec<Ref>) -> Self {
26        Self {
27            alternatives,
28            index: 0,
29        }
30    }
31
32    /// Commits to the next alternative, or [`BacktrackStep::Failed`] if none
33    /// remain.
34    pub fn choose(&mut self) -> BacktrackStep {
35        let Some(choice) = self.alternatives.get(self.index).cloned() else {
36            return BacktrackStep::Failed;
37        };
38        self.index += 1;
39        BacktrackStep::Choice(choice)
40    }
41
42    /// Backtracks the current choice and advances to the next alternative;
43    /// equivalent to [`Backtracker::choose`].
44    pub fn fail(&mut self) -> BacktrackStep {
45        self.choose()
46    }
47}