diff --git a/src/compiler.rs b/src/compiler.rs index f382d88..87a6910 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1275,36 +1275,51 @@ impl<'a> Compiler<'a> { //next, compile each clause: let mut clauses = clauses.iter(); let mut jump_idxes = vec![]; - while let Some((Ast::MatchClause(pattern, _, body), _)) = clauses.next() { + while let Some((Ast::MatchClause(pattern, guard, body), _)) = clauses.next() { self.emit_op(Op::ResetMatch); self.scope_depth += 1; let (Ast::TuplePattern(members), _) = pattern.as_ref() else { unreachable!() }; self.match_depth = arity; - let mut tup_jump_idxes = vec![]; + let mut jnm_idxes = vec![]; for member in members { self.match_depth -= 1; self.emit_op(Op::MatchDepth); self.emit_byte(self.match_depth); self.visit(member); - self.emit_op(Op::JumpIfNoMatch); - tup_jump_idxes.push(self.len()); - self.emit_byte(0xff); + jnm_idxes.push(self.stub_jump(Op::JumpIfNoMatch)); + // self.emit_op(Op::JumpIfNoMatch); + // tup_jump_idxes.push(self.len()); + // self.emit_byte(0xff); } - self.emit_op(Op::Jump); - let jump_idx = self.len(); - self.emit_byte(0xff); - for idx in tup_jump_idxes { - self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 2; + // let jump_idx = self.stub_jump(Op::Jump); + // self.emit_op(Op::Jump); + // let jump_idx = self.len(); + // self.emit_byte(0xff); + // for idx in jnm_idxes { + // self.patch_jump(idx, self.len() - idx - 3); + // // self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 2; + // } + // self.emit_op(Op::PopN); + // self.emit_byte(arity); + // for _ in 0..arity { + // self.emit_op(Op::Pop); + // } + // self.patch_jump(jump_idx, self.len() - jump_idx - 3); + // self.chunk.bytecode[jump_idx] = (self.len() - jump_idx) as u8 - 1; + // let mut no_match_jumps = vec![]; + // no_match_jumps.push(self.stub_jump(Op::JumpIfNoMatch)); + // self.emit_op(Op::JumpIfNoMatch); + // let jnm_idx = self.len(); + // self.emit_byte(0xff); + if guard.is_some() { + let guard_expr: &'static Spanned = + Box::leak(Box::new(guard.clone().unwrap())); + self.visit(guard_expr); + jnm_idxes.push(self.stub_jump(Op::JumpIfFalse)); + self.stack_depth -= 1; } - for _ in 0..arity { - self.emit_op(Op::Pop); - } - self.chunk.bytecode[jump_idx] = (self.len() - jump_idx) as u8 - 1; - self.emit_op(Op::JumpIfNoMatch); - let jnm_idx = self.len(); - self.emit_byte(0xff); self.visit(body); self.emit_op(Op::Store); self.scope_depth -= 1; @@ -1315,23 +1330,29 @@ impl<'a> Compiler<'a> { break; } } - while self.stack_depth > stack_depth + arity { + while self.stack_depth > stack_depth { self.pop(); } - self.stack_depth -= arity; - self.emit_op(Op::Jump); - jump_idxes.push(self.len()); - self.emit_byte(0xff); - self.chunk.bytecode[jnm_idx] = (self.len() - jnm_idx) as u8; + // self.stack_depth -= arity; + jump_idxes.push(self.stub_jump(Op::Jump)); + // self.emit_op(Op::Jump); + // jump_idxes.push(self.len()); + // self.emit_byte(0xff); + for idx in jnm_idxes { + self.patch_jump(idx, self.len() - idx - 3); + } + // self.chunk.bytecode[jnm_idx] = (self.len() - jnm_idx) as u8; self.scope_depth -= 1; } self.emit_op(Op::PanicNoMatch); for idx in jump_idxes { - self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1; + self.patch_jump(idx, self.len() - idx - 3); + // self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1; } - self.emit_op(Op::PopN); - self.emit_byte(arity); + // self.emit_op(Op::PopN); + // self.emit_byte(arity); self.stack_depth -= arity; + // println!("Op::Load at end of loop at byte {}", self.len()); self.emit_op(Op::Load); self.stack_depth += 1; self.leave_loop(); @@ -1344,8 +1365,10 @@ impl<'a> Compiler<'a> { } self.emit_op(Op::PopN); self.emit_byte(self.loop_root()); - self.emit_op(Op::JumpBack); - self.emit_byte(self.len() - self.loop_idx()); + self.emit_op(Op::Load); + self.jump(Op::JumpBack, self.len() - self.loop_idx()); + // self.emit_op(Op::JumpBack); + // self.emit_byte(self.len() - self.loop_idx()); } Panic(msg) => { self.visit(msg); diff --git a/src/main.rs b/src/main.rs index 529e77f..a3184b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,8 +75,9 @@ pub fn run(src: &'static str) { pub fn main() { env::set_var("RUST_BACKTRACE", "1"); let src = " -repeat 4 { - :foo +loop (1) with { + (0) -> :done + (1) -> recur (0) } "; run(src);