Files
OxideJS-New/crates/oxide_compiler/src/counter/stmt/exception.rs
T

80 lines
2.8 KiB
Rust

use super::*;
impl Compiler {
fn count_throw_statement(&self, stmt: &oxide_parser::ThrowStatement<'_>, ctx: &mut CompileCtx) {
self.count_expression(&stmt.argument, ctx);
ctx.projected_pc += 1; // THROW
}
fn count_try_statement(&self, stmt: &oxide_parser::TryStatement<'_>, ctx: &mut CompileCtx) {
let id = ctx.next_label_id();
let catch_label = Label::CatchBody(id);
let try_end_label = Label::TryEnd(id);
let has_catch = stmt.handler.is_some();
let has_finally = stmt.finalizer.is_some();
ctx.alloc_reg(); // result_reg
if has_finally {
ctx.projected_pc += 1; // TRY_FINALLY_BEGIN (before try body)
}
if has_catch {
ctx.projected_pc += 1; // TRY_BEGIN (before try body)
}
for s in &stmt.block.body {
self.count_statement(s, ctx);
}
ctx.projected_pc += 1; // LOAD_VAR result_reg (if try body has result)
if has_catch {
ctx.projected_pc += 1; // TRY_END
}
let jmp_needed = has_catch || has_finally;
if jmp_needed {
ctx.projected_pc += 1; // JMP
}
ctx.labels.label_map.insert(catch_label, ctx.projected_pc);
if let Some(catch) = &stmt.handler {
ctx.push_scope();
if let Some(param) = &catch.param {
// Mirror the emitter: the catch register is always allocated, but STORE_VAR is
// emitted only for an identifier binding — a destructuring catch param emits no
// store (that binding form is not implemented yet).
ctx.alloc_reg();
if let oxide_parser::BindingPattern::BindingIdentifier(_) = &param.pattern {
ctx.projected_pc += 1; // STORE_VAR
}
}
for cs in &catch.body.body {
self.count_statement(cs, ctx);
}
ctx.projected_pc += 1; // LOAD_VAR result_reg (if catch body has result)
ctx.pop_scope();
}
if let Some(finally) = &stmt.finalizer {
let finally_label = Label::FinallyBody(id);
ctx.labels.label_map.insert(finally_label, ctx.projected_pc);
for fs in &finally.body {
self.count_statement(fs, ctx);
}
ctx.projected_pc += 1; // LOAD_VAR result_reg (if finally has result)
ctx.projected_pc += 1; // TRY_FINALLY_END
}
ctx.labels.label_map.insert(try_end_label, ctx.projected_pc);
}
pub(in crate::counter) fn count_exception_domain(&self, stmt: &Statement, ctx: &mut CompileCtx) {
match stmt {
Statement::ThrowStatement(ts) => self.count_throw_statement(ts, ctx),
Statement::TryStatement(ts) => self.count_try_statement(ts, ctx),
_ => {}
}
}
}