lynxlang/
evaluator.rs

1use std::cell::RefCell;
2use std::cell::RefMut;
3use std::collections::HashMap;
4use std::ops::Deref;
5use std::rc::Rc;
6
7use crate::{ast::*, builtin::*, env::Env, object::Object, token::TokenType};
8
9pub struct Evaluator {
10    env: Rc<RefCell<Env>>,
11}
12
13impl Evaluator {
14    pub fn new(env: Rc<RefCell<Env>>) -> Self {
15        Evaluator { env }
16    }
17
18    pub fn builtin(&mut self) {
19        let builtins = make_builtin();
20        self.env = Rc::new(RefCell::new(Env::from(builtins)));
21
22        println!("22 {:?}", self.env);
23    }
24
25    pub fn eval_program(&mut self, program: AstNode) -> Option<Object> {
26        println!("{:?}", program);
27
28        match program {
29            AstNode::Program(statements) => {
30                let mut value = Some(Object::Null);
31
32                for statement in statements {
33                    value = self.eval_statement(statement);
34                }
35
36                value
37            }
38        }
39    }
40
41    pub fn get_env(&self) -> RefMut<Env> {
42        self.env.borrow_mut()
43    }
44
45    fn eval_statement(&mut self, statement: Statement) -> Option<Object> {
46        match statement {
47            Statement::Let(identifier, expr) => self.eval_let_statement(identifier, expr),
48            Statement::Return(expr) => self.eval_return_statement(expr),
49            Statement::Expr(expr) => self.eval_expression(expr),
50            Statement::BlockStatement(statements) => self.eval_block_statements(statements),
51        }
52    }
53
54    fn eval_let_statement(&mut self, identifier: Box<Expression>, expr: Box<Expression>) -> Option<Object> {
55        match *identifier {
56            Expression::Identifier(ident) => match self.eval_expression(expr) {
57                Some(value) => {
58                    self.env.deref().borrow_mut().set(ident, value);
59                    None
60                }
61                None => None,
62            },
63            _ => None,
64        }
65    }
66
67    fn eval_return_statement(&mut self, expr: Box<Expression>) -> Option<Object> {
68        self.eval_expression(expr)
69    }
70
71    fn eval_block_statement(&mut self, block_stmt: Statement) -> Option<Object> {
72        match block_stmt {
73            Statement::BlockStatement(stmts) => self.eval_block_statements(stmts),
74            _ => Some(Object::Null),
75        }
76    }
77
78    fn eval_block_statements(&mut self, block_stmts: Vec<Statement>) -> Option<Object> {
79        let mut value = Some(Object::Null);
80
81        for stmt in block_stmts {
82            value = self.eval_statement(stmt);
83        }
84
85        value
86    }
87
88    fn eval_expression(&mut self, expr: Box<Expression>) -> Option<Object> {
89        match *expr {
90            Expression::String(string) => self.eval_string(string),
91            Expression::Integer(int) => self.eval_integer(int),
92            Expression::Boolean(bl) => self.eval_boolean(bl),
93            Expression::Identifier(identifer) => self.eval_identifier(identifer),
94            Expression::Array(exprs) => self.eval_array_expression(exprs),
95            Expression::Hash(hashes) => self.eval_hash_expression(hashes),
96            Expression::Prefix(operator, expr) => self.eval_prefix_expression(operator, expr),
97            Expression::Infix(left, operator, right) => self.eval_infix_expression(left, operator, right),
98            Expression::If(condition, statement, else_statement) => {
99                self.eval_if_expression(condition, statement, else_statement)
100            }
101            Expression::While(condition, block_statement) => self.eval_while_expression(condition, block_statement),
102            Expression::Break => Some(Object::Break),
103            Expression::Fn(fn_name, fn_parameter, fn_body) => self.eval_fn_expression(*fn_name, fn_parameter, fn_body),
104            Expression::FnCall(fn_name, fn_parameter) => self.eval_fn_call_expression(fn_name, fn_parameter),
105            _ => Some(Object::Null),
106        }
107    }
108
109    fn eval_prefix_expression(&mut self, operator: TokenType, expr: Box<Expression>) -> Option<Object> {
110        match operator {
111            TokenType::BANG => {
112                let value = self.eval_expression(expr).unwrap();
113
114                if value.is_truthy() {
115                    Some(Object::Boolean(false))
116                } else {
117                    Some(Object::Boolean(true))
118                }
119            }
120            _ => Some(Object::Null),
121        }
122    }
123
124    fn get_integer_val(&mut self, object: Object) -> usize {
125        match object {
126            Object::Integer(i) => i,
127            _ => 0,
128        }
129    }
130
131    fn get_infix_objects(&mut self, left: &InfixExpression, right: &InfixExpression) -> (Object, Object) {
132        let left = self.eval_expression(left.clone()).unwrap();
133        let right = self.eval_expression(right.clone()).unwrap();
134
135        (left, right)
136    }
137
138    fn eval_infix_expression(
139        &mut self,
140        left: InfixExpression,
141        operator: TokenType,
142        right: InfixExpression,
143    ) -> Option<Object> {
144        let value = Some(Object::Null);
145
146        match operator {
147            TokenType::ADD => {
148                let (left_obj, right_obj) = self.get_infix_objects(&left, &right);
149                let left_val = self.get_integer_val(left_obj);
150                let right_val = self.get_integer_val(right_obj);
151
152                Some(Object::Integer(left_val + right_val))
153            }
154            TokenType::MINUS => {
155                let (left_obj, right_obj) = self.get_infix_objects(&left, &right);
156                let left_val = self.get_integer_val(left_obj);
157                let right_val = self.get_integer_val(right_obj);
158
159                Some(Object::Integer(left_val - right_val))
160            }
161            TokenType::MULTIPLY => {
162                let (left_obj, right_obj) = self.get_infix_objects(&left, &right);
163                let left_val = self.get_integer_val(left_obj);
164                let right_val = self.get_integer_val(right_obj);
165
166                Some(Object::Integer(left_val * right_val))
167            }
168            TokenType::DIVIDE => {
169                let (left_obj, right_obj) = self.get_infix_objects(&left, &right);
170                let left_val = self.get_integer_val(left_obj);
171                let right_val = self.get_integer_val(right_obj);
172
173                Some(Object::Integer(left_val / right_val))
174            }
175            _ => value,
176        }
177    }
178
179    fn eval_identifier(&mut self, identifier: String) -> Option<Object> {
180        match self.env.deref().borrow_mut().get(identifier.clone()) {
181            Some(value) => Some(value),
182            None => Some(Object::Error(format!("no identifier found: {}", identifier))),
183        }
184    }
185
186    fn eval_integer(&mut self, int: usize) -> Option<Object> {
187        Some(Object::Integer(int))
188    }
189
190    fn eval_string(&mut self, string: String) -> Option<Object> {
191        Some(Object::String(string))
192    }
193
194    fn eval_boolean(&mut self, bl: bool) -> Option<Object> {
195        Some(Object::Boolean(bl))
196    }
197
198    fn eval_array_expression(&mut self, exprs: Vec<Expression>) -> Option<Object> {
199        Some(Object::Array(
200            exprs
201                .into_iter()
202                .map(|expr| self.eval_expression(Box::new(expr)).unwrap_or(Object::Null))
203                .collect::<Vec<_>>(),
204        ))
205    }
206
207    fn eval_hash_expression(&mut self, hashes: Vec<(Expression, Expression)>) -> Option<Object> {
208        let mut hash_object = HashMap::<Object, Object>::new();
209
210        hashes.into_iter().for_each(|(k, v)| {
211            hash_object.insert(
212                self.eval_expression(Box::new(k)).unwrap_or(Object::Null),
213                self.eval_expression(Box::new(v)).unwrap_or(Object::Null),
214            );
215        });
216
217        Some(Object::Hash(hash_object))
218    }
219
220    fn eval_if_expression(
221        &mut self,
222        if_condition: IfCondition,
223        statements: Statement,
224        else_statements: Option<Statement>,
225    ) -> Option<Object> {
226        let condition = self.eval_expression(if_condition);
227
228        if let Some(condition_val) = condition {
229            if condition_val.is_truthy() {
230                self.eval_block_statement(statements)
231            } else if let Some(else_stmts) = else_statements {
232                self.eval_block_statement(else_stmts)
233            } else {
234                None
235            }
236        } else {
237            None
238        }
239    }
240
241    fn eval_while_expression(&mut self, while_condition: WhileCondition, block_stmt: Statement) -> Option<Object> {
242        let condition = self.eval_expression(while_condition).unwrap();
243
244        while condition.is_truthy() {
245            match block_stmt {
246                Statement::BlockStatement(ref stmts) => {
247                    for stmt in stmts {
248                        let mut _value = Some(Object::Null);
249
250                        _value = self.eval_statement(stmt.clone());
251
252                        if _value.eq(&Some(Object::Break)) {
253                            break;
254                        }
255                    }
256                }
257                _ => {
258                    break;
259                }
260            }
261        }
262
263        None
264    }
265
266    fn eval_fn_expression(
267        &mut self,
268        fn_name_expr: Expression,
269        fn_parameter: FnParameter,
270        fn_body: FnBody,
271    ) -> Option<Object> {
272        let fn_name = match fn_name_expr {
273            Expression::Identifier(str) => str,
274            _ => "".to_string(),
275        };
276
277        let fn_object = Object::Function(fn_parameter, fn_body, Rc::clone(&self.env));
278
279        if fn_name.is_empty() {
280            // let fn expression
281            Some(fn_object)
282        } else {
283            // fn declaration
284            self.env.borrow_mut().set(fn_name, fn_object);
285            None
286        }
287    }
288
289    fn enclose_fn_env(
290        &mut self,
291        arg_pair_vec: Vec<(&Expression, &Object)>,
292        outer_env: Rc<RefCell<Env>>,
293    ) -> Rc<RefCell<Env>> {
294        let mut enclosed_env = Env::enclosed_outer_env(Rc::clone(&outer_env));
295
296        for (key, value) in arg_pair_vec {
297            let name = match key {
298                Expression::Identifier(str) => str,
299                _ => "",
300            };
301
302            if !name.is_empty() {
303                enclosed_env.set(name.to_string(), value.clone());
304            }
305        }
306
307        Rc::new(RefCell::new(enclosed_env))
308    }
309
310    fn eval_fn_call_expression(&mut self, fn_name: FnName, fn_parameter: FnParameter) -> Option<Object> {
311        let arguments = fn_parameter
312            .iter()
313            .map(|expr| self.eval_expression(Box::new(expr.clone())).unwrap_or(Object::Null))
314            .collect::<Vec<Object>>();
315
316        let (parameters, stmt, outer_env) = match self.eval_expression(fn_name).unwrap() {
317            Object::Function(args, stmt, outer_env) => (args, stmt, outer_env),
318            Object::Builtin(func) => {
319                // invoke builtin methods
320                return Some(func(arguments));
321            }
322            _ => {
323                return None;
324            }
325        };
326
327        let original_env = Rc::clone(&self.env);
328
329        // https://stackoverflow.com/questions/156767/whats-the-difference-between-an-argument-and-a-parameter
330        let para_arg_pair = parameters.iter().zip(arguments.iter());
331
332        // create temporary env for eval function statements
333        self.env = self.enclose_fn_env(para_arg_pair.collect::<Vec<(&Expression, &Object)>>(), outer_env);
334
335        let fn_call_value = self.eval_block_statement(stmt);
336
337        // restore original env
338        self.env = original_env;
339
340        fn_call_value
341    }
342}
343
344#[cfg(test)]
345mod unit_test {
346    use crate::env::Env;
347    use crate::evaluator::Evaluator;
348    use crate::object::Object;
349    use crate::parser::Parser;
350    use std::cell::RefCell;
351    use std::rc::Rc;
352
353    fn get_eval_val(input: &str) -> Option<Object> {
354        let program = Parser::get(input).parse_program();
355
356        let mut evaluator = Evaluator::new(Rc::new(RefCell::new(Env::new())));
357
358        evaluator.builtin();
359
360        evaluator.eval_program(program)
361    }
362
363    #[test]
364    fn eval_integer() {
365        let evaluated = get_eval_val("12");
366        let expected = Some(Object::Integer(12));
367
368        assert_eq!(format!("{:?}", evaluated), format!("{:?}", expected));
369    }
370
371    #[test]
372    fn eval_boolean() {
373        assert_eq!(
374            format!("{:?}", get_eval_val("true")),
375            format!("{:?}", Some(Object::Boolean(true)))
376        );
377        assert_eq!(
378            format!("{:?}", get_eval_val("false")),
379            format!("{:?}", Some(Object::Boolean(false)))
380        );
381    }
382
383    #[test]
384    fn eval_string() {
385        assert_eq!(
386            format!("{:?}", get_eval_val(r#""foo_bar_123""#)),
387            format!("{:?}", Some(Object::String(String::from("foo_bar_123"))))
388        );
389    }
390
391    #[test]
392    fn eval_hash_expression() {
393        let hash_value = get_eval_val(
394            r#"
395    {
396        "foo": "bar",
397        1: 2,
398        2: [1234, true, "Lynx programming language"],
399        "abc": true
400    };
401    "#,
402        )
403        .unwrap();
404
405        match hash_value {
406            Object::Hash(hashes) => {
407                assert_eq!(
408                    hashes.get(&Object::String(String::from("abc"))),
409                    Some(&Object::Boolean(true))
410                );
411
412                assert_eq!(hashes.get(&Object::Integer(1)), Some(&Object::Integer(2)));
413
414                assert_eq!(
415                    hashes.get(&Object::String(String::from("foo"))),
416                    Some(&Object::String(String::from("bar")))
417                );
418
419                assert_eq!(
420                    hashes.get(&Object::Integer(2)),
421                    Some(&Object::Array(vec![
422                        Object::Integer(1234),
423                        Object::Boolean(true),
424                        Object::String(String::from("Lynx programming language"))
425                    ]))
426                );
427            }
428            _ => (),
429        }
430    }
431
432    #[test]
433    fn eval_array_expression() {
434        assert_eq!(
435            format!(
436                "{:?}",
437                get_eval_val(
438                    r#"[1234, true, "Lynx programming language", [1234, true, "Lynx programming language"]];"#
439                )
440            ),
441            format!(
442                "{:?}",
443                Some(Object::Array(vec![
444                    Object::Integer(1234),
445                    Object::Boolean(true),
446                    Object::String(String::from("Lynx programming language")),
447                    Object::Array(vec![
448                        Object::Integer(1234),
449                        Object::Boolean(true),
450                        Object::String(String::from("Lynx programming language"))
451                    ])
452                ]))
453            )
454        );
455    }
456
457    #[test]
458    fn eval_identifier() {
459        assert_eq!(
460            format!(
461                "{:?}",
462                get_eval_val(
463                    r#"
464                foo;
465            "#
466                )
467            ),
468            format!("{:?}", Some(Object::Error(String::from("no identifier found: foo"))))
469        );
470    }
471
472    #[test]
473    fn eval_let_statement() {
474        assert_eq!(
475            format!(
476                "{:?}",
477                get_eval_val(
478                    r#"
479                let foo = 123 + 4;
480                foo;
481            "#
482                )
483            ),
484            format!("{:?}", Some(Object::Integer(127)))
485        );
486    }
487
488    #[test]
489    fn eval_return_statement() {
490        assert_eq!(
491            format!("{:?}", get_eval_val(r#"return !false;"#)),
492            format!("{:?}", Some(Object::Boolean(true)))
493        );
494
495        assert_eq!(
496            format!("{:?}", get_eval_val(r#"return 123;"#)),
497            format!("{:?}", Some(Object::Integer(123)))
498        );
499
500        assert_eq!(
501            format!(
502                "{:?}",
503                get_eval_val(
504                    r#"
505                let foo = 123;
506                return foo;
507            "#
508                )
509            ),
510            format!("{:?}", Some(Object::Integer(123)))
511        );
512    }
513
514    #[test]
515    fn eval_prefix_expression() {
516        assert_eq!(
517            format!("{:?}", get_eval_val(r#"!false"#)),
518            format!("{:?}", Some(Object::Boolean(true)))
519        );
520
521        assert_eq!(
522            format!("{:?}", get_eval_val(r#"!true"#)),
523            format!("{:?}", Some(Object::Boolean(false)))
524        );
525    }
526
527    #[test]
528    fn eval_infix_expression() {
529        assert_eq!(
530            format!("{:?}", get_eval_val(r#"1 + 2 + 3 + 4 / 2 * 3"#)),
531            format!("{:?}", Some(Object::Integer(12)))
532        );
533    }
534
535    #[test]
536    fn eval_grouped_expression() {
537        assert_eq!(
538            format!("{:?}", get_eval_val(r#"(7 + 2) / 3"#)),
539            format!("{:?}", Some(Object::Integer(3)))
540        );
541
542        assert_eq!(
543            format!("{:?}", get_eval_val(r#"9 / (1 + 2)"#)),
544            format!("{:?}", Some(Object::Integer(3)))
545        );
546    }
547
548    #[test]
549    fn eval_if_expression() {
550        assert_eq!(
551            format!(
552                "{:?}",
553                get_eval_val(
554                    r#"
555                if (false) {
556                    false;
557                } else {
558                    true;
559                }
560            "#
561                )
562            ),
563            format!("{:?}", Some(Object::Boolean(true)))
564        );
565
566        assert_eq!(
567            format!(
568                "{:?}",
569                get_eval_val(
570                    r#"
571                let foo = 123;
572                if (foo) {
573                    let bar = "stuff";
574                    return bar;
575                } else {
576                    return 5;
577                }
578            "#
579                )
580            ),
581            format!("{:?}", Some(Object::String(String::from("stuff"))))
582        );
583    }
584
585    #[test]
586    fn eval_while_expression() {
587        // assert_eq!(
588        //     format!(
589        //         "{:?}",
590        //         get_eval_val(
591        //             r#"
592        //         while (foo) {
593        //             let bar = "stuff";
594
595        //             foo(bar);
596        //         }
597        //     "#
598        //         )
599        //     ),
600        //     format!("{:?}", Some(Object::Integer(3)))
601        // );
602        assert_eq!(1, 1);
603    }
604
605    #[test]
606    fn eval_fn_expression() {
607        let input = r#"
608            fn bar(foo, stuff) {
609                let another_bar = stuff;
610                return another_bar + foo;
611            }
612    "#;
613        let program = Parser::get(input).parse_program();
614        let mut evaluator = Evaluator::new(Rc::new(RefCell::new(Env::new())));
615        evaluator.eval_program(program);
616        let env_stored = evaluator.get_env().get("bar".to_string());
617
618        assert!(env_stored.is_some());
619    }
620
621    #[test]
622    fn eval_let_fn_expression() {
623        let input = r#"
624            let foo = fn(bar, stuff) {
625                let another_bar = stuff;
626                return another_bar + bar;
627            }
628    "#;
629        let program = Parser::get(input).parse_program();
630        let mut evaluator = Evaluator::new(Rc::new(RefCell::new(Env::new())));
631        evaluator.eval_program(program);
632
633        let env_stored = evaluator.get_env().get("foo".to_string());
634
635        assert!(env_stored.is_some());
636    }
637
638    #[test]
639    fn eval_fn_call_expression() {
640        let value = format!(
641            "{:?}",
642            get_eval_val(
643                r#"
644                fn bar(foo, stuff, var) {
645                    let another_bar = stuff;
646                    return another_bar + foo + var;
647                }
648                let value = bar(1, 2, 3);
649                value;
650        "#
651            )
652        );
653
654        println!("{:?}", value);
655
656        assert_eq!(value, format!("{:?}", Some(Object::Integer(6))));
657    }
658
659    #[test]
660    fn eval_let_fn_call_expression() {
661        let value = format!(
662            "{:?}",
663            get_eval_val(
664                r#"
665                let bar = fn(foo, stuff, var) {
666                    let another_bar = stuff;
667                    return another_bar + foo + var;
668                }
669                let value = bar(1, 2, 3);
670                value;
671        "#
672            )
673        );
674
675        println!("{:?}", value);
676
677        assert_eq!(value, format!("{:?}", Some(Object::Integer(6))));
678    }
679
680    #[test]
681    fn eval_fibonacci_fn() {
682        // todo
683        let value = format!(
684            "{:?}",
685            get_eval_val(
686                r#"
687                fn fibonacci(x) {
688                    if (x == 0) {
689                        return 0;
690                    } else {
691                        return 1;
692                    }
693                }
694                let foo = 123;
695                let fib_val = fibonacci(foo); 
696                fib_val; 
697        "#
698            )
699        );
700
701        println!("{:?}", value);
702
703        assert_eq!(value, format!("{:?}", Some(Object::Integer(1))));
704    }
705
706    #[test]
707    fn eval_build_ins() {
708        assert_eq!(
709            format!("{:?}", get_eval_val(r#"first([1, 2, 3]);"#)),
710            format!("{:?}", Some(Object::Integer(1)))
711        );
712
713        assert_eq!(
714            format!(
715                "{:?}",
716                get_eval_val(
717                    r#"
718            last([1, 2, 3]);
719            "#
720                )
721            ),
722            format!("{:?}", Some(Object::Integer(3)))
723        );
724
725        assert_eq!(
726            format!("{:?}", get_eval_val(r#"rest([1, 2, 3]);"#)),
727            format!(
728                "{:?}",
729                Some(Object::Array(vec![Object::Integer(2), Object::Integer(3)]))
730            )
731        );
732
733        assert_eq!(
734            format!("{:?}", get_eval_val(r#"len([1, 2, 3]);"#)),
735            format!("{:?}", Some(Object::Integer(3)))
736        );
737
738        assert_eq!(
739            format!("{:?}", get_eval_val(r#"push([1, 2, 3], 4);"#)),
740            format!(
741                "{:?}",
742                Some(Object::Array(vec![
743                    Object::Integer(1),
744                    Object::Integer(2),
745                    Object::Integer(3),
746                    Object::Integer(4)
747                ]))
748            )
749        );
750
751        assert_eq!(
752            format!("{:?}", get_eval_val(r#"unshift([1, 2, 3], 4);"#)),
753            format!(
754                "{:?}",
755                Some(Object::Array(vec![
756                    Object::Integer(4),
757                    Object::Integer(1),
758                    Object::Integer(2),
759                    Object::Integer(3)
760                ]))
761            )
762        );
763
764        // assert_eq!(
765        //     format!("{:?}", get_eval_val(r#"print([1, 2, 3]);"#)),
766        //     format!("{:?}", Some("[1, 2, 3]"))
767        // );
768    }
769}