Added closure test, accept ints in variable names
This commit is contained in:
parent
4ca2e61654
commit
c92f4e9e82
4
readme.md
Normal file
4
readme.md
Normal file
|
@ -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.
|
|
@ -346,4 +346,38 @@ mod tests {
|
||||||
|
|
||||||
run_test_cases(&test_cases);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,6 @@ impl Evaluator for TreeWalker {
|
||||||
Some(NULL)
|
Some(NULL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,13 +238,16 @@ impl TreeWalker {
|
||||||
fn apply_function(&self, function: Object, args: Vec<Object>) -> Option<Object> {
|
fn apply_function(&self, function: Object, args: Vec<Object>) -> Option<Object> {
|
||||||
let function = match function {
|
let function = match function {
|
||||||
Object::Function(f) => f,
|
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()))),
|
v => return Some(Object::Error(format!("not a function: {}", v.to_string()))),
|
||||||
};
|
};
|
||||||
|
println!("{:?}", function.env);
|
||||||
|
|
||||||
let mut enclosed_env = Environment::new_enclosed(function.env);
|
let mut enclosed_env = Environment::new_enclosed(function.env);
|
||||||
for (i, parameter) in function.parameters.iter().enumerate() {
|
for (i, parameter) in function.parameters.iter().enumerate() {
|
||||||
if args.len() <= i {
|
if args.len() <= i {
|
||||||
println!("{:?} {}", args, i);
|
|
||||||
return Some(Object::Error(format!("incorrect number of arguments")));
|
return Some(Object::Error(format!("incorrect number of arguments")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ impl<'a> Lexer<'a> {
|
||||||
fn read_identifier(&mut self, first: char) -> String {
|
fn read_identifier(&mut self, first: char) -> String {
|
||||||
let mut ident = String::new();
|
let mut ident = String::new();
|
||||||
ident.push(first);
|
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.push(self.read_char().unwrap());
|
||||||
}
|
}
|
||||||
ident
|
ident
|
||||||
|
|
Loading…
Reference in New Issue
Block a user