diff --git a/src/compiler.rs b/src/compiler.rs index 955a308..a6c79ef 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -747,7 +747,6 @@ impl<'a> Compiler<'a> { } // if we get here--not having jumped on no match--we're matched; jump the "no match" code - self.match_depth = match_depth + members.len(); let jump_idx = self.jump_stub(Op::Jump); // patch up the previous no match jumps to jump to clean-up code @@ -766,38 +765,46 @@ impl<'a> Compiler<'a> { // patch up the yes-matches unconditional jump self.patch_jump(jump_idx, self.len() - jump_idx - 3); + + // finally, for any further matches (e.g. nested lists/tuples) + // add increase the match depth, since we've added a bunch + // of bindings to the stack + self.match_depth = match_depth + members.len(); } ListPattern(members) => { self.emit_op(Op::MatchList); self.emit_byte(members.len()); - self.emit_op(Op::JumpIfNoMatch); - let before_load_list_idx = self.len(); - self.emit_byte(0xff); + let before_load_tup_idx = self.jump_stub(Op::JumpIfNoMatch); + let mut jump_idxes = vec![]; - self.match_depth += members.len(); + let match_depth = self.match_depth; + self.match_depth = members.len(); + self.emit_op(Op::LoadList); self.stack_depth += members.len(); + 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); - jump_idxes.push(self.len()); - self.emit_byte(0xff); + jump_idxes.push(self.jump_stub(Op::JumpIfNoMatch)); } - self.emit_op(Op::Jump); - let jump_idx = self.len(); - self.emit_byte(0xff); + + let jump_idx = self.jump_stub(Op::Jump); + for idx in jump_idxes { - self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1; + self.patch_jump(idx, self.len() - idx - 2) } - for _ in 0..members.len() { - self.emit_op(Op::Pop); - } - self.chunk.bytecode[before_load_list_idx] = - (self.len() - before_load_list_idx) as u8 - 1; - self.chunk.bytecode[jump_idx] = (self.len() - jump_idx) as u8 - 1; + + self.emit_op(Op::PopN); + self.emit_byte(members.len()); + + self.patch_jump(before_load_tup_idx, self.len() - before_load_tup_idx - 3); + + self.patch_jump(jump_idx, self.len() - jump_idx - 3); + + self.match_depth = match_depth + members.len(); } DictPattern(pairs) => { self.emit_op(Op::MatchDict);