sapphire-lang 0.8.0

Gradually typed scripting language where every value is an object and types are optional, checked at runtime
Documentation
use crate::gc::{GcHeap, GcRef};
use crate::vm::{define_native_class_method, HeapObject, VmError, VmValue};

fn math_arg(args: &[VmValue], method: &str, line: u32) -> Result<f64, VmError> {
    match args {
        [VmValue::Float(f)] => Ok(*f),
        [VmValue::Int(i)]   => Ok(*i as f64),
        [_] => Err(VmError::TypeError {
            message: format!("Math.{method}: argument must be numeric"), line,
        }),
        _ => Err(VmError::TypeError {
            message: format!("Math.{method} expects 1 argument, got {}", args.len()), line,
        }),
    }
}

fn math_sin(
    _heap: &mut GcHeap<HeapObject>,
    _recv: &VmValue,
    args: &[VmValue],
    line: u32,
) -> Result<VmValue, VmError> {
    math_arg(args, "sin", line).map(|f| VmValue::Float(f.sin()))
}

fn math_cos(
    _heap: &mut GcHeap<HeapObject>,
    _recv: &VmValue,
    args: &[VmValue],
    line: u32,
) -> Result<VmValue, VmError> {
    math_arg(args, "cos", line).map(|f| VmValue::Float(f.cos()))
}

fn math_asin(
    _heap: &mut GcHeap<HeapObject>,
    _recv: &VmValue,
    args: &[VmValue],
    line: u32,
) -> Result<VmValue, VmError> {
    math_arg(args, "asin", line).map(|f| VmValue::Float(f.asin()))
}

fn math_atan(
    _heap: &mut GcHeap<HeapObject>,
    _recv: &VmValue,
    args: &[VmValue],
    line: u32,
) -> Result<VmValue, VmError> {
    math_arg(args, "atan", line).map(|f| VmValue::Float(f.atan()))
}

pub fn register_class_methods(heap: &mut GcHeap<HeapObject>, class_ref: GcRef) {
    define_native_class_method(heap, class_ref, "sin",  1, math_sin);
    define_native_class_method(heap, class_ref, "cos",  1, math_cos);
    define_native_class_method(heap, class_ref, "asin", 1, math_asin);
    define_native_class_method(heap, class_ref, "atan", 1, math_atan);
}