From 36e1bf722a3d366cea20ab7315d63d588d23dc48 Mon Sep 17 00:00:00 2001 From: Dominick Allen Date: Sat, 20 Jun 2020 13:38:03 -0500 Subject: Working on a simple LISP/scheme interpreter. --- src/lib/eval/arith.rs | 34 ++++++++++++++++++++++++++++++++ src/lib/eval/mod.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 src/lib/eval/arith.rs create mode 100644 src/lib/eval/mod.rs (limited to 'src/lib/eval') 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; + + fn add(self, other: Type) -> Result { + 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; + +pub fn eval(expr: &SEXP, env: &mut Env) -> Result { + match expr { + Atom(ref x) => Ok(Atom((*x).clone())), + Sexpr(ref s) => seval(s, env) + } +} + +fn seval(sexpr: &[SEXP], env: &mut Env) -> Result { + 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 { + 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 { + 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)) +} -- cgit v1.2.3