Skip to content

Commit e22f8d9

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 e164a18 commit e22f8d9

File tree

3 files changed

+85
-1
lines changed

3 files changed

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

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)