1use std::cell::RefCell;
2
3use chialisp::classic::clvm_tools::binutils::disassemble;
4use clvm_traits::{FromClvm, destructure_tuple, match_tuple};
5use clvmr::{
6 Allocator, ChiaDialect, NodePtr,
7 dialect::{Dialect, OperatorSet},
8 error::EvalErr,
9 reduction::Reduction,
10};
11use colored::Colorize;
12
13use crate::ClvmOp;
14
15#[derive(Debug, Clone)]
16pub struct PrintMessage {
17 pub srcloc: String,
18 pub message: String,
19}
20
21#[derive(Debug, Clone)]
22pub struct DebugDialect {
23 flags: u32,
24 stdout: bool,
25 log: RefCell<Vec<PrintMessage>>,
26}
27
28impl DebugDialect {
29 pub fn new(flags: u32, stdout: bool) -> Self {
30 Self {
31 flags,
32 stdout,
33 log: RefCell::new(Vec::new()),
34 }
35 }
36
37 pub fn log(&self) -> Vec<PrintMessage> {
38 self.log.borrow().clone()
39 }
40
41 fn inner(&self) -> ChiaDialect {
42 ChiaDialect::new(self.flags)
43 }
44}
45
46impl Dialect for DebugDialect {
47 fn quote_kw(&self) -> u32 {
48 self.inner().quote_kw()
49 }
50
51 fn apply_kw(&self) -> u32 {
52 self.inner().apply_kw()
53 }
54
55 fn softfork_kw(&self) -> u32 {
56 self.inner().softfork_kw()
57 }
58
59 fn softfork_extension(&self, ext: u32) -> OperatorSet {
60 self.inner().softfork_extension(ext)
61 }
62
63 fn op(
64 &self,
65 allocator: &mut Allocator,
66 op: NodePtr,
67 args: NodePtr,
68 max_cost: u64,
69 extensions: OperatorSet,
70 ) -> Result<Reduction, EvalErr> {
71 if allocator.atom(op).as_ref() == ClvmOp::DebugPrint.to_atom() {
72 let Some(destructure_tuple!(srcloc, value, _)) =
73 <match_tuple!(String, NodePtr, NodePtr)>::from_clvm(allocator, args).ok()
74 else {
75 return Err(EvalErr::InvalidNilTerminator(args));
76 };
77
78 let message = disassemble(allocator, value, None);
79
80 if self.stdout {
81 eprintln!("{}: {}", srcloc.cyan().bold(), message);
82 }
83
84 self.log.borrow_mut().push(PrintMessage { srcloc, message });
85
86 return Ok(Reduction(0, NodePtr::NIL));
87 }
88
89 self.inner().op(allocator, op, args, max_cost, extensions)
90 }
91
92 fn allow_unknown_ops(&self) -> bool {
93 self.inner().allow_unknown_ops()
94 }
95}