From c92f4e9e828d65b555e24fb98d216d43a61f1309 Mon Sep 17 00:00:00 2001 From: Ishan Jain Date: Sat, 18 May 2024 08:46:19 +0530 Subject: [PATCH] Added closure test, accept ints in variable names --- readme.md | 4 ++++ src/evaluator/mod.rs | 34 ++++++++++++++++++++++++++++++++ src/evaluator/tree_walker/mod.rs | 6 ++++-- src/lexer/mod.rs | 2 +- 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..a555d29 --- /dev/null +++ b/readme.md @@ -0,0 +1,4 @@ +# Monkey Interpreter + +This project is my attempt at writing an interpreter while working through the book, [Writing an Interpreter in Go](https://interpreterbook.com/). +It supports all the features from the book. diff --git a/src/evaluator/mod.rs b/src/evaluator/mod.rs index 7774a33..2054912 100644 --- a/src/evaluator/mod.rs +++ b/src/evaluator/mod.rs @@ -346,4 +346,38 @@ mod tests { run_test_cases(&test_cases); } + + #[test] + fn test_closure() { + let test_cases = [( + "let newAdder = fn(x) { + fn(y) { x + y ; } ; + }; + let adder5 = newAdder(5); + adder5(10); + ", + Some(Object::Integer(15)), + )]; + + run_test_cases(&test_cases); + } + + #[test] + fn memory_test() { + let test_cases = [( + "let counter = fn(x) { + if (x > 100 ) { + return true; + } else { + let foobar = 9999; + counter(x+1); + } + }; + counter(0); + ", + Some(Object::Integer(15)), + )]; + + run_test_cases(&test_cases); + } } diff --git a/src/evaluator/tree_walker/mod.rs b/src/evaluator/tree_walker/mod.rs index 1039621..29e3381 100644 --- a/src/evaluator/tree_walker/mod.rs +++ b/src/evaluator/tree_walker/mod.rs @@ -84,7 +84,6 @@ impl Evaluator for TreeWalker { Some(NULL) } } - _ => None, }, } } @@ -239,13 +238,16 @@ impl TreeWalker { fn apply_function(&self, function: Object, args: Vec) -> Option { let function = match function { Object::Function(f) => f, + Object::Error(e) => { + return Some(Object::Error(format!("not a function: {}", e.to_string()))); + } v => return Some(Object::Error(format!("not a function: {}", v.to_string()))), }; + println!("{:?}", function.env); let mut enclosed_env = Environment::new_enclosed(function.env); for (i, parameter) in function.parameters.iter().enumerate() { if args.len() <= i { - println!("{:?} {}", args, i); return Some(Object::Error(format!("incorrect number of arguments"))); } diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index d23f618..9640ec4 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -158,7 +158,7 @@ impl<'a> Lexer<'a> { fn read_identifier(&mut self, first: char) -> String { let mut ident = String::new(); ident.push(first); - while self.peek_is_letter() { + while self.peek_is_letter() || self.peek_is_ascii_digit() { ident.push(self.read_char().unwrap()); } ident