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()?, + ])), + } + } +} |