rain-lang 0.0.1

An implementation of an RVSDG in Rust with a concept of lifetimes
Documentation
use crate::value::{
    ValueEnum, ValId,
    primitive::{
        logical::{Unary, Binary, LogicalOp}
    },
    expr::SexprArgs,
    error::{
        ValueError,
        NotAFunction
    }
};

impl SexprArgs {
    /// Apply a unary logical operation to an argument stack.
    /// Return whether any computation occured.
    pub(crate) fn apply_binary_logical(&mut self, b: Binary, _ptr: Option<&ValId>)
    -> Result<bool, ValueError> {
        let res = Ok(false);
        let left = if let Some(left) = self.pop() { left } else { return res };
        {
            let data = left.data();
            match data.value {
                ValueEnum::Bool(l) => {
                    if let Some(right) = self.pop() {
                        {
                            let data = right.data();
                            match data.value {
                                ValueEnum::Bool(r) => {
                                    self.push(ValId::from(b.apply(l, r)));
                                    return Ok(true)
                                },
                                //TODO: type errors and such
                                _ => {}
                            }
                        }
                        self.push(right);
                    }
                    self.push(ValId::from(b.partial_apply(l)));
                    return Ok(true)
                },
                //TODO: type errors and such
                _ => {}
            }
        }
        self.push(left);
        res
    }
    /// Apply a unary logical operation to an argument stack.
    /// Return whether any computation occured.
    pub(crate) fn apply_unary_logical(&mut self, u: Unary, _ptr: Option<&ValId>)
    -> Result<bool, ValueError> {
        let res = Ok(false);
        let arg = if let Some(arg) = self.pop() { arg } else { return res };
        {
            let data = arg.data();
            match data.value {
                ValueEnum::Bool(b) => {
                    self.push(ValId::from(u.apply(b)));
                    return Ok(true)
                },
                //TODO: type errors and such
                _ => {}
            }
        }
        // Cleanup
        self.push(arg);
        res
    }
    /// Apply a logical operation to an argument stack.
    /// Return whether any computation occured.
    pub(crate) fn apply_logical(&mut self, l: LogicalOp, ptr: Option<&ValId>)
    -> Result<bool, ValueError> {
        match l {
            LogicalOp::Binary(b) => self.apply_binary_logical(b, ptr),
            LogicalOp::Unary(u) => self.apply_unary_logical(u, ptr)
        }
    }
    /// Attempt to normalize these arguments
    pub(crate) fn try_normalize(&mut self) -> Result<(), ValueError> {
        while self.len() > 1 {
            let arg = self.pop().unwrap();
            match {
                let data = arg.data();
                match data.value {
                    ValueEnum::LogicalOp(l) => {
                        self.apply_logical(l, Some(&arg))
                    },
                    //TODO: sexpr flattening?
                    _ => {
                        if !data.value.applicable() { // This cannot be a function, giving an error
                            Err(ValueError::NotAFunction(NotAFunction{
                                applied: Some(arg.clone()),
                                argument: self.last().cloned()
                            }))
                        } else { Ok(false) }
                    }
                }
            } {
                Ok(true) => {},
                Ok(false) => { self.push(arg); return Ok(()) },
                Err(err) => { self.push(arg); return Err(err) }
            }
        }
        Ok(())
    }
}