roost_lang/
interpreter.rs

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    ////////////////////////////////////////
180
181    #[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}