summaryrefslogtreecommitdiff
path: root/src/lib/eval/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eval/mod.rs')
-rw-r--r--src/lib/eval/mod.rs62
1 files changed, 46 insertions, 16 deletions
diff --git a/src/lib/eval/mod.rs b/src/lib/eval/mod.rs
index b582397..adee0e5 100644
--- a/src/lib/eval/mod.rs
+++ b/src/lib/eval/mod.rs
@@ -1,54 +1,84 @@
-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::sexpr::SExpr;
+use super::sexpr::SExpr::*;
+use super::types::Type;
use super::types::Number;
+use super::environment::Environment;
pub mod arith;
-pub type Env = HashMap<String, SEXP>;
-
-pub fn eval(expr: &SEXP, env: &mut Env) -> Result<SEXP, String> {
+pub fn eval(expr: &SExpr, env: &mut Environment) -> Result<SExpr, 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> {
+fn seval(sexpr: &[SExpr], env: &mut Environment) -> Result<SExpr, 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()),
+ Atom(Type::Operator(x)) => *x,
+ Atom(Type::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> {
+fn op_eval(op: Op, expr: &[SExpr], env: &mut Environment) -> Result<SExpr, String> {
match op {
Add => op_add(expr, env),
+ Sub => op_sub(expr, env),
+ Mul => op_mul(expr, env),
+ Div => op_div(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));
+fn arith_op(
+ expr: &[SExpr],
+ env: &mut Environment,
+ identity: Number,
+ f: fn(Type, Type) -> Result<Type, String>) -> Result<SExpr, String>{
+
+ let mut acc = Type::Number(identity);
let mut i = 0;
+ if expr.len() > 1 {
+ let b = match eval(&expr[i], env)? {
+ Atom(x) => x,
+ Sexpr(_) => panic!("This should have evaluated to an atom")
+ };
+ acc = b;
+ i = 1;
+ }
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;
+ acc = (f(acc, b))?;
+ i += 1
}
- Ok(SEXP::Atom(acc))
+ Ok(SExpr::Atom(acc))
+}
+
+fn op_add(expr: &[SExpr], env: &mut Environment) -> Result<SExpr, String> {
+ arith_op(expr, env, Number::Int(0), |a, b| a + b)
+}
+
+fn op_sub(expr: &[SExpr], env: &mut Environment) -> Result<SExpr, String> {
+ arith_op(expr, env, Number::Int(0), |a, b| a - b)
+}
+
+fn op_mul(expr: &[SExpr], env: &mut Environment) -> Result<SExpr, String> {
+ arith_op(expr, env, Number::Int(1), |a, b| a * b)
+}
+
+fn op_div(expr: &[SExpr], env: &mut Environment) -> Result<SExpr, String> {
+ arith_op(expr, env, Number::Float(1.0), |a, b| a / b)
}