rl_lang/interpreter/stdlib/debug/
assert_approx_eq.rs1use crate::{
2 interpreter::{evaluator::Evaluator, stdlib::debug::common::as_f64, values::Value},
3 utils::{errors::Error, span::Span},
4};
5
6pub fn func(eval: &mut Evaluator, args: Vec<Value>, span: Span) -> Result<Value, Error> {
7 if args.len() < 2 || args.len() > 3 {
9 return Err(eval.err(
10 format!(
11 "assert_approx_eq: expects 2 or 3 arguments, got {}",
12 args.len()
13 ),
14 span,
15 ));
16 }
17
18 let (a, b) = (&args[0], &args[1]);
19 let (fa, fb) = match (as_f64(a), as_f64(b)) {
20 (Some(fa), Some(fb)) => (fa, fb),
21 _ => {
22 return Err(eval.err(
23 format!(
24 "assert_approx_eq: expects numeric arguments, got {} and {}",
25 a.type_name(),
26 b.type_name()
27 ),
28 span,
29 ));
30 }
31 };
32
33 let epsilon = match args.get(2) {
34 Some(v) => as_f64(v).ok_or_else(|| {
35 eval.err(
36 format!(
37 "assert_approx_eq: expects a numeric epsilon, got {}",
38 v.type_name()
39 ),
40 span,
41 )
42 })?,
43 None => 1e-9,
44 };
45
46 if (fa - fb).abs() > epsilon {
47 return Err(eval.err(
48 format!(
49 "assert_approx_eq failed: `{}` and `{}` differ by more than {}",
50 a, b, epsilon
51 ),
52 span,
53 ));
54 }
55
56 Ok(Value::Null)
57}