(&mut self, stmt: S)
| 242 | } |
| 243 | |
| 244 | fn generate_stmt<S: Into<Stmt<'gc>>>(&mut self, stmt: S) -> Result<(), VmError> { |
| 245 | let stmt = stmt.into(); |
| 246 | self.current_line = stmt.line(); |
| 247 | match stmt { |
| 248 | Stmt::Use { path, .. } => { |
| 249 | // Load the module name as a constant |
| 250 | let module_name = self.identifier_constant(path.lexeme); |
| 251 | self.emit(OpCode::ImportModule(module_name as u8)); |
| 252 | } |
| 253 | Stmt::Break { .. } => { |
| 254 | let exit_jump = self.emit_jump(OpCode::Jump(0)); |
| 255 | // Get the last scope's index |
| 256 | let last_idx = self.loop_scopes.len() - 1; |
| 257 | // Add the break jump to the current loop scope |
| 258 | self.loop_scopes[last_idx].breaks.push(exit_jump); |
| 259 | } |
| 260 | Stmt::Continue { .. } => { |
| 261 | while self.local_count > 0 |
| 262 | && self.locals[self.local_count - 1].depth > self.scope_depth |
| 263 | { |
| 264 | self.emit(OpCode::Pop(1)); |
| 265 | self.local_count -= 1; |
| 266 | } |
| 267 | |
| 268 | if let Some(loop_scope) = self.loop_scopes.last() { |
| 269 | self.emit_loop(loop_scope.increment); |
| 270 | } |
| 271 | } |
| 272 | Stmt::Expression { expression, .. } => { |
| 273 | self.generate_expr(expression)?; |
| 274 | // an expression statement evaluates the expression and discards the result |
| 275 | // since the result already exists in the stack, we can just pop it |
| 276 | self.emit(OpCode::Pop(1)); |
| 277 | } |
| 278 | Stmt::Let(VariableDecl { |
| 279 | name, |
| 280 | initializer, |
| 281 | visibility, |
| 282 | .. |
| 283 | }) => { |
| 284 | self.declare_variable(name, Mutability::Mutable); |
| 285 | if let Some(initial_value) = initializer { |
| 286 | self.generate_expr(initial_value)?; |
| 287 | } else { |
| 288 | self.emit(OpCode::Nil); |
| 289 | } |
| 290 | if self.scope_depth > 0 { |
| 291 | self.mark_initialized(); |
| 292 | } else { |
| 293 | let global = self.identifier_constant(name.lexeme); |
| 294 | self.emit(OpCode::DefineGlobal { |
| 295 | name_constant: global as u8, |
| 296 | visibility, |
| 297 | }); |
| 298 | } |
| 299 | } |
| 300 | Stmt::Const { |
| 301 | name, |
no test coverage detected