ksl 0.1.7

KSL core library and interpreter
Documentation
//! # ksl::builtin::range
//!
//! Built-in function `Range`.

use crate::{Environment, eval::apply::eval_apply, is_number_eq, value::Value};

pub(crate) fn builtin(args: &[Value], env: &Environment) -> Option<(Value, Environment)> {
    if let [v1, v2, v3] = &args[..] {
        match (
            eval_apply(v1, env),
            eval_apply(v2, env),
            eval_apply(v3, env),
        ) {
            (Some((Value::Number(start), _)), Some((Value::Number(step), _)), Some((Value::Number(bound), _))) => {
                if is_number_eq(step, 0.0) && is_number_eq(start, bound) {
                    Some((Value::List(vec![Value::Number(start)]), Environment::new()))
                } else if step * (bound - start) >= 0.0 {
                    let mut elements = Vec::new();
                    let mut current = start;
                    while step * (bound - current) >= 0.0 {
                        elements.push(Value::Number(current));
                        current = current + step;
                    }
                    Some((Value::List(elements), Environment::new()))
                } else {
                    eprintln!(concat!(
                        "Error[ksl::builtin::range]: ",
                        "No terminating range."
                    ));
                    None
                }
            }
            (Some((e1, _)), Some((e2, _)), Some((e3, _))) => {
                eprintln!(
                    concat!(
                        "Error[ksl::builtin::range]: ",
                        "Only accepts 3 numbers, but {:?} was passed."
                    ),
                    (e1, e2, e3)
                );
                None
            }
            _ => {
                eprintln!(
                    concat!(
                        "Error[ksl::builtin::range]: ",
                        "Cannot evaluate expression {:?}."
                    ),
                    (v1, v2, v3)
                );
                None
            }
        }
    } else {
        eprintln!(
            concat!(
                "Error[ksl::builtin::range]: ",
                "Only accepts 3 arguments, but {} were passed."
            ),
            args.len()
        );
        None
    }
}