use crate::ast::*; use crate::error::RuntimeError; use crate::interpreter::Signal; use super::{Value, Env, Function}; use std::rc::Rc; use std::cell::RefCell; impl super::Interpreter { // ======================================================================== // execute — dispatcher // ======================================================================== pub fn execute(&mut self, stmt: Stmt) -> Result { match stmt { Stmt::Let { name, initializer, mutable } => self.exec_let(name, initializer, mutable), Stmt::ExprStmt(expr) => self.exec_expr_stmt(expr), Stmt::Block(stmts) => self.exec_block(stmts), Stmt::If { condition, then_branch, else_branch } => { self.exec_if(condition, *then_branch, else_branch.map(|b| *b)) } Stmt::While { condition, body } => self.exec_while(condition, *body), Stmt::For { initializer, condition, step, body } => { self.exec_for(initializer, condition, step, *body) } Stmt::ForIn { var_name, iterable, body } => self.exec_for_in(var_name, iterable, *body), Stmt::Function { name, params, body } => self.exec_function(name, params, body), Stmt::Return(expr_opt) => self.exec_return(expr_opt), Stmt::Break => Ok(Signal::Break), Stmt::Continue => Ok(Signal::Continue), } } // ======================================================================== // exec_* methods // ======================================================================== fn exec_let(&mut self, name: String, initializer: Expr, mutable: bool) -> Result { let val = self.evaluate(initializer)?; self.env.borrow_mut().define(name, val, mutable); Ok(Signal::None) } fn exec_expr_stmt(&mut self, expr: Expr) -> Result { self.evaluate(expr)?; Ok(Signal::None) } fn exec_block(&mut self, stmts: Vec) -> Result { let previous = Rc::clone(&self.env); self.env = Rc::new(RefCell::new(Env::new(Some(previous)))); let mut signal = Signal::None; for s in stmts { signal = self.execute(s)?; if !matches!(signal, Signal::None) { break; } } let parent = self.env.borrow().parent.as_ref().unwrap().clone(); self.env = parent; Ok(signal) } fn exec_if( &mut self, condition: Expr, then_branch: Stmt, else_branch: Option, ) -> Result { let cond_val = self.evaluate(condition)?; if self.is_truthy(&cond_val) { self.execute(then_branch) } else if let Some(else_branch) = else_branch { self.execute(else_branch) } else { Ok(Signal::None) } } fn exec_while(&mut self, condition: Expr, body: Stmt) -> Result { loop { let cond_val = self.evaluate(condition.clone())?; if !self.is_truthy(&cond_val) { break; } match self.execute(body.clone())? { Signal::Break => break, Signal::Continue => continue, sig @ Signal::Return(_) => return Ok(sig), Signal::None => {} } } Ok(Signal::None) } fn exec_for( &mut self, initializer: Option>, condition: Option, step: Option, body: Stmt, ) -> Result { if let Some(init) = initializer { self.execute(*init)?; } loop { if let Some(cond) = &condition { let cond_val = self.evaluate(cond.clone())?; if !self.is_truthy(&cond_val) { break; } } match self.execute(body.clone())? { Signal::Break => break, Signal::Continue => { if let Some(step) = &step { self.evaluate(step.clone())?; } continue; } sig @ Signal::Return(_) => return Ok(sig), Signal::None => {} } if let Some(step) = &step { self.evaluate(step.clone())?; } } Ok(Signal::None) } fn exec_for_in( &mut self, var_name: String, iterable: Expr, body: Stmt, ) -> Result { let iter_val = self.evaluate(iterable)?; let items: Vec = match &iter_val { Value::Array(arr) => arr.borrow().clone(), Value::Object(obj) => obj.borrow().keys().map(|k| Value::String(k.clone())).collect(), Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(), _ => { return Err(RuntimeError::RuntimeError { message: "for-in requires an array, object, or string".into(), token: None, }); } }; let mut signal = Signal::None; for item in items { let previous = Rc::clone(&self.env); self.env = Rc::new(RefCell::new(Env::new(Some(previous)))); self.env.borrow_mut().define(var_name.clone(), item, true); signal = self.execute(body.clone())?; let parent = self.env.borrow().parent.as_ref().unwrap().clone(); self.env = parent; match signal { Signal::Break => { signal = Signal::None; break; } Signal::Continue => { signal = Signal::None; continue; } sig @ Signal::Return(_) => return Ok(sig), Signal::None => {} } } Ok(signal) } fn exec_function( &mut self, name: String, params: Vec, body: Vec, ) -> Result { let func = Value::Function(Rc::new(Function { params, body, env: Rc::clone(&self.env), name: Some(name.clone()), })); self.env.borrow_mut().define(name, func, true); Ok(Signal::None) } fn exec_return(&mut self, expr_opt: Option) -> Result { if let Some(expr) = expr_opt { Ok(Signal::Return(self.evaluate(expr)?)) } else { Ok(Signal::Return(Value::Nil)) } } }