roan_engine/interpreter/
conditions.rs1use crate::{context::Context, module::Module, value::Value, vm::VM};
2use roan_ast::{GetSpan, If, ThenElse};
3use tracing::debug;
4
5use anyhow::Result;
6use roan_error::{error::RoanError::NonBooleanCondition, TextSpan};
7
8impl Module {
9 pub fn interpret_then_else(
19 &mut self,
20 then_else: ThenElse,
21 ctx: &mut Context,
22 vm: &mut VM,
23 ) -> Result<Value> {
24 debug!("Interpreting then-else");
25
26 self.interpret_expr(&then_else.condition, ctx, vm)?;
27 let condition = vm.pop().unwrap();
28
29 let b = match condition {
30 Value::Bool(b) => b,
31 _ => condition.is_truthy(),
32 };
33
34 if b {
35 self.interpret_expr(&then_else.then_expr, ctx, vm)?;
36 } else {
37 self.interpret_expr(&then_else.else_expr, ctx, vm)?;
38 }
39
40 Ok(vm.pop().expect("Expected value on stack"))
41 }
42
43 pub fn interpret_if(&mut self, if_stmt: If, ctx: &mut Context, vm: &mut VM) -> Result<()> {
49 debug!("Interpreting if statement");
50
51 self.interpret_expr(&if_stmt.condition, ctx, vm)?;
52 let condition_value = vm.pop().expect("Expected value on stack");
53
54 let condition = match condition_value {
55 Value::Bool(b) => b,
56 Value::Null => false,
57 _ => {
58 return Err(NonBooleanCondition(
59 "If condition".into(),
60 TextSpan::combine(vec![if_stmt.if_token.span, if_stmt.condition.span()])
61 .unwrap(),
62 )
63 .into())
64 }
65 };
66
67 if condition {
68 self.execute_block(if_stmt.then_block, ctx, vm)?;
69 } else {
70 let mut executed = false;
71 for else_if in if_stmt.else_ifs {
72 self.interpret_expr(&else_if.condition, ctx, vm)?;
73 let else_if_condition = vm.pop().expect("Expected value on stack");
74
75 let else_if_result = match else_if_condition {
76 Value::Bool(b) => b,
77 Value::Null => false,
78 _ => {
79 return Err(NonBooleanCondition(
80 "Else if condition".into(),
81 else_if.condition.span(),
82 )
83 .into())
84 }
85 };
86
87 if else_if_result {
88 self.execute_block(else_if.block, ctx, vm)?;
89 executed = true;
90 break;
91 }
92 }
93
94 if !executed {
95 if let Some(else_block) = if_stmt.else_block {
96 self.execute_block(else_block.block, ctx, vm)?;
97 }
98 }
99 }
100
101 Ok(())
102 }
103}