scurry/interpreter/
mod.rs

1mod builtin;
2mod env;
3pub mod object;
4
5use self::env::Env;
6use self::object::*;
7use crate::ast::*;
8use crate::parser::Parser;
9use std::cell::RefCell;
10use std::collections::HashMap;
11use std::io::Write;
12use std::path::PathBuf;
13use std::rc::Rc;
14#[allow(unused_imports)]
15use std::{fs, io};
16
17macro_rules! loop_control {
18    ($interpreter:expr, $block:expr) => {{
19        let result = $interpreter.eval_block($block.clone())?;
20        if matches!(result, Object::ControlChange(ControlChange::Return(_))) {
21            return Ok(result);
22        }
23        if matches!(result, Object::ControlChange(ControlChange::Continue)) {
24            continue;
25        }
26        if matches!(result, Object::ControlChange(ControlChange::Break)) {
27            break;
28        }
29    }};
30}
31
32pub struct Interpreter<'a, T> {
33    out: &'a mut T,
34    env: Rc<RefCell<Env>>,
35}
36
37impl<'a, T: Write> Interpreter<'a, T> {
38    pub fn new(out: &'a mut T) -> Self {
39        let mut interpreter = Self {
40            out,
41            env: Rc::new(RefCell::new(Env::new())),
42        };
43        let std = [include_str!("core/iterator.scy")];
44        for contents in std {
45            let program = Parser::new(contents)
46                .parse()
47                .expect("should not have parser errors in std");
48            interpreter
49                .eval(program)
50                .expect("should execute std with no errors");
51        }
52        interpreter
53    }
54
55    pub fn eval(&mut self, program: Program) -> Result<(), RuntimeError> {
56        for stmt in program.0 {
57            self.eval_stmt(stmt)?;
58        }
59        Ok(())
60    }
61
62    pub fn eval_repl(&mut self, program: Program) -> EvalResult {
63        let mut result = Object::Nil;
64        for stmt in program.0 {
65            result = self.eval_stmt(stmt)?;
66            // Get rid of return val wrappers, no longer needed
67            while let Object::ControlChange(ControlChange::Return(val)) = result {
68                result = *val
69            }
70        }
71        Ok(result)
72    }
73
74    fn eval_block(&mut self, block: Block) -> EvalResult {
75        for stmt in block.0 {
76            let result = self.eval_stmt(stmt)?;
77            if matches!(result, Object::ControlChange(_)) {
78                return Ok(result);
79            }
80        }
81        Ok(Object::AbsoluteNil)
82    }
83
84    fn eval_stmt(&mut self, stmt: Stmt) -> EvalResult {
85        match stmt {
86            Stmt::Assign(AssignStmt {
87                name,
88                value,
89                line,
90                operator,
91                type_checked,
92                var_type,
93            }) => {
94                let value = self.eval_expr(value)?;
95                match name {
96                    Expr::Ident(ident, _) => {
97                        if let Some(op) = operator {
98                            let prev_val = self.eval_ident(&ident.0, line)?;
99                            let result = self.eval_infix_expr(op.into(), prev_val, value, line)?;
100                            if type_checked && !result.fits_type(var_type.clone()) {
101                                return Err(RuntimeError::MismatchedAssignType {
102                                    name: ident.0,
103                                    expected: var_type,
104                                    got: result.scurry_type().into(),
105                                    line,
106                                });
107                            }
108                            self.env.borrow_mut().set(ident.0, result);
109                        } else {
110                            if type_checked && !value.fits_type(var_type.clone()) {
111                                return Err(RuntimeError::MismatchedAssignType {
112                                    name: ident.0,
113                                    expected: var_type,
114                                    got: value.scurry_type().into(),
115                                    line,
116                                });
117                            }
118                            self.env.borrow_mut().set(ident.0, value);
119                        }
120                    }
121                    Expr::Dot(DotExpr { left, field, line }) => {
122                        let left = self.eval_expr(*left)?;
123                        let Object::Instance(instance) = left else {
124                            return Err(RuntimeError::DotOperatorNotSupported { obj: left.scurry_type(), line });
125                        };
126                        if instance.visibility != Visibility::Private {
127                            return Err(RuntimeError::UnrecognizedField {
128                                field: field.0,
129                                obj: Type::Instance(instance.component.name.0.clone()),
130                                line,
131                            });
132                        }
133                        if !instance.field_values.borrow().contains_key(&field.0) {
134                            return Err(RuntimeError::UnrecognizedField {
135                                field: field.0,
136                                obj: Type::Instance(instance.component.name.0.clone()),
137                                line,
138                            });
139                        }
140                        if let Some(op) = operator {
141                            let prev_val = self.eval_dot_expr(
142                                Object::Instance(instance.clone()),
143                                field.0.clone(),
144                                line,
145                            )?;
146                            let result = self.eval_infix_expr(op.into(), prev_val, value, line)?;
147                            if type_checked {
148                                let expect_type = instance
149                                    .component
150                                    .fields
151                                    .iter()
152                                    .filter_map(|(ident, ty)| (ident == &field).then_some(ty))
153                                    .last()
154                                    .expect("field should exist in component");
155                                if !result.fits_type(expect_type.clone()) {
156                                    return Err(RuntimeError::MismatchedAssignType {
157                                        name: field.0,
158                                        expected: expect_type.clone(),
159                                        got: result.scurry_type().into(),
160                                        line,
161                                    });
162                                }
163                            }
164                            instance.field_values.borrow_mut().insert(field.0, result);
165                        } else {
166                            if type_checked {
167                                let expect_type = instance
168                                    .component
169                                    .fields
170                                    .iter()
171                                    .filter_map(|(ident, ty)| (ident == &field).then_some(ty))
172                                    .last()
173                                    .expect("field should exist in component");
174                                if !value.fits_type(expect_type.clone()) {
175                                    return Err(RuntimeError::MismatchedAssignType {
176                                        name: field.0,
177                                        expected: expect_type.clone(),
178                                        got: value.scurry_type().into(),
179                                        line,
180                                    });
181                                }
182                            }
183                            instance.field_values.borrow_mut().insert(field.0, value);
184                        }
185                    }
186                    Expr::Index(IndexExpr { left, index, line }) => {
187                        let left = self.eval_expr(*left)?;
188                        let index = self.eval_expr(*index)?;
189                        match (&left, &index) {
190                            (
191                                Object::Map(map),
192                                Object::Int(_) | Object::String(_) | Object::Bool(_),
193                            ) => {
194                                if let Some(op) = operator {
195                                    let prev_val = self.eval_index_expr(
196                                        Object::Map(map.clone()),
197                                        index.clone(),
198                                        line,
199                                    )?;
200                                    let result =
201                                        self.eval_infix_expr(op.into(), prev_val, value, line)?;
202                                    map.borrow_mut().insert(index, result);
203                                } else {
204                                    map.borrow_mut().insert(index, value);
205                                }
206                            }
207                            (Object::Array(arr), Object::Int(i)) => {
208                                if *i < 0 {
209                                    if i.unsigned_abs() as usize > arr.borrow().len() {
210                                        return Err(RuntimeError::IndexOutOfRange {
211                                            obj: left,
212                                            index: *i,
213                                            line,
214                                        });
215                                    }
216                                    let rev_idx = arr.borrow().len() - 1;
217                                    if let Some(op) = operator {
218                                        let prev_val = self.eval_index_expr(
219                                            Object::Array(arr.clone()),
220                                            index.clone(),
221                                            line,
222                                        )?;
223                                        let result =
224                                            self.eval_infix_expr(op.into(), prev_val, value, line)?;
225                                        arr.borrow_mut()[rev_idx] = result;
226                                    } else {
227                                        arr.borrow_mut()[rev_idx] = value;
228                                    }
229                                    return Ok(Object::AbsoluteNil);
230                                }
231                                let idx = *i as usize;
232                                if arr.borrow().len() == 0 || idx > arr.borrow().len() - 1 {
233                                    return Err(RuntimeError::IndexOutOfRange {
234                                        obj: left,
235                                        index: *i,
236                                        line,
237                                    });
238                                } else if let Some(op) = operator {
239                                    let prev_val = self.eval_index_expr(
240                                        Object::Array(arr.clone()),
241                                        index.clone(),
242                                        line,
243                                    )?;
244                                    let result =
245                                        self.eval_infix_expr(op.into(), prev_val, value, line)?;
246                                    arr.borrow_mut()[idx] = result;
247                                } else {
248                                    arr.borrow_mut()[idx] = value;
249                                }
250                            }
251                            _ => {
252                                return Err(RuntimeError::IndexOperatorNotSupported {
253                                    obj: left.scurry_type(),
254                                    index_type: index.scurry_type(),
255                                    line,
256                                });
257                            }
258                        }
259                    }
260                    // Cannot assign in this manner
261                    _ => return Err(RuntimeError::CannotAssign { expr: name, line }),
262                }
263                Ok(Object::AbsoluteNil)
264            }
265            Stmt::While(WhileStmt { condition, block }) => self.eval_while_stmt(condition, block),
266            Stmt::Return(ReturnStmt { value }) => Ok(Object::ControlChange(ControlChange::Return(
267                Box::new(self.eval_expr(value)?),
268            ))),
269            Stmt::Break => Ok(Object::ControlChange(ControlChange::Break)),
270            Stmt::Continue => Ok(Object::ControlChange(ControlChange::Continue)),
271            Stmt::Function(FunctionStmt {
272                name,
273                params,
274                block,
275                visibility,
276                ..
277            }) => {
278                let func = Object::Function {
279                    params,
280                    body: block,
281                    env: Rc::clone(&self.env),
282                    bound: None,
283                    visibility: Some(visibility),
284                };
285                self.env.borrow_mut().set(name.0, func);
286                Ok(Object::AbsoluteNil)
287            }
288            Stmt::Declaration(DeclarationStmt {
289                name,
290                methods,
291                fields,
292                embeds,
293                visibility,
294            }) => {
295                let embedded = {
296                    let mut embedded = Vec::new();
297                    for embed in embeds {
298                        let embed_component = match self.env.borrow().get(&embed.name.0) {
299                            Some(Object::Component(component)) => component,
300                            _ => {
301                                return Err(RuntimeError::InvalidEmbed {
302                                    name: embed.name.0,
303                                    line: embed.line,
304                                });
305                            }
306                        };
307                        embedded.push(EmbedComponent {
308                            component: embed_component,
309                            assigned: embed.assigned,
310                            type_checked: embed.type_checked,
311                        });
312                    }
313                    embedded
314                };
315                let mut exports = Vec::new();
316                let mut comp_methods = HashMap::new();
317                for func in methods {
318                    comp_methods.insert(
319                        func.name.0.clone(),
320                        Object::Function {
321                            params: func.params,
322                            body: func.block,
323                            env: Rc::clone(&self.env),
324                            bound: None,
325                            visibility: None,
326                        },
327                    );
328                    if func.visibility == Visibility::Public {
329                        exports.push(func.name.0)
330                    }
331                }
332                self.env.borrow_mut().set(
333                    name.0.clone(),
334                    Object::Component(Component {
335                        name,
336                        fields,
337                        methods: comp_methods,
338                        exports,
339                        embeds: embedded,
340                        visibility,
341                    }),
342                );
343                Ok(Object::AbsoluteNil)
344            }
345            Stmt::For(ForStmt {
346                iter_ident,
347                expr,
348                block,
349                line,
350            }) => self.eval_for_stmt(iter_ident, expr, block, line),
351            Stmt::If(IfStmt {
352                condition,
353                true_block,
354                else_block,
355                elifs,
356            }) => self.eval_if_stmt(condition, true_block, else_block, elifs),
357            Stmt::Switch(SwitchStmt {
358                expr,
359                cases,
360                default,
361            }) => {
362                let switch = self.eval_expr(expr)?;
363                self.eval_switch_stmt(switch, cases, default)
364            }
365            Stmt::Import(ImportStmt {
366                target,
367                alias,
368                line,
369            }) => self.eval_import_stmt(target, alias, line),
370            Stmt::Expr(expr) => self.eval_expr(expr),
371        }
372    }
373
374    fn eval_expr(&mut self, expr: Expr) -> EvalResult {
375        match expr {
376            Expr::Literal(Literal::Nil) => Ok(Object::Nil),
377            Expr::Literal(Literal::Integer(i)) => Ok(Object::Int(i)),
378            Expr::Literal(Literal::Boolean(b)) => Ok(Object::Bool(b)),
379            Expr::Literal(Literal::String(s)) => Ok(Object::String(s)),
380            Expr::Literal(Literal::Float(f)) => Ok(Object::Float(f)),
381            Expr::Literal(Literal::Array(arr)) => {
382                let mut array = Vec::new();
383                for expr in arr {
384                    array.push(self.eval_expr(expr)?);
385                }
386                Ok(Object::Array(Rc::new(RefCell::new(array))))
387            }
388            Expr::Literal(Literal::Map(map)) => {
389                let mut pairs = HashMap::new();
390                for (key, value) in map {
391                    pairs.insert(self.eval_expr(key)?, self.eval_expr(value)?);
392                }
393                Ok(Object::Map(Rc::new(RefCell::new(pairs))))
394            }
395            Expr::Ident(Ident(name), line) => self.eval_ident(&name, line),
396            Expr::Index(IndexExpr { left, index, line }) => {
397                let expr = self.eval_expr(*left)?;
398                let index = self.eval_expr(*index)?;
399                self.eval_index_expr(expr, index, line)
400            }
401            Expr::Unbound(UnboundExpr { ident, value }) => {
402                let expr = self.eval_expr(*value)?;
403                Ok(self.eval_unbound_expr(ident, expr))
404            }
405            Expr::Function(FunctionExpr { params, block, .. }) => Ok(Object::Function {
406                params,
407                body: block,
408                env: Rc::clone(&self.env),
409                bound: None,
410                visibility: None,
411            }),
412            Expr::Dot(DotExpr { left, field, line }) => {
413                let expr = self.eval_expr(*left)?;
414                self.eval_dot_expr(expr, field.0, line)
415            }
416            Expr::Call(CallExpr {
417                func,
418                args,
419                line,
420                type_checked,
421            }) => {
422                let func = self.eval_expr(*func)?;
423                let args = {
424                    let mut result = Vec::new();
425                    for arg in args {
426                        result.push(self.eval_expr(arg)?);
427                    }
428                    result
429                };
430                self.eval_call_expr(func, args, type_checked, line)
431            }
432            Expr::Prefix(PrefixExpr { left, op, line }) => {
433                let left = self.eval_expr(*left)?;
434                self.eval_prefix_expr(op, left, line)
435            }
436            Expr::Infix(InfixExpr {
437                left,
438                op,
439                right,
440                line,
441            }) => {
442                let left = self.eval_expr(*left)?;
443                // For short-circuit evaluation
444                if matches!(op, InfixOp::LogicalAnd | InfixOp::LogicalOr) {
445                    return self
446                        .eval_logical_and_or(op, left, *right)
447                        .expect("op should be logical and/or");
448                }
449                let right = self.eval_expr(*right)?;
450                self.eval_infix_expr(op, left, right, line)
451            }
452        }
453    }
454
455    fn eval_ident(&self, name: &str, line: usize) -> EvalResult {
456        let val = self.env.borrow().get(name);
457        if let Some(val) = val {
458            Ok(val)
459        } else if name == "println" {
460            Ok(Object::Println)
461        } else if let Some(func) = builtin::get_builtin_func(name) {
462            Ok(Object::Builtin(func))
463        } else {
464            Err(RuntimeError::VariableNotFound {
465                name: name.to_owned(),
466                line,
467            })
468        }
469    }
470
471    fn eval_prefix_expr(&mut self, op: PrefixOp, expr: Object, line: usize) -> EvalResult {
472        match op {
473            PrefixOp::Bang => self.eval_bang_op(expr, line),
474            PrefixOp::Minus => self.eval_minus_op(expr, line),
475            PrefixOp::Plus => self.eval_plus_op(expr, line),
476        }
477    }
478
479    fn eval_bang_op(&self, expr: Object, line: usize) -> EvalResult {
480        match expr {
481            Object::Bool(b) => Ok(Object::Bool(!b)),
482            Object::Nil => Ok(Object::Bool(true)),
483            _ => Err(RuntimeError::InvalidUnaryOperand {
484                op: PrefixOp::Bang,
485                operand: expr.scurry_type(),
486                line,
487            }),
488        }
489    }
490
491    fn eval_minus_op(&self, expr: Object, line: usize) -> EvalResult {
492        match expr {
493            Object::Int(i) => Ok(Object::Int(-i)),
494            Object::Float(f) => Ok(Object::Float(-f)),
495            _ => Err(RuntimeError::InvalidUnaryOperand {
496                op: PrefixOp::Minus,
497                operand: expr.scurry_type(),
498                line,
499            }),
500        }
501    }
502
503    fn eval_plus_op(&self, expr: Object, line: usize) -> EvalResult {
504        match expr {
505            Object::Int(_) => Ok(expr),
506            Object::Float(_) => Ok(expr),
507            _ => Err(RuntimeError::InvalidUnaryOperand {
508                op: PrefixOp::Plus,
509                operand: expr.scurry_type(),
510                line,
511            }),
512        }
513    }
514
515    fn eval_infix_expr(
516        &mut self,
517        op: InfixOp,
518        left: Object,
519        right: Object,
520        line: usize,
521    ) -> EvalResult {
522        macro_rules! special_op {
523            ($instance:expr, $name:ident) => {
524                if let Some(add) = $instance.get_special(SpecialMethod::$name) {
525                    let args = vec![Object::Instance($instance.clone_with_private()), right];
526                    self.eval_call_expr(add.clone(), args, false, line)
527                } else {
528                    unreachable!()
529                }
530            };
531        }
532        match (&left, &right) {
533            (Object::Int(x), Object::Int(y)) => self.eval_int_infix_expr(op, *x, *y, line),
534            (Object::Float(x), Object::Float(y)) => self.eval_float_infix_expr(op, *x, *y, line),
535            (Object::Int(x), Object::Float(y)) => {
536                self.eval_float_infix_expr(op, *x as f32, *y, line)
537            }
538            (Object::Float(x), Object::Int(y)) => {
539                self.eval_float_infix_expr(op, *x, *y as f32, line)
540            }
541            (Object::Bool(left), Object::Bool(right)) => {
542                self.eval_bool_infix_expr(op, *left, *right, line)
543            }
544            (Object::String(s1), Object::String(s2)) => {
545                self.eval_string_infix_expr(op, s1, s2, line)
546            }
547            (Object::Instance(instance), _) if instance.has_special(SpecialMethod::Add) => {
548                special_op!(instance, Add)
549            }
550            (Object::Instance(instance), _) if instance.has_special(SpecialMethod::Sub) => {
551                special_op!(instance, Sub)
552            }
553            (Object::Instance(instance), _) if instance.has_special(SpecialMethod::Div) => {
554                special_op!(instance, Div)
555            }
556            (Object::Instance(instance), _) if instance.has_special(SpecialMethod::Mul) => {
557                special_op!(instance, Mul)
558            }
559            (Object::Instance(instance), _) if instance.has_special(SpecialMethod::Mod) => {
560                special_op!(instance, Mod)
561            }
562            _ => match op {
563                InfixOp::Eq => Ok(Object::Bool(left == right)),
564                InfixOp::NotEq => Ok(Object::Bool(left != right)),
565                _ => Err(RuntimeError::InvalidBinaryOperand {
566                    op,
567                    left: left.scurry_type(),
568                    right: right.scurry_type(),
569                    line,
570                }),
571            },
572        }
573    }
574
575    fn eval_int_infix_expr(&self, op: InfixOp, x: i32, y: i32, line: usize) -> EvalResult {
576        macro_rules! check_overflow {
577            ($op:ident) => {
578                x.$op(y).map_or(
579                    Err(RuntimeError::IntegerOverflow {
580                        op,
581                        left: x,
582                        right: y,
583                        line,
584                    }),
585                    |x| Ok(Object::Int(x)),
586                )
587            };
588        }
589        macro_rules! check_zero_div {
590            ($op:ident) => {
591                x.$op(y).map_or(
592                    Err(RuntimeError::DivisionByZero {
593                        op,
594                        left: Number::Int(x),
595                        right: Number::Int(y),
596                        line,
597                    }),
598                    |x| Ok(Object::Int(x)),
599                )
600            };
601        }
602
603        match op {
604            InfixOp::Plus => check_overflow!(checked_add),
605            InfixOp::Minus => check_overflow!(checked_sub),
606            InfixOp::Asterisk => check_overflow!(checked_mul),
607            InfixOp::Slash => {
608                if y == 0 {
609                    Err(RuntimeError::DivisionByZero {
610                        op: InfixOp::Slash,
611                        left: Number::Int(x),
612                        right: Number::Int(y),
613                        line,
614                    })
615                } else {
616                    Ok(Object::Float(x as f32 / y as f32))
617                }
618            }
619            InfixOp::Modulo => check_zero_div!(checked_rem),
620            InfixOp::Eq => Ok(Object::Bool(x == y)),
621            InfixOp::NotEq => Ok(Object::Bool(x != y)),
622            InfixOp::Gt => Ok(Object::Bool(x > y)),
623            InfixOp::Lt => Ok(Object::Bool(x < y)),
624            InfixOp::Ge => Ok(Object::Bool(x >= y)),
625            InfixOp::Le => Ok(Object::Bool(x <= y)),
626            InfixOp::LogicalOr => Err(RuntimeError::InvalidBinaryOperand {
627                op: InfixOp::LogicalOr,
628                left: Type::Int,
629                right: Type::Int,
630                line,
631            }),
632            InfixOp::LogicalAnd => Err(RuntimeError::InvalidBinaryOperand {
633                op: InfixOp::LogicalAnd,
634                left: Type::Int,
635                right: Type::Int,
636                line,
637            }),
638        }
639    }
640
641    fn eval_float_infix_expr(&self, op: InfixOp, x: f32, y: f32, line: usize) -> EvalResult {
642        match op {
643            InfixOp::Plus => Ok(Object::Float(x + y)),
644            InfixOp::Minus => Ok(Object::Float(x - y)),
645            InfixOp::Asterisk => Ok(Object::Float(x * y)),
646            InfixOp::Slash => {
647                let result = x / y;
648                if result.is_infinite() {
649                    Err(RuntimeError::DivisionByZero {
650                        op: InfixOp::Slash,
651                        left: Number::Float(x),
652                        right: Number::Float(y),
653                        line,
654                    })
655                } else {
656                    Ok(Object::Float(result))
657                }
658            }
659            InfixOp::Modulo => {
660                let result = x % y;
661                if result.is_nan() {
662                    Err(RuntimeError::DivisionByZero {
663                        op: InfixOp::Modulo,
664                        left: Number::Float(x),
665                        right: Number::Float(y),
666                        line,
667                    })
668                } else {
669                    Ok(Object::Float(result))
670                }
671            }
672            InfixOp::Eq => Ok(Object::Bool(x == y)),
673            InfixOp::NotEq => Ok(Object::Bool(x != y)),
674            InfixOp::Gt => Ok(Object::Bool(x > y)),
675            InfixOp::Lt => Ok(Object::Bool(x < y)),
676            InfixOp::Ge => Ok(Object::Bool(x >= y)),
677            InfixOp::Le => Ok(Object::Bool(x <= y)),
678            InfixOp::LogicalOr => Err(RuntimeError::InvalidBinaryOperand {
679                op: InfixOp::LogicalOr,
680                left: Type::Float,
681                right: Type::Float,
682                line,
683            }),
684            InfixOp::LogicalAnd => Err(RuntimeError::InvalidBinaryOperand {
685                op: InfixOp::LogicalAnd,
686                left: Type::Float,
687                right: Type::Float,
688                line,
689            }),
690        }
691    }
692
693    fn eval_bool_infix_expr(
694        &self,
695        op: InfixOp,
696        left: bool,
697        right: bool,
698        line: usize,
699    ) -> EvalResult {
700        match op {
701            InfixOp::Eq => Ok(Object::Bool(left == right)),
702            InfixOp::NotEq => Ok(Object::Bool(left != right)),
703            _ => Err(RuntimeError::InvalidBinaryOperand {
704                op,
705                left: Type::Bool,
706                right: Type::Bool,
707                line,
708            }),
709        }
710    }
711
712    fn eval_logical_and_or(
713        &mut self,
714        op: InfixOp,
715        left: Object,
716        right: Expr,
717    ) -> Option<EvalResult> {
718        match op {
719            InfixOp::LogicalOr => {
720                if left.is_truthy() {
721                    Some(Ok(Object::Bool(true)))
722                } else {
723                    Some(
724                        self.eval_expr(right)
725                            .map(|obj| Object::Bool(obj.is_truthy())),
726                    )
727                }
728            }
729            InfixOp::LogicalAnd => {
730                if !left.is_truthy() {
731                    Some(Ok(Object::Bool(false)))
732                } else {
733                    Some(
734                        self.eval_expr(right)
735                            .map(|obj| Object::Bool(obj.is_truthy())),
736                    )
737                }
738            }
739            _ => None,
740        }
741    }
742
743    fn eval_string_infix_expr(&self, op: InfixOp, s1: &str, s2: &str, line: usize) -> EvalResult {
744        match op {
745            InfixOp::Plus => Ok(Object::String(s1.to_owned() + s2)),
746            InfixOp::Eq => Ok(Object::Bool(s1 == s2)),
747            InfixOp::NotEq => Ok(Object::Bool(s1 != s2)),
748            _ => Err(RuntimeError::InvalidBinaryOperand {
749                op,
750                left: Type::String,
751                right: Type::String,
752                line,
753            }),
754        }
755    }
756
757    fn eval_if_stmt(
758        &mut self,
759        condition: Expr,
760        true_block: Block,
761        else_block: Option<Block>,
762        elifs: Vec<ElifStmt>,
763    ) -> EvalResult {
764        if self.eval_expr(condition)?.is_truthy() {
765            self.eval_block(true_block)
766        } else {
767            for elif in elifs {
768                if self.eval_expr(elif.condition)?.is_truthy() {
769                    return self.eval_block(elif.block);
770                }
771            }
772            if let Some(block) = else_block {
773                self.eval_block(block)
774            } else {
775                Ok(Object::AbsoluteNil)
776            }
777        }
778    }
779
780    fn eval_index_expr(&mut self, obj: Object, index: Object, line: usize) -> EvalResult {
781        match (&obj, &index) {
782            (Object::Array(arr), Object::Int(i)) => {
783                if arr.borrow().is_empty() {
784                    return Err(RuntimeError::IndexOutOfRange {
785                        obj,
786                        index: *i,
787                        line,
788                    });
789                }
790                if *i < 0 {
791                    if i.unsigned_abs() as usize > arr.borrow().len() {
792                        return Err(RuntimeError::IndexOutOfRange {
793                            obj,
794                            index: *i,
795                            line,
796                        });
797                    }
798                    return match arr
799                        .borrow()
800                        .iter()
801                        .rev()
802                        .take(i.unsigned_abs() as usize)
803                        .last()
804                    {
805                        Some(item) => Ok(item.clone()),
806                        None => Err(RuntimeError::IndexOutOfRange {
807                            obj: obj.clone(),
808                            index: *i,
809                            line,
810                        }),
811                    };
812                }
813                let idx = *i as usize;
814                if idx > arr.borrow().len() - 1 {
815                    Err(RuntimeError::IndexOutOfRange {
816                        obj,
817                        index: *i,
818                        line,
819                    })
820                } else {
821                    Ok(arr.borrow()[idx].clone())
822                }
823            }
824            (Object::String(s), Object::Int(i)) => {
825                if s.is_empty() {
826                    return Err(RuntimeError::IndexOutOfRange {
827                        obj,
828                        index: *i,
829                        line,
830                    });
831                }
832                if *i < 0 {
833                    if i.unsigned_abs() as usize > s.len() {
834                        return Err(RuntimeError::IndexOutOfRange {
835                            obj,
836                            index: *i,
837                            line,
838                        });
839                    }
840                    return match s.chars().rev().take(i.unsigned_abs() as usize).last() {
841                        Some(item) => Ok(Object::String(item.to_string())),
842                        None => Err(RuntimeError::IndexOutOfRange {
843                            obj,
844                            index: *i,
845                            line,
846                        }),
847                    };
848                }
849                match s.chars().nth(*i as usize) {
850                    Some(c) => Ok(Object::String(c.to_string())),
851                    None => Err(RuntimeError::IndexOutOfRange {
852                        obj,
853                        index: *i,
854                        line,
855                    }),
856                }
857            }
858            (Object::Map(map), Object::Int(_) | Object::Bool(_) | Object::String(_)) => {
859                match map.borrow().get(&index) {
860                    Some(obj) => Ok(obj.clone()),
861                    None => Err(RuntimeError::KeyNotFound {
862                        obj: obj.clone(),
863                        key: index,
864                        line,
865                    }),
866                }
867            }
868            _ => Err(RuntimeError::IndexOperatorNotSupported {
869                obj: obj.scurry_type(),
870                index_type: index.scurry_type(),
871                line,
872            }),
873        }
874    }
875
876    fn eval_while_stmt(&mut self, condition: Expr, block: Block) -> EvalResult {
877        while self.eval_expr(condition.clone())?.is_truthy() {
878            loop_control!(self, block.clone());
879        }
880        Ok(Object::AbsoluteNil)
881    }
882
883    fn eval_for_stmt(
884        &mut self,
885        iter_ident: Ident,
886        expr: Expr,
887        block: Block,
888        line: usize,
889    ) -> EvalResult {
890        let obj = self.eval_expr(expr)?;
891        match obj {
892            Object::Array(arr) => {
893                for obj in arr.borrow().iter() {
894                    self.env.borrow_mut().set(iter_ident.0.clone(), obj.clone());
895                    loop_control!(self, block.clone());
896                }
897                Ok(Object::AbsoluteNil)
898            }
899            Object::Map(map) => {
900                for (key, _) in map.borrow().iter() {
901                    self.env.borrow_mut().set(iter_ident.0.clone(), key.clone());
902                    loop_control!(self, block.clone());
903                }
904                Ok(Object::AbsoluteNil)
905            }
906            Object::String(string) => {
907                for char in string.chars() {
908                    self.env
909                        .borrow_mut()
910                        .set(iter_ident.0.clone(), Object::String(char.to_string()));
911                    loop_control!(self, block.clone());
912                }
913                Ok(Object::AbsoluteNil)
914            }
915            Object::Instance(instance) => {
916                for (embed, embed_instance) in
917                    instance.component.embeds.iter().zip(instance.embeds.iter())
918                {
919                    if embed.component.name.0 == "Iterator" {
920                        let mut next = self.eval_call_expr(
921                            embed_instance
922                                .component
923                                .methods
924                                .get("next")
925                                .unwrap()
926                                .clone(),
927                            vec![Object::Instance(embed_instance.clone_with_private())],
928                            false,
929                            line,
930                        )?;
931                        loop {
932                            if let Object::Instance(ref next_obj) = next {
933                                if next_obj.component.name.0 == "StopIteration" {
934                                    return Ok(Object::AbsoluteNil);
935                                }
936                            }
937                            self.env
938                                .borrow_mut()
939                                .set(iter_ident.0.clone(), next.clone());
940                            loop_control!(self, block.clone());
941                            next = self.eval_call_expr(
942                                embed_instance
943                                    .component
944                                    .methods
945                                    .get("next")
946                                    // FIX: Wrong iterator type
947                                    .unwrap()
948                                    .clone(),
949                                vec![Object::Instance(embed_instance.clone_with_private())],
950                                false,
951                                line,
952                            )?;
953                        }
954                    }
955                }
956                Ok(Object::AbsoluteNil)
957            }
958            _ => Err(RuntimeError::CannotIterate {
959                obj: obj.scurry_type(),
960                line,
961            }),
962        }
963    }
964
965    fn eval_switch_stmt(
966        &mut self,
967        switch: Object,
968        cases: Vec<Case>,
969        default: Option<Block>,
970    ) -> EvalResult {
971        for case in cases {
972            for condition in case.conditions {
973                if switch == self.eval_expr(condition)? {
974                    return self.eval_block(case.block);
975                }
976            }
977        }
978        if let Some(block) = default {
979            self.eval_block(block)
980        } else {
981            Ok(Object::AbsoluteNil)
982        }
983    }
984
985    fn eval_call_expr(
986        &mut self,
987        func: Object,
988        mut args: Vec<Object>,
989        type_checked: bool,
990        line: usize,
991    ) -> EvalResult {
992        match func {
993            Object::Function {
994                params,
995                body,
996                env,
997                bound,
998                ..
999            } => {
1000                if let Some(obj) = bound {
1001                    args.insert(0, Object::Instance((*obj).clone_with_private()));
1002                }
1003                if params.len() != args.len() {
1004                    return Err(RuntimeError::NotEnoughArgs {
1005                        got: args.len(),
1006                        want: params.len(),
1007                        line,
1008                    });
1009                }
1010                if type_checked {
1011                    for (arg, (name, ty)) in args.iter().zip(&params) {
1012                        if !arg.fits_type(ty.clone()) {
1013                            return Err(RuntimeError::WrongArgType {
1014                                name: name.0.clone(),
1015                                expected: ty.clone(),
1016                                got: arg.scurry_type().into(),
1017                                line,
1018                            });
1019                        }
1020                    }
1021                }
1022                let outer = Rc::clone(&self.env);
1023                let func_env = {
1024                    let mut scope = Env::new_enclosed(Rc::clone(&env));
1025                    for (arg, param) in args.iter().zip(params) {
1026                        scope.set(param.0 .0, arg.clone());
1027                    }
1028                    scope
1029                };
1030                self.env = Rc::new(RefCell::new(func_env));
1031                let result = self.eval_block(body)?;
1032                self.env = outer;
1033                if let Object::ControlChange(ControlChange::Return(mut val)) = result {
1034                    if let Object::Instance(ref mut instance) = *val {
1035                        instance.visibility = Visibility::Public;
1036                    }
1037                    Ok(*val)
1038                } else if result.is_absnil() {
1039                    Ok(Object::Nil)
1040                } else {
1041                    Ok(result)
1042                }
1043            }
1044            Object::Component(component) => {
1045                let rc_component = Rc::new(component);
1046                let mut instance = Instance {
1047                    component: Rc::clone(&rc_component),
1048                    field_values: Rc::new(RefCell::new(
1049                        Rc::clone(&rc_component)
1050                            .fields
1051                            .iter()
1052                            .map(|(name, _)| (name.0.to_owned(), Object::Nil))
1053                            .collect(),
1054                    )),
1055                    embeds: Vec::new(),
1056                    visibility: Visibility::Public,
1057                };
1058                if let Some(func) = instance.get_special(SpecialMethod::New) {
1059                    args.insert(0, Object::Instance(instance.clone_with_private()));
1060                    self.eval_call_expr(func.clone(), args, type_checked, line)?;
1061                }
1062                for embed in &Rc::clone(&rc_component).embeds {
1063                    let mut args = Vec::new();
1064                    for embed_field in &embed.assigned {
1065                        match embed_field {
1066                            EmbedField::ParentField(field) => {
1067                                let arg = self.eval_dot_expr(
1068                                    Object::Instance(instance.clone_with_private()),
1069                                    field.to_owned(),
1070                                    line,
1071                                )?;
1072                                args.push(arg)
1073                            }
1074                            EmbedField::Expr(expr) => args.push(self.eval_expr(expr.clone())?),
1075                        }
1076                    }
1077                    let embed_instance = self.eval_call_expr(
1078                        Object::Component(embed.component.clone()),
1079                        args,
1080                        embed.type_checked,
1081                        line,
1082                    )?;
1083                    if let Object::Instance(inst) = embed_instance {
1084                        instance.embeds.push(inst);
1085                    } else {
1086                        unreachable!()
1087                    }
1088                }
1089                Ok(Object::Instance(instance))
1090            }
1091            Object::Builtin(func) => func(args, line),
1092            Object::Println => {
1093                writeln!(
1094                    self.out,
1095                    "{}",
1096                    args.into_iter()
1097                        .map(|arg| {
1098                            if let Object::String(s) = arg {
1099                                s + " "
1100                            } else {
1101                                arg.to_string() + " "
1102                            }
1103                        })
1104                        .collect::<String>()
1105                        .strip_suffix(" ")
1106                        .unwrap_or_default()
1107                )
1108                .unwrap();
1109                Ok(Object::Nil)
1110            }
1111            Object::BuiltinMethod { bound, function } => {
1112                function(*bound, args, line).expect("bound type should match")
1113            }
1114            Object::Instance(instance) if instance.has_special(SpecialMethod::Call) => {
1115                if let Some(func) = instance.get_special(SpecialMethod::Call) {
1116                    args.insert(0, Object::Instance(instance.clone_with_private()));
1117                    self.eval_call_expr(func.clone(), args, type_checked, line)
1118                } else {
1119                    unreachable!()
1120                }
1121            }
1122            // Not a function
1123            _ => Err(RuntimeError::NotCallable {
1124                obj: func.scurry_type(),
1125                line,
1126            }),
1127        }
1128    }
1129
1130    fn eval_dot_expr(&self, left: Object, field: String, line: usize) -> EvalResult {
1131        macro_rules! builtin_methods {
1132            ($t:ident, $func:ident) => {
1133                match builtin::$func(&field) {
1134                    Some(method) => Ok(Object::BuiltinMethod {
1135                        bound: Box::new(left),
1136                        function: method,
1137                    }),
1138                    None => Err(RuntimeError::UnrecognizedField {
1139                        field,
1140                        obj: Type::$t,
1141                        line,
1142                    }),
1143                }
1144            };
1145        }
1146
1147        match left {
1148            Object::Instance(Instance {
1149                ref component,
1150                ref field_values,
1151                ref embeds,
1152                ref visibility,
1153            }) => match field_values.borrow().get(&field) {
1154                // Field is there and correct visibility
1155                Some(value) if visibility == &Visibility::Private => Ok(value.clone()),
1156                // Field is there, but visibility is wrong and there is no method with the same
1157                // name
1158                Some(_)
1159                    if visibility == &Visibility::Public
1160                        && component.methods.get(&field).is_none() =>
1161                {
1162                    Err(RuntimeError::UnrecognizedField {
1163                        field,
1164                        obj: left.scurry_type(),
1165                        line,
1166                    })
1167                }
1168                // Field is not there or any of the above cases were not activated
1169                None | Some(_) => match component.methods.get(&field) {
1170                    Some(method) => {
1171                        if let Object::Function {
1172                            params, body, env, ..
1173                        } = method
1174                        {
1175                            if visibility == &Visibility::Public
1176                                && !component.exports.contains(&field)
1177                            {
1178                                Err(RuntimeError::UnrecognizedField {
1179                                    field,
1180                                    obj: left.scurry_type(),
1181                                    line,
1182                                })
1183                            } else {
1184                                Ok(Object::Function {
1185                                    params: params.clone(),
1186                                    body: body.clone(),
1187                                    env: env.clone(),
1188                                    bound: Some(Rc::new(Instance {
1189                                        component: component.clone(),
1190                                        field_values: field_values.clone(),
1191                                        embeds: embeds.clone(),
1192                                        visibility: visibility.clone(),
1193                                    })),
1194                                    visibility: None,
1195                                })
1196                            }
1197                        } else {
1198                            unreachable!()
1199                        }
1200                    }
1201                    None => {
1202                        for embed in embeds {
1203                            if let Some(Object::Function {
1204                                params, body, env, ..
1205                            }) = embed.component.methods.get(&field)
1206                            {
1207                                if !embed.component.exports.contains(&field) {
1208                                    return Err(RuntimeError::UnrecognizedField {
1209                                        field,
1210                                        obj: left.scurry_type(),
1211                                        line,
1212                                    });
1213                                }
1214                                return Ok(Object::Function {
1215                                    params: params.clone(),
1216                                    body: body.clone(),
1217                                    env: env.clone(),
1218                                    bound: Some(Rc::new(embed.clone())),
1219                                    visibility: None,
1220                                });
1221                            }
1222                        }
1223                        Err(RuntimeError::UnrecognizedField {
1224                            field,
1225                            obj: left.scurry_type(),
1226                            line,
1227                        })
1228                    }
1229                },
1230            },
1231
1232            Object::Module { ref exports, .. } => {
1233                exports
1234                    .get(&field)
1235                    .cloned()
1236                    .ok_or(RuntimeError::UnrecognizedField {
1237                        field,
1238                        obj: left.scurry_type(),
1239                        line,
1240                    })
1241            }
1242
1243            Object::Array(_) => builtin_methods!(Array, get_array_method),
1244            Object::Map(_) => builtin_methods!(Map, get_map_method),
1245            Object::String(_) => builtin_methods!(String, get_string_method),
1246            Object::Int(_) => builtin_methods!(Int, get_int_method),
1247            Object::Float(_) => builtin_methods!(Float, get_float_method),
1248
1249            _ => Err(RuntimeError::DotOperatorNotSupported {
1250                obj: left.scurry_type(),
1251                line,
1252            }),
1253        }
1254    }
1255
1256    fn eval_import_stmt(
1257        &mut self,
1258        target: String,
1259        alias: Option<Ident>,
1260        line: usize,
1261    ) -> EvalResult {
1262        let path = PathBuf::from(target);
1263        // Check that no extension was given
1264        if path.extension().is_some() {
1265            return Err(RuntimeError::CouldNotReadFile { name: path, line });
1266        }
1267        let contents = fs::read_to_string(path.with_extension("scy")).map_err(|_| {
1268            RuntimeError::CouldNotReadFile {
1269                name: path.clone(),
1270                line,
1271            }
1272        })?;
1273        let parser = Parser::new(&contents);
1274        let program = parser.parse().map_err(|err| RuntimeError::ParserErrors {
1275            contents,
1276            errs: err,
1277        })?;
1278        let mut module_interpreter = Interpreter::new(self.out);
1279        module_interpreter.eval(program)?;
1280        let name = {
1281            if let Some(alias) = alias {
1282                alias.0
1283            } else {
1284                path.display().to_string()
1285            }
1286        };
1287        self.env.borrow_mut().set(
1288            name,
1289            Object::Module {
1290                file: path,
1291                exports: Rc::new(module_interpreter.env.borrow_mut().symbols()),
1292            },
1293        );
1294        Ok(Object::AbsoluteNil)
1295    }
1296
1297    fn eval_unbound_expr(&mut self, ident: Ident, val: Object) -> Object {
1298        if let Some(var) = self.env.borrow().get(&ident.0) {
1299            return var;
1300        }
1301        self.env.borrow_mut().set(ident.0, val.clone());
1302        val
1303    }
1304}
1305
1306#[cfg(test)]
1307mod tests {
1308    use std::{fs::File, io::Write};
1309
1310    use super::*;
1311    use crate::parser::Parser;
1312
1313    macro_rules! test_eval {
1314        ($inputs:expr, $expecteds:expr) => {
1315            for (input, expected) in $inputs.iter().zip($expecteds) {
1316                let parser = Parser::new(input);
1317                let program = parser.parse().expect("Should have no parser errors");
1318                let stdout = &mut io::stdout();
1319                let mut interpreter = Interpreter::new(stdout);
1320                assert_eq!(
1321                    expected,
1322                    interpreter
1323                        .eval_repl(program)
1324                        .expect("Should evaluate with no errors")
1325                );
1326            }
1327        };
1328    }
1329
1330    macro_rules! runtime_error_eval {
1331        ($inputs:expr, $errs:expr) => {
1332            for (input, err) in $inputs.iter().zip($errs) {
1333                let parser = Parser::new(input);
1334                let program = parser.parse().expect("Should have no parser errors");
1335                let stdout = &mut io::stdout();
1336                let mut interpreter = Interpreter::new(stdout);
1337                assert_eq!(
1338                    err,
1339                    interpreter
1340                        .eval_repl(program)
1341                        .expect_err("Should evaluate with an error")
1342                );
1343            }
1344        };
1345    }
1346
1347    #[test]
1348    fn eval_integer_literal() {
1349        let inputs = ["1;", "333;"];
1350        let expecteds = [Object::Int(1), Object::Int(333)];
1351
1352        test_eval!(inputs, expecteds)
1353    }
1354
1355    #[test]
1356    fn eval_float_literal() {
1357        let inputs = ["1.3;", "333.333;"];
1358        let expecteds = [Object::Float(1.3), Object::Float(333.333)];
1359
1360        test_eval!(inputs, expecteds)
1361    }
1362
1363    #[test]
1364    fn eval_string_literal() {
1365        let inputs = ["\"test\";", "\"string literal\";"];
1366        let expecteds = [
1367            Object::String("test".to_owned()),
1368            Object::String("string literal".to_owned()),
1369        ];
1370
1371        test_eval!(inputs, expecteds)
1372    }
1373
1374    #[test]
1375    fn eval_boolean_literal() {
1376        let inputs = ["True;", "False;"];
1377        let expecteds = [Object::Bool(true), Object::Bool(false)];
1378
1379        test_eval!(inputs, expecteds)
1380    }
1381
1382    #[test]
1383    fn eval_array_literal() {
1384        let inputs = ["[1, 2, 3];"];
1385        let expecteds = [array![Object::Int(1), Object::Int(2), Object::Int(3)]];
1386
1387        test_eval!(inputs, expecteds)
1388    }
1389
1390    #[test]
1391    fn eval_ident() {
1392        let inputs = ["x = 3; x;"];
1393        let expecteds = [Object::Int(3)];
1394
1395        test_eval!(inputs, expecteds)
1396    }
1397
1398    #[test]
1399    fn eval_integer_prefix_ops() {
1400        let inputs = ["-1;", "+2;"];
1401        let expecteds = [Object::Int(-1), Object::Int(2)];
1402
1403        test_eval!(inputs, expecteds)
1404    }
1405
1406    #[test]
1407    fn eval_boolean_prefix_ops() {
1408        let inputs = ["!True;", "!False;"];
1409        let expecteds = [Object::Bool(false), Object::Bool(true)];
1410
1411        test_eval!(inputs, expecteds)
1412    }
1413
1414    #[test]
1415    fn eval_integer_binary_ops() {
1416        let inputs = [
1417            "1 + 1;", "2 - 2;", "3 * 3;", "4 / 4;", "20 % 2;", "3 == 3;", "4 != 4;", "10 > 3;",
1418            "6 < 0;", "30 >= 9;", "7 <= 7;", "9 / 4;",
1419        ];
1420        let expecteds = [
1421            Object::Int(2),
1422            Object::Int(0),
1423            Object::Int(9),
1424            Object::Float(1.0),
1425            Object::Int(0),
1426            Object::Bool(true),
1427            Object::Bool(false),
1428            Object::Bool(true),
1429            Object::Bool(false),
1430            Object::Bool(true),
1431            Object::Bool(true),
1432            Object::Float(2.25),
1433        ];
1434
1435        test_eval!(inputs, expecteds)
1436    }
1437
1438    #[test]
1439    fn eval_boolean_binary_ops() {
1440        let inputs = [
1441            "True == True;",
1442            "False != True;",
1443            "True && False;",
1444            "False || True;",
1445        ];
1446        let expecteds = [
1447            Object::Bool(true),
1448            Object::Bool(true),
1449            Object::Bool(false),
1450            Object::Bool(true),
1451        ];
1452
1453        test_eval!(inputs, expecteds)
1454    }
1455
1456    #[test]
1457    fn eval_string_binary_ops() {
1458        let inputs = ["\"test\" == \"test\";", "\"testing\" != \"testing\";"];
1459        let expecteds = [Object::Bool(true), Object::Bool(false)];
1460
1461        test_eval!(inputs, expecteds)
1462    }
1463
1464    #[test]
1465    fn invalid_unary_operands() {
1466        let inputs = ["-True;", "!3;", "+False;"];
1467        let errs = [
1468            RuntimeError::InvalidUnaryOperand {
1469                op: PrefixOp::Minus,
1470                operand: Type::Bool,
1471                line: 1,
1472            },
1473            RuntimeError::InvalidUnaryOperand {
1474                op: PrefixOp::Bang,
1475                operand: Type::Int,
1476                line: 1,
1477            },
1478            RuntimeError::InvalidUnaryOperand {
1479                op: PrefixOp::Plus,
1480                operand: Type::Bool,
1481                line: 1,
1482            },
1483        ];
1484
1485        runtime_error_eval!(inputs, errs)
1486    }
1487
1488    #[test]
1489    fn invalid_binary_operands() {
1490        let inputs = ["\"test\" + 1;", "False - 3;"];
1491        let errs = [
1492            RuntimeError::InvalidBinaryOperand {
1493                op: InfixOp::Plus,
1494                left: Type::String,
1495                right: Type::Int,
1496                line: 1,
1497            },
1498            RuntimeError::InvalidBinaryOperand {
1499                op: InfixOp::Minus,
1500                left: Type::Bool,
1501                right: Type::Int,
1502                line: 1,
1503            },
1504        ];
1505
1506        runtime_error_eval!(inputs, errs)
1507    }
1508
1509    #[test]
1510    fn eval_float_infix_expr() {
1511        let inputs = [
1512            "1.1 + 2.0;",
1513            "4.4 - 1.2;",
1514            "2.2 / 2.0;",
1515            "2.2 * 2.0;",
1516            "2.0 == 1.0;",
1517            "3.1 != 4.2;",
1518        ];
1519        let expecteds = [
1520            Object::Float(3.1),
1521            Object::Float(3.2),
1522            Object::Float(1.1),
1523            Object::Float(4.4),
1524            Object::Bool(false),
1525            Object::Bool(true),
1526        ];
1527
1528        test_eval!(inputs, expecteds)
1529    }
1530
1531    #[test]
1532    fn eval_num_infix_expr_mixed() {
1533        let inputs = ["2 * 2.3;", "7.6 - 2;", "4.0 == 4;", "30.0 % 2;"];
1534        let expecteds = [
1535            Object::Float(4.6),
1536            Object::Float(5.6),
1537            Object::Bool(true),
1538            Object::Float(0.0),
1539        ];
1540
1541        test_eval!(inputs, expecteds)
1542    }
1543
1544    #[test]
1545    fn eval_string_infix_expr() {
1546        let inputs = ["\"hello\" + \" world\";"];
1547        let expecteds = [Object::String("hello world".to_owned())];
1548
1549        test_eval!(inputs, expecteds)
1550    }
1551
1552    #[test]
1553    fn eval_if_stmt() {
1554        let inputs = [
1555            "if True { x = 3; }; x;",
1556            "if False {} else { x = 3; }; x;",
1557            "if False {} elif True { x = 3; } else {}; x;",
1558            "if False {} elif False {} elif False {} else {}",
1559        ];
1560        let expecteds = [
1561            Object::Int(3),
1562            Object::Int(3),
1563            Object::Int(3),
1564            Object::AbsoluteNil,
1565        ];
1566
1567        test_eval!(inputs, expecteds);
1568    }
1569
1570    #[test]
1571    fn eval_array_index_expr() {
1572        let inputs = [
1573            "[1, 2, 3][1];",
1574            "[1, 2, 3][-1];",
1575            "[1, 2, 3][0];",
1576            "[1, 2, 3][-1];",
1577            "[1, 2, 3][-2];",
1578        ];
1579        let expecteds = [
1580            Object::Int(2),
1581            Object::Int(3),
1582            Object::Int(1),
1583            Object::Int(3),
1584            Object::Int(2),
1585        ];
1586
1587        test_eval!(inputs, expecteds)
1588    }
1589
1590    #[test]
1591    fn array_out_of_range_indices() {
1592        let inputs = ["[1, 2, 3][3];", "[][0];", "[1, 2, 3][-4];"];
1593        let errs = [
1594            RuntimeError::IndexOutOfRange {
1595                obj: array![Object::Int(1), Object::Int(2), Object::Int(3)],
1596                index: 3,
1597                line: 1,
1598            },
1599            RuntimeError::IndexOutOfRange {
1600                obj: Object::Array(Rc::new(RefCell::new(Vec::new()))),
1601                index: 0,
1602                line: 1,
1603            },
1604            RuntimeError::IndexOutOfRange {
1605                obj: array![Object::Int(1), Object::Int(2), Object::Int(3)],
1606                index: -4,
1607                line: 1,
1608            },
1609        ];
1610
1611        runtime_error_eval!(inputs, errs)
1612    }
1613
1614    #[test]
1615    fn eval_string_index_expr() {
1616        let inputs = ["\"test\"[0];", "\"test\"[2];", "\"test\"[-1];"];
1617        let expecteds = [
1618            Object::String("t".to_owned()),
1619            Object::String("s".to_owned()),
1620            Object::String("t".to_owned()),
1621        ];
1622
1623        test_eval!(inputs, expecteds)
1624    }
1625
1626    #[test]
1627    fn string_out_of_range_indices() {
1628        let inputs = ["\"test\"[10];", "\"test\"[-10];", "\"\"[0];"];
1629        let errs = [
1630            RuntimeError::IndexOutOfRange {
1631                obj: Object::String("test".to_owned()),
1632                index: 10,
1633                line: 1,
1634            },
1635            RuntimeError::IndexOutOfRange {
1636                obj: Object::String("test".to_owned()),
1637                index: -10,
1638                line: 1,
1639            },
1640            RuntimeError::IndexOutOfRange {
1641                obj: Object::String("".to_owned()),
1642                index: 0,
1643                line: 1,
1644            },
1645        ];
1646
1647        runtime_error_eval!(inputs, errs)
1648    }
1649
1650    #[test]
1651    fn eval_map_literal() {
1652        let inputs = ["{1: 2, \"test\": 3, True: 33};", "{}"];
1653        let map = {
1654            let mut map = HashMap::new();
1655            map.insert(Object::Int(1), Object::Int(2));
1656            map.insert(Object::String("test".to_owned()), Object::Int(3));
1657            map.insert(Object::Bool(true), Object::Int(33));
1658            map
1659        };
1660        let expecteds = [
1661            Object::Map(Rc::new(RefCell::new(map))),
1662            Object::Map(Rc::new(RefCell::new(HashMap::new()))),
1663        ];
1664
1665        test_eval!(inputs, expecteds)
1666    }
1667
1668    #[test]
1669    fn map_index_expr() {
1670        let inputs = [
1671            "{43: 33}[43];",
1672            "{\"test\": 44}[\"test\"];",
1673            "{True: 2}[True];",
1674        ];
1675        let expecteds = [Object::Int(33), Object::Int(44), Object::Int(2)];
1676
1677        test_eval!(inputs, expecteds)
1678    }
1679
1680    #[test]
1681    fn invalid_key_in_map_index_expr() {
1682        let inputs = ["{}[44];", "{1: 3}[33];"];
1683        let map = {
1684            let mut map = HashMap::new();
1685            map.insert(Object::Int(1), Object::Int(3));
1686            map
1687        };
1688        let errs = [
1689            RuntimeError::KeyNotFound {
1690                obj: Object::Map(Rc::new(RefCell::new(HashMap::new()))),
1691                key: Object::Int(44),
1692                line: 1,
1693            },
1694            RuntimeError::KeyNotFound {
1695                obj: Object::Map(Rc::new(RefCell::new(map))),
1696                key: Object::Int(33),
1697                line: 1,
1698            },
1699        ];
1700
1701        runtime_error_eval!(inputs, errs)
1702    }
1703
1704    #[test]
1705    fn eval_while_statement() {
1706        let inputs = [
1707            "x = 0; while x != 3 { x = x + 1; }; x;",
1708            "x = 2; while False { x = 0; }; x;",
1709        ];
1710        let expecteds = [Object::Int(3), Object::Int(2)];
1711
1712        test_eval!(inputs, expecteds)
1713    }
1714
1715    #[test]
1716    fn eval_for_stmt() {
1717        let inputs = [
1718            "for x in [1, 2, 3] { y = x; }; y;",
1719            "for x in {44: 3} { y = x; }; y;",
1720            "for x in \"test\" { y = x; }; y;",
1721        ];
1722        let expecteds = [
1723            Object::Int(3),
1724            Object::Int(44),
1725            Object::String("t".to_owned()),
1726        ];
1727
1728        test_eval!(inputs, expecteds)
1729    }
1730
1731    #[test]
1732    fn cannot_iterate_through_some_types() {
1733        let inputs = ["for x in 1 {}", "for x in True {}", "for x in 3.3 {}"];
1734        let errs = [
1735            RuntimeError::CannotIterate {
1736                obj: Type::Int,
1737                line: 1,
1738            },
1739            RuntimeError::CannotIterate {
1740                obj: Type::Bool,
1741                line: 1,
1742            },
1743            RuntimeError::CannotIterate {
1744                obj: Type::Float,
1745                line: 1,
1746            },
1747        ];
1748
1749        runtime_error_eval!(inputs, errs)
1750    }
1751
1752    #[test]
1753    fn eval_function_expr() {
1754        let inputs = ["fn(x, y) {}", "fn() {}"];
1755        let expecteds = [
1756            Object::Function {
1757                params: vec![
1758                    (Ident("x".to_owned()), TypeAnnotation::default()),
1759                    (Ident("y".to_owned()), TypeAnnotation::default()),
1760                ],
1761                body: Block(Vec::new()),
1762                env: Rc::new(RefCell::new(Env::new())),
1763                bound: None,
1764                visibility: None,
1765            },
1766            Object::Function {
1767                params: Vec::new(),
1768                body: Block(Vec::new()),
1769                env: Rc::new(RefCell::new(Env::new())),
1770                bound: None,
1771                visibility: None,
1772            },
1773        ];
1774
1775        test_eval!(inputs, expecteds)
1776    }
1777
1778    #[test]
1779    fn eval_function_calls() {
1780        let inputs = ["fn(x, y) { return x + y; }(1, 2);"];
1781        let expecteds = [Object::Int(3)];
1782
1783        test_eval!(inputs, expecteds)
1784    }
1785
1786    #[test]
1787    fn eval_function_calls_with_outer_env() {
1788        let inputs = ["x = 3; fn(y) { return x - y; }(2);"];
1789        let expecteds = [Object::Int(1)];
1790
1791        test_eval!(inputs, expecteds)
1792    }
1793
1794    #[test]
1795    fn err_on_uncallable_object() {
1796        let inputs = ["1();"];
1797        let errs = [RuntimeError::NotCallable {
1798            obj: Type::Int,
1799            line: 1,
1800        }];
1801
1802        runtime_error_eval!(inputs, errs)
1803    }
1804
1805    #[test]
1806    fn eval_basic_decl_statement() {
1807        let inputs = [
1808            "decl Test { field }; Test;",
1809            "decl Test { fn x(self, x) {} }; Test;",
1810        ];
1811        let expecteds = [
1812            Object::Component(Component {
1813                name: Ident("Test".to_owned()),
1814                fields: vec![(Ident("field".to_owned()), TypeAnnotation::default())],
1815                methods: HashMap::new(),
1816                embeds: Vec::new(),
1817                exports: Vec::new(),
1818                visibility: Visibility::Private,
1819            }),
1820            Object::Component(Component {
1821                name: Ident("Test".to_owned()),
1822                fields: Vec::new(),
1823                methods: {
1824                    let mut map = HashMap::new();
1825                    map.insert(
1826                        "x".to_owned(),
1827                        Object::Function {
1828                            params: vec![
1829                                (Ident("self".to_owned()), TypeAnnotation::default()),
1830                                (Ident("x".to_owned()), TypeAnnotation::default()),
1831                            ],
1832                            body: Block(Vec::new()),
1833                            env: Rc::new(RefCell::new(Env::new())),
1834                            bound: None,
1835                            visibility: None,
1836                        },
1837                    );
1838                    map
1839                },
1840                embeds: Vec::new(),
1841                exports: Vec::new(),
1842                visibility: Visibility::Private,
1843            }),
1844        ];
1845
1846        test_eval!(inputs, expecteds)
1847    }
1848
1849    #[test]
1850    fn eval_embed_in_decl_statement() {
1851        let inputs = [
1852            "decl Test { fn x(self, y) {} }; decl Test2 { [Test] {} }; Test2;",
1853            "decl Test { fn $new(self, param) {} }; decl Test2 { field [Test] { field } }; Test2;",
1854        ];
1855        let expecteds = [
1856            Object::Component(Component {
1857                name: Ident("Test2".to_owned()),
1858                fields: Vec::new(),
1859                methods: HashMap::new(),
1860                embeds: vec![EmbedComponent {
1861                    component: Component {
1862                        name: Ident("Test".to_owned()),
1863                        fields: Vec::new(),
1864                        methods: {
1865                            let mut map = HashMap::new();
1866                            map.insert(
1867                                "x".to_owned(),
1868                                Object::Function {
1869                                    params: vec![
1870                                        (Ident("self".to_owned()), TypeAnnotation::default()),
1871                                        (Ident("y".to_owned()), TypeAnnotation::default()),
1872                                    ],
1873                                    body: Block(Vec::new()),
1874                                    env: Rc::new(RefCell::new(Env::new())),
1875                                    bound: None,
1876                                    visibility: None,
1877                                },
1878                            );
1879                            map
1880                        },
1881                        embeds: Vec::new(),
1882                        exports: Vec::new(),
1883                        visibility: Visibility::Private,
1884                    },
1885                    assigned: Vec::new(),
1886                    type_checked: false,
1887                }],
1888                exports: Vec::new(),
1889                visibility: Visibility::Private,
1890            }),
1891            Object::Component(Component {
1892                name: Ident("Test2".to_owned()),
1893                fields: vec![(Ident("field".to_owned()), TypeAnnotation::default())],
1894                methods: HashMap::new(),
1895                embeds: vec![EmbedComponent {
1896                    component: Component {
1897                        name: Ident("Test".to_owned()),
1898                        fields: Vec::new(),
1899                        methods: {
1900                            let mut map = HashMap::new();
1901                            map.insert(
1902                                "$new".to_owned(),
1903                                Object::Function {
1904                                    params: vec![
1905                                        (Ident("self".to_owned()), TypeAnnotation::default()),
1906                                        (Ident("param".to_owned()), TypeAnnotation::default()),
1907                                    ],
1908                                    body: Block(Vec::new()),
1909                                    env: Rc::new(RefCell::new(Env::new())),
1910                                    bound: None,
1911                                    visibility: None,
1912                                },
1913                            );
1914                            map
1915                        },
1916                        embeds: Vec::new(),
1917                        exports: Vec::new(),
1918                        visibility: Visibility::Private,
1919                    },
1920                    assigned: vec![EmbedField::Expr(Expr::Ident(Ident("field".to_owned()), 1))],
1921                    type_checked: false,
1922                }],
1923                exports: Vec::new(),
1924                visibility: Visibility::Private,
1925            }),
1926        ];
1927
1928        test_eval!(inputs, expecteds)
1929    }
1930
1931    #[test]
1932    fn eval_exprs_in_assigned_fields() {
1933        let inputs = ["decl Test { field fn $new(self, field) { self.field = field; } exp fn test(self) { return self.field; } }; decl Test2 { [Test] { 1 + 1 } }; Test2().test();"];
1934        let expecteds = [Object::Int(2)];
1935
1936        test_eval!(inputs, expecteds)
1937    }
1938
1939    #[test]
1940    fn eval_object_instance() {
1941        let inputs = [
1942            "decl Test { field }; Test();",
1943            "decl Test { fn $new(self, x) {} }; Test(3);",
1944        ];
1945        let expecteds = [
1946            Object::Instance(Instance {
1947                component: Rc::new(Component {
1948                    name: Ident("Test".to_owned()),
1949                    fields: vec![(Ident("field".to_owned()), TypeAnnotation::default())],
1950                    methods: HashMap::new(),
1951                    embeds: Vec::new(),
1952                    exports: Vec::new(),
1953                    visibility: Visibility::Private,
1954                }),
1955                field_values: Rc::new(RefCell::new({
1956                    let mut map = HashMap::new();
1957                    map.insert("field".to_owned(), Object::Nil);
1958                    map
1959                })),
1960                embeds: Vec::new(),
1961                visibility: Visibility::Public,
1962            }),
1963            Object::Instance(Instance {
1964                component: Rc::new(Component {
1965                    name: Ident("Test".to_owned()),
1966                    fields: Vec::new(),
1967                    methods: {
1968                        let mut map = HashMap::new();
1969                        map.insert(
1970                            "$new".to_owned(),
1971                            Object::Function {
1972                                params: vec![
1973                                    (Ident("self".to_owned()), TypeAnnotation::default()),
1974                                    (Ident("x".to_owned()), TypeAnnotation::default()),
1975                                ],
1976                                body: Block(Vec::new()),
1977                                env: Rc::new(RefCell::new(Env::new())),
1978                                bound: None,
1979                                visibility: None,
1980                            },
1981                        );
1982                        map
1983                    },
1984                    embeds: Vec::new(),
1985                    exports: Vec::new(),
1986                    visibility: Visibility::Private,
1987                }),
1988                field_values: Rc::new(RefCell::new(HashMap::new())),
1989                visibility: Visibility::Public,
1990                embeds: Vec::new(),
1991            }),
1992        ];
1993
1994        test_eval!(inputs, expecteds)
1995    }
1996
1997    #[test]
1998    fn eval_methods_and_dot_expr() {
1999        let inputs = [
2000            "decl Test { exp fn x(self, y) { return y; } }; Test().x(3);",
2001            "decl Test { exp fn x(self) { return 3; } }; Test().x();",
2002            "decl Test { field exp fn x(self) { return self.field; } }; Test().x();",
2003        ];
2004        let expecteds = [Object::Int(3), Object::Int(3), Object::Nil];
2005
2006        test_eval!(inputs, expecteds)
2007    }
2008
2009    #[test]
2010    fn eval_embedded_methods_in_component_instances() {
2011        let inputs = [
2012            "decl Test { exp fn x(self) { return 3; } }; decl Test2 { [Test] {} }; Test2().x();",
2013        ];
2014        let expecteds = [Object::Int(3)];
2015
2016        test_eval!(inputs, expecteds)
2017    }
2018
2019    #[test]
2020    fn private_methods_usable_in_component() {
2021        let inputs = ["decl Test { exp fn x(self) { return self.y(); } fn y(self) { return 3; } }; Test().x();"];
2022        let expecteds = [Object::Int(3)];
2023
2024        test_eval!(inputs, expecteds)
2025    }
2026
2027    #[test]
2028    fn invalid_use_of_dot_operator() {
2029        let inputs = ["True.field;"];
2030        let errs = [RuntimeError::DotOperatorNotSupported {
2031            obj: Type::Bool,
2032            line: 1,
2033        }];
2034
2035        runtime_error_eval!(inputs, errs)
2036    }
2037
2038    #[test]
2039    fn unrecognized_field_in_component_instance() {
2040        let inputs = ["decl Test { field }; Test().invalid;"];
2041        let errs = [RuntimeError::UnrecognizedField {
2042            field: "invalid".to_owned(),
2043            obj: Type::Instance("Test".to_owned()),
2044            line: 1,
2045        }];
2046
2047        runtime_error_eval!(inputs, errs)
2048    }
2049
2050    #[test]
2051    fn invalid_embed() {
2052        let inputs = ["decl Test { [DoesNotExist] {} }; Test();"];
2053        let errs = [RuntimeError::InvalidEmbed {
2054            name: "DoesNotExist".to_owned(),
2055            line: 1,
2056        }];
2057
2058        runtime_error_eval!(inputs, errs);
2059    }
2060
2061    #[test]
2062    fn field_assignment() {
2063        let inputs =
2064            ["decl Test { field fn $new(self) { self.field = 5; } exp fn field(self) { return self.field; } }; x = Test(); x.field();"];
2065        let expecteds = [Object::Int(5)];
2066
2067        test_eval!(inputs, expecteds)
2068    }
2069
2070    #[test]
2071    fn index_assignment_on_maps() {
2072        let inputs = ["x = {}; x[\"test\"] = 55; x[\"test\"];"];
2073        let expecteds = [Object::Int(55)];
2074
2075        test_eval!(inputs, expecteds)
2076    }
2077
2078    #[test]
2079    fn index_assignment_on_arrays() {
2080        let inputs = ["x = [1, 2, 3]; x[2] = 8; x[2];"];
2081        let expecteds = [Object::Int(8)];
2082
2083        test_eval!(inputs, expecteds)
2084    }
2085
2086    #[test]
2087    fn cannot_index_assign_on_out_of_bounds_array() {
2088        let inputs = ["x = [1, 2, 3]; x[5] = 3;"];
2089        let errs = [RuntimeError::IndexOutOfRange {
2090            obj: Object::Array(Rc::new(RefCell::new(vec![
2091                Object::Int(1),
2092                Object::Int(2),
2093                Object::Int(3),
2094            ]))),
2095            index: 5,
2096            line: 1,
2097        }];
2098
2099        runtime_error_eval!(inputs, errs)
2100    }
2101
2102    #[test]
2103    fn eval_switch_stmt() {
2104        let inputs = [
2105            "switch 3 { case 3 { x = 3; } }; x;",
2106            "switch 3 { case 9 | 3 { x = 4; } }; x;",
2107            "switch \"hello\" { case \"helo\" { x = 5; } case 3 { x = 3; } default { x = 8; } }; x;"
2108        ];
2109        let expecteds = [Object::Int(3), Object::Int(4), Object::Int(8)];
2110
2111        test_eval!(inputs, expecteds)
2112    }
2113
2114    #[test]
2115    fn return_from_nested_block() {
2116        let inputs = [
2117            "fn x(y) { for i in y { return i; } }; x([1, 2, 3]);",
2118            "fn x() { while True { return 3; } }; x();",
2119            "fn x() { if True { return 3; } }; x();",
2120            "fn x() { switch 3 { case 3 { return 4; } } }; x();",
2121        ];
2122        let expecteds = [
2123            Object::Int(1),
2124            Object::Int(3),
2125            Object::Int(3),
2126            Object::Int(4),
2127        ];
2128
2129        test_eval!(inputs, expecteds)
2130    }
2131
2132    #[test]
2133    fn eval_break_and_continue() {
2134        let inputs = [
2135            "y = 0; for i in [1, 2, 3] { break; y = y + 1; }; y;",
2136            "y = 0; for i in [1, 2, 3] { if i == 2 { continue; }; y = y + 1; }; y;",
2137        ];
2138        let expecteds = [Object::Int(0), Object::Int(2)];
2139
2140        test_eval!(inputs, expecteds)
2141    }
2142
2143    #[test]
2144    fn builtin_type() {
2145        let inputs = ["type(3);", "type([1, 2, 3]);"];
2146        let expecteds = [
2147            Object::String("Int".to_owned()),
2148            Object::String("Array".to_owned()),
2149        ];
2150
2151        test_eval!(inputs, expecteds)
2152    }
2153
2154    #[test]
2155    fn builtins_error_with_wrong_number_of_args() {
2156        let inputs = ["type(3, 3);"];
2157        let errs = [RuntimeError::NotEnoughArgs {
2158            got: 2,
2159            want: 1,
2160            line: 1,
2161        }];
2162
2163        runtime_error_eval!(inputs, errs)
2164    }
2165
2166    #[test]
2167    fn builtin_array_push() {
2168        let inputs = ["x = [1, 2, 3]; x.push(3); x;", "[1, 2, 3].push(4);"];
2169        let expecteds = [
2170            Object::Array(Rc::new(RefCell::new(vec![
2171                Object::Int(1),
2172                Object::Int(2),
2173                Object::Int(3),
2174                Object::Int(3),
2175            ]))),
2176            Object::Nil,
2177        ];
2178
2179        test_eval!(inputs, expecteds)
2180    }
2181
2182    #[test]
2183    fn builtin_array_len() {
2184        let inputs = ["[1, 2, 2].len();"];
2185        let expecteds = [Object::Int(3)];
2186
2187        test_eval!(inputs, expecteds)
2188    }
2189
2190    #[test]
2191    fn builtin_array_pop() {
2192        let inputs = ["x = [1, 2, 3]; x.pop(); x;", "[1, 2, 3].pop();"];
2193        let expecteds = [
2194            Object::Array(Rc::new(RefCell::new(vec![Object::Int(1), Object::Int(2)]))),
2195            Object::Int(3),
2196        ];
2197
2198        test_eval!(inputs, expecteds)
2199    }
2200
2201    #[test]
2202    fn builtin_string_len() {
2203        let inputs = ["\"test\".len();"];
2204        let expecteds = [Object::Int(4)];
2205
2206        test_eval!(inputs, expecteds)
2207    }
2208
2209    #[test]
2210    fn builtin_string_trim() {
2211        let inputs = ["\"test     \".trim();"];
2212        let expecteds = [Object::String("test".to_owned())];
2213
2214        test_eval!(inputs, expecteds)
2215    }
2216
2217    #[test]
2218    fn builtin_int_abs() {
2219        let inputs = ["(-1).abs();", "1.abs();"];
2220        let expecteds = [Object::Int(1), Object::Int(1)];
2221
2222        test_eval!(inputs, expecteds)
2223    }
2224
2225    #[test]
2226    fn builtin_int_to_float() {
2227        let inputs = ["1.to_float();"];
2228        let expecteds = [Object::Float(1.0)];
2229
2230        test_eval!(inputs, expecteds)
2231    }
2232
2233    #[test]
2234    fn builtin_float_abs() {
2235        let inputs = ["(-1.0).abs();", "1.0.abs();"];
2236        let expecteds = [Object::Float(1.0), Object::Float(1.0)];
2237
2238        test_eval!(inputs, expecteds)
2239    }
2240
2241    #[test]
2242    fn builtin_float_to_int() {
2243        let inputs = ["1.4.to_int();", "1.0.to_int();", "1.8.to_int();"];
2244        let expecteds = [Object::Int(1), Object::Int(1), Object::Int(1)];
2245
2246        test_eval!(inputs, expecteds)
2247    }
2248
2249    #[test]
2250    fn builtin_map_remove() {
2251        let inputs = ["x = {1: 3}; x.remove(1); x;"];
2252        let expecteds = [Object::Map(Rc::new(RefCell::new(HashMap::new())))];
2253
2254        test_eval!(inputs, expecteds)
2255    }
2256
2257    #[test]
2258    fn assign_stmt_works_with_any_expression() {
2259        let inputs = ["x = [1, 2, [1]]; x[2][0] = 3; x[2];"];
2260        let expecteds = [Object::Array(Rc::new(RefCell::new(vec![Object::Int(3)])))];
2261
2262        test_eval!(inputs, expecteds)
2263    }
2264
2265    #[test]
2266    fn cannot_assign_to_wrong_expr_type() {
2267        let inputs = ["1 = 3;"];
2268        let errs = [RuntimeError::CannotAssign {
2269            expr: Expr::Literal(Literal::Integer(1)),
2270            line: 1,
2271        }];
2272
2273        runtime_error_eval!(inputs, errs)
2274    }
2275
2276    #[test]
2277    fn eval_operator_assignment() {
2278        let inputs = [
2279            "x = 0; x += 1; x;",
2280            "x = 0; x -= 1; x;",
2281            "x = 2; x *= 2; x;",
2282            "x = 2; x /= 2; x;",
2283            "x = 20; x %= 2; x;",
2284        ];
2285        let expecteds = [
2286            Object::Int(1),
2287            Object::Int(-1),
2288            Object::Int(4),
2289            Object::Float(1.0),
2290            Object::Int(0),
2291        ];
2292
2293        test_eval!(inputs, expecteds);
2294    }
2295
2296    #[test]
2297    fn eval_operator_assignment_in_hashmap() {
2298        let inputs = ["x = {\"hello\": 0}; x[\"hello\"] -= 1; x[\"hello\"];"];
2299        let expecteds = [Object::Int(-1)];
2300
2301        test_eval!(inputs, expecteds)
2302    }
2303
2304    #[test]
2305    fn eval_operator_assignment_in_array() {
2306        let inputs = ["x = [1, 2, 3]; x[0] *= 4; x[0];"];
2307        let expecteds = [Object::Int(4)];
2308
2309        test_eval!(inputs, expecteds)
2310    }
2311
2312    #[test]
2313    fn eval_operator_assignment_in_struct_field() {
2314        let inputs = ["decl Test { test fn $new(self) { self.test = 0; self.test += 1; } exp fn show(self) { return self.test; } }; x = Test(); x.show();"];
2315        let expecteds = [Object::Int(1)];
2316
2317        test_eval!(inputs, expecteds)
2318    }
2319
2320    #[test]
2321    fn eval_import_stmt() {
2322        let mut file = File::create("test.scy").expect("should create file correctly");
2323        file.write_all(b"exp fn test() { return 1; }")
2324            .expect("should write bytes");
2325
2326        let inputs = ["import \"test\"; test.test();"];
2327        let expecteds = [Object::Int(1)];
2328
2329        test_eval!(inputs, expecteds);
2330
2331        fs::remove_file("test.scy").expect("should remove file");
2332    }
2333
2334    #[test]
2335    fn import_stmt_errors_with_invalid_file() {
2336        let inputs = [
2337            "import \"doesnotexist\";",
2338            "import \"\";",
2339            "import \"test.txt\";",
2340        ];
2341        let errs = [
2342            RuntimeError::CouldNotReadFile {
2343                name: PathBuf::from("doesnotexist"),
2344                line: 1,
2345            },
2346            RuntimeError::CouldNotReadFile {
2347                name: PathBuf::from(""),
2348                line: 1,
2349            },
2350            RuntimeError::CouldNotReadFile {
2351                name: PathBuf::from("test.txt"),
2352                line: 1,
2353            },
2354        ];
2355
2356        runtime_error_eval!(inputs, errs)
2357    }
2358
2359    #[test]
2360    fn plus_op_overload() {
2361        let inputs =
2362            ["decl Test { fn $add(self, other) { return other + 1; } }; x = Test(); x + 1;"];
2363        let expecteds = [Object::Int(2)];
2364
2365        test_eval!(inputs, expecteds)
2366    }
2367
2368    #[test]
2369    fn minus_op_overload() {
2370        let inputs =
2371            ["decl Test { fn $sub(self, other) { return other + 1; } }; x = Test(); x - 1;"];
2372        let expecteds = [Object::Int(2)];
2373
2374        test_eval!(inputs, expecteds)
2375    }
2376
2377    #[test]
2378    fn mul_op_overload() {
2379        let inputs =
2380            ["decl Test { fn $mul(self, other) { return other + 1; } }; x = Test(); x * 1;"];
2381        let expecteds = [Object::Int(2)];
2382
2383        test_eval!(inputs, expecteds)
2384    }
2385
2386    #[test]
2387    fn div_op_overload() {
2388        let inputs =
2389            ["decl Test { fn $div(self, other) { return other + 1; } }; x = Test(); x / 1;"];
2390        let expecteds = [Object::Int(2)];
2391
2392        test_eval!(inputs, expecteds)
2393    }
2394
2395    #[test]
2396    fn mod_op_overload() {
2397        let inputs =
2398            ["decl Test { fn $mod(self, other) { return other + 1; } }; x = Test(); x % 1;"];
2399        let expecteds = [Object::Int(2)];
2400
2401        test_eval!(inputs, expecteds)
2402    }
2403
2404    #[test]
2405    fn non_operator_overloaded_components_throws_runtime_error() {
2406        let inputs = ["decl Test {}; Test() + 1;"];
2407        let errs = [RuntimeError::InvalidBinaryOperand {
2408            op: InfixOp::Plus,
2409            left: Type::Instance("Test".to_owned()),
2410            right: Type::Int,
2411            line: 1,
2412        }];
2413
2414        runtime_error_eval!(inputs, errs)
2415    }
2416
2417    #[test]
2418    fn eval_type_checked_function_call() {
2419        let inputs = ["fn x(y: Int) { return 1; }; x(1)!;"];
2420        let expecteds = [Object::Int(1)];
2421
2422        test_eval!(inputs, expecteds)
2423    }
2424
2425    #[test]
2426    fn type_checked_function_call_with_mismatched_type_throws_error() {
2427        let inputs = [
2428            "fn x(y: Int) {}; x(3.3)!;",
2429            "fn x(y: Int | Float) {}; x([1])!;",
2430        ];
2431        let errs = [
2432            RuntimeError::WrongArgType {
2433                name: "y".to_owned(),
2434                expected: TypeAnnotation::from_iter([AstType::Int]),
2435                got: AstType::Float,
2436                line: 1,
2437            },
2438            RuntimeError::WrongArgType {
2439                name: "y".to_owned(),
2440                expected: TypeAnnotation::from_iter([AstType::Int, AstType::Float]),
2441                got: AstType::Array,
2442                line: 1,
2443            },
2444        ];
2445
2446        runtime_error_eval!(inputs, errs)
2447    }
2448
2449    #[test]
2450    fn type_checked_function_call_works_with_instances() {
2451        let inputs = ["decl Test {}; fn x(y: Test) {}; x(Test())!;"];
2452        let expecteds = [Object::Nil];
2453
2454        test_eval!(inputs, expecteds)
2455    }
2456
2457    #[test]
2458    fn type_checked_assignment() {
2459        let inputs = ["x!: Int = 3;"];
2460        let expecteds = [Object::AbsoluteNil];
2461
2462        test_eval!(inputs, expecteds)
2463    }
2464
2465    #[test]
2466    fn type_checked_assignment_with_mismatched_type_throws_error() {
2467        let inputs = ["x!: Int = 3.3;"];
2468        let errs = [RuntimeError::MismatchedAssignType {
2469            name: "x".to_owned(),
2470            expected: TypeAnnotation::from_iter([AstType::Int]),
2471            got: AstType::Float,
2472            line: 1,
2473        }];
2474
2475        runtime_error_eval!(inputs, errs)
2476    }
2477
2478    #[test]
2479    fn cannot_return_public_access_from_method() {
2480        let inputs = ["decl Test { field fn $new(self) { self.field = 3; } exp fn test(self) { return self; } }; Test().test().field;"];
2481        let errs = [RuntimeError::UnrecognizedField {
2482            field: "field".to_owned(),
2483            obj: Type::Instance("Test".to_owned()),
2484            line: 1,
2485        }];
2486
2487        runtime_error_eval!(inputs, errs)
2488    }
2489
2490    #[test]
2491    fn type_checked_field_assign_throws_error_with_mismatched_type() {
2492        let inputs = ["decl Test { field: Int fn $new(self) { self.field! = 3.3; } }; Test();"];
2493        let errs = [RuntimeError::MismatchedAssignType {
2494            name: "field".to_owned(),
2495            expected: TypeAnnotation::from_iter([AstType::Int]),
2496            got: AstType::Float,
2497            line: 1,
2498        }];
2499
2500        runtime_error_eval!(inputs, errs)
2501    }
2502
2503    #[test]
2504    fn parent_field_assignment_to_embed() {
2505        let inputs = ["
2506            decl Test {
2507                field
2508                fn $new(self, field) { self.field = field; }
2509                exp fn value(self) { return self.field; }
2510            }
2511            decl Test2 {
2512                field
2513                [Test] { .field }
2514            }
2515            test = Test2();
2516            test.value();"];
2517        let expecteds = [Object::Nil];
2518
2519        test_eval!(inputs, expecteds)
2520    }
2521
2522    #[test]
2523    fn type_checked_embeds() {
2524        let inputs = ["
2525            decl Test {
2526                fn $new(self, i: Int) {}
2527            }
2528            decl Test2 {
2529                [Test]! { 3.3 }
2530            }
2531            Test2();
2532        "];
2533        let errs = [RuntimeError::WrongArgType {
2534            name: "i".to_owned(),
2535            expected: TypeAnnotation::from_iter([AstType::Int]),
2536            got: AstType::Float,
2537            line: 8,
2538        }];
2539
2540        runtime_error_eval!(inputs, errs)
2541    }
2542
2543    #[test]
2544    fn short_circuit_evaluation() {
2545        let inputs = ["0 == 0 || 1 / 0;", "0 != 0 && 1 / 0;"];
2546        let expecteds = [Object::Bool(true), Object::Bool(false)];
2547
2548        test_eval!(inputs, expecteds)
2549    }
2550
2551    #[test]
2552    fn println_writes() {
2553        let input = "println(3);";
2554        let expected = "3\n";
2555
2556        let parser = Parser::new(input);
2557        let program = parser.parse().expect("Should have no parser errors");
2558        let mut out = Vec::new();
2559        let mut interpreter = Interpreter::new(&mut out);
2560        interpreter
2561            .eval(program)
2562            .expect("should evaluate with no errors");
2563        assert_eq!(expected, String::from_utf8(out).unwrap())
2564    }
2565
2566    #[test]
2567    fn div_by_zero_causes_runtime_error() {
2568        let inputs = ["9 / 0;", "9 % 0;"];
2569        let errs = [
2570            RuntimeError::DivisionByZero {
2571                op: InfixOp::Slash,
2572                left: Number::Int(9),
2573                right: Number::Int(0),
2574                line: 1,
2575            },
2576            RuntimeError::DivisionByZero {
2577                op: InfixOp::Modulo,
2578                left: Number::Int(9),
2579                right: Number::Int(0),
2580                line: 1,
2581            },
2582        ];
2583
2584        runtime_error_eval!(inputs, errs)
2585    }
2586
2587    #[test]
2588    fn unbound_returns_and_assigns_when_var_unbound() {
2589        let inputs = ["x ? 3;", "x ? 3; x;"];
2590        let expecteds = [Object::Int(3), Object::Int(3)];
2591
2592        test_eval!(inputs, expecteds);
2593    }
2594
2595    #[test]
2596    fn unbound_returns_var_when_var_is_assigned() {
2597        let inputs = ["x = 55; x ? 3;"];
2598        let expecteds = [Object::Int(55)];
2599
2600        test_eval!(inputs, expecteds);
2601    }
2602}