From 410af116fe02f515a1741612721ccca41f187b45 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Sat, 23 Oct 2021 17:44:52 -0700 Subject: commit work-in-progress --- src/cexpr.rs | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 19 ++++++++- src/sexpr.rs | 4 +- 3 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 src/cexpr.rs (limited to 'src') 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 { + 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, Vec), + Product(Option, Vec), + Power(Box, Box), + Factorial(Box), + UnaryFunction(String, Box), + + // TODO: Infinity? + // TODO: Limit? + // TODO: Vector? +} + +impl CExpr { + + pub fn from_sexpr(sexpr: &SExpr) -> Result { + + // 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) -> Result { + 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::, String>>()?, + )) + }, + SExpr::SBuiltin("*") => { + }, + SExpr::SBuiltin("^") => { + }, + _ => { + unimplemented!() + } + } + } +*/ + + pub fn new_sum(list: &Vec) -> Result { + unimplemented!() + } + + pub fn new_product(list: &Vec) -> Result { + unimplemented!() + } + + pub fn to_sexpr(&self) -> Result { + 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::, 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::, 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", ]; -- cgit v1.2.3