evaluator/
lib.rs

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        // l => return Err(format!("unknown literal: {}", *l))
268    }
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        // let illegal_cases = [
493        //     "len(1)",
494        //     r#"len("one", "two")"#,
495        //     "first(1)",
496        //     "last(1)",
497        //     "push(1, 1)"
498        // ];
499    }
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}