arithmetic_eval/fns/
std.rs

1//! Functions that require the Rust standard library.
2
3use std::fmt;
4
5use crate::{exec::ModuleId, CallContext, EvalResult, NativeFn, SpannedValue, Value};
6
7/// Acts similarly to the `dbg!` macro, outputting the argument(s) to stderr and returning
8/// them. If a single argument is provided, it's returned as-is; otherwise, the arguments
9/// are wrapped into a tuple.
10///
11/// # Examples
12///
13/// ```
14/// # use arithmetic_parser::grammars::{F32Grammar, Parse, Untyped};
15/// # use arithmetic_eval::{fns, Environment, ExecutableModule, Value};
16/// # fn main() -> anyhow::Result<()> {
17/// let program = "dbg(1 + 2) > 2.5";
18/// let program = Untyped::<F32Grammar>::parse_statements(program)?;
19/// let module = ExecutableModule::new("test_dbg", &program)?;
20///
21/// let mut env = Environment::new();
22/// env.insert_native_fn("dbg", fns::Dbg);
23/// let value = module.with_env(&env)?.run()?;
24/// // Should output `[test_assert:1:5] 1 + 2 = 3` to stderr.
25/// assert_eq!(value, Value::Bool(true));
26/// # Ok(())
27/// # }
28/// ```
29#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
30#[derive(Debug, Clone, Copy, Default)]
31pub struct Dbg;
32
33impl Dbg {
34    fn print_value<T: fmt::Display>(module_id: &dyn ModuleId, value: &SpannedValue<T>) {
35        eprintln!(
36            "[{module}:{line}:{col}] {val}",
37            module = module_id,
38            line = value.location_line(),
39            col = value.get_column(),
40            val = value.extra
41        );
42    }
43}
44
45impl<T: fmt::Display> NativeFn<T> for Dbg {
46    fn evaluate(
47        &self,
48        mut args: Vec<SpannedValue<T>>,
49        ctx: &mut CallContext<'_, T>,
50    ) -> EvalResult<T> {
51        let module_id = ctx.call_location().module_id();
52        for arg in &args {
53            Self::print_value(module_id, arg);
54        }
55
56        Ok(if args.len() == 1 {
57            args.pop().unwrap().extra
58        } else {
59            Value::Tuple(args.into_iter().map(|spanned| spanned.extra).collect())
60        })
61    }
62}