diff options
Diffstat (limited to 'src/cexpr.rs')
| -rw-r--r-- | src/cexpr.rs | 132 | 
1 files changed, 132 insertions, 0 deletions
| diff --git a/src/cexpr.rs b/src/cexpr.rs new file mode 100644 index 0000000..bac316c --- /dev/null +++ b/src/cexpr.rs @@ -0,0 +1,132 @@ +/* + * Canonical Expressions + * + * AKA, simplified, normalized algebraic expressions. + * + */ + +use crate::sexpr::SExpr; + +pub enum NumericConstant { +    Pi, // 3.141592... +    E,  // 2.718281... +    Infinity, +} + +#[derive(Clone, PartialEq)] +pub enum CNumber { +    Integer(i64), +    Rational(i64, u64), +    // Float +    // Constant +} + +impl CNumber { +    pub fn to_sexpr(&self) -> Result<SExpr, String> { +        match self { +            CNumber::Integer(v) => Ok(SExpr::SInteger(*v)), +            CNumber::Rational(a, b) => Ok(SExpr::SList(vec![ +                SExpr::SBuiltin("/".to_string()), +                SExpr::SInteger(*a), +                SExpr::SInteger(*b as i64), +            ])), +        } +    } +} + +#[derive(Clone, PartialEq)] +pub enum CExpr { +    Symbol(String), +    Number(CNumber), +    Sum(Option<CNumber>, Vec<CExpr>), +    Product(Option<CNumber>, Vec<CExpr>), +    Power(Box<CExpr>, Box<CExpr>), +    Factorial(Box<CExpr>), +    UnaryFunction(String, Box<CExpr>), + +    // TODO: Infinity? +    // TODO: Limit? +    // TODO: Vector? +} + +impl CExpr { + +    pub fn from_sexpr(sexpr: &SExpr) -> Result<CExpr, String> { + +        // not all cases are handled; some atoms are covered trivialy +        match sexpr { +            SExpr::SNull => Err("null not handled".to_string()), +            SExpr::STrue | SExpr::SFalse => Err("booleans not handled".to_string()), +            SExpr::SInteger(v) => Ok(CExpr::Number(CNumber::Integer(*v))), +            SExpr::SFloat(v) => Err("floats not handled".to_string()), +            SExpr::SBuiltin(v) => Ok(CExpr::Symbol(v.to_string())), +            SExpr::SSymbol(v) => Err(format!("symbols (quoted identifiers) not handled: {}", v)), +            SExpr::SIdentifier(v) => Ok(CExpr::Symbol(v.to_string())), +            SExpr::SString(_) => Err("null not handled".to_string()), +            SExpr::SList(_) => Err("null not handled".to_string()), +            //SExpr::SList(l) => CExpr::from_sexpr_list(l), +        } +    } + +/* +    pub fn from_sexpr_list(list: &Vec<SExpr>) -> Result<CExpr, String> { +        if list.is_empty() { +            unimplemented!() +        } +        match list[0] { +            SExpr::SBuiltin("+") => { +                Ok(CExpr::Sum( +                    // XXX +                    None, +                    list[1..].iter().map(|v| CExpr::from_sexpr(v)).collect::<Result<Vec<SExpr>, String>>()?, +                )) +            }, +            SExpr::SBuiltin("*") => { +            }, +            SExpr::SBuiltin("^") => { +            }, +            _ => { +                unimplemented!() +            } +        } +    } +*/ + +    pub fn new_sum(list: &Vec<SExpr>) -> Result<CExpr, String> { +        unimplemented!() +    } + +    pub fn new_product(list: &Vec<SExpr>) -> Result<CExpr, String> { +        unimplemented!() +    } + +    pub fn to_sexpr(&self) -> Result<SExpr, String> { +        match self { +            CExpr::Symbol(s) => Ok(SExpr::SIdentifier(s.to_string())), +            CExpr::Number(n) => n.to_sexpr(), +            CExpr::Sum(n, l) => Ok(SExpr::SList(vec![ +                SExpr::SBuiltin("+".to_string()), +                SExpr::SList(l.iter().map(|v| v.to_sexpr()).collect::<Result<Vec<SExpr>, String>>()?), +                // XXX: n +            ])), +            CExpr::Product(n, l) => Ok(SExpr::SList(vec![ +                SExpr::SBuiltin("*".to_string()), +                SExpr::SList(l.iter().map(|v| v.to_sexpr()).collect::<Result<Vec<SExpr>, String>>()?), +                // XXX: n +            ])), +            CExpr::Power(a, b) => Ok(SExpr::SList(vec![ +                SExpr::SBuiltin("^".to_string()), +                a.to_sexpr()?, +                b.to_sexpr()?, +            ])), +            CExpr::Factorial(v) => Ok(SExpr::SList(vec![ +                SExpr::SIdentifier("factorial".to_string()), +                v.to_sexpr()?, +            ])), +            CExpr::UnaryFunction(s, v) => Ok(SExpr::SList(vec![ +                SExpr::SIdentifier(s.to_string()), +                v.to_sexpr()?, +            ])), +        } +    } +} | 
