Skip to main content

rue_lir/
debug_dialect.rs

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}