1mod builtins;
2mod object;
3pub mod environment;
4
5use parser::ast::*;
6use crate::environment::*;
7use crate::object::{EvalError, Object};
8use parser::lexer::token::{TokenKind, Token};
9use std::rc::Rc;
10use std::cell::RefCell;
11use crate::builtins::BUILTINS;
12use std::collections::HashMap;
13
14pub fn eval(node: Node, env: &Env) -> Result<Rc<Object>, EvalError> {
15 match node {
16 Node::Program(p) => eval_block_statements(&p.statements, env),
17 Node::Statement(statements) => eval_statement(&statements, env),
18 Node::Expression(expression) => eval_expression(&expression, env),
19 }
20}
21
22fn eval_block_statements(statements: &Vec<Statement>, env: &Env) -> Result<Rc<Object>, EvalError> {
23 let mut result = Rc::new(Object::Null);
24 for statement in statements {
25 let val = eval_statement(statement, &Rc::clone(env))?;
26 match *val {
27 Object::ReturnValue(_) => return Ok(val),
28 _ => { result = val; }
29 }
30 }
31
32 return Ok(result);
33}
34
35fn eval_statement(statement: &Statement, env: &Env) -> Result<Rc<Object>, EvalError> {
36 match statement {
37 Statement::Expr(expr) => eval_expression(expr, env),
38 Statement::Return(expr) => {
39 let val = eval_expression(expr, env)?;
40 return Ok(Rc::new(Object::ReturnValue(val)));
41 },
42 Statement::Let(id, expr) => {
43 let val = eval_expression(expr, &Rc::clone(env))?;
44 let obj: Rc<Object> = Rc::clone(&val);
45 env.borrow_mut().set(id.clone(), obj);
46 return Ok(Rc::new(Object::Null));
47 }
48 }
49}
50
51fn is_truthy(obj: &Object) -> bool {
52 match obj {
53 Object::Null => return false,
54 Object::Boolean(false) => return false,
55 _ => true,
56 }
57}
58
59fn eval_expression(expression: &Expression, env: &Env) -> Result<Rc<Object>, EvalError> {
60 match expression {
61 Expression::LITERAL(literal) => eval_literal(literal, env),
62 Expression::PREFIX(op, expr) => {
63 let right = eval_expression(expr, &Rc::clone(env))?;
64 return eval_prefix(op, &right);
65 }
66 Expression::INFIX(op, left, right) => {
67 let left = eval_expression(left, &Rc::clone(env))?;
68 let right = eval_expression(right, &Rc::clone(env))?;
69 return eval_infix(op, &left, &right);
70 }
71 Expression::IF(condition, consequence, alternative) => {
72 let condition = eval_expression(condition, &Rc::clone(env))?;
73 if is_truthy(&condition) {
74 eval_block_statements(&(consequence.0), env)
75 } else {
76 match alternative {
77 Some(alt) => eval_block_statements(&(alt.0), env),
78 None => Ok(Rc::new(Object::Null))
79 }
80 }
81 }
82 Expression::IDENTIFIER(id) => eval_identifier(&id, env),
83 Expression::FUNCTION(params, body) => {
84 return Ok(Rc::new(Object::Function(params.clone(), body.clone(), Rc::clone(env))));
85 }
86 Expression::FunctionCall(func, args) => {
87 let func = eval_expression(func, &Rc::clone(env))?;
88 let args = eval_expressions(args, env)?;
89 apply_function(&func, &args)
90 }
91 Expression::Index(left, index) => {
92 let literal = eval_expression(left, &Rc::clone(env))?;
93 let index = eval_expression(index, env)?;
94 eval_index_expression(&literal, &index)
95 }
96 }
97}
98
99fn eval_index_expression(left: &Rc<Object>, index: &Rc<Object>) -> Result<Rc<Object>, EvalError> {
100 match (&**left, &**index) {
101 (Object::Array(arr), Object::Integer(idx)) => {
102 match arr.get(*idx as usize) {
103 Some(obj) => return Ok(Rc::clone(obj)),
104 None => return Ok(Rc::new(Object::Null))
105 }
106 },
107 (Object::Hash(map), key) => {
108 if !(key.is_hashable()) {
109 return Err(format!("not a valid hash key"))
110 }
111
112 match map.get(key) {
113 Some(obj) => return Ok(Rc::clone(obj)),
114 None => return Ok(Rc::new(Object::Null))
115 }
116 },
117 _ => return Err(format!("index operator not supported for {}", left)),
118 }
119}
120
121fn apply_function(function: &Rc<Object>, args: &Vec<Rc<Object>>) -> Result<Rc<Object>, EvalError> {
122 match &**function {
123 Object::Function(params, body, env) => {
124 let mut env = Environment::new_enclosed_environment(&env);
125
126 params.iter().enumerate().for_each(|(i, param)| {
127 env.set(param.clone(), args[i].clone());
128 });
129
130 let evaluated = eval_block_statements(&body.0, &Rc::new(RefCell::new(env)))?;
131 return unwrap_return(evaluated);
132
133 },
134 Object::Builtin(b) => Ok(b(args.to_vec())),
135 f => Err(format!("expected {} to be a function", f))
136 }
137}
138
139fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
140 if let Object::ReturnValue(val) = &*obj {
141 Ok(Rc::clone(&val))
142 } else {
143 Ok(obj)
144 }
145}
146
147fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
148 let mut list = Vec::new();
149 for expr in exprs {
150 let val = eval_expression(expr, &Rc::clone(env))?;
151 list.push(val);
152 }
153
154 Ok(list)
155}
156
157fn eval_identifier(id: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
158 match env.borrow().get(id) {
159 Some(obj) => Ok(obj.clone()),
160 None => {
161 match BUILTINS.get(id) {
162 Some(obj) => Ok(Rc::new(Object::Builtin(*obj))),
163 None => Err(format!("unknown identifier {}", id)),
164 }
165 }
166 }
167}
168
169fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
170 match op.kind {
171 TokenKind::BANG => eval_prefix_bang(right),
172 TokenKind::MINUS => eval_prefix_minus(right),
173 _ => Err(format!("unknown prefix operator: {}", op))
174 }
175}
176
177fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
178 match *expr {
179 Object::Null => Ok(Rc::new(Object::Boolean(true))),
180 Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
181 _ => Ok(Rc::new(Object::Boolean(false)))
182 }
183}
184
185fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
186 match *expr {
187 Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
188 _ => Err(format!("can't apply prefix minus operator: {}", expr))
189 }
190}
191
192fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
193 match (left, right) {
194 (Object::Integer(left), Object::Integer(right)) => {
195 return eval_integer_infix(op, *left, *right);
196 }
197 (Object::Boolean(left), Object::Boolean(right)) => {
198 return eval_boolean_infix(op, *left, *right);
199 }
200 (Object::String(left), Object::String(right)) => {
201 return eval_string_infix(op, left.to_string(), right.to_string());
202 }
203 _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right))
204 }
205}
206
207fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
208 let result = match &op.kind {
209 TokenKind::PLUS => Object::Integer(left + right),
210 TokenKind::MINUS => Object::Integer(left - right),
211 TokenKind::ASTERISK => Object::Integer(left * right),
212 TokenKind::SLASH => Object::Integer(left / right),
213 TokenKind::LT => Object::Boolean(left < right),
214 TokenKind::GT => Object::Boolean(left > right),
215 TokenKind::EQ => Object::Boolean(left == right),
216 TokenKind::NotEq => Object::Boolean(left != right),
217 op => return Err(format!("Invalid infix operator {} for int", op))
218 };
219
220 Ok(Rc::from(result))
221}
222
223fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
224 let result = match &op.kind {
225 TokenKind::EQ => Object::Boolean(left == right),
226 TokenKind::NotEq => Object::Boolean(left != right),
227 op => return Err(format!("Invalid infix operator for int: {}", op))
228 };
229
230 Ok(Rc::from(result))
231}
232
233fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
234 let result = match &op.kind {
235 TokenKind::EQ => Object::Boolean(left == right),
236 TokenKind::NotEq => Object::Boolean(left != right),
237 TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
238 op => return Err(format!("Invalid infix {} operator for string", op))
239 };
240
241 Ok(Rc::from(result))
242}
243
244fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
245 match literal {
246 Literal::Integer(i) => Ok(Rc::from(Object::Integer(*i))),
247 Literal::Boolean(b) => Ok(Rc::from(Object::Boolean(*b))),
248 Literal::String(s) => Ok(Rc::from(Object::String(s.clone()))),
249 Literal::Array(elements) => {
250 let list = eval_expressions(elements, env)?;
251 return Ok(Rc::from(Object::Array(list)));
252 }
253 Literal::Hash(map) => {
254 let mut hash_map = HashMap::new();
255
256 for (k, v) in map {
257 let key = eval_expression(k, env)?;
258 if !key.is_hashable() {
259 return Err(format!("key {} is not hashable", key));
260 }
261 let value = eval_expression(v, env)?;
262 hash_map.insert(key, value);
263 }
264
265 return Ok(Rc::new(Object::Hash(hash_map)));
266 }
267 }
269}
270
271#[cfg(test)]
272mod tests {
273 use parser::*;
274 use crate::eval;
275 use std::rc::Rc;
276 use std::cell::RefCell;
277 use crate::environment::*;
278
279 fn apply_test(test_cases: &[(&str, &str)]) {
280 let env: Env = Rc::new(RefCell::new(Default::default()));
281 for (input, expected) in test_cases {
282 match parse(input) {
283 Ok(node) => {
284 match eval(node, &env) {
285 Ok(evaluated) => assert_eq!(&format!("{}", evaluated), expected),
286 Err(e) => assert_eq!(&format!("{}", e), expected),
287 }
288 }
289 Err(e) => panic!("parse error: {}", e[0])
290 }
291 }
292 }
293
294 #[test]
295 fn test_integer_expressions() {
296 let test_case = [
297 ("1", "1"),
298 ("-10", "-10"),
299 ("5 + 5 + 5 + 5 - 10", "10"),
300 ("2 * 2 * 2 * 2 * 2", "32"),
301 ("(5 + 10 * 2 + 15 / 3) * 2 + -10", "50"),
302 ];
303 apply_test(&test_case);
304 }
305
306 #[test]
307 fn test_boolean_expressions() {
308 let test_case = [
309 ("true", "true"),
310 ("false", "false"),
311 ("1 < 2", "true"),
312 ("1 > 2", "false"),
313 ("1 < 1", "false"),
314 ("1 > 1", "false"),
315 ("1 == 1", "true"),
316 ("1 != 1", "false"),
317 ("1 == 2", "false"),
318 ("1 != 2", "true"),
319 ("true == true", "true"),
320 ("false == false", "true"),
321 ("true == false", "false"),
322 ("true != false", "true"),
323 ("false != true", "true"),
324 ("(1 < 2) == true", "true"),
325 ("(1 < 2) == false", "false"),
326 ("(1 > 2) == true", "false"),
327 ("(1 > 2) == false", "true"),
328 ];
329 apply_test(&test_case);
330 }
331
332 #[test]
333 fn test_bang_operators() {
334 let test_case = [
335 ("!true", "false"),
336 ("!false", "true"),
337 ("!5", "false"),
338 ("!!true", "true"),
339 ("!!false", "false"),
340 ("!!5", "true"),
341 ];
342 apply_test(&test_case);
343 }
344
345 #[test]
346 fn test_if_else_expressions() {
347 let test_case = [
348 ("if (true) { 10 }", "10"),
349 ("if (false) { 10 }", "null"),
350 ("if (1) { 10 }", "10"),
351 ("if (1 < 2) { 10 }", "10"),
352 ("if (1 > 2) { 10 }", "null"),
353 ("if (1 > 2) { 10 } else { 20 }", "20"),
354 ("if (1 < 2) { 10 } else { 20 }", "10"),
355 ];
356 apply_test(&test_case);
357 }
358
359 #[test]
360 fn test_return_statements() {
361 let test_case = [
362 ("return 10;", "10"),
363 ("return 10; 9;", "10"),
364 ("return 2 * 5; 9;", "10"),
365 ("9; return 2 * 5; 9;", "10"),
366 ("if (10 > 1) { return 10; }", "10"),
367 (
368 "if (10 > 1) { \
369 if (10 > 1) { \
370 return 10; \
371 } \
372 return 1; \
373 }",
374 "10",
375 ),
376 (
377 "let f = fn(x) { \
378 return x; \
379 x + 10; \
380 }; \
381 f(10);",
382 "10",
383 ),
384 (
385 "let f = fn(x) { \
386 let result = x + 10; \
387 return result; \
388 return 10; \
389 }; \
390 f(10);",
391 "20",
392 ),
393 ];
394 apply_test(&test_case);
395 }
396
397 #[test]
398 fn test_let_statements() {
399 let test_case = [
400 ("let a = 5; a;", "5"),
401 ("let a = 5 * 5; a;", "25"),
402 ("let a = 5; let b = a; b;", "5"),
403 ("let a = 5; let b = a; let c = a + b + 5; c;", "15"),
404 ];
405 apply_test(&test_case);
406 }
407
408 #[test]
409 fn test_function_object() {
410 let test_case = [("fn(x) { x + 2; };", "fn(x) { (x + 2) }")];
411 apply_test(&test_case);
412 }
413
414 #[test]
415 fn test_function_application() {
416 let test_case = [
417 ("let identity = fn(x) { x; }; identity(5);", "5"),
418 ("let identity = fn(x) { return x; }; identity(5);", "5"),
419 ("let double = fn(x) { x * 2; }; double(5);", "10"),
420 ("let add = fn(x, y) { x + y; }; add(5, 5);", "10"),
421 (
422 "let add = fn(x, y) { x + y; }; add(5 + 5, add(5, 5));",
423 "20",
424 ),
425 ("fn(x) { x; }(5)", "5"),
426 ];
427 apply_test(&test_case);
428 }
429
430 #[test]
431 fn test_string_concatenation() {
432 let test_case = [
433 (r#""Hello" + " " + "World!""#, "Hello World!"),
434 (r#""Hello" == "Hello""#, "true"),
435 (r#""Hello" == "Hi""#, "false"),
436 ];
437 apply_test(&test_case);
438 }
439
440 #[test]
441 fn test_builtin_functions() {
442 let test_case = [
443 (r#"len("")"#, "0"),
444 (r#"len("four")"#, "4"),
445 (r#"len("hello world")"#, "11"),
446 ];
447 apply_test(&test_case);
448 }
449
450
451 #[test]
452 fn test_array_literals() {
453 let test_case = [("[1, 2 * 2, 3 + 3]", "[1, 4, 6]")];
454 apply_test(&test_case);
455 }
456
457 #[test]
458 fn test_array_index_expressions() {
459 let test_case = [
460 ("let i = 0; [1][i];", "1"),
461 ("[1, 2, 3][1 + 1];", "3"),
462 ("let myArray = [1, 2, 3]; myArray[2];", "3"),
463 (
464 "let myArray = [1, 2, 3]; myArray[0] + myArray[1] + myArray[2];",
465 "6",
466 ),
467 (
468 "let myArray = [1, 2, 3]; let i = myArray[0]; myArray[i]",
469 "2",
470 ),
471 ("[1, 2, 3][3]", "null"),
472 ("[1, 2, 3][-1]", "null"),
473 ];
474 apply_test(&test_case);
475 }
476
477 #[test]
478 fn test_array_builtin_functions() {
479 let test_case = [
480 ("len([1, 2, 3])", "3"),
481 ("len([])", "0"),
482 (r#"puts("hello", "world!")"#, "null"),
483 ("first([1, 2, 3])", "1"),
484 ("first([])", "null"),
485 ("last([1, 2, 3])", "3"),
486 ("last([])", "null"),
487 ("rest([1, 2, 3])", "[2, 3]"),
488 ("rest([])", "null"),
489 ("push([], 1)", "[1]"),
490 ];
491 apply_test(&test_case);
492 }
500
501 #[test]
502 fn test_hash_index_expressions() {
503 let test_case = [
504 (r#"{"foo": 5}["foo"]"#, "5"),
505 (r#"{"foo": 5}["bar"]"#, "null"),
506 (r#"let key = "foo"; {"foo": 5}[key]"#, "5"),
507 (r#"{}["foo"]"#, "null"),
508 (r#"{5: 5}[5]"#, "5"),
509 (r#"{true: 5}[true]"#, "5"),
510 (r#"{false: 5}[false]"#, "5"),
511 ];
512 apply_test(&test_case);
513 }
514
515}