tenda_runtime/
runtime.rs

1use std::{cell::RefCell, fmt::Debug, rc::Rc};
2use tenda_common::span::SourceSpan;
3use tenda_parser::{self, ast};
4use tenda_reporting::Diagnostic;
5
6use crate::{
7    associative_array::{AssociativeArray, AssociativeArrayKey},
8    attach_span_if_missing,
9    environment::{Environment, ValueCell},
10    frame::Frame,
11    function::{Function, FunctionObject},
12    platform::{self},
13    runtime_error::{Result, RuntimeError},
14    stack::{Stack, StackError},
15    value::{Value, ValueType},
16    FunctionName, FunctionRuntimeMetadata, StackFrame,
17};
18
19#[derive(Debug)]
20pub struct Runtime {
21    stack: Stack,
22    platform: Box<dyn platform::Platform>,
23}
24
25impl Runtime {
26    pub fn new(platform: impl platform::Platform + 'static) -> Self {
27        Runtime {
28            stack: Stack::new(),
29            platform: Box::new(platform),
30        }
31    }
32
33    pub fn eval(&mut self, ast: &ast::Ast) -> Result<Value> {
34        self.interpret_ast(ast)
35    }
36
37    pub fn get_global_env(&self) -> &Environment {
38        self.stack.global().get_env()
39    }
40
41    pub fn get_global_env_mut(&mut self) -> &mut Environment {
42        self.stack.global_mut().get_env_mut()
43    }
44
45    pub fn get_platform(&self) -> &dyn platform::Platform {
46        self.platform.as_ref()
47    }
48
49    fn interpret_ast(&mut self, ast: &ast::Ast) -> Result<Value> {
50        let mut last_value = Value::Nil;
51
52        let ast::Ast { inner: ast, .. } = ast;
53
54        for stmt in ast {
55            let value = self.interpret_stmt(stmt)?;
56
57            last_value = value;
58
59            if self.stack.has_return_value()
60                || self.stack.has_loop_break_flag()
61                || self.stack.has_loop_continue_flag()
62            {
63                break;
64            }
65        }
66
67        Ok(last_value)
68    }
69
70    fn interpret_stmt(&mut self, stmt: &ast::Stmt) -> Result<Value> {
71        use ast::Stmt::*;
72
73        match stmt {
74            Expr(expr) => self.visit_expr(expr),
75            Decl(decl) => self.visit_decl(decl),
76            Cond(cond) => self.visit_cond(cond),
77            Block(block) => self.visit_block(block),
78            Return(return_value) => self.visit_return(return_value),
79            While(while_stmt) => self.visit_while(while_stmt),
80            ForEach(for_each) => self.visit_for_each(for_each),
81            Break(break_stmt) => self.visit_break(break_stmt),
82            Continue(continue_stmt) => self.visit_continue(continue_stmt),
83        }
84        .map_err(|mut err| attach_span_if_missing!(err, stmt.get_span()))
85    }
86}
87
88impl Runtime {
89    fn visit_decl(&mut self, decl: &ast::Decl) -> Result<Value> {
90        use ast::Decl::*;
91
92        match decl {
93            Local(local) => self.visit_local_decl(local)?,
94            Function(function) => self.visit_function_decl(function)?,
95        };
96
97        Ok(Value::Nil)
98    }
99
100    fn visit_expr(&mut self, expr: &ast::Expr) -> Result<Value> {
101        use ast::Expr::*;
102
103        match expr {
104            Binary(binary) => self.visit_binary(binary),
105            Unary(unary) => self.visit_unary(unary),
106            Ternary(ternary) => self.visit_ternary(ternary),
107            Grouping(grouping) => self.visit_grouping(grouping),
108            List(list) => self.visit_list(list),
109            Literal(literal) => self.visit_literal(literal),
110            Call(call) => self.visit_call(call),
111            Assign(assign) => self.visit_assign(assign),
112            Access(indexing) => self.visit_access(indexing),
113            Variable(variable) => self.visit_variable(variable),
114            AssociativeArray(associative_array) => self.visit_associative_array(associative_array),
115            AnonymousFunction(anonymous_function) => {
116                self.visit_anonymous_function(anonymous_function)
117            }
118        }
119    }
120
121    fn visit_block(&mut self, block: &ast::Block) -> Result<Value> {
122        let ast::Block { inner, .. } = block;
123
124        self.stack.push(Frame::new());
125
126        self.interpret_ast(inner)?;
127
128        self.stack.pop();
129
130        Ok(Value::Nil)
131    }
132
133    fn visit_return(&mut self, return_stmt: &ast::Return) -> Result<Value> {
134        let ast::Return { value, .. } = return_stmt;
135
136        if let Some(expr) = value {
137            let value = self.visit_expr(expr)?;
138            self.stack.set_return_value(ValueCell::new(value));
139        }
140
141        Ok(Value::Nil)
142    }
143
144    fn visit_cond(&mut self, cond: &ast::Cond) -> Result<Value> {
145        let ast::Cond {
146            cond,
147            then,
148            or_else,
149            ..
150        } = cond;
151
152        if self.visit_expr(cond)?.to_bool() {
153            self.interpret_stmt(then)?;
154        } else if let Some(or_else) = or_else {
155            self.interpret_stmt(or_else)?;
156        };
157
158        Ok(Value::Nil)
159    }
160
161    fn visit_while(&mut self, while_stmt: &ast::While) -> Result<Value> {
162        let ast::While { cond, body, .. } = while_stmt;
163
164        while self.visit_expr(cond)?.to_bool() && !self.stack.has_loop_break_flag() {
165            self.interpret_stmt(body)?;
166
167            self.stack.set_loop_continue_flag(false);
168        }
169
170        self.stack.set_loop_break_flag(false);
171
172        Ok(Value::Nil)
173    }
174
175    fn visit_for_each(&mut self, for_each: &ast::ForEach) -> Result<Value> {
176        let ast::ForEach {
177            item,
178            iterable,
179            body,
180            span,
181        } = for_each;
182
183        let iterable = self.visit_expr(iterable)?;
184
185        if !iterable.is_iterable() {
186            return Err(Box::new(RuntimeError::NotIterable {
187                value: iterable.kind(),
188                span: Some(span.clone()),
189                stacktrace: vec![],
190            }));
191        }
192
193        for value in iterable {
194            let mut frame = Frame::new();
195
196            let stored_value = if item.captured {
197                ValueCell::new_shared(value.clone())
198            } else {
199                ValueCell::new(value.clone())
200            };
201
202            frame.get_env_mut().set(item.name.clone(), stored_value);
203
204            self.stack.push(frame);
205            self.interpret_stmt(body)?;
206
207            if self.stack.has_loop_break_flag() {
208                break;
209            }
210
211            self.stack.set_loop_continue_flag(false);
212            self.stack.pop();
213        }
214
215        self.stack.set_loop_break_flag(false);
216
217        Ok(Value::Nil)
218    }
219
220    fn visit_break(&mut self, _break_stmt: &ast::Break) -> Result<Value> {
221        self.stack.set_loop_break_flag(true);
222
223        Ok(Value::Nil)
224    }
225
226    fn visit_continue(&mut self, _continue_stmt: &ast::Continue) -> Result<Value> {
227        self.stack.set_loop_continue_flag(true);
228
229        Ok(Value::Nil)
230    }
231}
232
233impl Runtime {
234    fn visit_local_decl(&mut self, local: &ast::LocalDecl) -> Result<Value> {
235        let ast::LocalDecl {
236            name, value, span, ..
237        } = local;
238
239        let value = self.visit_expr(value)?;
240
241        let value = match local.captured {
242            true => ValueCell::new_shared(value),
243            false => ValueCell::new(value),
244        };
245
246        match self.stack.define(name.clone(), value) {
247            Ok(_) => Ok(Value::Nil),
248            Err(err) => match err {
249                StackError::AlreadyDeclared => Err(Box::new(RuntimeError::AlreadyDeclared {
250                    var_name: name.to_string(),
251                    span: Some(span.clone()),
252                    help: Some("declare a variável com outro nome ou use `=` para atribuir um novo valor a ela".to_string()),
253                    stacktrace: vec![],
254                })),
255                _ => unreachable!(),
256            },
257        }
258    }
259
260    fn visit_function_decl(&mut self, function: &ast::FunctionDecl) -> Result<Value> {
261        let ast::FunctionDecl {
262            name, params, body, ..
263        } = function;
264
265        let metadata =
266            FunctionRuntimeMetadata::new(Some(function.span.clone()), Some(name.clone()));
267        let func = self.create_function(params, body.clone(), Some(metadata));
268
269        match self
270            .stack
271            .define(name.clone(), ValueCell::new(Value::Function(func)))
272        {
273            Ok(_) => Ok(Value::Nil),
274            Err(err) => match err {
275                StackError::AlreadyDeclared => Err(Box::new(RuntimeError::AlreadyDeclared {
276                    var_name: name.to_string(),
277                    span: Some(function.span.clone()),
278                    help: Some("declare a função com outro nome".to_string()),
279                    stacktrace: vec![],
280                })),
281                _ => unreachable!(),
282            },
283        }
284    }
285}
286
287impl Runtime {
288    fn visit_binary(&mut self, binary: &ast::BinaryOp) -> Result<Value> {
289        let ast::BinaryOp {
290            lhs, op, rhs, span, ..
291        } = binary;
292
293        use ast::BinaryOperator::*;
294        use Value::*;
295
296        let lhs = self.visit_expr(lhs)?;
297
298        match op {
299            LogicalAnd => {
300                if lhs.to_bool() {
301                    return self.visit_expr(rhs);
302                } else {
303                    return Ok(lhs);
304                }
305            }
306            LogicalOr => {
307                if lhs.to_bool() {
308                    return Ok(lhs);
309                } else {
310                    return self.visit_expr(rhs);
311                }
312            }
313            _ => {}
314        };
315
316        let rhs = self.visit_expr(rhs)?;
317
318        let value = match op {
319            Add => match (lhs, rhs) {
320                (Number(lhs), Number(rhs)) => Number(lhs + rhs),
321                (String(lhs), String(rhs)) => String(format!("{}{}", lhs, rhs)),
322                (String(lhs), rhs) => String(format!("{}{}", lhs, rhs)),
323                (lhs, String(rhs)) => String(format!("{}{}", lhs, rhs)),
324                (List(lhs), List(rhs)) => {
325                    let mut list = lhs.borrow().clone();
326                    list.extend_from_slice(&rhs.borrow());
327
328                    List(Rc::new(RefCell::new(list)))
329                }
330                (Date(rhs), Number(millis)) => Value::Date(rhs + millis as i64),
331                (Number(millis), Date(rhs)) => Value::Date(rhs + millis as i64),
332                (lhs, rhs) => {
333                    return Err(Box::new(RuntimeError::TypeMismatch {
334                        first: lhs.kind(),
335                        second: rhs.kind(),
336                        span: Some(span.clone()),
337                        message: Some(format!("não é possível somar '{}' e '{}'", lhs, rhs)),
338                        stacktrace: vec![],
339                    }));
340                }
341            },
342            Subtract => match (lhs, rhs) {
343                (Number(lhs), Number(rhs)) => Number(lhs - rhs),
344                (Date(rhs), Number(millis)) => Value::Date(rhs - millis as i64),
345                (Number(millis), Date(rhs)) => Value::Date(rhs - millis as i64),
346                (lhs, rhs) => {
347                    return Err(Box::new(RuntimeError::TypeMismatch {
348                        first: lhs.kind(),
349                        second: rhs.kind(),
350                        span: Some(span.clone()),
351                        message: Some(format!("não é possível subtrair '{}' de '{}'", rhs, lhs)),
352                        stacktrace: vec![],
353                    }));
354                }
355            },
356            Multiply => match (lhs, rhs) {
357                (Number(lhs), Number(rhs)) => Number(lhs * rhs),
358                (lhs, rhs) => {
359                    return Err(Box::new(RuntimeError::TypeMismatch {
360                        first: lhs.kind(),
361                        second: rhs.kind(),
362                        span: Some(span.clone()),
363                        message: Some(format!(
364                            "não é possível multiplicar '{}' por '{}'",
365                            lhs, rhs
366                        )),
367                        stacktrace: vec![],
368                    }));
369                }
370            },
371            Divide => match (lhs, rhs) {
372                (Number(_), Number(0.0)) => {
373                    return Err(Box::new(RuntimeError::DivisionByZero {
374                        span: Some(span.clone()),
375                        stacktrace: vec![],
376                    }));
377                }
378                (Number(lhs), Number(rhs)) => Number(lhs / rhs),
379                (lhs, rhs) => {
380                    return Err(Box::new(RuntimeError::TypeMismatch {
381                        first: lhs.kind(),
382                        second: rhs.kind(),
383                        span: Some(span.clone()),
384                        message: Some(format!("não é possível dividir '{}' por '{}'", lhs, rhs)),
385                        stacktrace: vec![],
386                    }));
387                }
388            },
389            Exponentiation => match (lhs, rhs) {
390                (Number(lhs), Number(rhs)) => Number(lhs.powf(rhs)),
391                (lhs, rhs) => {
392                    return Err(Box::new(RuntimeError::TypeMismatch {
393                        first: lhs.kind(),
394                        second: rhs.kind(),
395                        span: Some(span.clone()),
396                        message: Some(format!(
397                            "não é possível elevar '{}' à potência de '{}'",
398                            lhs, rhs
399                        )),
400                        stacktrace: vec![],
401                    }));
402                }
403            },
404            Modulo => match (lhs, rhs) {
405                (Number(lhs), Number(rhs)) => Number(lhs % rhs),
406                (lhs, rhs) => {
407                    return Err(Box::new(RuntimeError::TypeMismatch {
408                        first: lhs.kind(),
409                        second: rhs.kind(),
410                        span: Some(span.clone()),
411                        message: Some(format!(
412                            "não é possível encontrar o resto da divisão de '{}' por '{}'",
413                            lhs, rhs
414                        )),
415                        stacktrace: vec![],
416                    }));
417                }
418            },
419            Equality => match (lhs, rhs) {
420                (Number(lhs), Number(rhs)) => Boolean(lhs == rhs),
421                (Boolean(lhs), Boolean(rhs)) => Boolean(lhs == rhs),
422                (String(lhs), String(rhs)) => Boolean(lhs == rhs),
423                (List(lhs), List(rhs)) => Boolean(lhs == rhs),
424                (Value::Range(lhs_start, lhs_end), Value::Range(rhs_start, rhs_end)) => {
425                    Boolean(lhs_start == rhs_start && lhs_end == rhs_end)
426                }
427                (AssociativeArray(lhs), AssociativeArray(rhs)) => Boolean(lhs == rhs),
428                (Nil, Nil) => Boolean(true),
429                (Function(lhs), Function(rhs)) => Boolean(lhs == rhs),
430                (Date(lhs), Date(rhs)) => Boolean(lhs == rhs),
431                _ => Boolean(false),
432            },
433            Inequality => match (lhs, rhs) {
434                (Number(lhs), Number(rhs)) => Boolean(lhs != rhs),
435                (Boolean(lhs), Boolean(rhs)) => Boolean(lhs != rhs),
436                (String(lhs), String(rhs)) => Boolean(lhs != rhs),
437                (List(lhs), List(rhs)) => Boolean(lhs != rhs),
438                (Value::Range(lhs_start1, lhs_end1), Value::Range(rhs_start2, rhs_end2)) => {
439                    Boolean(lhs_start1 != rhs_start2 || lhs_end1 != rhs_end2)
440                }
441                (AssociativeArray(lhs), AssociativeArray(rhs)) => Boolean(lhs != rhs),
442                (Nil, Nil) => Boolean(false),
443                (Function(lhs), Function(rhs)) => Boolean(lhs != rhs),
444                (Date(lhs), Date(rhs)) => Boolean(lhs != rhs),
445                _ => Boolean(true),
446            },
447            Greater => match (lhs, rhs) {
448                (Number(lhs), Number(rhs)) => Boolean(lhs > rhs),
449                (String(lhs), String(rhs)) => Boolean(lhs > rhs),
450                (Date(lhs), Date(rhs)) => Boolean(lhs > rhs),
451                (lhs, rhs) => {
452                    return Err(Box::new(RuntimeError::TypeMismatch {
453                        first: lhs.kind(),
454                        second: rhs.kind(),
455                        span: Some(span.clone()),
456                        message: Some(format!(
457                            "não é possível aplicar a operação de 'maior que' para '{}' e '{}'",
458                            lhs, rhs
459                        )),
460                        stacktrace: vec![],
461                    }));
462                }
463            },
464            GreaterOrEqual => match (lhs, rhs) {
465                (Number(lhs), Number(rhs)) => Boolean(lhs >= rhs),
466                (String(lhs), String(rhs)) => Boolean(lhs >= rhs),
467                (Date(lhs), Date(rhs)) => Boolean(lhs >= rhs),
468                (lhs, rhs) => {
469                    return Err(Box::new(RuntimeError::TypeMismatch {
470                        first: lhs.kind(),
471                        second: rhs.kind(),
472                        span: Some(span.clone()),
473                        message: Some(format!(
474                            "não é possível aplicar a operação de 'maior ou igual' para '{}' e '{}'",
475                            lhs, rhs
476                        )),
477                        stacktrace: vec![],
478                    }));
479                }
480            },
481            Less => match (lhs, rhs) {
482                (Number(lhs), Number(rhs)) => Boolean(lhs < rhs),
483                (String(lhs), String(rhs)) => Boolean(lhs < rhs),
484                (Date(lhs), Date(rhs)) => Boolean(lhs < rhs),
485                (lhs, rhs) => {
486                    return Err(Box::new(RuntimeError::TypeMismatch {
487                        first: lhs.kind(),
488                        second: rhs.kind(),
489                        span: Some(span.clone()),
490                        message: Some(format!(
491                            "não é possível aplicar a operação de 'menor que' para '{}' e '{}'",
492                            lhs, rhs
493                        )),
494                        stacktrace: vec![],
495                    }));
496                }
497            },
498            LessOrEqual => match (lhs, rhs) {
499                (Number(lhs), Number(rhs)) => Boolean(lhs <= rhs),
500                (String(lhs), String(rhs)) => Boolean(lhs <= rhs),
501                (Date(lhs), Date(rhs)) => Boolean(lhs <= rhs),
502                (lhs, rhs) => {
503                    return Err(Box::new(RuntimeError::TypeMismatch {
504                        first: lhs.kind(),
505                        second: rhs.kind(),
506                        span: Some(span.clone()),
507                        message: Some(format!(
508                            "não é possível aplicar a operação de 'menor ou igual a' para '{}' e '{}'",
509                            lhs,
510                            rhs,
511                        )),
512                        stacktrace: vec![],
513                    }));
514                }
515            },
516            ast::BinaryOperator::Range => match (lhs, rhs) {
517                (Number(lhs), Number(_)) if lhs != lhs.trunc() || !lhs.is_finite() => {
518                    return Err(Box::new(RuntimeError::InvalidRangeBounds {
519                        bound: lhs,
520                        span: Some(span.clone()),
521                        stacktrace: vec![],
522                    }));
523                }
524                (Number(_), Number(rhs)) if rhs != rhs.trunc() || !rhs.is_finite() => {
525                    return Err(Box::new(RuntimeError::InvalidRangeBounds {
526                        bound: rhs,
527                        span: Some(span.clone()),
528                        stacktrace: vec![],
529                    }));
530                }
531                (Number(lhs), Number(rhs)) => Value::Range(lhs as usize, rhs as usize),
532                (lhs, rhs) => {
533                    return Err(Box::new(RuntimeError::TypeMismatch {
534                        first: lhs.kind(),
535                        second: rhs.kind(),
536                        span: Some(span.clone()),
537                        message: Some(format!(
538                            "não é possível criar um intervalo entre '{}' e '{}'",
539                            lhs, rhs
540                        )),
541                        stacktrace: vec![],
542                    }));
543                }
544            },
545            Has => match (lhs, rhs) {
546                (List(list), value) => Boolean(list.borrow().contains(&value)),
547                (AssociativeArray(associative_array), key) => {
548                    let key = self.resolve_associative_array_key(key).map_err(|mut src| {
549                        src.set_span(span);
550                        src
551                    })?;
552
553                    Boolean(associative_array.borrow().contains_key(&key))
554                }
555                (lhs, rhs) => {
556                    return Err(Box::new(RuntimeError::TypeMismatch {
557                        first: lhs.kind(),
558                        second: rhs.kind(),
559                        span: Some(span.clone()),
560                        message: Some(format!(
561                            "não é possível verificar se '{}' contém '{}'",
562                            lhs, rhs
563                        )),
564                        stacktrace: vec![],
565                    }));
566                }
567            },
568            Lacks => match (lhs, rhs) {
569                (List(list), value) => Boolean(!list.borrow().contains(&value)),
570                (AssociativeArray(associative_array), key) => {
571                    let key = self.resolve_associative_array_key(key).map_err(|mut src| {
572                        src.set_span(span);
573                        src
574                    })?;
575
576                    Boolean(!associative_array.borrow().contains_key(&key))
577                }
578                (lhs, rhs) => {
579                    return Err(Box::new(RuntimeError::TypeMismatch {
580                        first: lhs.kind(),
581                        second: rhs.kind(),
582                        span: Some(span.clone()),
583                        message: Some(format!(
584                            "não é possível verificar se '{}' não contém '{}'",
585                            lhs, rhs
586                        )),
587                        stacktrace: vec![],
588                    }));
589                }
590            },
591            LogicalAnd => unreachable!(),
592            LogicalOr => unreachable!(),
593        };
594
595        Ok(value)
596    }
597
598    fn visit_unary(&mut self, unary: &ast::UnaryOp) -> Result<Value> {
599        let ast::UnaryOp { op, rhs, span } = unary;
600
601        use ast::UnaryOperator::*;
602        use Value::*;
603
604        let rhs = self.visit_expr(rhs)?;
605
606        let expr = match op {
607            Negative => match rhs {
608                Number(rhs) => Number(-rhs),
609                _ => {
610                    return Err(Box::new(RuntimeError::UnexpectedTypeError {
611                        expected: ValueType::Number,
612                        found: rhs.kind(),
613                        span: Some(span.clone()),
614                        message: Some(format!(
615                            "não é possível negar valor de tipo '{}'; esperado '{}'",
616                            rhs.kind(),
617                            ValueType::Number
618                        )),
619                        stacktrace: vec![],
620                    }));
621                }
622            },
623            LogicalNot => Value::Boolean(!rhs.to_bool()),
624        };
625
626        Ok(expr)
627    }
628
629    fn visit_ternary(&mut self, ternary: &ast::TernaryOp) -> Result<Value> {
630        let ast::TernaryOp {
631            cond,
632            then,
633            or_else,
634            span,
635        } = ternary;
636
637        let cond_value = self.visit_expr(cond)?;
638
639        if cond_value.to_bool() {
640            self.visit_expr(then)
641        } else {
642            self.visit_expr(or_else)
643        }
644        .map_err(|mut err| attach_span_if_missing!(err, span))
645    }
646
647    fn visit_call(&mut self, call: &ast::Call) -> Result<Value> {
648        let ast::Call { callee, args, span } = call;
649
650        let callee = self.visit_expr(callee)?;
651
652        let args = args
653            .iter()
654            .map(|arg| self.visit_expr(arg))
655            .collect::<Result<Vec<_>>>()?;
656
657        match callee {
658            Value::Function(func) if args.len() != func.get_params().len() => {
659                Err(Box::new(RuntimeError::WrongNumberOfArguments {
660                    expected: func.get_params().len(),
661                    found: args.len(),
662                    span: Some(span.clone()),
663                    stacktrace: vec![],
664                }))
665            }
666            Value::Function(func) => self
667                .call_function(func, args, Some(span.clone()))
668                .map_err(|mut err| attach_span_if_missing!(err, span)),
669            _ => Err(Box::new(RuntimeError::UnexpectedTypeError {
670                expected: ValueType::Function,
671                found: callee.kind(),
672                span: Some(span.clone()),
673                message: Some(format!(
674                    "não é possível chamar um valor de tipo '{}' como função",
675                    callee.kind()
676                )),
677                stacktrace: vec![],
678            })),
679        }
680    }
681
682    fn visit_access(&mut self, index: &ast::Access) -> Result<Value> {
683        let ast::Access {
684            subscripted,
685            index,
686            span,
687        } = index;
688
689        let subscripted = self.visit_expr(subscripted)?;
690
691        match subscripted {
692            Value::List(list) => self.visit_list_access(&list.borrow(), index),
693            Value::String(string) => self.visit_string_access(&string, index),
694            Value::AssociativeArray(associative_array) => {
695                self.visit_associative_array_access(associative_array.borrow().clone(), index)
696            }
697            value => Err(Box::new(RuntimeError::WrongIndexType {
698                value: value.kind(),
699                span: Some(span.clone()),
700                stacktrace: vec![],
701            })),
702        }
703    }
704
705    fn visit_list(&mut self, list: &ast::List) -> Result<Value> {
706        let mut elements = Vec::with_capacity(list.elements.len());
707
708        for e in &list.elements {
709            let value = self.visit_expr(e)?;
710            elements.push(value);
711        }
712
713        Ok(Value::List(Rc::new(RefCell::new(elements))))
714    }
715
716    fn visit_grouping(&mut self, grouping: &ast::Grouping) -> Result<Value> {
717        let ast::Grouping { expr, .. } = grouping;
718
719        self.visit_expr(expr)
720    }
721
722    fn visit_literal(&mut self, literal: &ast::Literal) -> Result<Value> {
723        let ast::Literal { value, .. } = literal;
724
725        Ok(value.clone().into())
726    }
727
728    fn visit_variable(&mut self, variable: &ast::Variable) -> Result<Value> {
729        let ast::Variable { name, span, .. } = variable;
730
731        self.stack.lookup(name).map(|v| v.extract()).ok_or(Box::new(
732            RuntimeError::UndefinedReference {
733                var_name: name.clone(),
734                span: Some(span.clone()),
735                help: Some(format!(
736                    "você precisa definir a variável '{}' antes de usá-la: `seja {} = ...`",
737                    name, name
738                )),
739                stacktrace: vec![],
740            },
741        ))
742    }
743
744    fn visit_assign(&mut self, assign: &ast::Assign) -> Result<Value> {
745        let ast::Assign {
746            name: variable,
747            value,
748            span,
749        } = assign;
750
751        match &**variable {
752            ast::Expr::Variable(ast::Variable { name, .. }) => {
753                let value = self.visit_expr(value)?;
754
755                let result = self
756                    .stack
757                    .assign(name.clone(), ValueCell::new(value.clone()));
758
759                match result {
760                    Ok(_) => Ok(value),
761                    Err(err) => match err {
762                        StackError::AssignToUndefined(name) => {
763                            Err(Box::new(RuntimeError::UndefinedReference {
764                                var_name: name.clone(),
765                                span: Some(span.clone()),
766                                help: Some(format!(
767                                    "talvez você queria definir a variável '{}': `seja {} = ...`",
768                                    name, name
769                                )),
770                                stacktrace: vec![],
771                            }))
772                        }
773                        _ => unreachable!(),
774                    },
775                }
776            }
777            ast::Expr::Access(ast::Access {
778                index,
779                subscripted,
780                span: lvalue_span,
781            }) => {
782                let subscripted = self.visit_expr(subscripted)?;
783
784                match subscripted {
785                    Value::List(list) => {
786                        self.visit_list_assign(list, index, value)
787                    }
788                    Value::AssociativeArray(associative_array) => {
789                        self.visit_associative_array_assign(associative_array, index, value)
790                    }
791                    Value::String(_) => Err(Box::new(RuntimeError::ImmutableString {
792                        span: Some(span.clone()),
793                        help: Some(
794                            concat!(
795                                "em vez de tentar modificar o texto, você pode criar um novo texto\n",
796                                "concatenando o texto original com o novo texto: `texto = texto + ...`\n",
797                                "ou usando funções como `Texto.substitua(...)`\n",
798                                "veja as funções disponíveis em `Texto` para mais possibilidades"
799                            )
800                            .to_string(),
801                        ),
802                        stacktrace: vec![],
803                    })),
804                    value => Err(Box::new(RuntimeError::WrongIndexType {
805                        value: value.kind(),
806                        span: Some(lvalue_span.clone()),
807                        stacktrace: vec![],
808                    })),
809                }
810            }
811            _ => unreachable!(),
812        }
813    }
814
815    fn visit_associative_array(
816        &mut self,
817        associative_array: &ast::AssociativeArray,
818    ) -> Result<Value> {
819        let ast::AssociativeArray { elements, span } = associative_array;
820
821        let mut map = indexmap::IndexMap::new();
822
823        for (key, value) in elements {
824            let key = self.visit_literal(key)?;
825            let key = self
826                .resolve_associative_array_key(key)
827                .map_err(|mut source| {
828                    source.set_span(span);
829                    source
830                })?;
831
832            let value = self.visit_expr(value)?;
833
834            map.insert(key, value);
835        }
836
837        Ok(Value::AssociativeArray(Rc::new(RefCell::new(map))))
838    }
839
840    fn visit_anonymous_function(
841        &mut self,
842        anonymous_function: &ast::AnonymousFunction,
843    ) -> Result<Value> {
844        let ast::AnonymousFunction {
845            params, body, span, ..
846        } = anonymous_function;
847
848        let metadata = FunctionRuntimeMetadata::new(Some(span.clone()), None);
849        let func = self.create_function(params, body.clone(), Some(metadata));
850
851        Ok(Value::Function(func))
852    }
853}
854
855impl Runtime {
856    fn visit_list_access(&mut self, list: &[Value], index: &ast::Expr) -> Result<Value> {
857        let span = index.get_span();
858        let index = self.resolve_index(index)?;
859
860        if index >= list.len() {
861            return Err(Box::new(RuntimeError::IndexOutOfBounds {
862                index,
863                len: list.len(),
864                span: Some(span.clone()),
865                help: vec!["verifique se o índice está dentro dos limites da lista antes de tentar acessá-lo".to_string()],
866                stacktrace: vec![],
867            }));
868        }
869
870        Ok(list[index].clone())
871    }
872
873    fn visit_string_access(&mut self, string: &str, index: &ast::Expr) -> Result<Value> {
874        let span = index.get_span();
875        let index = self.resolve_index(index)?;
876
877        if let Some(char) = string.chars().nth(index) {
878            Ok(Value::String(char.to_string()))
879        } else {
880            Err(Box::new(RuntimeError::IndexOutOfBounds {
881                index,
882                len: string.len(),
883                span: Some(span.clone()),
884                help: vec![
885                    "verifique o tamanho do texto antes de tentar acessar uma posição nele"
886                        .to_string(),
887                ],
888                stacktrace: vec![],
889            }))
890        }
891    }
892
893    fn visit_associative_array_access(
894        &mut self,
895        associative_array: AssociativeArray,
896        index: &ast::Expr,
897    ) -> Result<Value> {
898        let span = index.get_span();
899        let index = self.visit_expr(index)?;
900        let index = self
901            .resolve_associative_array_key(index)
902            .map_err(|mut source| {
903                source.set_span(span);
904                source
905            })?;
906
907        match associative_array.get(&index) {
908            Some(value) => Ok(value.clone()),
909            None => Err(Box::new(RuntimeError::AssociativeArrayKeyNotFound {
910                key: index,
911                span: Some(span.clone()),
912                stacktrace: vec![],
913            })),
914        }
915    }
916
917    fn visit_list_assign(
918        &mut self,
919        list: Rc<RefCell<Vec<Value>>>,
920        index: &ast::Expr,
921        value: &ast::Expr,
922    ) -> Result<Value> {
923        let index_span = index.get_span();
924
925        let value = self.visit_expr(value)?;
926        let index = self.resolve_index(index)?;
927
928        let mut list = list.borrow_mut();
929
930        if index >= list.len() {
931            return Err(Box::new(RuntimeError::IndexOutOfBounds {
932                index,
933                len: list.len(),
934                span: Some(index_span.clone()),
935                help: vec![
936                    "verifique se o índice está dentro dos limites da lista antes de tentar acessá-lo".to_string(),
937                    "se a sua intenção era adicionar um novo elemento à lista, use `Lista.insira`".to_string()
938                ],
939                stacktrace: vec![],
940            }));
941        }
942
943        list[index] = value.clone();
944
945        Ok(value)
946    }
947
948    fn visit_associative_array_assign(
949        &mut self,
950        associative_array: Rc<RefCell<indexmap::IndexMap<AssociativeArrayKey, Value>>>,
951        index: &ast::Expr,
952        value: &ast::Expr,
953    ) -> Result<Value> {
954        let span = index.get_span();
955
956        let value = self.visit_expr(value)?;
957        let index = self.visit_expr(index)?;
958        let index = self
959            .resolve_associative_array_key(index)
960            .map_err(|mut source| {
961                source.set_span(span);
962                source
963            })?;
964
965        let mut associative_array = associative_array.borrow_mut();
966
967        associative_array.insert(index, value.clone());
968
969        Ok(value)
970    }
971}
972
973impl Runtime {
974    pub fn call_function(
975        &mut self,
976        func: Function,
977        args: Vec<Value>,
978        span: Option<SourceSpan>,
979    ) -> Result<Value> {
980        let args = func
981            .get_params()
982            .iter()
983            .zip(args)
984            .map(|(a, b)| (a.clone(), b))
985            .collect();
986
987        let context_frame = Frame::from_env(func.get_env().clone());
988
989        self.stack.push(context_frame);
990
991        let result = match func.object {
992            FunctionObject::Builtin { func_ptr, env, .. } => func_ptr(args, self, env),
993            FunctionObject::UserDefined { body, .. } => {
994                for (param, arg_value) in args.into_iter() {
995                    let stored_value = if param.is_captured {
996                        ValueCell::new_shared(arg_value)
997                    } else {
998                        ValueCell::new(arg_value)
999                    };
1000
1001                    self.stack.define(param.name.clone(), stored_value).unwrap();
1002                }
1003
1004                let is_expr = matches!(body.as_ref(), ast::Stmt::Expr(_));
1005
1006                match self.interpret_stmt(&body) {
1007                    Ok(value) => {
1008                        if is_expr {
1009                            Ok(value)
1010                        } else {
1011                            let value = self
1012                                .stack
1013                                .consume_return_value()
1014                                .map(|v| v.extract())
1015                                .unwrap_or(Value::Nil);
1016
1017                            Ok(value)
1018                        }
1019                    }
1020                    Err(mut err) => {
1021                        let trace = StackFrame::new(
1022                            func.metadata
1023                                .as_ref()
1024                                .and_then(|m| m.get_name().clone())
1025                                .map(FunctionName::Named)
1026                                .unwrap_or(FunctionName::TopLevel),
1027                            span.clone(),
1028                        );
1029
1030                        if let Some(stacktrace) = err.get_mut_stacktrace() {
1031                            stacktrace.push(trace);
1032                        } else {
1033                            err.set_stacktrace(vec![trace]);
1034                        }
1035
1036                        Err(err)
1037                    }
1038                }
1039            }
1040        };
1041
1042        self.stack.pop();
1043
1044        result
1045    }
1046
1047    fn create_function(
1048        &self,
1049        params: &[ast::FunctionParam],
1050        body: Box<ast::Stmt>,
1051        metadata: Option<FunctionRuntimeMetadata>,
1052    ) -> Function {
1053        let mut context = Environment::new();
1054
1055        for frame in self.stack.into_iter() {
1056            for (name, value) in frame.get_env() {
1057                if params.iter().any(|param| param.name == *name) {
1058                    continue;
1059                }
1060
1061                if let ValueCell::Shared(value) = value {
1062                    context.set(name.clone(), ValueCell::Shared(value.clone()));
1063                }
1064            }
1065        }
1066
1067        let mut func = Function::new(
1068            params.iter().map(|p| p.clone().into()).collect(),
1069            context,
1070            body,
1071        );
1072
1073        if let Some(metadata) = metadata {
1074            func.set_metadata(metadata);
1075        }
1076
1077        func
1078    }
1079
1080    fn resolve_associative_array_key(
1081        &mut self,
1082        key: Value,
1083    ) -> std::result::Result<AssociativeArrayKey, Box<RuntimeError>> {
1084        match key {
1085            Value::String(value) => Ok(AssociativeArrayKey::String(value)),
1086            Value::Number(value) if !value.is_finite() || value.trunc() != value => {
1087                Err(Box::new(RuntimeError::InvalidNumberAssociativeArrayKey {
1088                    key: value,
1089                    span: None,
1090                    stacktrace: vec![],
1091                }))
1092            }
1093            Value::Number(value) => Ok(AssociativeArrayKey::Number(value as i64)),
1094            val => Err(Box::new(RuntimeError::InvalidTypeAssociativeArrayKey {
1095                key: val.kind(),
1096                span: None,
1097                stacktrace: vec![],
1098            })),
1099        }
1100    }
1101
1102    fn resolve_index(&mut self, index: &ast::Expr) -> Result<usize> {
1103        let span = index.get_span();
1104
1105        match self.visit_expr(index)? {
1106            Value::Number(num) if !num.is_finite() || num.trunc() != num || num < 0.0 => {
1107                Err(Box::new(RuntimeError::InvalidIndex {
1108                    index: num,
1109                    span: Some(span.clone()),
1110                    stacktrace: vec![],
1111                }))
1112            }
1113            Value::Number(num) => Ok(num as usize),
1114            val => Err(Box::new(RuntimeError::UnexpectedTypeError {
1115                expected: ValueType::Number,
1116                found: val.kind(),
1117                span: Some(span.clone()),
1118                message: Some(format!(
1119                    "não é possível indexar com '{}'; esperado '{}'",
1120                    val.kind(),
1121                    ValueType::Number
1122                )),
1123                stacktrace: vec![],
1124            })),
1125        }
1126    }
1127}