diff --git a/crates/oxide_compiler/src/stmt/iteration/do_while.rs b/crates/oxide_compiler/src/stmt/iteration/do_while.rs index 6390477a..4f30af69 100644 --- a/crates/oxide_compiler/src/stmt/iteration/do_while.rs +++ b/crates/oxide_compiler/src/stmt/iteration/do_while.rs @@ -1,5 +1,4 @@ use crate::compiler::{CompileCtx, Compiler, Label}; -use oxide_bytecode::opcode; use oxide_parser::Statement; impl Compiler { @@ -21,14 +20,13 @@ impl Compiler { let id = ctx.next_label_id(); let start_label = Label::DoWhileStart(id); let end_label = Label::DoWhileEnd(id); + ctx.labels.label_map.insert(start_label, ctx.bytecode.len()); ctx.push_loop(end_label, start_label); let n_labeled = ctx.take_pending_loop_labels(end_label, start_label); self.emit_statement(&dw.body, ctx)?; let test_reg = self.emit_expression(&dw.test, ctx)?; - let start_pos = ctx.resolve_label(start_label)?; - let offset = (start_pos as isize) - (ctx.bytecode.len() as isize); - let offset = ctx.checked_jump_offset(offset); - ctx.emit(opcode::encode_jmp_if_true(test_reg, offset)); + ctx.emit_jmp_if_true_labeled(test_reg, start_label); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); ctx.pop_label_scopes(n_labeled); ctx.pop_loop(); Ok(None) diff --git a/crates/oxide_compiler/src/stmt/iteration/for_.rs b/crates/oxide_compiler/src/stmt/iteration/for_.rs index e3e27c00..9fd96147 100644 --- a/crates/oxide_compiler/src/stmt/iteration/for_.rs +++ b/crates/oxide_compiler/src/stmt/iteration/for_.rs @@ -72,21 +72,18 @@ impl Compiler { } } } + ctx.labels.label_map.insert(start_label, ctx.bytecode.len()); if let Some(test) = &fr.test { let test_reg = self.emit_expression(test, ctx)?; - let end_pos = ctx.resolve_label(end_label)?; - let offset = (end_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, end_label); } self.emit_statement(&fr.body, ctx)?; + ctx.labels.label_map.insert(update_label, ctx.bytecode.len()); if let Some(update) = &fr.update { self.emit_expression(update, ctx)?; } - let start_pos = ctx.resolve_label(start_label)?; - let offset = (start_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(start_label); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); ctx.pop_label_scopes(n_labeled); ctx.pop_loop(); Ok(None) diff --git a/crates/oxide_compiler/src/stmt/iteration/for_in.rs b/crates/oxide_compiler/src/stmt/iteration/for_in.rs index 241d94b8..497dbde0 100644 --- a/crates/oxide_compiler/src/stmt/iteration/for_in.rs +++ b/crates/oxide_compiler/src/stmt/iteration/for_in.rs @@ -42,15 +42,13 @@ impl Compiler { let end_label = Label::ForInEnd(id); let obj_reg = self.emit_expression(&fi.right, ctx)?; ctx.emit(opcode::encode(OpCode::FOR_IN_INIT, 0, obj_reg, 0)); + ctx.labels.label_map.insert(start_label, ctx.bytecode.len()); ctx.push_loop(end_label, start_label); let n_labeled = ctx.take_pending_loop_labels(end_label, start_label); let done_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::FOR_IN_DONE, done_reg, 0, 0)); - let end_pos = ctx.resolve_label(end_label)?; - let cleanup_jmp_offset = (end_pos as isize) - (ctx.bytecode.len() as isize); ctx.emit(opcode::encode_jmp_if_false(done_reg, 2)); - let cleanup_jmp_offset = ctx.checked_jump_offset(cleanup_jmp_offset); - ctx.emit(opcode::encode_jmp(cleanup_jmp_offset)); + ctx.emit_jmp_labeled(end_label); let key_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::FOR_IN_NEXT, key_reg, 0, 0)); match &fi.left { @@ -74,10 +72,8 @@ impl Compiler { _ => return Err("unsupported for-in left-hand side".into()), } self.emit_statement(&fi.body, ctx)?; - let start_pos = ctx.resolve_label(start_label)?; - let offset = (start_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(start_label); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); ctx.emit(opcode::encode(OpCode::FOR_IN_CLEANUP, 0, 0, 0)); ctx.pop_label_scopes(n_labeled); ctx.pop_loop(); diff --git a/crates/oxide_compiler/src/stmt/iteration/for_of.rs b/crates/oxide_compiler/src/stmt/iteration/for_of.rs index 353d9d10..8be2f208 100644 --- a/crates/oxide_compiler/src/stmt/iteration/for_of.rs +++ b/crates/oxide_compiler/src/stmt/iteration/for_of.rs @@ -48,14 +48,12 @@ impl Compiler { let end_label = Label::ForOfEnd(id); let iter_src_reg = self.emit_expression(&fo.right, ctx)?; ctx.emit(opcode::encode(OpCode::FOR_OF_INIT, 0, iter_src_reg, 0)); + ctx.labels.label_map.insert(start_label, ctx.bytecode.len()); ctx.push_loop(end_label, start_label); let n_labeled = ctx.take_pending_loop_labels(end_label, start_label); let has_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::FOR_OF_DONE, has_reg, 0, 0)); - let end_pos = ctx.resolve_label(end_label)?; - let offset = (end_pos as isize) - (ctx.bytecode.len() as isize); - let offset = ctx.checked_jump_offset(offset); - ctx.emit(opcode::encode_jmp_if_false(has_reg, offset)); + ctx.emit_jmp_if_false_labeled(has_reg, end_label); let val_reg = ctx.alloc_reg(); ctx.emit(opcode::encode(OpCode::FOR_OF_NEXT, val_reg, 0, 0)); match &fo.left { @@ -78,10 +76,8 @@ impl Compiler { _ => return Err("unsupported for-of left-hand side".into()), } self.emit_statement(&fo.body, ctx)?; - let start_pos = ctx.resolve_label(start_label)?; - let offset = (start_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(start_label); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); ctx.emit(opcode::encode(OpCode::FOR_OF_CLOSE, 0, 0, 0)); ctx.pop_label_scopes(n_labeled); ctx.pop_loop(); diff --git a/crates/oxide_compiler/src/stmt/iteration/while_loop.rs b/crates/oxide_compiler/src/stmt/iteration/while_loop.rs index 68ba0e57..9b15d1dc 100644 --- a/crates/oxide_compiler/src/stmt/iteration/while_loop.rs +++ b/crates/oxide_compiler/src/stmt/iteration/while_loop.rs @@ -1,5 +1,4 @@ use crate::compiler::{CompileCtx, Compiler, Label}; -use oxide_bytecode::opcode; use oxide_parser::Statement; impl Compiler { @@ -22,18 +21,14 @@ impl Compiler { let id = ctx.next_label_id(); let start_label = Label::WhileStart(id); let end_label = Label::WhileEnd(id); + ctx.labels.label_map.insert(start_label, ctx.bytecode.len()); ctx.push_loop(end_label, start_label); let n_labeled = ctx.take_pending_loop_labels(end_label, start_label); let test_reg = self.emit_expression(&wh.test, ctx)?; - let end_pos = ctx.resolve_label(end_label)?; - let offset = (end_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, end_label); self.emit_statement(&wh.body, ctx)?; - let start_pos = ctx.resolve_label(start_label)?; - let offset = (start_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(start_label); + ctx.labels.label_map.insert(end_label, ctx.bytecode.len()); ctx.pop_label_scopes(n_labeled); ctx.pop_loop(); Ok(None)