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}