Skip to content

Commit 0b6b6f8

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 0b6b6f8

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-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: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,78 @@ 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(
151+
&mut self,
152+
node: &RedeemNode<J>,
153+
input: super::FrameIter,
154+
output: NodeOutput,
155+
) {
156+
let input_val = Value::from_padded_bits(&mut input.clone(), &node.arrow().source)
157+
.expect("input from bit machine will always be well-formed");
158+
eprintln!(
159+
"[{:4}] exec {:10} {}",
160+
self.exec_count,
161+
node.inner(),
162+
node.arrow()
163+
);
164+
eprintln!(" input {input_val}");
165+
match output.clone() {
166+
NodeOutput::NonTerminal => { /* don't bother describing non-terminal output */ }
167+
NodeOutput::JetFailed => eprintln!(" JET FAILED"),
168+
NodeOutput::Success(mut output) => {
169+
let output_val = Value::from_padded_bits(&mut output, &node.arrow().target)
170+
.expect("input from bit machine will always be well-formed");
171+
eprintln!(" output {output_val}");
172+
}
173+
}
174+
175+
if let crate::node::Inner::AssertL(_, cmr) = node.inner() {
176+
// SimplicityHL, when compiling in "debug mode", tags nodes by inserting
177+
// synthetic AssertL nodes where the "cmr" is actually a key into a lookup
178+
// table of debug information. An implementation of ExecTracker within
179+
// the compiler itself might do a lookup here to output more useful
180+
// information to the user.
181+
eprintln!(" [debug] assertL CMR {cmr}");
182+
}
183+
184+
ExecTracker::<J>::visit_node(&mut self.inner, node, input, output);
185+
self.exec_count += 1;
186+
eprintln!();
187+
}
188+
}
189+
190+
impl<J: Jet> PruneTracker<J> for StderrTracker {
191+
fn contains_left(&self, ihr: Ihr) -> bool {
192+
if PruneTracker::<J>::contains_left(&self.inner, ihr) {
193+
true
194+
} else {
195+
eprintln!("Pruning unexecuted left child of IHR {ihr}");
196+
false
197+
}
198+
}
199+
200+
fn contains_right(&self, ihr: Ihr) -> bool {
201+
if PruneTracker::<J>::contains_right(&self.inner, ihr) {
202+
true
203+
} else {
204+
eprintln!("Pruning unexecuted right child of IHR {ihr}");
205+
false
206+
}
207+
}
208+
}

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)