summaryrefslogtreecommitdiff
path: root/src/lib/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eval')
-rw-r--r--src/lib/eval/arith.rs34
-rw-r--r--src/lib/eval/mod.rs54
2 files changed, 88 insertions, 0 deletions
diff --git a/src/lib/eval/arith.rs b/src/lib/eval/arith.rs
new file mode 100644
index 0000000..fae69de
--- /dev/null
+++ b/src/lib/eval/arith.rs
@@ -0,0 +1,34 @@
+use std::ops::Add;
+use super::super::types::Type;
+use super::super::types::Type::*;
+use super::super::types::Number;
+
+impl Add for Type {
+ type Output = Result<Type, String>;
+
+ fn add(self, other: Type) -> Result<Type, String> {
+ match (self, other) {
+ (Bool(_), _) | (_, Bool(_)) |
+ (Str(_), _) | (_, Str(_)) |
+ (Operator(_), _) | (_, Operator(_)) => {
+ Err("Cannot add these types".to_string())
+ },
+ (Number(Number::Int(i)), Number(Number::Float(f))) |
+ (Number(Number::Float(f)), Number(Number::Int(i))) => {
+ Ok(Number(Number::Float(f + i as f32)))
+ },
+
+ (Number(Number::Int(a)), Number(Number::Int(b))) => {
+ Ok(Number(Number::Int(a + b)))
+ },
+
+ (Number(Number::Float(a)), Number(Number::Float(b))) => {
+ Ok(Number(Number::Float(a + b)))
+ },
+
+ (Symbol(_), Number(_)) |
+ (Number(_), Symbol(_)) |
+ (Symbol(_), Symbol(_)) => Err("Not yet implemented".to_string())
+ }
+ }
+}
diff --git a/src/lib/eval/mod.rs b/src/lib/eval/mod.rs
new file mode 100644
index 0000000..b582397
--- /dev/null
+++ b/src/lib/eval/mod.rs
@@ -0,0 +1,54 @@
+use std::collections::HashMap;
+use super::types::Op;
+use super::types::Op::*;
+use super::types::SEXP;
+use super::types::SEXP::*;
+use super::types::Type::*;
+use super::types::Number;
+
+pub mod arith;
+
+pub type Env = HashMap<String, SEXP>;
+
+pub fn eval(expr: &SEXP, env: &mut Env) -> Result<SEXP, String> {
+ match expr {
+ Atom(ref x) => Ok(Atom((*x).clone())),
+ Sexpr(ref s) => seval(s, env)
+ }
+}
+
+fn seval(sexpr: &[SEXP], env: &mut Env) -> Result<SEXP, String> {
+ if sexpr.is_empty() {
+ return Err("Empty S Expression".to_string())
+ }
+
+ let op = match &sexpr[0] {
+ Atom(Operator(x)) => *x,
+ Atom(Symbol(_s)) => return Err("Not yet implemented".to_string()),
+ x => return Err(format!("{:?} is not a procedure", x))
+ };
+
+ op_eval(op, &sexpr[1..], env)
+}
+
+fn op_eval(op: Op, expr: &[SEXP], env: &mut Env) -> Result<SEXP, String> {
+ match op {
+ Add => op_add(expr, env),
+ //Define => define(expr, env),
+ _ => Err("Not yet implemented".to_string())
+ }
+}
+
+fn op_add(expr: &[SEXP], env: &mut Env) -> Result<SEXP, String> {
+ let mut acc = Number(Number::Int(0));
+ let mut i = 0;
+ while i < expr.len() {
+ let b = match eval(&expr[i], env)? {
+ Atom(x) => x,
+ Sexpr(_) => panic!("This should have evaluated to an atom")
+ };
+ acc = (acc + b)?;
+ i += 1;
+ }
+ Ok(SEXP::Atom(acc))
+}