From f6bfe0975b0695f8108f88bb7c3353fb4f8dee76 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Wed, 18 Jun 2025 17:50:30 -0400 Subject: [PATCH] update repeat w/ new jumps --- src/compiler.rs | 58 +++++++++++++------------------------------------ src/main.rs | 9 +++----- 2 files changed, 18 insertions(+), 49 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 210b727..f382d88 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1112,8 +1112,7 @@ impl<'a> Compiler<'a> { MatchClause(..) => unreachable!(), Fn(name, body, doc) => { let name = if name.is_empty() { "anonymous" } else { name }; - // first, declare the function - // TODO: or, check if the function has already been declared! + let FnBody(fn_body) = &body.as_ref().0 else { unreachable!() }; @@ -1155,35 +1154,26 @@ impl<'a> Compiler<'a> { compiler.emit_op(Op::MatchDepth); compiler.emit_byte(compiler.match_depth); compiler.visit(member); - compiler.emit_op(Op::JumpIfNoMatch); - tup_jump_idxes.push(compiler.len()); - compiler.emit_byte(0xff); + tup_jump_idxes.push(compiler.stub_jump(Op::JumpIfNoMatch)); } if pattern.is_empty() { compiler.emit_op(Op::Match); } - compiler.emit_op(Op::Jump); - let jump_idx = compiler.len(); - compiler.emit_byte(0xff); + let jump_idx = compiler.stub_jump(Op::Jump); for idx in tup_jump_idxes { - compiler.chunk.bytecode[idx] = compiler.len() as u8 - idx as u8 - 2; + compiler.patch_jump(idx, compiler.len() - idx - 3); } for _ in 0..arity { compiler.emit_op(Op::Pop); } - compiler.chunk.bytecode[jump_idx] = compiler.len() as u8 - jump_idx as u8 - 1; + compiler.patch_jump(jump_idx, compiler.len() - jump_idx - 3); let mut no_match_jumps = vec![]; - compiler.emit_op(Op::JumpIfNoMatch); - // let jnm_idx = compiler.len(); - no_match_jumps.push(compiler.len()); - compiler.emit_byte(0xff); + no_match_jumps.push(compiler.stub_jump(Op::JumpIfNoMatch)); if guard.is_some() { let guard_expr: &'static Spanned = Box::leak(Box::new(guard.clone().unwrap())); compiler.visit(guard_expr); - compiler.emit_op(Op::JumpIfFalse); - no_match_jumps.push(self.len()); - compiler.emit_byte(0xff); + no_match_jumps.push(compiler.stub_jump(Op::JumpIfFalse)); compiler.stack_depth -= 1; } compiler.visit(clause_body); @@ -1196,15 +1186,12 @@ impl<'a> Compiler<'a> { break; } } - while compiler.stack_depth > 0 { - compiler.pop(); - } + compiler.pop_n(compiler.stack_depth); compiler.stack_depth = 0; compiler.emit_op(Op::Return); for idx in no_match_jumps { - compiler.chunk.bytecode[idx] = compiler.len() as u8 - idx as u8 - 1; + compiler.patch_jump(idx, compiler.len() - idx - 3); } - // compiler.chunk.bytecode[jnm_idx] = compiler.len() as u8 - jnm_idx as u8 - 1; compiler.scope_depth -= 1; std::mem::swap(&mut compiler.upvalues, &mut upvalues); @@ -1245,42 +1232,27 @@ impl<'a> Compiler<'a> { self.bind(name); } FnBody(_) => unreachable!(), - // TODO: add a check to make sure times >= 0 - // TODO: fix this so that the algorithm is actually correct - // * truncate - // * check that it's 0 or more, panic if not - // * jump if 0 to end of loop - // * body - // * pop - // * decrement counter (which is now at the top of the stack) - // * jump back to jump if 0 instruction Repeat(times, body) => { self.visit(times); self.emit_op(Op::Truncate); // skip the decrement the first time self.emit_op(Op::Jump); + self.emit_byte(0); self.emit_byte(1); // begin repeat self.emit_op(Op::Decrement); let repeat_begin = self.len(); self.emit_op(Op::Duplicate); - // self.stack_depth += 1; - self.emit_op(Op::JumpIfZero); - self.emit_byte(0xff); + let jiz_idx = self.stub_jump(Op::JumpIfZero); // compile the body self.visit(body); // pop whatever value the body returns self.pop(); - // self.emit_op(Op::Pop); - self.emit_op(Op::JumpBack); + let jump_back = self.stub_jump(Op::JumpBack); // set jump points - let repeat_end = self.len(); - self.emit_byte(repeat_end - repeat_begin); - self.chunk.bytecode[repeat_begin + 2] = (repeat_end - repeat_begin - 2) as u8; - // pop the counter - // self.pop(); - // self.emit_op(Op::Pop); - // and emit nil + self.patch_jump(jump_back, self.len() - repeat_begin - 2); + self.patch_jump(jiz_idx, self.len() - repeat_begin - 4); + self.pop(); self.emit_constant(Value::Nil); } Loop(value, clauses) => { diff --git a/src/main.rs b/src/main.rs index d02f13c..529e77f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,13 +73,10 @@ pub fn run(src: &'static str) { } pub fn main() { - // env::set_var("RUST_BACKTRACE", "1"); + env::set_var("RUST_BACKTRACE", "1"); let src = " -match :foo with { - :foo if false -> :bar - :bar -> :baz - :foo if true -> :quux - :thing -> :oops +repeat 4 { + :foo } "; run(src);