Skip to main content

rl_lang/interpreter/stdlib/math/
power.rs

1use crate::{
2    interpreter::{evaluator::Evaluator, values::Value},
3    utils::{errors::Error, span::Span},
4};
5
6pub fn std_pow(eval: &mut Evaluator, args: Vec<Value>, span: Span) -> Result<Value, Error> {
7    if args.len() != 2 {
8        return Err(eval.err(
9            format!("pow() expects 2 arguments, got {}", args.len()),
10            span,
11        ));
12    }
13    let mut iter = args.into_iter();
14    let base = normalize_numeric(iter.next().unwrap());
15    let exponent = normalize_numeric(iter.next().unwrap());
16
17    match (base, exponent) {
18        (Value::Integer(a), Value::Integer(b)) => {
19            let b = b as u32;
20            Ok(Value::Integer(a.pow(b)))
21        }
22        (Value::Integer(a), Value::Float(b)) => Ok(Value::Float((a as f64).powf(b))),
23        (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a.powf(b))),
24        (Value::Float(a), Value::Integer(b)) => Ok(Value::Float(a.powi(b as i32))),
25        _ => Err(eval.err("pow() expects numeric arguments".to_string(), span)),
26    }
27}
28
29// widen the byte to integer
30// more types will be implemented later
31// or being strict after adding explicit cast
32fn normalize_numeric(v: Value) -> Value {
33    match v {
34        Value::Byte(b) => Value::Integer(b as i64),
35        other => other,
36    }
37}