diff --git a/crates/oxide_compiler/src/compiler.rs b/crates/oxide_compiler/src/compiler.rs index 8ec55ce..ffa196c 100644 --- a/crates/oxide_compiler/src/compiler.rs +++ b/crates/oxide_compiler/src/compiler.rs @@ -880,10 +880,8 @@ impl Compiler { ) } - #[expect(clippy::too_many_arguments)] - fn pre_scan_function_expressions( - &self, stmts: &[Statement], parent_ctx: &mut CompileCtx, - ) -> Result<(), String> { + #[allow(clippy::too_many_arguments)] + fn pre_scan_function_expressions(&self, stmts: &[Statement], parent_ctx: &mut CompileCtx) -> Result<(), String> { for stmt in stmts { self.pre_scan_stmt(stmt, parent_ctx)?; } @@ -893,16 +891,30 @@ impl Compiler { fn pre_scan_stmt(&self, stmt: &Statement, parent_ctx: &mut CompileCtx) -> Result<(), String> { match stmt { Statement::ExpressionStatement(es) => self.pre_scan_expr(&es.expression, parent_ctx)?, - Statement::ReturnStatement(rs) => { if let Some(a) = &rs.argument { self.pre_scan_expr(a, parent_ctx)?; } } + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + self.pre_scan_expr(a, parent_ctx)?; + } + } Statement::IfStatement(is) => { self.pre_scan_expr(&is.test, parent_ctx)?; self.pre_scan_stmt(&is.consequent, parent_ctx)?; - if let Some(alt) = &is.alternate { self.pre_scan_stmt(alt, parent_ctx)?; } + if let Some(alt) = &is.alternate { + self.pre_scan_stmt(alt, parent_ctx)?; + } } Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { if let Some(e) = init.as_expression() { self.pre_scan_expr(e, parent_ctx)?; } } - if let Some(t) = &fs.test { self.pre_scan_expr(t, parent_ctx)?; } - if let Some(u) = &fs.update { self.pre_scan_expr(u, parent_ctx)?; } + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + self.pre_scan_expr(e, parent_ctx)?; + } + } + if let Some(t) = &fs.test { + self.pre_scan_expr(t, parent_ctx)?; + } + if let Some(u) = &fs.update { + self.pre_scan_expr(u, parent_ctx)?; + } self.pre_scan_stmt(&fs.body, parent_ctx)?; } Statement::BlockStatement(bs) => self.pre_scan_function_expressions(&bs.body, parent_ctx)?, @@ -926,19 +938,45 @@ impl Compiler { Expression::ArrowFunctionExpression(_ae) => {} Expression::CallExpression(ce) => { self.pre_scan_expr(&ce.callee, parent_ctx)?; - for arg in &ce.arguments { if let Some(e) = arg.as_expression() { self.pre_scan_expr(e, parent_ctx)?; } } + for arg in &ce.arguments { + if let Some(e) = arg.as_expression() { + self.pre_scan_expr(e, parent_ctx)?; + } + } + } + Expression::BinaryExpression(be) => { + self.pre_scan_expr(&be.left, parent_ctx)?; + self.pre_scan_expr(&be.right, parent_ctx)?; + } + Expression::ConditionalExpression(ce) => { + self.pre_scan_expr(&ce.test, parent_ctx)?; + self.pre_scan_expr(&ce.consequent, parent_ctx)?; + self.pre_scan_expr(&ce.alternate, parent_ctx)?; + } + Expression::ArrayExpression(ae) => { + for e in &ae.elements { + if let Some(e) = e.as_expression() { + self.pre_scan_expr(e, parent_ctx)?; + } + } + } + Expression::SequenceExpression(se) => { + for e in &se.expressions { + self.pre_scan_expr(e, parent_ctx)?; + } + } + Expression::AssignmentExpression(ae) => { + self.pre_scan_expr(&ae.right, parent_ctx)?; + } + Expression::UnaryExpression(ue) => { + self.pre_scan_expr(&ue.argument, parent_ctx)?; } - Expression::BinaryExpression(be) => { self.pre_scan_expr(&be.left, parent_ctx)?; self.pre_scan_expr(&be.right, parent_ctx)?; } - Expression::ConditionalExpression(ce) => { self.pre_scan_expr(&ce.test, parent_ctx)?; self.pre_scan_expr(&ce.consequent, parent_ctx)?; self.pre_scan_expr(&ce.alternate, parent_ctx)?; } - Expression::ArrayExpression(ae) => { for e in &ae.elements { if let Some(e) = e.as_expression() { self.pre_scan_expr(e, parent_ctx)?; } } } - Expression::SequenceExpression(se) => { for e in &se.expressions { self.pre_scan_expr(e, parent_ctx)?; } } - Expression::AssignmentExpression(ae) => { self.pre_scan_expr(&ae.right, parent_ctx)?; } - Expression::UnaryExpression(ue) => { self.pre_scan_expr(&ue.argument, parent_ctx)?; } _ => {} } Ok(()) } + #[allow(clippy::too_many_arguments)] pub(crate) fn compile_function_body_with_field_hooks<'a, C, E>( &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, is_expression_body: bool, extra_bindings: &[(&str, u8)], body_context: FunctionBodyContext, @@ -1117,13 +1155,13 @@ impl Compiler { } } - debug_assert_eq!( - counted_pc, - ctx.bytecode.len(), - "counter/emitter instruction drift in function body (before implicit RETURN): counted {} vs emitted {}", - counted_pc, - ctx.bytecode.len() - ); + if counted_pc != ctx.bytecode.len() { + return Err(format!( + "counter/emitter instruction drift in function body (before implicit RETURN): counted {} vs emitted {}", + counted_pc, + ctx.bytecode.len() + )); + } // Emit implicit RETURN: expression body returns the last expression, // statement body returns undefined. @@ -1237,13 +1275,13 @@ impl Compiler { } crate::compiler_debug!("emitter: {} bytes emitted", ctx.bytecode.len()); - debug_assert_eq!( - counted_pc, - ctx.bytecode.len(), - "counter/emitter instruction drift in top-level module (before result store + HALT): counted {} vs emitted {}", - counted_pc, - ctx.bytecode.len() - ); + if counted_pc != ctx.bytecode.len() { + return Err(format!( + "counter/emitter instruction drift in top-level module (before result store + HALT): counted {} vs emitted {}", + counted_pc, + ctx.bytecode.len() + )); + } if let Some(r) = last_result { ctx.emit(opcode::encode(OpCode::LOAD_VAR, 0, r, 0)); diff --git a/crates/oxide_compiler/src/counter/expr/assignment.rs b/crates/oxide_compiler/src/counter/expr/assignment.rs deleted file mode 100644 index 5f75613..0000000 --- a/crates/oxide_compiler/src/counter/expr/assignment.rs +++ /dev/null @@ -1,116 +0,0 @@ -use super::*; - -impl Compiler { - fn count_assignment_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::AssignmentExpression(assign) = expr else { - return; - }; - - if let oxide_parser::AssignmentTarget::StaticMemberExpression(member) = &assign.left { - if let Some(logical_op) = assign.operator.to_logical_operator() { - self.count_static_member_logical_assignment(member, logical_op, &assign.right, ctx); - return; - } - self.count_expression(&member.object, ctx); - self.count_expression(&assign.right, ctx); - // Both plain (IC_SET_PROP) and compound (COMPOUND_MEMBER_*) emit one opcode + 3 ext - // words after the key load — no extra instruction for the compound case. - ctx.count_load_const(); // key - ctx.count_ic_set_with_ext(); // IC_SET_PROP or COMPOUND_MEMBER_* + 3 ext words - } else if let oxide_parser::AssignmentTarget::ComputedMemberExpression(member) = &assign.left { - if let Some(logical_op) = assign.operator.to_logical_operator() { - self.count_computed_member_logical_assignment(member, logical_op, &assign.right, ctx); - return; - } - self.count_expression(&member.object, ctx); - self.count_expression(&member.expression, ctx); - self.count_expression(&assign.right, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; // SET_PROP_DYNAMIC - } else if let oxide_parser::AssignmentTarget::PrivateFieldExpression(member) = &assign.left { - self.count_expression(&member.object, ctx); - self.count_expression(&assign.right, ctx); - ctx.count_load_const(); // private id - ctx.count_instr(); // SET_PRIVATE - } else if let oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(ati) = &assign.left { - let name = ati.name.as_str(); - // Check if target is an upvalue or captured cell - let is_upvalue = ctx.current_upvalue_captures.iter().any(|u| u.name == name); - let is_captured = ctx.scopes.symbols.lookup_is_captured(name); - if let Some(logical_op) = assign.operator.to_logical_operator() { - self.count_identifier_logical_assignment(logical_op, &assign.right, ctx); - } else { - self.count_expression(&assign.right, ctx); - if assign.operator != AssignmentOperator::Assign { - ctx.projected_pc += 1; // COMPOUND_* on var - } else if is_upvalue { - ctx.count_instr(); // STORE_UPVALUE - } else if is_captured { - ctx.count_instr(); // CELL_SET - } else { - ctx.alloc_reg(); - ctx.projected_pc += 1; // STORE_VAR - } - } - } else if let oxide_parser::AssignmentTarget::ArrayAssignmentTarget(ap) = &assign.left { - self.count_expression(&assign.right, ctx); - self.count_array_assignment(ap, ctx); - } else if let oxide_parser::AssignmentTarget::ObjectAssignmentTarget(op) = &assign.left { - self.count_expression(&assign.right, ctx); - self.count_object_assignment(op, ctx); - } else { - self.count_expression(&assign.right, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; - } - } - - fn count_static_member_logical_assignment( - &self, member: &oxide_parser::StaticMemberExpression<'_>, logical_op: LogicalOperator, right: &Expression, - ctx: &mut CompileCtx, - ) { - let id = ctx.next_label_id(); - self.count_expression(&member.object, ctx); - ctx.count_load_const(); // key - ctx.count_load_var(); // current value copy - ctx.count_ic_instr_with_ext(); // IC_GET_PROP + 3 ext - self.count_logical_assign_test(logical_op, id, ctx); - self.count_expression(right, ctx); - ctx.count_ic_set_with_ext(); // IC_SET_PROP + 3 ext - ctx.projected_pc += 1; // LOAD_VAR result <- rhs - ctx.labels.label_map.insert(Label::TernaryEnd(id), ctx.projected_pc); - } - - fn count_computed_member_logical_assignment( - &self, member: &oxide_parser::ComputedMemberExpression<'_>, logical_op: LogicalOperator, right: &Expression, - ctx: &mut CompileCtx, - ) { - let id = ctx.next_label_id(); - self.count_expression(&member.object, ctx); - self.count_expression(&member.expression, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; // GET_PROP_DYNAMIC - self.count_logical_assign_test(logical_op, id, ctx); - self.count_expression(right, ctx); - ctx.projected_pc += 1; // SET_PROP_DYNAMIC - ctx.projected_pc += 1; // LOAD_VAR result <- rhs - ctx.labels.label_map.insert(Label::TernaryEnd(id), ctx.projected_pc); - } - - fn count_identifier_logical_assignment( - &self, logical_op: LogicalOperator, right: &Expression, ctx: &mut CompileCtx, - ) { - let id = ctx.next_label_id(); - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_VAR result <- current var - self.count_logical_assign_test(logical_op, id, ctx); - self.count_expression(right, ctx); - ctx.projected_pc += 1; // STORE_VAR - ctx.projected_pc += 1; // LOAD_VAR result <- rhs - ctx.labels.label_map.insert(Label::TernaryEnd(id), ctx.projected_pc); - } - - pub(in crate::counter) fn count_assignment(&self, expr: &Expression, ctx: &mut CompileCtx) { - self.count_assignment_expression(expr, ctx); - } -} diff --git a/crates/oxide_compiler/src/counter/expr/call.rs b/crates/oxide_compiler/src/counter/expr/call.rs deleted file mode 100644 index e7df509..0000000 --- a/crates/oxide_compiler/src/counter/expr/call.rs +++ /dev/null @@ -1,78 +0,0 @@ -use super::*; - -impl Compiler { - fn count_call_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::CallExpression(call) = expr else { - return; - }; - if matches!(&call.callee, Expression::Super(_)) { - for arg in &call.arguments { - if let Some(expr) = arg.as_expression() { - self.count_expression(expr, ctx); - } - } - ctx.alloc_reg(); - ctx.count_call_instr_with_arg_ext(); // SUPER_CALL + arg_count ext word - // Mirror emit: derived-ctor instance fields are injected right after super(). - if let Some(words) = ctx.after_super_count_words.take() { - ctx.projected_pc += words; - } - return; - } - - match &call.callee { - Expression::PrivateFieldExpression(member) => { - self.count_expression(&member.object, ctx); - ctx.count_private_access(); - } - Expression::StaticMemberExpression(member) => { - if matches!(&member.object, Expression::Super(_)) { - ctx.count_load_var(); // this register - ctx.count_load_const(); // key - ctx.alloc_reg(); // callee - ctx.count_instr(); // SUPER_GET_PROP - } else { - self.count_expression(&member.object, ctx); - ctx.count_load_const(); // key - ctx.count_load_var(); // callee object copy - ctx.count_ic_instr_with_ext(); // IC_GET_PROP + 3 ext words - } - } - _ => { - self.count_expression(&call.callee, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; - } - } - - for arg in &call.arguments { - if let Some(expr) = arg.as_expression() { - self.count_expression(expr, ctx); - } - } - ctx.count_call_instr_with_arg_ext(); // CALL/CALL_NATIVE + arg_count ext word - ctx.count_load_var(); // result <- regs[0] - } - - fn count_new_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::NewExpression(ne) = expr else { - return; - }; - self.count_expression(&ne.callee, ctx); - for arg in &ne.arguments { - if let Some(expr) = arg.as_expression() { - self.count_expression(expr, ctx); - } - } - ctx.alloc_reg(); // result register - ctx.count_instr_with_ext(1); // NEW_EXPRESSION + arg_count ext word - } - - pub(in crate::counter) fn count_call_domain(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::CallExpression(_) => self.count_call_expression(expr, ctx), - Expression::NewExpression(_) => self.count_new_expression(expr, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/expr/chain.rs b/crates/oxide_compiler/src/counter/expr/chain.rs deleted file mode 100644 index c8f9588..0000000 --- a/crates/oxide_compiler/src/counter/expr/chain.rs +++ /dev/null @@ -1,17 +0,0 @@ -use super::*; - -impl Compiler { - pub(in crate::counter) fn count_chain_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::ChainExpression(chain) = expr else { - return; - }; - let id = ctx.next_label_id(); - self.count_chain_element(&chain.expression, true, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_VAR result <- chain value - ctx.projected_pc += 1; // JMP over short-circuit writer - ctx.labels.label_map.insert(Label::TernaryElse(id), ctx.projected_pc); - ctx.projected_pc += 1; // LOAD_CONST undefined - ctx.labels.label_map.insert(Label::TernaryEnd(id), ctx.projected_pc); - } -} diff --git a/crates/oxide_compiler/src/counter/expr/control.rs b/crates/oxide_compiler/src/counter/expr/control.rs deleted file mode 100644 index a77cb5a..0000000 --- a/crates/oxide_compiler/src/counter/expr/control.rs +++ /dev/null @@ -1,79 +0,0 @@ -use super::*; - -impl Compiler { - fn count_conditional_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::ConditionalExpression(cond) = expr else { - return; - }; - let id = ctx.next_label_id(); - let else_label = Label::TernaryElse(id); - let end_label = Label::TernaryEnd(id); - - self.count_expression(&cond.test, ctx); - ctx.projected_pc += 1; // JMP_IF_FALSE - self.count_expression(&cond.consequent, ctx); - ctx.alloc_reg(); // result register - ctx.projected_pc += 1; // LOAD_VAR result <- consequent - ctx.projected_pc += 1; // JMP to end - ctx.labels.label_map.insert(else_label, ctx.projected_pc); - self.count_expression(&cond.alternate, ctx); - ctx.projected_pc += 1; // LOAD_VAR result <- alternate - ctx.labels.label_map.insert(end_label, ctx.projected_pc); - } - - fn count_sequence_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::SequenceExpression(seq) = expr else { - return; - }; - for e in &seq.expressions { - self.count_expression(e, ctx); - } - } - - fn count_logical_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::LogicalExpression(log) = expr else { - return; - }; - self.count_expression(&log.left, ctx); - - let is_simple = is_side_effect_free(&log.left) && is_side_effect_free(&log.right); - - if is_simple { - self.count_expression(&log.right, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; // AND/OR - } else if matches!(log.operator, LogicalOperator::Coalesce) { - // Mirror emit_logical_expression's Coalesce path: it patches raw bytecode - // positions and does NOT consume a label id. Consuming one here would shift - // every later construct's label id and break resolve_label at emit time. - ctx.alloc_reg(); // dup register - ctx.projected_pc += 1; // LOAD_VAR (DUP) - ctx.projected_pc += 1; // JMP_IF_NULLISH - ctx.projected_pc += 1; // JMP over RHS on non-nullish - self.count_expression(&log.right, ctx); - ctx.projected_pc += 1; // LOAD_VAR (overwrite) - } else { - let id = ctx.next_label_id(); - ctx.alloc_reg(); // dup register - ctx.projected_pc += 1; // LOAD_VAR (DUP) - ctx.projected_pc += 1; // JMP_IF_FALSE or JMP_IF_TRUE - self.count_expression(&log.right, ctx); - ctx.projected_pc += 1; // LOAD_VAR (overwrite) - let skip_label = match log.operator { - LogicalOperator::And => Label::TernaryEnd(id), - LogicalOperator::Or => Label::TernaryElse(id), - LogicalOperator::Coalesce => unreachable!("coalesce handled above"), - }; - ctx.labels.label_map.insert(skip_label, ctx.projected_pc); - } - } - - pub(in crate::counter) fn count_conditional_chain(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::ConditionalExpression(_) => self.count_conditional_expression(expr, ctx), - Expression::SequenceExpression(_) => self.count_sequence_expression(expr, ctx), - Expression::LogicalExpression(_) => self.count_logical_expression(expr, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/expr/function.rs b/crates/oxide_compiler/src/counter/expr/function.rs deleted file mode 100644 index 5706acc..0000000 --- a/crates/oxide_compiler/src/counter/expr/function.rs +++ /dev/null @@ -1,29 +0,0 @@ -use super::*; - -impl Compiler { - fn count_arrow_function_expression(&self, ctx: &mut CompileCtx) { - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_CONST - } - - fn count_function_expression(&self, ctx: &mut CompileCtx) { - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_CONST - } - - fn count_class_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::ClassExpression(class) = expr else { - return; - }; - self.count_class(class, ctx); - } - - pub(in crate::counter) fn count_function_domain(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::ArrowFunctionExpression(_) => self.count_arrow_function_expression(ctx), - Expression::FunctionExpression(_) => self.count_function_expression(ctx), - Expression::ClassExpression(_) => self.count_class_expression(expr, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/expr/literal.rs b/crates/oxide_compiler/src/counter/expr/literal.rs deleted file mode 100644 index 8660209..0000000 --- a/crates/oxide_compiler/src/counter/expr/literal.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::*; - -impl Compiler { - /// Domain entry point: count any literal expression. The central - /// `count_expression` match delegates all literal variants here in one arm. - /// Numeric/String/Boolean/Null share the default single-`LOAD_CONST` shape; - /// RegExp emits three instructions. - pub(in crate::counter) fn count_literal(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::RegExpLiteral(_) => self.count_regexp_literal(ctx), - _ => self.count_default_expression(ctx), - } - } - - pub(in crate::counter) fn count_this_expression(&self, ctx: &mut CompileCtx) { - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_VAR from reg 254 - } - - pub(in crate::counter) fn count_identifier_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::Identifier(ident) = expr else { - return; - }; - let name = ident.name.as_str(); - - // Check if this is an upvalue reference (nested closure) - for up in &ctx.current_upvalue_captures { - if up.name == name { - ctx.alloc_reg(); - ctx.count_instr(); // LOAD_UPVALUE - return; - } - } - - // Check if the owner's binding is captured (cell access) - if ctx.scopes.symbols.lookup_is_captured(name) { - ctx.alloc_reg(); - ctx.count_instr(); // CELL_GET - return; - } - - if CompileCtx::is_known_builtin(name) { - let _ = ctx.lookup_or_builtin(name); - } - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_VAR - } - - fn count_regexp_literal(&self, ctx: &mut CompileCtx) { - ctx.alloc_reg(); // pattern reg (LOAD_CONST) - ctx.projected_pc += 1; - ctx.alloc_reg(); // flags reg (LOAD_CONST) - ctx.projected_pc += 1; - ctx.alloc_reg(); // result reg (CREATE_REGEXP) - ctx.projected_pc += 1; - } - - pub(in crate::counter) fn count_default_expression(&self, ctx: &mut CompileCtx) { - ctx.alloc_reg(); - ctx.projected_pc += 1; // LOAD_CONST or LOAD_VAR - } -} diff --git a/crates/oxide_compiler/src/counter/expr/member.rs b/crates/oxide_compiler/src/counter/expr/member.rs deleted file mode 100644 index 609aef4..0000000 --- a/crates/oxide_compiler/src/counter/expr/member.rs +++ /dev/null @@ -1,53 +0,0 @@ -use super::*; - -impl Compiler { - fn count_static_member_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::StaticMemberExpression(member) = expr else { - return; - }; - if matches!(&member.object, Expression::Super(_)) { - ctx.count_load_const(); // key - ctx.count_load_var(); // this - ctx.alloc_reg(); // result - ctx.count_instr(); // SUPER_GET_PROP - return; - } - self.count_expression(&member.object, ctx); - ctx.count_load_const(); // key - ctx.count_ic_instr_with_ext(); // IC_GET_PROP + 3 ext words - } - - fn count_computed_member_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::ComputedMemberExpression(member) = expr else { - return; - }; - self.count_expression(&member.object, ctx); - self.count_expression(&member.expression, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; // GET_PROP_DYNAMIC - } - - fn count_private_field_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::PrivateFieldExpression(member) = expr else { - return; - }; - self.count_expression(&member.object, ctx); - ctx.count_private_access(); - } - - pub(in crate::counter) fn count_parenthesized_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::ParenthesizedExpression(p) = expr else { - return; - }; - self.count_expression(&p.expression, ctx); - } - - pub(in crate::counter) fn count_member_domain(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::StaticMemberExpression(_) => self.count_static_member_expression(expr, ctx), - Expression::ComputedMemberExpression(_) => self.count_computed_member_expression(expr, ctx), - Expression::PrivateFieldExpression(_) => self.count_private_field_expression(expr, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/expr/mod.rs b/crates/oxide_compiler/src/counter/expr/mod.rs deleted file mode 100644 index 2697d10..0000000 --- a/crates/oxide_compiler/src/counter/expr/mod.rs +++ /dev/null @@ -1,48 +0,0 @@ -use super::*; - -mod assignment; -mod call; -mod chain; -mod control; -mod function; -mod literal; -mod member; -mod object; -mod operator; -mod template; - -impl Compiler { - pub(crate) fn count_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::BinaryExpression(_) - | Expression::PrivateInExpression(_) - | Expression::UnaryExpression(_) - | Expression::UpdateExpression(_) => self.count_operator(expr, ctx), - Expression::CallExpression(_) | Expression::NewExpression(_) => self.count_call_domain(expr, ctx), - Expression::AssignmentExpression(_) => self.count_assignment(expr, ctx), - Expression::ConditionalExpression(_) - | Expression::SequenceExpression(_) - | Expression::LogicalExpression(_) => self.count_conditional_chain(expr, ctx), - Expression::ChainExpression(_) => self.count_chain_expression(expr, ctx), - Expression::ObjectExpression(_) | Expression::ArrayExpression(_) => self.count_object_domain(expr, ctx), - Expression::TemplateLiteral(_) | Expression::TaggedTemplateExpression(_) => { - self.count_template_domain(expr, ctx) - } - Expression::ArrowFunctionExpression(_) - | Expression::FunctionExpression(_) - | Expression::ClassExpression(_) => self.count_function_domain(expr, ctx), - Expression::StaticMemberExpression(_) - | Expression::ComputedMemberExpression(_) - | Expression::PrivateFieldExpression(_) => self.count_member_domain(expr, ctx), - Expression::ParenthesizedExpression(_) => self.count_parenthesized_expression(expr, ctx), - Expression::ThisExpression(_) => self.count_this_expression(ctx), - Expression::Identifier(_) => self.count_identifier_expression(expr, ctx), - Expression::NumericLiteral(_) - | Expression::StringLiteral(_) - | Expression::BooleanLiteral(_) - | Expression::NullLiteral(_) - | Expression::RegExpLiteral(_) => self.count_literal(expr, ctx), - _ => self.count_default_expression(ctx), - } - } -} diff --git a/crates/oxide_compiler/src/counter/expr/operator.rs b/crates/oxide_compiler/src/counter/expr/operator.rs deleted file mode 100644 index 2e4b8a7..0000000 --- a/crates/oxide_compiler/src/counter/expr/operator.rs +++ /dev/null @@ -1,130 +0,0 @@ -use super::*; - -impl Compiler { - fn count_binary_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::BinaryExpression(bin) = expr else { - return; - }; - let checkpoint = ctx.reg_checkpoint(); - self.count_expression(&bin.left, ctx); - self.count_expression(&bin.right, ctx); - ctx.projected_pc += 1; // ADD/SUB/MUL/DIV/etc. - if is_side_effect_free(&bin.left) && is_side_effect_free(&bin.right) { - ctx.restore_reg_checkpoint(checkpoint.saturating_add(1)); - } - } - - fn count_private_in_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::PrivateInExpression(pin) = expr else { - return; - }; - self.count_expression(&pin.right, ctx); - ctx.count_private_access(); - } - - fn count_unary_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::UnaryExpression(un) = expr else { - return; - }; - match un.operator { - UnaryOperator::Delete => self.count_delete_expression(&un.argument, ctx), - _ => { - self.count_expression(&un.argument, ctx); - ctx.projected_pc += 1; // NEG/TYPEOF/VOID/NOT - } - } - } - - fn count_delete_expression(&self, argument: &Expression, ctx: &mut CompileCtx) { - match argument { - Expression::Identifier(_) => { - // SyntaxError at compile time, no bytecode cost. - } - Expression::StaticMemberExpression(member) => { - self.count_expression(&member.object, ctx); - ctx.count_delete_static(); - } - Expression::ComputedMemberExpression(member) => { - self.count_expression(&member.object, ctx); - self.count_expression(&member.expression, ctx); - ctx.projected_pc += 1; // DELETE_PROP_DYNAMIC - } - Expression::ChainExpression(chain) => { - self.count_delete_chain_expression(&chain.expression, ctx); - } - _ => {} - } - } - - fn count_delete_chain_expression(&self, chain: &ChainElement, ctx: &mut CompileCtx) { - match chain { - ChainElement::StaticMemberExpression(member) => { - self.count_expression(&member.object, ctx); - if member.optional { - self.count_optional_guard(ctx); - } - ctx.count_delete_static(); - } - ChainElement::ComputedMemberExpression(member) => { - self.count_expression(&member.object, ctx); - if member.optional { - self.count_optional_guard(ctx); - } - self.count_expression(&member.expression, ctx); - ctx.projected_pc += 1; // DELETE_PROP_DYNAMIC - } - _ => {} - } - ctx.projected_pc += 1; // JMP over nullish true writer - ctx.projected_pc += 1; // LOAD_CONST true - } - - fn count_update_expression(&self, expr: &Expression, ctx: &mut CompileCtx) { - let Expression::UpdateExpression(update) = expr else { - return; - }; - match &update.argument { - SimpleAssignmentTarget::AssignmentTargetIdentifier(id) => { - let name = id.name.as_str(); - let is_upvalue = ctx.current_upvalue_captures.iter().any(|u| u.name == name); - let is_captured = ctx.scopes.symbols.lookup_is_captured(name); - if is_upvalue || is_captured { - ctx.alloc_reg(); // val_reg - ctx.count_instr(); // LOAD_UPVALUE or CELL_GET - ctx.count_load_const(); // 1, alloc + instr - ctx.count_instr(); // ADD/SUB - ctx.count_instr(); // STORE_UPVALUE or CELL_SET - } else { - ctx.alloc_reg(); - ctx.projected_pc += 1; - } - } - SimpleAssignmentTarget::StaticMemberExpression(member) => { - self.count_expression(&member.object, ctx); - ctx.count_load_const(); // key - ctx.alloc_reg(); - ctx.count_ic_instr_with_ext(); // MEMBER_INC/MEMBER_DEC + 3 ext words - } - SimpleAssignmentTarget::ComputedMemberExpression(member) => { - self.count_expression(&member.object, ctx); - self.count_expression(&member.expression, ctx); - ctx.alloc_reg(); - ctx.projected_pc += 1; - } - _ => { - ctx.alloc_reg(); - ctx.projected_pc += 1; - } - } - } - - pub(in crate::counter) fn count_operator(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::BinaryExpression(_) => self.count_binary_expression(expr, ctx), - Expression::PrivateInExpression(_) => self.count_private_in_expression(expr, ctx), - Expression::UnaryExpression(_) => self.count_unary_expression(expr, ctx), - Expression::UpdateExpression(_) => self.count_update_expression(expr, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/helper/binding.rs b/crates/oxide_compiler/src/counter/helper/binding.rs index a7c081a..a870aaf 100644 --- a/crates/oxide_compiler/src/counter/helper/binding.rs +++ b/crates/oxide_compiler/src/counter/helper/binding.rs @@ -46,7 +46,7 @@ impl Compiler { } } - pub(in crate::counter) fn count_rest_array(&self, ctx: &mut CompileCtx) { + pub(crate) fn count_rest_array(&self, ctx: &mut CompileCtx) { ctx.alloc_reg(); // rest ctx.count_instr(); // NEW_ARRAY ctx.count_load_const(); // idx = 0 @@ -61,9 +61,7 @@ impl Compiler { ctx.count_jump(); // JMP } - pub(in crate::counter) fn count_array_assignment( - &self, ap: &oxide_parser::ArrayAssignmentTarget, ctx: &mut CompileCtx, - ) { + pub(crate) fn count_array_assignment(&self, ap: &oxide_parser::ArrayAssignmentTarget, ctx: &mut CompileCtx) { ctx.count_instr(); // FOR_OF_INIT for elem in &ap.elements { ctx.alloc_reg(); @@ -86,9 +84,7 @@ impl Compiler { ctx.count_instr(); // FOR_OF_CLOSE } - pub(in crate::counter) fn count_object_assignment( - &self, op: &oxide_parser::ObjectAssignmentTarget, ctx: &mut CompileCtx, - ) { + pub(crate) fn count_object_assignment(&self, op: &oxide_parser::ObjectAssignmentTarget, ctx: &mut CompileCtx) { for prop in &op.properties { match prop { oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) => { @@ -118,7 +114,7 @@ impl Compiler { } } - pub(in crate::counter) fn count_assignment_maybe_default( + pub(crate) fn count_assignment_maybe_default( &self, target: &oxide_parser::AssignmentTargetMaybeDefault, ctx: &mut CompileCtx, ) { match target { @@ -144,9 +140,7 @@ impl Compiler { } } - pub(in crate::counter) fn count_assign_target( - &self, target: &oxide_parser::AssignmentTarget, ctx: &mut CompileCtx, - ) { + pub(crate) fn count_assign_target(&self, target: &oxide_parser::AssignmentTarget, ctx: &mut CompileCtx) { match target { oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(_) => { ctx.alloc_reg(); diff --git a/crates/oxide_compiler/src/counter/helper/member.rs b/crates/oxide_compiler/src/counter/helper/member.rs index 16313a2..68c066d 100644 --- a/crates/oxide_compiler/src/counter/helper/member.rs +++ b/crates/oxide_compiler/src/counter/helper/member.rs @@ -1,13 +1,13 @@ use super::super::*; impl Compiler { - pub(in crate::counter) fn count_object_property_read_static(&self, ctx: &mut CompileCtx) { + pub(crate) fn count_object_property_read_static(&self, ctx: &mut CompileCtx) { ctx.count_load_var(); // prop/object temp ctx.count_load_const(); // key reg ctx.count_ic_instr_with_ext(); // IC_GET_PROP + 3 ext words } - pub(in crate::counter) fn count_object_property_read_key( + pub(crate) fn count_object_property_read_key( &self, key: &oxide_parser::PropertyKey, computed: bool, ctx: &mut CompileCtx, ) { if !computed { @@ -38,12 +38,12 @@ impl Compiler { ctx.count_instr(); // GET_PROP_DYNAMIC } - pub(in crate::counter) fn count_optional_guard(&self, ctx: &mut CompileCtx) { + pub(crate) fn count_optional_guard(&self, ctx: &mut CompileCtx) { ctx.count_load_var(); // dup ctx.count_jump(); // JMP_IF_NULLISH } - pub(in crate::counter) fn count_static_member_get_preserve_base( + pub(crate) fn count_static_member_get_preserve_base( &self, member: &oxide_parser::StaticMemberExpression, short_chain: bool, ctx: &mut CompileCtx, ) { self.count_chainable_expression(&member.object, short_chain, ctx); @@ -55,7 +55,7 @@ impl Compiler { ctx.count_ic_instr_with_ext(); // IC_GET_PROP + 3 ext words } - pub(in crate::counter) fn count_computed_member_get_preserve_base( + pub(crate) fn count_computed_member_get_preserve_base( &self, member: &oxide_parser::ComputedMemberExpression, short_chain: bool, ctx: &mut CompileCtx, ) { self.count_chainable_expression(&member.object, short_chain, ctx); @@ -67,7 +67,7 @@ impl Compiler { ctx.count_instr(); // GET_PROP_DYNAMIC } - pub(in crate::counter) fn count_chain_call( + pub(crate) fn count_chain_call( &self, call: &oxide_parser::CallExpression, short_chain: bool, ctx: &mut CompileCtx, ) { match &call.callee { @@ -113,9 +113,7 @@ impl Compiler { ctx.count_load_var(); // result <- regs[0] } - pub(in crate::counter) fn count_chainable_expression( - &self, expr: &Expression, short_chain: bool, ctx: &mut CompileCtx, - ) { + pub(crate) fn count_chainable_expression(&self, expr: &Expression, short_chain: bool, ctx: &mut CompileCtx) { match expr { Expression::StaticMemberExpression(member) => { self.count_static_member_get_preserve_base(member, short_chain, ctx) @@ -136,9 +134,7 @@ impl Compiler { } } - pub(in crate::counter) fn count_chain_element( - &self, element: &ChainElement, short_chain: bool, ctx: &mut CompileCtx, - ) { + pub(crate) fn count_chain_element(&self, element: &ChainElement, short_chain: bool, ctx: &mut CompileCtx) { match element { ChainElement::StaticMemberExpression(member) => { self.count_static_member_get_preserve_base(member, short_chain, ctx) @@ -158,7 +154,7 @@ impl Compiler { } } - pub(in crate::counter) fn count_logical_assign_test(&self, op: LogicalOperator, id: u32, ctx: &mut CompileCtx) { + pub(crate) fn count_logical_assign_test(&self, op: LogicalOperator, id: u32, ctx: &mut CompileCtx) { match op { LogicalOperator::And | LogicalOperator::Or => { ctx.projected_pc += 1; diff --git a/crates/oxide_compiler/src/counter/helper/mod.rs b/crates/oxide_compiler/src/counter/helper/mod.rs index a9ad521..7ebbb06 100644 --- a/crates/oxide_compiler/src/counter/helper/mod.rs +++ b/crates/oxide_compiler/src/counter/helper/mod.rs @@ -1,3 +1,2 @@ mod binding; -mod class; mod member; diff --git a/crates/oxide_compiler/src/counter/mod.rs b/crates/oxide_compiler/src/counter/mod.rs index 7600a40..2d74bfb 100644 --- a/crates/oxide_compiler/src/counter/mod.rs +++ b/crates/oxide_compiler/src/counter/mod.rs @@ -1,10 +1,17 @@ +#[allow(unused_imports)] +use crate::compiler::{ + is_int_literal, is_side_effect_free, BinaryOperator, CompileCtx, Compiler, FunctionBodyContext, Label, ParamSpec, +}; +#[allow(unused_imports)] +use oxide_bytecode::module::Constant; +#[allow(unused_imports)] +use oxide_bytecode::opcode::{self, OpCode}; +#[allow(unused_imports)] use oxide_parser::{ - AssignmentOperator, ChainElement, ClassElement, Expression, ForStatementInit, LogicalOperator, - MethodDefinitionKind, SimpleAssignmentTarget, Statement, UnaryOperator, VariableDeclarationKind, + AssignmentOperator, AssignmentTarget, AssignmentTargetMaybeDefault, AssignmentTargetProperty, BindingPattern, + ChainElement, Class, ClassElement, Expression, ForStatementInit, ForStatementLeft, LogicalOperator, + MethodDefinitionKind, ObjectAssignmentTarget, PropertyKey, PropertyKind, SimpleAssignmentTarget, Statement, + UnaryOperator, UpdateOperator, VariableDeclarationKind, }; -use crate::compiler::{is_side_effect_free, CompileCtx, Compiler, Label}; - -mod expr; -mod helper; -mod stmt; +pub mod helper; diff --git a/crates/oxide_compiler/src/counter/stmt/basic.rs b/crates/oxide_compiler/src/counter/stmt/basic.rs deleted file mode 100644 index a1eaa2e..0000000 --- a/crates/oxide_compiler/src/counter/stmt/basic.rs +++ /dev/null @@ -1,51 +0,0 @@ -use super::*; - -impl Compiler { - fn count_expression_statement(&self, stmt: &oxide_parser::ExpressionStatement<'_>, ctx: &mut CompileCtx) { - self.count_expression(&stmt.expression, ctx); - } - - fn count_return_statement(&self, stmt: &oxide_parser::ReturnStatement<'_>, ctx: &mut CompileCtx) { - if let Some(arg) = &stmt.argument { - self.count_expression(arg, ctx); - } - ctx.projected_pc += 1; // RETURN - } - - fn count_break_statement(&self, ctx: &mut CompileCtx) { - ctx.projected_pc += 1; // JMP - } - - fn count_continue_statement(&self, ctx: &mut CompileCtx) { - ctx.projected_pc += 1; // JMP - } - - fn count_labeled_statement(&self, stmt: &oxide_parser::LabeledStatement<'_>, ctx: &mut CompileCtx) { - let body_is_loop = matches!( - stmt.body, - Statement::WhileStatement(_) - | Statement::DoWhileStatement(_) - | Statement::ForStatement(_) - | Statement::ForInStatement(_) - | Statement::ForOfStatement(_) - ); - if body_is_loop { - self.count_statement(&stmt.body, ctx); - } else { - let id = ctx.next_label_id(); - self.count_statement(&stmt.body, ctx); - ctx.labels.label_map.insert(Label::LabeledEnd(id), ctx.projected_pc); - } - } - - pub(in crate::counter) fn count_basic(&self, stmt: &Statement, ctx: &mut CompileCtx) { - match stmt { - Statement::ExpressionStatement(es) => self.count_expression_statement(es, ctx), - Statement::ReturnStatement(ret) => self.count_return_statement(ret, ctx), - Statement::BreakStatement(_) => self.count_break_statement(ctx), - Statement::ContinueStatement(_) => self.count_continue_statement(ctx), - Statement::LabeledStatement(ls) => self.count_labeled_statement(ls, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/stmt/block.rs b/crates/oxide_compiler/src/counter/stmt/block.rs deleted file mode 100644 index 3106ec7..0000000 --- a/crates/oxide_compiler/src/counter/stmt/block.rs +++ /dev/null @@ -1,15 +0,0 @@ -use super::*; - -impl Compiler { - fn count_block_statement(&self, block: &oxide_parser::BlockStatement<'_>, ctx: &mut CompileCtx) { - for s in &block.body { - self.count_statement(s, ctx); - } - } - - pub(in crate::counter) fn count_block_domain(&self, stmt: &Statement, ctx: &mut CompileCtx) { - if let Statement::BlockStatement(block) = stmt { - self.count_block_statement(block, ctx); - } - } -} diff --git a/crates/oxide_compiler/src/counter/stmt/control.rs b/crates/oxide_compiler/src/counter/stmt/control.rs deleted file mode 100644 index e8441dd..0000000 --- a/crates/oxide_compiler/src/counter/stmt/control.rs +++ /dev/null @@ -1,30 +0,0 @@ -use super::*; - -impl Compiler { - fn count_if_statement(&self, stmt: &oxide_parser::IfStatement<'_>, ctx: &mut CompileCtx) { - let id = ctx.next_label_id(); - let else_label = Label::IfElse(id); - let end_label = Label::IfEnd(id); - - self.count_expression(&stmt.test, ctx); - ctx.projected_pc += 1; // JMP_IF_FALSE - self.count_statement(&stmt.consequent, ctx); - ctx.alloc_reg(); // result register - ctx.projected_pc += 1; // LOAD_VAR result <- consequent - if stmt.alternate.is_some() { - ctx.projected_pc += 1; // JMP (skip else) - } - ctx.labels.label_map.insert(else_label, ctx.projected_pc); - if let Some(alt_stmt) = &stmt.alternate { - self.count_statement(alt_stmt, ctx); - ctx.projected_pc += 1; // LOAD_VAR result <- alternate - } - ctx.labels.label_map.insert(end_label, ctx.projected_pc); - } - - pub(in crate::counter) fn count_control_domain(&self, stmt: &Statement, ctx: &mut CompileCtx) { - if let Statement::IfStatement(ifs) = stmt { - self.count_if_statement(ifs, ctx); - } - } -} diff --git a/crates/oxide_compiler/src/counter/stmt/mod.rs b/crates/oxide_compiler/src/counter/stmt/mod.rs deleted file mode 100644 index 2de33e7..0000000 --- a/crates/oxide_compiler/src/counter/stmt/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -use super::*; - -mod basic; -mod block; -mod control; -mod declaration; -mod exception; -mod iteration; -mod switch; - -impl Compiler { - pub(crate) fn count_statement(&self, stmt: &Statement, ctx: &mut CompileCtx) { - match stmt { - Statement::ExpressionStatement(_) - | Statement::ReturnStatement(_) - | Statement::BreakStatement(_) - | Statement::ContinueStatement(_) - | Statement::LabeledStatement(_) => self.count_basic(stmt, ctx), - Statement::BlockStatement(_) => self.count_block_domain(stmt, ctx), - Statement::VariableDeclaration(_) | Statement::FunctionDeclaration(_) | Statement::ClassDeclaration(_) => { - self.count_declaration_domain(stmt, ctx) - } - Statement::IfStatement(_) => self.count_control_domain(stmt, ctx), - Statement::WhileStatement(_) - | Statement::DoWhileStatement(_) - | Statement::ForStatement(_) - | Statement::ForInStatement(_) - | Statement::ForOfStatement(_) => self.count_iteration_domain(stmt, ctx), - Statement::SwitchStatement(_) => self.count_switch_domain(stmt, ctx), - Statement::ThrowStatement(_) | Statement::TryStatement(_) => self.count_exception_domain(stmt, ctx), - _ => {} - } - } -} diff --git a/crates/oxide_compiler/src/counter/stmt/switch.rs b/crates/oxide_compiler/src/counter/stmt/switch.rs deleted file mode 100644 index ab33275..0000000 --- a/crates/oxide_compiler/src/counter/stmt/switch.rs +++ /dev/null @@ -1,45 +0,0 @@ -use super::*; - -impl Compiler { - fn count_switch_statement(&self, stmt: &oxide_parser::SwitchStatement<'_>, ctx: &mut CompileCtx) { - let id = ctx.next_label_id(); - let end_label = Label::SwitchEnd(id); - ctx.push_switch(end_label); - - self.count_expression(&stmt.discriminant, ctx); - let compare_reg_checkpoint = ctx.reg_checkpoint(); - - let cases = &stmt.cases; - for case in cases.iter() { - if let Some(test) = &case.test { - self.count_expression(test, ctx); - ctx.projected_pc += 1; // EQ - ctx.alloc_reg(); // eq result - ctx.projected_pc += 1; // JMP_IF_TRUE - ctx.restore_reg_checkpoint(compare_reg_checkpoint); - } - } - - let has_default = cases.iter().any(|c| c.test.is_none()); - if !has_default { - ctx.projected_pc += 1; // JMP to SwitchEnd (no match) - } - - for (case_idx, case) in cases.iter().enumerate() { - let case_label = Label::SwitchCase(id, case_idx as u32); - ctx.labels.label_map.insert(case_label, ctx.projected_pc); - for s in &case.consequent { - self.count_statement(s, ctx); - } - } - - ctx.labels.label_map.insert(end_label, ctx.projected_pc); - ctx.pop_switch(); - } - - pub(in crate::counter) fn count_switch_domain(&self, stmt: &Statement, ctx: &mut CompileCtx) { - if let Statement::SwitchStatement(sw) = stmt { - self.count_switch_statement(sw, ctx); - } - } -} diff --git a/crates/oxide_compiler/src/emitter/expr/mod.rs b/crates/oxide_compiler/src/emitter/expr/mod.rs deleted file mode 100644 index 6270571..0000000 --- a/crates/oxide_compiler/src/emitter/expr/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -use super::*; - -mod assignment; -mod call; -mod function; -mod literal; -mod member; -mod object; -mod operator; -mod template; diff --git a/crates/oxide_compiler/src/emitter/mod.rs b/crates/oxide_compiler/src/emitter/mod.rs index a31c6e3..af52c91 100644 --- a/crates/oxide_compiler/src/emitter/mod.rs +++ b/crates/oxide_compiler/src/emitter/mod.rs @@ -1,3 +1,4 @@ +#![allow(unused_imports)] use crate::compiler::Label; use oxide_bytecode::module::Constant; use oxide_bytecode::opcode::{self, OpCode}; @@ -12,9 +13,6 @@ use crate::compiler::{ is_int_literal, is_side_effect_free, BinaryOperator, CompileCtx, Compiler, FunctionBodyContext, ParamSpec, }; -mod expr; -mod stmt; - impl Compiler { fn emit_optional_guard(&self, reg: u8, short_label: Label, ctx: &mut CompileCtx) -> Result<(), String> { let short_pos = ctx.resolve_label(short_label)?; @@ -157,7 +155,7 @@ impl Compiler { } } - fn emit_chain_element( + pub(crate) fn emit_chain_element( &self, element: &ChainElement, short_label: Option