1#[macro_use]
2mod built_in;
3mod runtime_result;
4pub mod value;
5
6use rust_decimal::{prelude::ToPrimitive, Decimal};
7
8#[cfg(feature = "no_std_io")]
9use crate::io::Write;
10use crate::{
11 error::{Result, Span},
12 nodes::*,
13 tokens::TokenKind,
14};
15#[cfg(not(feature = "no_std_io"))]
16use std::io::Write;
17use std::{collections::HashMap, mem, rc::Rc};
18
19use self::{
20 runtime_result::RuntimeResult,
21 value::{
22 members::BuiltInMethods,
23 types::{self, Type},
24 BuiltIn, ToValue, Value, WrappedValue,
25 },
26};
27
28macro_rules! try_visit {
29 ($call:expr) => {{
30 let res: RuntimeResult = $call;
31 if res.should_return() {
32 return Ok(res);
33 }
34 res.take_value()
35 }};
36}
37
38macro_rules! simple_expr {
39 ($name:ident: $type:ident, $next:ident; $($tt:tt)+) => {
40 fn $name(&mut self, node: &'tree $type) -> Result<RuntimeResult<'tree>> {
41 let mut base = try_visit!(self.$next(&node.base)?);
42 simple_expr!(@kind self, node, base, $next, $($tt)+);
43 Ok(RuntimeResult::new(Some(base)))
44 }
45 };
46 (@kind $self:ident, $node:ident, $base:ident, $next:ident, $method:ident) => {
47 for other in &$node.following {
48 let other = try_visit!($self.$next(other)?);
49 let out = $base
50 .borrow()
51 .$method(&other.borrow(), &$node.span)?
52 .wrapped();
53 $base = out;
54 }
55 };
56 (@kind $self:ident, $node:ident, $base:ident, $next:ident, $($tok:ident => $method:ident),+ $(,)?) => {
57 for (tok, other) in &$node.following {
58 let other = try_visit!($self.$next(other)?);
59 let out = match tok {
60 $(TokenKind::$tok => $base.borrow().$method(&other.borrow(), &$node.span),)+
61 _ => unreachable!(),
62 }?
63 .wrapped();
64 $base = out;
65 }
66 };
67}
68
69macro_rules! built_in {
70 ($name:literal, $($built_in:tt)*) => {
71 ($name, Value::BuiltIn(BuiltIn::$($built_in)*).wrapped())
72 };
73}
74
75pub struct Interpreter<'tree, StdOut, StdErr, Exit>
76where
77 StdOut: Write,
78 StdErr: Write,
79 Exit: FnOnce(i32),
80{
81 program: &'tree Program,
82 pub scopes: Vec<HashMap<&'tree str, WrappedValue<'tree>>>,
83 pub scope_idx: usize,
84 stdout: StdOut,
85 stderr: StdErr,
86 exit_callback: Option<Exit>,
87 built_in_methods: BuiltInMethods<'tree>,
88}
89
90impl<'tree, StdOut, StdErr, Exit> Interpreter<'tree, StdOut, StdErr, Exit>
91where
92 StdOut: Write,
93 StdErr: Write,
94 Exit: FnOnce(i32),
95{
96 pub fn new(
97 program: &'tree Program,
98 stdout: StdOut,
99 stderr: StdErr,
100 exit_callback: Exit,
101 ) -> Self {
102 Self {
103 program,
104 scopes: vec![HashMap::from([
105 built_in!(
106 "print",
107 Print {
108 newline: false,
109 stderr: false
110 },
111 ),
112 built_in!(
113 "printl",
114 Print {
115 newline: true,
116 stderr: false
117 },
118 ),
119 built_in!(
120 "eprint",
121 Print {
122 newline: false,
123 stderr: true
124 },
125 ),
126 built_in!(
127 "eprintl",
128 Print {
129 newline: true,
130 stderr: true
131 },
132 ),
133 built_in!("typeOf", Function(built_in::type_of)),
134 built_in!("assert", Function(built_in::assert)),
135 built_in!("throw", Function(built_in::throw)),
136 built_in!("exit", Exit),
137 built_in!("debug", Debug),
138 ("answer", Value::Number(42.into()).wrapped()),
139 ])],
140 scope_idx: 0,
141 stdout,
142 stderr,
143 exit_callback: Some(exit_callback),
144 built_in_methods: BuiltInMethods::new(),
145 }
146 }
147
148 #[inline]
149 pub fn run(&mut self, new_scope: bool) -> Result<RuntimeResult<'tree>> {
150 self.visit_program(self.program, new_scope)
151 }
152
153 fn push_scope(&mut self) {
154 self.scopes.push(HashMap::new());
155 self.scope_idx += 1;
156 }
157
158 fn pop_scope(&mut self) {
159 self.scopes.pop();
160 self.scope_idx -= 1;
161 }
162
163 fn add_var(&mut self, name: &'tree str, value: WrappedValue<'tree>) {
164 self.scopes.last_mut().unwrap().insert(name, value);
165 }
166
167 fn get_var(&self, name: &str, span: &Span) -> Result<(&WrappedValue<'tree>, usize)> {
168 for (idx, scope) in self.scopes.iter().enumerate().rev() {
169 if let Some(var) = scope.get(name) {
170 return Ok((var, idx));
171 }
172 }
173 error!(
174 ReferenceError,
175 *span, "Variable with name '{}' not found", name,
176 );
177 }
178
179 #[inline]
182 fn visit_program(
183 &mut self,
184 node: &'tree Program,
185 new_scope: bool,
186 ) -> Result<RuntimeResult<'tree>> {
187 self.visit_statements(node, new_scope)
188 }
189
190 fn visit_statements(
191 &mut self,
192 node: &'tree Statements,
193 new_scope: bool,
194 ) -> Result<RuntimeResult<'tree>> {
195 if new_scope {
196 self.push_scope();
197 }
198 let mut result = RuntimeResult::new(None);
199 for stmt in node {
200 result = self.visit_statement(stmt)?;
201 if result.should_return() {
202 break;
203 }
204 }
205 if new_scope {
206 self.pop_scope();
207 }
208 Ok(if result.value.is_none() && !result.should_return() {
209 RuntimeResult::new(Some(Value::Null.wrapped()))
210 } else {
211 result
212 })
213 }
214
215 #[inline]
216 fn visit_block(&mut self, node: &'tree Block, new_scope: bool) -> Result<RuntimeResult<'tree>> {
217 self.visit_statements(node, new_scope)
218 }
219
220 fn visit_statement(&mut self, node: &'tree Statement) -> Result<RuntimeResult<'tree>> {
221 match node {
222 Statement::Var(node) => self.visit_var_stmt(node),
223 Statement::Function(node) => self.visit_function_decl(node),
224 Statement::Class(node) => self.visit_class_decl(node),
225 Statement::Break(node) => self.visit_break_stmt(node),
226 Statement::Continue(node) => self.visit_continue_stmt(node),
227 Statement::Return(node) => self.visit_return_stmt(node),
228 Statement::Expr(node) => self.visit_expression(node),
229 }
230 }
231
232 fn visit_var_stmt(&mut self, node: &'tree VarStmt) -> Result<RuntimeResult<'tree>> {
233 let val = match &node.expr {
234 Some(node) => try_visit!(self.visit_expression(node)?),
235 None => Value::Null.wrapped(),
236 };
237 self.add_var(&node.ident, val);
238 Ok(RuntimeResult::new(None))
239 }
240
241 fn visit_function_decl(&mut self, node: &'tree FunctionDecl) -> Result<RuntimeResult<'tree>> {
242 self.add_var(
243 &node.ident,
244 Value::Function {
245 args: &node.args,
246 block: &node.block,
247 }
248 .wrapped(),
249 );
250 Ok(RuntimeResult::new(None))
251 }
252
253 fn visit_class_decl(&mut self, node: &'tree ClassDecl) -> Result<RuntimeResult<'tree>> {
254 let class = Value::Null.wrapped();
255 let mut statics: HashMap<&str, _> = HashMap::new();
256 let mut non_statics = vec![];
257 for member in &node.block.members {
258 match (member.is_static, &member.kind) {
259 (true, MemberKind::Attribute(node)) => {
260 statics.insert(
261 &node.ident,
262 match &node.expr {
263 Some(node) => try_visit!(self.visit_expression(node)?),
264 None => Value::Null.wrapped(),
265 },
266 );
267 }
268 (true, MemberKind::Method(node)) => {
269 statics.insert(
270 &node.ident,
271 Value::Function {
272 args: &node.args,
273 block: &node.block,
274 }
275 .wrapped(),
276 );
277 }
278 (false, member) => {
279 non_statics.push(member);
280 }
281 }
282 }
283 *class.borrow_mut() = Value::Class {
284 statics,
285 non_statics,
286 };
287 self.add_var(&node.ident, class);
288 Ok(RuntimeResult::new(None))
289 }
290
291 fn visit_break_stmt(&mut self, node: &'tree BreakStmt) -> Result<RuntimeResult<'tree>> {
292 let val = match &node.expr {
293 Some(node) => try_visit!(self.visit_expression(node)?),
294 None => Value::Null.wrapped(),
295 };
296 Ok(RuntimeResult::success_break(val))
297 }
298
299 fn visit_continue_stmt(&mut self, _: &'tree ContinueStmt) -> Result<RuntimeResult<'tree>> {
300 Ok(RuntimeResult::success_continue())
301 }
302
303 fn visit_return_stmt(&mut self, node: &'tree ReturnStmt) -> Result<RuntimeResult<'tree>> {
304 let val = match &node.expr {
305 Some(node) => try_visit!(self.visit_expression(node)?),
306 None => Value::Null.wrapped(),
307 };
308 Ok(RuntimeResult::success_return(val))
309 }
310
311 #[inline]
312 fn visit_expression(&mut self, node: &'tree Expression) -> Result<RuntimeResult<'tree>> {
313 self.visit_range_expr(node)
314 }
315
316 fn visit_range_expr(&mut self, node: &'tree RangeExpr) -> Result<RuntimeResult<'tree>> {
317 match node {
318 RangeExpr::None(node) => self.visit_or_expr(node),
319 RangeExpr::Closed(left, tok, right, span) => {
320 let left = try_visit!(self.visit_or_expr(left)?);
321 let right = try_visit!(self.visit_or_expr(right)?);
322 let inclusive = tok == &TokenKind::DotsInclusive;
323 let range = match (&*left.borrow(), &*right.borrow()) {
324 (Value::Number(start), Value::Number(end)) => {
325 if !start.fract().is_zero() || !end.fract().is_zero() {
326 error!(ValueError, *span, "Range bounds have to be integers");
327 }
328 let start = start.to_i128().unwrap();
329 let end = end.to_i128().unwrap();
330 let end = end - !inclusive as i128;
331 Value::Range {
332 start: Some(start),
333 end: Some(end),
334 }
335 }
336 _ => error!(TypeError, *span, "Range bounds have to be of type 'number'"),
337 };
338 Ok(RuntimeResult::new(Some(range.wrapped())))
339 }
340 RangeExpr::OpenEnd(left, span) => {
341 let left = try_visit!(self.visit_or_expr(left)?);
342 let range = match &*left.borrow() {
343 Value::Number(start) => {
344 if !start.fract().is_zero() {
345 error!(ValueError, *span, "Range bounds have to be integers");
346 }
347 let start = start.to_i128().unwrap();
348 Value::Range {
349 start: Some(start),
350 end: None,
351 }
352 }
353 _ => error!(TypeError, *span, "Range bounds have to be of type 'number'"),
354 };
355 Ok(RuntimeResult::new(Some(range.wrapped())))
356 }
357 RangeExpr::OpenStart(tok, right, span) => {
358 let right = try_visit!(self.visit_or_expr(right)?);
359 let inclusive = tok == &TokenKind::DotsInclusive;
360 let range = match &*right.borrow() {
361 Value::Number(end) => {
362 if !end.fract().is_zero() {
363 error!(ValueError, *span, "Range bounds have to be integers");
364 }
365 let end = end.to_i128().unwrap();
366 let end = end - !inclusive as i128;
367 Value::Range {
368 start: None,
369 end: Some(end),
370 }
371 }
372 _ => error!(TypeError, *span, "Range bounds have to be of type 'number'"),
373 };
374 Ok(RuntimeResult::new(Some(range.wrapped())))
375 }
376 RangeExpr::Open => Ok(RuntimeResult::new(Some(
377 Value::Range {
378 start: None,
379 end: None,
380 }
381 .wrapped(),
382 ))),
383 }
384 }
385
386 fn visit_or_expr(&mut self, node: &'tree OrExpr) -> Result<RuntimeResult<'tree>> {
387 let base = try_visit!(self.visit_and_expr(&node.base)?);
388 if !node.following.is_empty() {
389 if base.borrow().is_false() {
390 return Ok(RuntimeResult::new(Some(Value::Bool(false).wrapped())));
391 }
392 for other in &node.following {
393 if try_visit!(self.visit_and_expr(other)?).borrow().is_false() {
394 return Ok(RuntimeResult::new(Some(Value::Bool(false).wrapped())));
395 }
396 }
397 return Ok(RuntimeResult::new(Some(Value::Bool(true).wrapped())));
398 }
399 Ok(RuntimeResult::new(Some(base)))
400 }
401
402 fn visit_and_expr(&mut self, node: &'tree AndExpr) -> Result<RuntimeResult<'tree>> {
403 let base = try_visit!(self.visit_bit_or_expr(&node.base)?);
404 if !node.following.is_empty() {
405 if base.borrow().is_true() {
406 return Ok(RuntimeResult::new(Some(Value::Bool(true).wrapped())));
407 }
408 for other in &node.following {
409 if try_visit!(self.visit_bit_or_expr(other)?)
410 .borrow()
411 .is_true()
412 {
413 return Ok(RuntimeResult::new(Some(Value::Bool(true).wrapped())));
414 }
415 }
416 return Ok(RuntimeResult::new(Some(Value::Bool(false).wrapped())));
417 }
418 Ok(RuntimeResult::new(Some(base)))
419 }
420
421 simple_expr!(visit_bit_or_expr: BitOrExpr, visit_bit_xor_expr; or);
422 simple_expr!(visit_bit_xor_expr: BitXorExpr, visit_bit_and_expr; xor);
423 simple_expr!(visit_bit_and_expr: BitAndExpr, visit_eq_expr; and);
424
425 fn visit_eq_expr(&mut self, node: &'tree EqExpr) -> Result<RuntimeResult<'tree>> {
426 let left = try_visit!(self.visit_rel_expr(&node.left)?);
427 let out = if let Some((tok, right)) = &node.right {
428 let right = try_visit!(self.visit_rel_expr(right)?);
429 Value::Bool(match tok {
430 TokenKind::Equal => left == right,
431 TokenKind::NotEqual => left != right,
432 _ => unreachable!(),
433 })
434 .wrapped()
435 } else {
436 left
437 };
438 Ok(RuntimeResult::new(Some(out)))
439 }
440
441 fn visit_rel_expr(&mut self, node: &'tree RelExpr) -> Result<RuntimeResult<'tree>> {
442 let left = try_visit!(self.visit_shift_expr(&node.left)?);
443 let out = if let Some((tok, right)) = &node.right {
444 let right = try_visit!(self.visit_shift_expr(right)?);
445 match tok {
446 TokenKind::LessThan => left.borrow().lt(&right.borrow(), &node.span),
447 TokenKind::LessThanOrEqual => left.borrow().le(&right.borrow(), &node.span),
448 TokenKind::GreaterThan => left.borrow().gt(&right.borrow(), &node.span),
449 TokenKind::GreaterThanOrEqual => left.borrow().ge(&right.borrow(), &node.span),
450 _ => unreachable!(),
451 }?
452 .wrapped()
453 } else {
454 left
455 };
456 Ok(RuntimeResult::new(Some(out)))
457 }
458
459 simple_expr!(
460 visit_shift_expr: ShiftExpr, visit_add_expr;
461 ShiftLeft => shl,
462 ShiftRight => shr,
463 );
464
465 simple_expr!(
466 visit_add_expr: AddExpr, visit_mul_expr;
467 Plus => add,
468 Minus => sub,
469 );
470
471 simple_expr!(
472 visit_mul_expr: MulExpr, visit_unary_expr;
473 Star => mul,
474 Slash => div,
475 Rem => rem,
476 Backslash => div_floor,
477 );
478
479 fn visit_unary_expr(&mut self, node: &'tree UnaryExpr) -> Result<RuntimeResult<'tree>> {
480 match node {
481 UnaryExpr::Unary {
482 span,
483 operator,
484 expr,
485 } => {
486 let base = try_visit!(self.visit_unary_expr(expr)?);
487 let out = match operator {
488 TokenKind::Plus => Value::Number(Decimal::ZERO).add(&base.borrow(), span)?,
489 TokenKind::Minus => Value::Number(Decimal::ZERO).sub(&base.borrow(), span)?,
490 TokenKind::Not => Value::Bool(base.borrow().is_false()),
491 _ => unreachable!(),
492 }
493 .wrapped();
494 Ok(RuntimeResult::new(Some(out)))
495 }
496 UnaryExpr::Done(node) => self.visit_exp_expr(node),
497 }
498 }
499
500 fn visit_exp_expr(&mut self, node: &'tree ExpExpr) -> Result<RuntimeResult<'tree>> {
501 let mut base = try_visit!(self.visit_assign_expr(&node.base)?);
502 if let Some(exponent) = &node.exponent {
503 let exponent = try_visit!(self.visit_unary_expr(exponent)?);
504 let out = base.borrow().pow(&exponent.borrow(), &node.span)?.wrapped();
505 base = out;
506 }
507 Ok(RuntimeResult::new(Some(base)))
508 }
509
510 fn visit_assign_expr(&mut self, node: &'tree AssignExpr) -> Result<RuntimeResult<'tree>> {
511 let left = try_visit!(self.visit_call_expr(&node.left)?);
512 if let Some((tok, right)) = &node.right {
513 let left_type = types::type_of(&left.borrow());
514 if let Type::Class | Type::Object | Type::Range = left_type {
515 error!(TypeError, node.span, "Cannot reassign type '{}'", left_type,);
516 }
517 let right = try_visit!(self.visit_expression(right)?);
518 let new_value = match tok {
519 TokenKind::Assign => right.borrow().clone(),
520 TokenKind::StarAssign => left.borrow().mul(&right.borrow(), &node.span)?,
521 TokenKind::SlashAssign => left.borrow().div(&right.borrow(), &node.span)?,
522 TokenKind::BackslashAssign => {
523 left.borrow().div_floor(&right.borrow(), &node.span)?
524 }
525 TokenKind::RemAssign => left.borrow().rem(&right.borrow(), &node.span)?,
526 TokenKind::PlusAssign => left.borrow().add(&right.borrow(), &node.span)?,
527 TokenKind::MinusAssign => left.borrow().sub(&right.borrow(), &node.span)?,
528 TokenKind::ShiftLeftAssign => left.borrow().shl(&right.borrow(), &node.span)?,
529 TokenKind::ShiftRightAssign => left.borrow().shr(&right.borrow(), &node.span)?,
530 TokenKind::BitAndAssign => left.borrow().and(&right.borrow(), &node.span)?,
531 TokenKind::BitXorAssign => left.borrow().xor(&right.borrow(), &node.span)?,
532 TokenKind::BitOrAssign => left.borrow().or(&right.borrow(), &node.span)?,
533 _ => unreachable!(),
534 };
535 let new_type = types::type_of(&new_value);
536 if left_type != new_type && left_type != Type::Null && new_type != Type::Null {
537 error!(
538 TypeError,
539 node.span, "Cannot change type by reassigning, create a new variable instead",
540 );
541 }
542 *left.borrow_mut() = new_value;
543 }
544 Ok(RuntimeResult::new(Some(left)))
545 }
546
547 fn visit_call_expr(&mut self, node: &'tree CallExpr) -> Result<RuntimeResult<'tree>> {
548 let (mut parent, result) = self.visit_member_expr(&node.base)?;
549 if result.should_return() {
550 return Ok(result);
551 }
552 let mut base = result.take_value();
553 for part in &node.following {
554 let out = match part {
555 CallPart::Args(args) => self.call_value(&base, args, &parent, &node.span)?,
556 CallPart::Member(MemberPart::Field(ident)) => {
557 Value::get_field(&base, ident, &self.built_in_methods, &node.span)?
558 }
559 CallPart::Member(MemberPart::Index(expr)) => {
560 Value::index(&base, &try_visit!(self.visit_expression(expr)?), &node.span)?
561 }
562 };
563 mem::swap(&mut base, &mut parent);
564 base = out;
565 }
566 Ok(RuntimeResult::new(Some(base)))
567 }
568
569 pub fn call_value(
570 &mut self,
571 value: &WrappedValue<'tree>,
572 call_args: &'tree Args,
573 parent: &WrappedValue<'tree>,
574 span: &Span,
575 ) -> Result<WrappedValue<'tree>> {
576 match &*value.borrow() {
577 Value::Function { args, block } => {
578 if args.len() != call_args.len() {
579 error!(
580 TypeError,
581 *span,
582 "Function takes {} arguments, however {} were supllied",
583 args.len(),
584 call_args.len(),
585 );
586 }
587 self.push_scope();
588 if *parent.borrow() != Value::Null {
589 self.add_var("this", Rc::clone(parent));
590 }
591 for (idx, arg) in args.iter().enumerate() {
592 let val = self.visit_expression(&call_args[idx])?.take_value();
593 self.add_var(arg, val);
594 }
595 let res = self.visit_block(block, false)?;
596 self.pop_scope();
597 Ok(if let Some(val) = res.return_value {
598 val
599 } else {
600 res.take_value()
601 })
602 }
603 Value::BuiltIn(func) => {
604 let mut args = vec![];
605 for arg in call_args {
606 args.push(self.visit_expression(arg)?.take_value());
607 }
608
609 let out = match func {
610 BuiltIn::Function(func) => func(args, span)?,
611 BuiltIn::Method(func) => func(parent, args, span)?,
612 BuiltIn::Print {
613 newline,
614 stderr: false,
615 } => built_in::print(args, &mut self.stdout, span, *newline)?,
616 BuiltIn::Print {
617 newline,
618 stderr: true,
619 } => built_in::print(args, &mut self.stderr, span, *newline)?,
620 BuiltIn::Exit => {
621 built_in::exit(args, self.exit_callback.take().unwrap(), span)?
622 }
623 BuiltIn::Debug => built_in::debug(args, &mut self.stderr, span)?,
624 };
625 Ok(out)
626 }
627 Value::Class { non_statics, .. } => {
628 if !call_args.is_empty() {
629 error!(
630 TypeError,
631 *span,
632 "Class constructors take no arguments, however {} were supplied",
633 call_args.len(),
634 );
635 }
636 let object = Value::Null.wrapped();
637 let mut fields: HashMap<&str, _> = HashMap::new();
638 for member in non_statics {
639 match member {
640 MemberKind::Attribute(node) => {
641 fields.insert(
642 &node.ident,
643 match &node.expr {
644 Some(node) => self.visit_expression(node)?.take_value(),
645 None => Value::Null.wrapped(),
646 },
647 );
648 }
649 MemberKind::Method(node) => {
650 fields.insert(
651 &node.ident,
652 Value::Function {
653 args: &node.args,
654 block: &node.block,
655 }
656 .wrapped(),
657 );
658 }
659 }
660 }
661 *object.borrow_mut() = Value::Object(fields);
662 Ok(object)
663 }
664 _ => error!(
665 TypeError,
666 *span,
667 "Type '{}' is not callable",
668 types::type_of(&value.borrow()),
669 ),
670 }
671 }
672
673 fn visit_member_expr(
674 &mut self,
675 node: &'tree MemberExpr,
676 ) -> Result<(WrappedValue<'tree>, RuntimeResult<'tree>)> {
677 let res = self.visit_atom(&node.base)?;
678 if res.should_return() {
679 return Ok((Value::Null.wrapped(), res));
680 }
681 let mut base = res.take_value();
682 let mut parent = Value::Null.wrapped();
683 for part in &node.following {
684 let out = match part {
685 MemberPart::Field(ident) => {
686 Value::get_field(&base, ident, &self.built_in_methods, &node.span)?
687 }
688 MemberPart::Index(expr) => {
689 let res = self.visit_expression(expr)?;
690 if res.should_return() {
691 return Ok((Value::Null.wrapped(), res));
692 }
693 Value::index(&base, &res.take_value(), &node.span)?
694 }
695 };
696 mem::swap(&mut parent, &mut base);
697 base = out;
698 }
699 Ok((parent, RuntimeResult::new(Some(base))))
700 }
701
702 fn visit_atom(&mut self, node: &'tree Atom) -> Result<RuntimeResult<'tree>> {
703 let out = match node {
704 Atom::Number(val) => Value::Number(*val).wrapped(),
705 Atom::Bool(val) => Value::Bool(*val).wrapped(),
706 Atom::String(val) => Value::String(val.clone()).wrapped(),
707 Atom::Null => Value::Null.wrapped(),
708 Atom::Identifier { span, name } => Rc::clone(self.get_var(name, span)?.0),
709 Atom::Expr(node) => try_visit!(self.visit_expression(node)?),
710 Atom::List(nodes) => {
711 let results = nodes
712 .iter()
713 .map(|node| self.visit_expression(node))
714 .collect::<Result<Vec<_>>>()?;
715 let mut values = vec![];
716 for res in results {
717 if res.should_return() {
718 return Ok(res);
719 }
720 values.push(res.take_value());
721 }
722 Value::List(values).wrapped()
723 }
724 Atom::IfExpr(node) => try_visit!(self.visit_if_expr(node)?),
725 Atom::ForExpr(node) => try_visit!(self.visit_for_expr(node)?),
726 Atom::WhileExpr(node) => try_visit!(self.visit_while_expr(node)?),
727 Atom::LoopExpr(node) => try_visit!(self.visit_loop_expr(node)?),
728 Atom::FunExpr(node) => try_visit!(self.visit_fun_expr(node)?),
729 Atom::ClassExpr(node) => try_visit!(self.visit_class_expr(node)?),
730 Atom::TryExpr(node) => try_visit!(self.visit_try_expr(node)?),
731 Atom::BlockExpr(node) => try_visit!(self.visit_block_expr(node)?),
732 };
733 Ok(RuntimeResult::new(Some(out)))
734 }
735
736 fn visit_if_expr(&mut self, node: &'tree IfExpr) -> Result<RuntimeResult<'tree>> {
737 let cond = try_visit!(self.visit_expression(&node.cond)?);
738 let out = if cond.borrow().is_true() {
739 try_visit!(self.visit_block(&node.block, true)?)
740 } else if let Some(block) = &node.else_block {
741 try_visit!(self.visit_block(block, true)?)
742 } else {
743 Value::Null.wrapped()
744 };
745 Ok(RuntimeResult::new(Some(out)))
746 }
747
748 fn visit_for_expr(&mut self, node: &'tree ForExpr) -> Result<RuntimeResult<'tree>> {
749 let iter = try_visit!(self.visit_expression(&node.iter)?);
750 let iter = iter.borrow();
751 let iter = iter.to_iter(&node.span)?;
752 let mut out = Value::Null.wrapped();
753 for item in iter {
754 self.push_scope();
755 self.add_var(&node.ident, item);
756 let res = self.visit_block(&node.block, false)?;
757 if res.should_continue {
758 continue;
759 } else if let Some(val) = res.break_value {
760 out = val;
761 } else if res.return_value.is_some() {
762 return Ok(res);
763 }
764 }
765 Ok(RuntimeResult::new(Some(out)))
766 }
767
768 fn visit_while_expr(&mut self, node: &'tree WhileExpr) -> Result<RuntimeResult<'tree>> {
769 let out = loop {
770 let cond = try_visit!(self.visit_expression(&node.cond)?);
771 if cond.borrow().is_false() {
772 break Value::Null.wrapped();
773 }
774
775 let res = self.visit_block(&node.block, true)?;
776 if res.should_continue {
777 continue;
778 } else if let Some(val) = res.break_value {
779 break val;
780 } else if res.return_value.is_some() {
781 return Ok(res);
782 }
783 };
784 Ok(RuntimeResult::new(Some(out)))
785 }
786
787 fn visit_loop_expr(&mut self, node: &'tree LoopExpr) -> Result<RuntimeResult<'tree>> {
788 let out = loop {
789 let res = self.visit_block(&node.block, true)?;
790 if res.should_continue {
791 continue;
792 } else if let Some(val) = res.break_value {
793 break val;
794 } else if res.return_value.is_some() {
795 return Ok(res);
796 }
797 };
798 Ok(RuntimeResult::new(Some(out)))
799 }
800
801 fn visit_fun_expr(&mut self, node: &'tree FunExpr) -> Result<RuntimeResult<'tree>> {
802 let out = Value::Function {
803 args: &node.args,
804 block: &node.block,
805 }
806 .wrapped();
807 Ok(RuntimeResult::new(Some(out)))
808 }
809
810 fn visit_class_expr(&mut self, node: &'tree ClassExpr) -> Result<RuntimeResult<'tree>> {
811 let class = Value::Null.wrapped();
812 let mut statics: HashMap<&str, _> = HashMap::new();
813 let mut non_statics = vec![];
814 for member in &node.block.members {
815 match (member.is_static, &member.kind) {
816 (true, MemberKind::Attribute(node)) => {
817 statics.insert(
818 &node.ident,
819 match &node.expr {
820 Some(node) => try_visit!(self.visit_expression(node)?),
821 None => Value::Null.wrapped(),
822 },
823 );
824 }
825 (true, MemberKind::Method(node)) => {
826 statics.insert(
827 &node.ident,
828 Value::Function {
829 args: &node.args,
830 block: &node.block,
831 }
832 .wrapped(),
833 );
834 }
835 (false, member) => {
836 non_statics.push(member);
837 }
838 }
839 }
840 *class.borrow_mut() = Value::Class {
841 statics,
842 non_statics,
843 };
844 Ok(RuntimeResult::new(Some(class)))
845 }
846
847 fn visit_try_expr(&mut self, node: &'tree TryExpr) -> Result<RuntimeResult<'tree>> {
848 let res = self.visit_block(&node.try_block, true);
849 if let Err(e) = res {
850 self.push_scope();
851 self.add_var(&node.ident, e.to_value().wrapped());
852 let out = try_visit!(self.visit_block(&node.catch_block, false)?);
853 self.pop_scope();
854 Ok(RuntimeResult::new(Some(out)))
855 } else {
856 res
857 }
858 }
859
860 #[inline]
861 fn visit_block_expr(&mut self, node: &'tree BlockExpr) -> Result<RuntimeResult<'tree>> {
862 self.visit_block(node, true)
863 }
864}