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 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 _ => 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 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 .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(¶ms) {
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 _ => 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 Some(value) if visibility == &Visibility::Private => Ok(value.clone()),
1156 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 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 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}