diff --git a/src/environment.rs b/src/environment.rs index f9bf56a..f6cd58b 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,5 +1,5 @@ -use crate::parser::Datum; use crate::parser::make_symbol; +use crate::parser::Datum; use crate::primitives; use std::mem; @@ -8,10 +8,12 @@ type Frame = Vec; pub type Env = Vec; pub fn get_global_environment() -> Env { - vec![vec![(make_symbol("+"), Datum::Procedure(primitives::add)), - (make_symbol("*"), Datum::Procedure(primitives::mul)), - (make_symbol("-"), Datum::Procedure(primitives::sub)), - (make_symbol("="), Datum::Procedure(primitives::eq))]] + vec![vec![ + (make_symbol("+"), Datum::Procedure(primitives::add)), + (make_symbol("*"), Datum::Procedure(primitives::mul)), + (make_symbol("-"), Datum::Procedure(primitives::sub)), + (make_symbol("="), Datum::Procedure(primitives::eq)), + ]] } pub fn lookup_variable_value(var: &Datum, env: &Env) -> Datum { @@ -79,4 +81,4 @@ pub fn extend_environment(vars: Datum, vals: Datum, env: &mut Env) -> Datum { pub fn shrink_environment(env: &mut Env) -> Datum { env.pop(); Datum::Unspecified -} \ No newline at end of file +} diff --git a/src/interpreter.rs b/src/interpreter.rs index 1ea2d00..b5d3fa6 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,9 +1,9 @@ -use crate::parser::Datum; -use crate::parser::Datum::*; -use crate::parser::make_symbol; use crate::environment; use crate::environment::Env; - +use crate::parser::make_symbol; +use crate::parser::Datum; +use crate::parser::Datum::*; + fn is_true(exp: &Datum) -> bool { match exp { Boolean(b) => *b, @@ -16,7 +16,7 @@ fn is_true(exp: &Datum) -> bool { fn has_tag(vec: &Vec, tag: &str) -> bool { if vec.len() == 0 { return false; - } + } if let Symbol(s) = &vec[0] { if s == tag { return true; @@ -49,7 +49,7 @@ fn interpret_define(args: &Vec, env: &mut Env) -> Datum { let var = &args[1]; let val = interpret(&args[2], env); environment::define_variable(var, val, env) - }, + } List(v) => { // procedure definition let definition_var = &v[0]; @@ -65,8 +65,8 @@ fn interpret_define(args: &Vec, env: &mut Env) -> Datum { let lambda_body = Datum::List(args[2..].to_vec()); let lambda = Datum::List(vec![make_symbol("lambda"), lambda_parameters, lambda_body]); environment::define_variable(definition_var, lambda, env) - }, - _ => panic!("INTERPRET-DEFINE -- cannot define {:?}", args) + } + _ => panic!("INTERPRET-DEFINE -- cannot define {:?}", args), } } @@ -106,8 +106,8 @@ fn interpret_application(vec: &Vec, env: &mut Env) -> Datum { } environment::shrink_environment(env); r - }, - _ => panic!("INTERPRET-APPLICATION -- not-aplicable {:?}", args[0]) + } + _ => panic!("INTERPRET-APPLICATION -- not-aplicable {:?}", args[0]), } } diff --git a/src/main.rs b/src/main.rs index 540d63b..b7bfac8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,46 @@ +mod environment; mod interpreter; mod lexer; mod parser; mod primitives; -mod environment; +use std::io; +use std::io::prelude::*; -fn main() { - // let scm_code = "(if (= 1 1) (+ 1 1) (* 2 3 4))"; - // let scm_code = "(begin (define a (+ 2 2)) (* 3 2) (* a a a))"; - let scm_code = "(begin (define (f n) (if (= n 1) 1 (* n (f (- n 1))))) (f 10))"; +fn repl() { + let mut env = environment::get_global_environment(); + loop { + let mut input = String::new(); + print!(" ]=> "); + io::stdout().flush().ok().expect("Could not flush stdout"); + match io::stdin().read_line(&mut input) { + Ok(_) => { + let tokens = lexer::read(&input); + let datum = parser::parse(tokens); + let result = interpreter::interpret(&datum, &mut env); + println!("{:?}", result); + } + Err(error) => println!("error: {}", error), + } + } +} + +fn interpret_code(scm_code: &str) { let tokens = lexer::read(scm_code); let datum = parser::parse(tokens); let mut env = environment::get_global_environment(); let result = interpreter::interpret(&datum, &mut env); println!("{:?}", result); } + +fn interpret_file() {} + +fn main() { + // let scm_code = "(begin (define (f n) (if (= n 1) 1 (* n (f (- n 1))))) (f 10))"; + let scm_code = ""; + + if scm_code.len() > 0 { + interpret_code(scm_code); + } else { + repl(); + } +} diff --git a/src/primitives.rs b/src/primitives.rs index 34ed86d..3bd0427 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -66,8 +66,12 @@ pub fn eq(args: Vec) -> Datum { for i in 2..args.len() { let current = &args[i]; match (first, current) { - (Boolean(b1), Boolean(b2)) => {return Boolean(b1 == b2);}, - (Number(n1), Number(n2)) => {return Boolean(n1 == n2);}, + (Boolean(b1), Boolean(b2)) => { + return Boolean(b1 == b2); + } + (Number(n1), Number(n2)) => { + return Boolean(n1 == n2); + } _ => { println!("{:?} is not equal to {:?}", first, current); return Boolean(false); @@ -76,4 +80,4 @@ pub fn eq(args: Vec) -> Datum { } Boolean(true) } -} \ No newline at end of file +}