diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cexpr.rs | 132 | ||||
-rw-r--r-- | src/main.rs | 19 | ||||
-rw-r--r-- | src/sexpr.rs | 4 |
3 files changed, 152 insertions, 3 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()?, + ])), + } + } +} diff --git a/src/main.rs b/src/main.rs index 6b2bc57..0f67aa4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,9 @@ use std::io::Write; use std::path::Path; mod sexpr; +mod cexpr; + +use cexpr::CExpr; fn repl(verbose: bool) { @@ -56,7 +59,21 @@ fn repl(verbose: bool) { continue; } }; - println!("{}", sexpr::sexpr_repr(&ast).unwrap()); + let expr = match CExpr::from_sexpr(&ast) { + Ok(v) => v, + Err(e) => { + println!("couldn't parse as math: {}", e); + continue; + }, + }; + match expr.to_sexpr() { + Ok(out) => println!("{}", sexpr::sexpr_repr(&ast).unwrap()), + Err(e) => { + println!("couldn't return to sexpr: {}", e); + continue; + }, + + } } } diff --git a/src/sexpr.rs b/src/sexpr.rs index 6cef563..da1012e 100644 --- a/src/sexpr.rs +++ b/src/sexpr.rs @@ -16,9 +16,9 @@ use std::path::Path; //////////// Types and Constants -const SEXPR_BUILTINS: [&'static str; 14] = [ +const SEXPR_BUILTINS: [&'static str; 15] = [ "=", ">", ">=", "<", "<=", - "+", "-", "*", "/", + "+", "-", "*", "/", "^", "exp", "log", "sin", "cos", "tan", ]; |