diff options
| -rw-r--r-- | rust/Cargo.toml | 2 | ||||
| -rw-r--r-- | rust/sample/test_let.txt | 1 | ||||
| -rw-r--r-- | rust/src/io.rs | 47 | ||||
| -rw-r--r-- | rust/src/lambda.rs | 61 | ||||
| -rw-r--r-- | rust/src/lib.rs | 4 | ||||
| -rw-r--r-- | rust/src/main.rs | 2 | ||||
| -rw-r--r-- | rust/src/parser.rs | 2 | ||||
| -rw-r--r-- | rust/tests/interpret_test.rs | 4 |
8 files changed, 69 insertions, 54 deletions
diff --git a/rust/Cargo.toml b/rust/Cargo.toml index bb52045..442a9ac 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,7 +11,7 @@ proptest = "1.0.0" [lib] name = "lambda" -path = "src/lambda.rs" +path = "src/lib.rs" [[bin]] name = "lambda" diff --git a/rust/sample/test_let.txt b/rust/sample/test_let.txt new file mode 100644 index 0000000..6027cd0 --- /dev/null +++ b/rust/sample/test_let.txt @@ -0,0 +1 @@ +(let (foo (lam x x)) ((let (foo foo) foo) 13)) diff --git a/rust/src/io.rs b/rust/src/io.rs new file mode 100644 index 0000000..33d8c4e --- /dev/null +++ b/rust/src/io.rs @@ -0,0 +1,47 @@ +use std::{ + fs::read_to_string, + io::{BufRead, BufReader, Read, Write}, +}; + +use crate::{ + ast::Value, + lambda::{eval, eval_all, Environment}, + parser::parse, +}; + +pub fn eval_file(file_name: &str) -> String { + let content = read_to_string(file_name).unwrap(); + let values = parse(&content.to_string()); + eval_all(&values) + .iter() + .map(|v| v.to_string()) + .collect::<Vec<String>>() + .join(" ") +} + +pub fn repl<I: Read, O: Write>(inp: &mut I, outp: &mut O) { + let mut env = Environment::new(); + let mut reader = BufReader::new(inp); + loop { + let mut input = String::new(); + write!(outp, "> ").unwrap(); + outp.flush().unwrap(); + match reader.read_line(&mut input) { + Ok(0) => break, + Ok(_) => (), + Err(e) => { + writeln!(outp, "{}", e).unwrap(); + break; + } + } + let values = parse(&input); + let results = values + .iter() + .map(|v| eval(v, &mut env)) + .collect::<Vec<Value>>(); + for result in results { + writeln!(outp, "{}", result).unwrap(); + outp.flush().unwrap(); + } + } +} diff --git a/rust/src/lambda.rs b/rust/src/lambda.rs index 5dbcdb2..2586de6 100644 --- a/rust/src/lambda.rs +++ b/rust/src/lambda.rs @@ -1,24 +1,16 @@ use rand::Rng; -use std::{ - collections::HashMap, - fs::read_to_string, - io::{BufRead, BufReader, Read, Write}, -}; +use std::collections::HashMap; -mod ast; -use ast::*; - -mod parser; -use parser::*; +use crate::ast::*; #[derive(Debug, PartialEq)] -struct Environment<'a> { +pub struct Environment<'a> { parent: Box<Option<&'a Environment<'a>>>, bindings: HashMap<String, Value>, } impl<'a> Environment<'a> { - fn new() -> Self { + pub fn new() -> Self { Environment { parent: Box::new(None), bindings: HashMap::new(), @@ -52,49 +44,18 @@ impl<'a> Environment<'a> { } } -pub fn eval_file(file_name: &str) -> String { - let content = read_to_string(file_name).unwrap(); - let values = parse(&content.to_string()); - eval_all(&values) - .iter() - .map(|v| v.to_string()) - .collect::<Vec<String>>() - .join(" ") -} - -pub fn repl<I: Read, O: Write>(inp: &mut I, outp: &mut O) { - let mut env = Environment::new(); - let mut reader = BufReader::new(inp); - loop { - let mut input = String::new(); - write!(outp, "> ").unwrap(); - outp.flush().unwrap(); - match reader.read_line(&mut input) { - Ok(0) => break, - Ok(_) => (), - Err(e) => { - writeln!(outp, "{}", e).unwrap(); - break; - } - } - let values = parse(&input); - let results = values - .iter() - .map(|v| eval(v, &mut env)) - .collect::<Vec<Value>>(); - for result in results { - writeln!(outp, "{}", result).unwrap(); - outp.flush().unwrap(); - } +impl<'a> Default for Environment<'a> { + fn default() -> Self { + Self::new() } } -fn eval_all(values: &[Value]) -> Vec<Value> { +pub fn eval_all(values: &[Value]) -> Vec<Value> { let mut env = Environment::new(); values.iter().map(|v| eval(v, &mut env)).collect() } -fn eval(arg: &Value, env: &mut Environment) -> Value { +pub fn eval(arg: &Value, env: &mut Environment) -> Value { match arg { Value::Def(var, value) => { env.bind(var, value); @@ -162,7 +123,9 @@ fn gensym() -> String { #[cfg(test)] mod lambda_test { - use crate::{eval, eval_all, parse, Environment, Value}; + use crate::parser::parse; + + use super::{eval, eval_all, Environment, Value}; fn parse1(string: &str) -> Value { parse(string).pop().unwrap() diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 0000000..a8cf18e --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,4 @@ +pub mod ast; +pub mod io; +pub mod lambda; +pub mod parser; diff --git a/rust/src/main.rs b/rust/src/main.rs index 136e868..b0e8ed9 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -3,7 +3,7 @@ use std::{ io::{stdin, stdout}, }; -use lambda::{eval_file, repl}; +use lambda::io::{eval_file, repl}; fn main() { if args().count() > 1 { diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 121a10f..2a5fef4 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -235,7 +235,7 @@ fn parse_number(token: &Token) -> Result<Value, String> { #[cfg(test)] mod tests { - use crate::parse_total; + use super::parse_total; use super::Token::*; use super::Value; diff --git a/rust/tests/interpret_test.rs b/rust/tests/interpret_test.rs index 40c3ee5..0ca3356 100644 --- a/rust/tests/interpret_test.rs +++ b/rust/tests/interpret_test.rs @@ -1,4 +1,4 @@ -use lambda::eval_file; +use lambda::io::{eval_file, repl}; #[test] fn interpreter_can_read_and_interpret_file() { @@ -12,6 +12,6 @@ fn interpreter_can_read_and_interpret_file() { fn repl_can_read_and_interpret_input() { let input = "(def id (lam x x))\n(id 12)"; let mut output = Vec::new(); - lambda::repl(&mut input.as_bytes(), &mut output); + repl(&mut input.as_bytes(), &mut output); assert_eq!("> true\n> 12\n> ", String::from_utf8(output).unwrap()); } |
