Skip to content

Commit ed79edf

Browse files
committed
bit_machine: add example StderrTracker which outputs stuff to stderr
Outputting to stderr is not super useful but this can be used as a demo of what the tracker is able to do.
1 parent 6013bd5 commit ed79edf

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

src/bit_machine/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ use crate::{Cmr, FailEntropy, Value};
2222
use frame::Frame;
2323

2424
pub use self::limits::LimitError;
25-
pub use self::tracker::{ExecTracker, NoTracker, NodeOutput, PruneTracker, SetTracker};
25+
pub use self::tracker::{
26+
ExecTracker, NoTracker, NodeOutput, PruneTracker, SetTracker, StderrTracker,
27+
};
2628

2729
/// An iterator over the contents of a read or write frame which yields bits.
2830
pub type FrameIter<'a> = crate::BitIter<core::iter::Copied<core::slice::Iter<'a, u8>>>;
@@ -228,6 +230,9 @@ impl BitMachine {
228230

229231
/// Execute the given `program` on the Bit Machine, using the given environment and tracker.
230232
///
233+
/// See [`crate::bit_machine::StderrTracker`] as an example which outputs various debug
234+
/// data for each node, providing a track of the bit machine's operation.
235+
///
231236
/// ## Precondition
232237
///
233238
/// The Bit Machine is constructed via [`Self::for_program()`] to ensure enough space.

src/bit_machine/tracker.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,73 @@ impl<J: Jet> ExecTracker<J> for NoTracker {
131131
}
132132
}
133133
}
134+
135+
/// Tracker that just outputs all its activity to stderr.
136+
#[derive(Clone, Debug, Default)]
137+
pub struct StderrTracker {
138+
exec_count: usize,
139+
inner: SetTracker,
140+
}
141+
142+
impl StderrTracker {
143+
/// Constructs a new empty [`StderrTracker`], ready for use.
144+
pub fn new() -> Self {
145+
Self::default()
146+
}
147+
}
148+
149+
impl<J: Jet> ExecTracker<J> for StderrTracker {
150+
fn visit_node(&mut self, node: &RedeemNode<J>, input: super::FrameIter, output: NodeOutput) {
151+
let input_val = Value::from_padded_bits(&mut input.clone(), &node.arrow().source)
152+
.expect("input from bit machine will always be well-formed");
153+
eprintln!(
154+
"[{:4}] exec {:10} {}",
155+
self.exec_count,
156+
node.inner(),
157+
node.arrow()
158+
);
159+
eprintln!(" input {input_val}");
160+
match output.clone() {
161+
NodeOutput::NonTerminal => { /* don't bother describing non-terminal output */ }
162+
NodeOutput::JetFailed => eprintln!(" JET FAILED"),
163+
NodeOutput::Success(mut output) => {
164+
let output_val = Value::from_padded_bits(&mut output, &node.arrow().target)
165+
.expect("input from bit machine will always be well-formed");
166+
eprintln!(" output {output_val}");
167+
}
168+
}
169+
170+
if let crate::node::Inner::AssertL(_, cmr) = node.inner() {
171+
// SimplicityHL, when compiling in "debug mode", tags nodes by inserting
172+
// synthetic AssertL nodes where the "cmr" is actually a key into a lookup
173+
// table of debug information. An implementation of ExecTracker within
174+
// the compiler itself might do a lookup here to output more useful
175+
// information to the user.
176+
eprintln!(" [debug] assertL CMR {cmr}");
177+
}
178+
179+
ExecTracker::<J>::visit_node(&mut self.inner, node, input, output);
180+
self.exec_count += 1;
181+
eprintln!();
182+
}
183+
}
184+
185+
impl<J: Jet> PruneTracker<J> for StderrTracker {
186+
fn contains_left(&self, ihr: Ihr) -> bool {
187+
if PruneTracker::<J>::contains_left(&self.inner, ihr) {
188+
true
189+
} else {
190+
eprintln!("Pruning unexecuted left child of IHR {ihr}");
191+
false
192+
}
193+
}
194+
195+
fn contains_right(&self, ihr: Ihr) -> bool {
196+
if PruneTracker::<J>::contains_right(&self.inner, ihr) {
197+
true
198+
} else {
199+
eprintln!("Pruning unexecuted right child of IHR {ihr}");
200+
false
201+
}
202+
}
203+
}

src/node/redeem.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ impl<J: Jet> RedeemNode<J> {
293293
self.prune_with_tracker(env, &mut SetTracker::default())
294294
}
295295

296+
/// Prune the redeem program, as in [`Self::prune`], but with a custom tracker which
297+
/// can introspect or control pruning.
298+
///
299+
/// See [`crate::bit_machine::StderrTracker`] as an example which outputs the IHR of
300+
/// each case combinator that we prune a child of.
296301
pub fn prune_with_tracker<T: PruneTracker<J>>(
297302
&self,
298303
env: &J::Environment,

0 commit comments

Comments
 (0)