aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cexpr.rs132
-rw-r--r--src/main.rs19
-rw-r--r--src/sexpr.rs4
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",
];