1use crate::{
2 context::Context,
3 module::{loaders::remove_surrounding_quotes, ExportType, Module, StoredConst, StoredFunction},
4 value::Value,
5 vm::VM,
6};
7use anyhow::Result;
8use roan_ast::{Block, Fn, GetSpan, Let, Loop, Stmt, Token, Use, While};
9use roan_error::{
10 error::{
11 RoanError,
12 RoanError::{FailedToImportModule, ImportError, NonBooleanCondition},
13 },
14 print_diagnostic, TextSpan,
15};
16use tracing::debug;
17
18impl Module {
19 pub fn interpret_stmt(&mut self, stmt: Stmt, ctx: &mut Context, vm: &mut VM) -> Result<()> {
25 match stmt {
26 Stmt::Fn(f) => self.interpret_function(f, ctx)?,
27 Stmt::Use(u) => self.interpret_use(u, ctx, vm)?,
28 Stmt::While(while_stmt) => self.interpret_while(while_stmt, ctx, vm)?,
29 Stmt::Loop(loop_stmt) => self.interpret_loop(loop_stmt, ctx, vm)?,
30 Stmt::Block(block) => self.execute_block(block, ctx, vm)?,
31 Stmt::If(if_stmt) => self.interpret_if(if_stmt, ctx, vm)?,
32 Stmt::Break(token) => {
33 debug!("Interpreting break statement");
34 return Err(RoanError::LoopBreak(token.span).into());
35 }
36 Stmt::Continue(token) => {
37 debug!("Interpreting continue statement");
38 return Err(RoanError::LoopContinue(token.span).into());
39 }
40 Stmt::Throw(throw) => self.interpret_throw(throw, ctx, vm)?,
41 Stmt::Try(try_stmt) => self.interpret_try(try_stmt, ctx, vm)?,
42 Stmt::Let(l) => self.interpret_let(l, vm, ctx)?,
43 Stmt::Expr(expr) => self.interpret_expr(expr.as_ref(), ctx, vm)?,
44 Stmt::Return(r) => {
45 debug!("Interpreting return: {:?}", r);
46
47 if let Some(expr) = r.expr {
48 self.interpret_expr(expr.as_ref(), ctx, vm)?;
49 } else {
50 vm.push(Value::Void);
51 }
52 }
53 Stmt::Struct(struct_stmt) => self.interpret_struct(struct_stmt, ctx)?,
54 Stmt::TraitDef(trait_stmt) => self.interpret_trait(trait_stmt, ctx)?,
55 Stmt::StructImpl(impl_stmt) => self.interpret_struct_impl(impl_stmt, ctx)?,
56 Stmt::TraitImpl(impl_stmt) => self.interpret_trait_impl(impl_stmt, ctx)?,
57 Stmt::Const(c) => {
58 let def_expr = c.expr.clone();
59 let ident_literal = c.ident.literal();
60 let is_public = c.public;
61
62 self.interpret_expr(&def_expr, ctx, vm)?;
63
64 let val = vm.pop().expect("Expected value on stack");
65
66 let stored_val = StoredConst {
67 ident: c.ident.clone(),
68 value: val.clone(),
69 };
70
71 self.consts.push(stored_val.clone());
72
73 if is_public {
74 self.exports
75 .push((ident_literal, ExportType::Const(stored_val)));
76 }
77 }
78 }
79
80 Ok(())
81 }
82
83 pub fn interpret_let(&mut self, l: Let, vm: &mut VM, ctx: &mut Context) -> Result<()> {
90 debug!("Interpreting let: {:?}", l.ident);
91 self.interpret_expr(l.initializer.as_ref(), ctx, vm)?;
92
93 let val = vm.pop().unwrap();
94 let ident = l.ident.literal();
95
96 if let Some(type_annotation) = &l.type_annotation {
97 let type_name = type_annotation.type_name.literal();
98
99 if type_annotation.is_array {
100 match val.clone() {
101 Value::Vec(v) => {
102 for item in v.iter() {
104 item.check_type(&type_name, l.initializer.span())?
105 }
106 }
107 _ => {
108 return Err(RoanError::TypeMismatch(
109 format!(
110 "Expected array of type {} but got {}",
111 type_name,
112 val.type_name()
113 ),
114 l.initializer.span(),
115 )
116 .into());
117 }
118 }
119 } else {
120 if val.is_null() && type_annotation.is_nullable {
121 self.declare_variable(ident.clone(), val);
122 return Ok(());
123 }
124
125 val.check_type(
126 &type_name,
127 TextSpan::combine(vec![
128 l.ident.span,
129 type_annotation.type_name.span.clone(),
130 l.initializer.span(),
131 ])
132 .unwrap(),
133 )?
134 }
135 }
136
137 self.declare_variable(ident.clone(), val);
138
139 Ok(())
140 }
141
142 pub fn handle_loop_result(&mut self, result: Result<()>) -> Result<()> {
149 match result {
150 Ok(_) => {}
151 Err(e) => match e.downcast::<RoanError>() {
152 Ok(RoanError::LoopBreak(_)) => {}
153 Ok(RoanError::LoopContinue(_)) => {}
154 Ok(other) => return Err(other.into()),
155 Err(e) => return Err(e),
156 },
157 }
158
159 Ok(())
160 }
161
162 pub fn interpret_loop(
168 &mut self,
169 loop_stmt: Loop,
170 ctx: &mut Context,
171 vm: &mut VM,
172 ) -> Result<()> {
173 debug!("Interpreting infinite loop");
174 loop {
175 self.enter_scope();
176 let result = self.execute_block(loop_stmt.block.clone(), ctx, vm);
177 self.exit_scope();
178
179 self.handle_loop_result(result)?
180 }
181 }
182
183 pub fn interpret_while(
189 &mut self,
190 while_stmt: While,
191 ctx: &mut Context,
192 vm: &mut VM,
193 ) -> Result<()> {
194 debug!("Interpreting while loop");
195
196 loop {
197 self.interpret_expr(&while_stmt.condition, ctx, vm)?;
198 let condition_value = vm.pop().expect("Expected value on stack");
199
200 let condition = match condition_value {
201 Value::Bool(b) => b,
202 _ => {
203 return Err(NonBooleanCondition(
204 "While loop condition".into(),
205 while_stmt.condition.span(),
206 )
207 .into())
208 }
209 };
210
211 if !condition {
212 break;
213 }
214
215 self.enter_scope();
216 let result = self.execute_block(while_stmt.block.clone(), ctx, vm);
217 self.exit_scope();
218
219 self.handle_loop_result(result)?
220 }
221
222 Ok(())
223 }
224
225 pub fn interpret_function(&mut self, function: Fn, ctx: &mut Context) -> Result<()> {
231 debug!("Interpreting function: {}", function.name);
232
233 self.functions.push(StoredFunction::Function {
234 function: function.clone(),
235 defining_module: self.id(),
236 });
237
238 if function.public {
239 self.exports.push((
240 function.name.clone(),
241 ExportType::Function(function.clone()),
242 ));
243 }
244
245 ctx.upsert_module(self.id().clone(), self.clone());
246 Ok(())
247 }
248
249 pub fn interpret_use(&mut self, u: Use, ctx: &mut Context, vm: &mut VM) -> Result<()> {
255 debug!("Interpreting use: {}", u.from.literal());
256
257 let mut loaded_module = ctx
258 .load_module(&self.clone(), remove_surrounding_quotes(&u.from.literal()))
259 .map_err(|err| {
260 FailedToImportModule(
261 u.from.literal().to_string(),
262 err.to_string(),
263 u.from.span.clone(),
264 )
265 })?;
266
267 match loaded_module.parse() {
268 Ok(_) => {}
269 Err(e) => {
270 print_diagnostic(e, Some(loaded_module.source().content()));
271 std::process::exit(1);
272 }
273 }
274
275 match loaded_module.interpret(ctx, vm) {
276 Ok(_) => {}
277 Err(e) => {
278 print_diagnostic(e, Some(loaded_module.source().content()));
279 std::process::exit(1);
280 }
281 }
282
283 let imported_items: Vec<(String, &Token)> =
285 u.items.iter().map(|i| (i.literal(), i)).collect();
286
287 for (name, item) in imported_items {
288 let export = loaded_module.exports.iter().find(|(n, _)| n == &name);
289
290 if let Some((name, value)) = export {
291 debug!("Importing {} from {}", name, u.from.literal());
292 match value {
293 ExportType::Function(f) => {
294 self.functions.push(StoredFunction::Function {
295 function: f.clone(),
296 defining_module: loaded_module.id(),
297 });
298 }
299 ExportType::Struct(s) => {
300 self.structs.push(s.clone());
301 }
302 ExportType::Trait(t) => {
303 self.traits.push(t.clone());
304 }
305 ExportType::Const(c) => {
306 self.consts.push(c.clone());
307 }
308 }
309 } else {
310 return Err(ImportError(name, item.span.clone()).into());
311 }
312 }
313
314 Ok(())
315 }
316
317 pub fn execute_block(&mut self, block: Block, ctx: &mut Context, vm: &mut VM) -> Result<()> {
322 debug!("Interpreting block statement");
323
324 self.enter_scope();
325 for stmt in block.stmts {
326 self.interpret_stmt(stmt, ctx, vm)?;
327 }
328 self.exit_scope();
329 Ok(())
330 }
331}