From f51eaca6a886e6b52138685b8d35fb55bb101e46 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 5 Aug 2026 00:34:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=80=BB=E8=BE=91=E8=BF=90?= =?UTF-8?q?=E7=AE=97=E8=B7=B3=E8=BD=AC=E6=94=B9=E7=BB=8F=20fixup=20?= =?UTF-8?q?=E5=BB=B6=E8=BF=9F=E5=8F=91=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oxide_compiler/src/expr/operator/mod.rs | 52 ++++++------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/crates/oxide_compiler/src/expr/operator/mod.rs b/crates/oxide_compiler/src/expr/operator/mod.rs index fdf59ae9..a79f1a6b 100644 --- a/crates/oxide_compiler/src/expr/operator/mod.rs +++ b/crates/oxide_compiler/src/expr/operator/mod.rs @@ -173,15 +173,15 @@ impl Compiler { 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. + let id = ctx.next_label_id(); 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) + ctx.labels.label_map.insert(Label::TernaryElse(id), ctx.projected_pc); + ctx.labels.label_map.insert(Label::TernaryEnd(id), ctx.projected_pc); } else { let id = ctx.next_label_id(); ctx.alloc_reg(); // dup register @@ -366,23 +366,18 @@ impl Compiler { let end_label = Label::TernaryEnd(id); let test_reg = self.emit_expression(&cond.test, ctx)?; - let else_pos = ctx.resolve_label(else_label)?; - let end_pos = ctx.resolve_label(end_label)?; - - let offset = (else_pos as isize) - (ctx.bytecode.len() as isize); - let offset = ctx.checked_jump_offset(offset); - ctx.emit(opcode::encode_jmp_if_false(test_reg, offset)); + ctx.emit_jmp_if_false_labeled(test_reg, else_label); let cons_reg = self.emit_expression(&cond.consequent, ctx)?; let result_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::LOAD_VAR, result_reg, cons_reg, 0)); - let offset = (end_pos as isize) - (ctx.bytecode.len() as isize); - let offset = ctx.checked_jump_offset(offset); - ctx.emit(opcode::encode_jmp(offset)); + ctx.emit_jmp_labeled(end_label); + ctx.labels.label_map.insert(else_label, ctx.bytecode.len()); let alt_reg = self.emit_expression(&cond.alternate, ctx)?; ctx.emit(opcode::encode(OpCode::LOAD_VAR, result_reg, alt_reg, 0)); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); Ok(result_reg) } @@ -405,22 +400,17 @@ impl Compiler { } if matches!(log.operator, LogicalOperator::Coalesce) { + let id = ctx.next_label_id(); + let rhs_label = Label::TernaryElse(id); + let end_label = Label::TernaryEnd(id); let dup_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::LOAD_VAR, dup_reg, left_reg, 0)); - let nullish_jump_pos = ctx.bytecode.len(); - ctx.emit(opcode::encode_jmp_if_nullish(dup_reg, 0)); - let end_jump_pos = ctx.bytecode.len(); - ctx.emit(opcode::encode_jmp(0)); - let rhs_pos = ctx.bytecode.len(); + ctx.emit_jmp_if_nullish_labeled(dup_reg, rhs_label); + ctx.emit_jmp_labeled(end_label); + ctx.labels.label_map.insert(rhs_label, ctx.bytecode.len()); let right_reg = self.emit_expression(&log.right, ctx)?; ctx.emit(opcode::encode(OpCode::LOAD_VAR, dup_reg, right_reg, 0)); - let end_pos = ctx.bytecode.len(); - let offset = (rhs_pos as isize) - (nullish_jump_pos as isize); - let offset = ctx.checked_jump_offset(offset); - ctx.bytecode[nullish_jump_pos] = opcode::encode_jmp_if_nullish(dup_reg, offset); - let offset = (end_pos as isize) - (end_jump_pos as isize); - let offset = ctx.checked_jump_offset(offset); - ctx.bytecode[end_jump_pos] = opcode::encode_jmp(offset); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); return Ok(dup_reg); } @@ -430,26 +420,18 @@ impl Compiler { LogicalOperator::Or => Label::TernaryElse(id), LogicalOperator::Coalesce => return Err("invalid logical operator dispatch".into()), }; - let skip_pos = ctx.resolve_label(skip_label)?; - let dup_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::LOAD_VAR, dup_reg, left_reg, 0)); - let offset = (skip_pos as isize) - (ctx.bytecode.len() as isize); match log.operator { - LogicalOperator::And => { - let offset = ctx.checked_jump_offset(offset); - ctx.emit(opcode::encode_jmp_if_false(dup_reg, offset)); - } - LogicalOperator::Or => { - let offset = ctx.checked_jump_offset(offset); - ctx.emit(opcode::encode_jmp_if_true(dup_reg, offset)); - } + LogicalOperator::And => ctx.emit_jmp_if_false_labeled(dup_reg, skip_label), + LogicalOperator::Or => ctx.emit_jmp_if_true_labeled(dup_reg, skip_label), LogicalOperator::Coalesce => return Err("invalid logical operator dispatch".into()), } let right_reg = self.emit_expression(&log.right, ctx)?; ctx.emit(opcode::encode(OpCode::LOAD_VAR, dup_reg, right_reg, 0)); + ctx.labels.label_map.insert(skip_label, ctx.bytecode.len()); Ok(dup_reg) }