match now uses new jump; micro-optimize pop_n
This commit is contained in:
parent
77f1627132
commit
23298c8538
|
@ -410,7 +410,7 @@ impl<'a> Compiler<'a> {
|
|||
self.chunk.bytecode.push(low);
|
||||
}
|
||||
|
||||
fn jump_stub(&mut self, op: Op) -> usize {
|
||||
fn stub_jump(&mut self, op: Op) -> usize {
|
||||
let out = self.chunk.bytecode.len();
|
||||
self.emit_op(op);
|
||||
self.emit_byte(0xff);
|
||||
|
@ -554,10 +554,16 @@ impl<'a> Compiler<'a> {
|
|||
}
|
||||
|
||||
fn pop_n(&mut self, n: usize) {
|
||||
match n {
|
||||
0 => (),
|
||||
1 => self.pop(),
|
||||
n => {
|
||||
self.emit_op(Op::PopN);
|
||||
self.emit_byte(n);
|
||||
self.stack_depth -= n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enter_loop(&mut self) {
|
||||
self.loop_info
|
||||
|
@ -657,10 +663,10 @@ impl<'a> Compiler<'a> {
|
|||
}
|
||||
If(cond, then, r#else) => {
|
||||
self.visit(cond);
|
||||
let jif_idx = self.jump_stub(Op::JumpIfFalse);
|
||||
let jif_idx = self.stub_jump(Op::JumpIfFalse);
|
||||
self.stack_depth -= 1;
|
||||
self.visit(then);
|
||||
let jump_idx = self.jump_stub(Op::Jump);
|
||||
let jump_idx = self.stub_jump(Op::Jump);
|
||||
self.visit(r#else);
|
||||
self.stack_depth -= 1;
|
||||
let end_idx = self.len();
|
||||
|
@ -722,7 +728,7 @@ impl<'a> Compiler<'a> {
|
|||
self.emit_op(Op::MatchTuple);
|
||||
self.emit_byte(members.len());
|
||||
// skip everything if tuple lengths don't match
|
||||
let before_load_tup_idx = self.jump_stub(Op::JumpIfNoMatch);
|
||||
let before_load_tup_idx = self.stub_jump(Op::JumpIfNoMatch);
|
||||
|
||||
// set up the per-member conditional logic
|
||||
let mut jump_idxes = vec![];
|
||||
|
@ -743,11 +749,11 @@ impl<'a> Compiler<'a> {
|
|||
// visit the pattern member
|
||||
self.visit(member);
|
||||
// and jump if there's no match
|
||||
jump_idxes.push(self.jump_stub(Op::JumpIfNoMatch));
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfNoMatch));
|
||||
}
|
||||
|
||||
// if we get here--not having jumped on no match--we're matched; jump the "no match" code
|
||||
let jump_idx = self.jump_stub(Op::Jump);
|
||||
let jump_idx = self.stub_jump(Op::Jump);
|
||||
|
||||
// patch up the previous no match jumps to jump to clean-up code
|
||||
for idx in jump_idxes {
|
||||
|
@ -774,7 +780,7 @@ impl<'a> Compiler<'a> {
|
|||
ListPattern(members) => {
|
||||
self.emit_op(Op::MatchList);
|
||||
self.emit_byte(members.len());
|
||||
let before_load_tup_idx = self.jump_stub(Op::JumpIfNoMatch);
|
||||
let before_load_tup_idx = self.stub_jump(Op::JumpIfNoMatch);
|
||||
|
||||
let mut jump_idxes = vec![];
|
||||
let match_depth = self.match_depth;
|
||||
|
@ -788,10 +794,10 @@ impl<'a> Compiler<'a> {
|
|||
self.emit_op(Op::MatchDepth);
|
||||
self.emit_byte(self.match_depth);
|
||||
self.visit(member);
|
||||
jump_idxes.push(self.jump_stub(Op::JumpIfNoMatch));
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfNoMatch));
|
||||
}
|
||||
|
||||
let jump_idx = self.jump_stub(Op::Jump);
|
||||
let jump_idx = self.stub_jump(Op::Jump);
|
||||
|
||||
for idx in jump_idxes {
|
||||
self.patch_jump(idx, self.len() - idx - 2)
|
||||
|
@ -809,7 +815,7 @@ impl<'a> Compiler<'a> {
|
|||
DictPattern(pairs) => {
|
||||
self.emit_op(Op::MatchDict);
|
||||
self.emit_byte(pairs.len());
|
||||
let before_load_dict_idx = self.jump_stub(Op::JumpIfNoMatch);
|
||||
let before_load_dict_idx = self.stub_jump(Op::JumpIfNoMatch);
|
||||
|
||||
let mut jump_idxes = vec![];
|
||||
let dict_stack_pos = self.stack_depth - 1;
|
||||
|
@ -821,9 +827,9 @@ impl<'a> Compiler<'a> {
|
|||
self.emit_op(Op::LoadDictValue);
|
||||
self.emit_byte(dict_stack_pos);
|
||||
self.visit(pattern);
|
||||
jump_idxes.push(self.jump_stub(Op::JumpIfNoMatch));
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfNoMatch));
|
||||
}
|
||||
let jump_idx = self.jump_stub(Op::Jump);
|
||||
let jump_idx = self.stub_jump(Op::Jump);
|
||||
|
||||
for idx in jump_idxes {
|
||||
self.patch_jump(idx, self.len() - idx - 2);
|
||||
|
@ -867,9 +873,7 @@ impl<'a> Compiler<'a> {
|
|||
self.emit_op(Op::MatchString);
|
||||
self.emit_byte(pattern_idx);
|
||||
|
||||
self.emit_op(Op::JumpIfNoMatch);
|
||||
let jnm_idx = self.len();
|
||||
self.emit_byte(0xff);
|
||||
let jnm_idx = self.stub_jump(Op::JumpIfNoMatch);
|
||||
|
||||
self.emit_op(Op::PushStringMatches);
|
||||
self.emit_byte(pattern_idx);
|
||||
|
@ -885,7 +889,7 @@ impl<'a> Compiler<'a> {
|
|||
self.stack_depth += 1;
|
||||
}
|
||||
|
||||
self.chunk.bytecode[jnm_idx] = (self.len() - jnm_idx - 1) as u8;
|
||||
self.patch_jump(jnm_idx, self.len() - jnm_idx - 3);
|
||||
}
|
||||
PairPattern(_, _) => unreachable!(),
|
||||
Tuple(members) => {
|
||||
|
@ -953,12 +957,10 @@ impl<'a> Compiler<'a> {
|
|||
for arg in args {
|
||||
self.visit(arg);
|
||||
self.emit_op(Op::Stash);
|
||||
self.emit_op(Op::JumpIfTrue);
|
||||
jump_idxes.push(self.len());
|
||||
self.emit_byte(0xff);
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfTrue));
|
||||
}
|
||||
for idx in jump_idxes {
|
||||
self.chunk.bytecode[idx] = (self.len() - idx + 2) as u8;
|
||||
self.patch_jump(idx, self.len() - idx);
|
||||
}
|
||||
self.emit_op(Op::Load);
|
||||
} else {
|
||||
|
@ -973,12 +975,10 @@ impl<'a> Compiler<'a> {
|
|||
for arg in args {
|
||||
self.visit(arg);
|
||||
self.emit_op(Op::Stash);
|
||||
self.emit_op(Op::JumpIfFalse);
|
||||
jump_idxes.push(self.len());
|
||||
self.emit_byte(0xff);
|
||||
jump_idxes.push(self.stub_jump(Op::JumpIfFalse));
|
||||
}
|
||||
for idx in jump_idxes {
|
||||
self.chunk.bytecode[idx] = (self.len() - idx + 2) as u8;
|
||||
self.patch_jump(idx, self.len() - idx);
|
||||
}
|
||||
self.emit_op(Op::Load);
|
||||
} else {
|
||||
|
@ -1048,20 +1048,16 @@ impl<'a> Compiler<'a> {
|
|||
let mut clauses = clauses.iter();
|
||||
while let Some((WhenClause(cond, body), _)) = clauses.next() {
|
||||
self.visit(cond.as_ref());
|
||||
self.emit_op(Op::JumpIfFalse);
|
||||
let jif_jump_idx = self.len();
|
||||
self.emit_byte(0xff);
|
||||
let jif_jump_idx = self.stub_jump(Op::JumpIfFalse);
|
||||
self.stack_depth -= 1;
|
||||
self.visit(body);
|
||||
self.stack_depth -= 1;
|
||||
self.emit_op(Op::Jump);
|
||||
jump_idxes.push(self.len());
|
||||
self.emit_byte(0xff);
|
||||
self.chunk.bytecode[jif_jump_idx] = (self.len() - jif_jump_idx) as u8 - 1;
|
||||
jump_idxes.push(self.stub_jump(Op::Jump));
|
||||
self.patch_jump(jif_jump_idx, self.len() - jif_jump_idx - 3);
|
||||
}
|
||||
self.emit_op(Op::PanicNoWhen);
|
||||
for idx in jump_idxes {
|
||||
self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1;
|
||||
self.patch_jump(idx, self.len() - idx - 3);
|
||||
}
|
||||
self.stack_depth += 1;
|
||||
}
|
||||
|
@ -1076,16 +1072,12 @@ impl<'a> Compiler<'a> {
|
|||
self.scope_depth += 1;
|
||||
self.match_depth = 0;
|
||||
self.visit(pattern);
|
||||
self.emit_op(Op::JumpIfNoMatch);
|
||||
no_match_jumps.push(self.len());
|
||||
self.emit_byte(0xff);
|
||||
no_match_jumps.push(self.stub_jump(Op::JumpIfNoMatch));
|
||||
if guard.is_some() {
|
||||
let guard_expr: &'static Spanned<Ast> =
|
||||
Box::leak(Box::new(guard.clone().unwrap()));
|
||||
self.visit(guard_expr);
|
||||
self.emit_op(Op::JumpIfFalse);
|
||||
no_match_jumps.push(self.len());
|
||||
self.emit_byte(0xff);
|
||||
no_match_jumps.push(self.stub_jump(Op::JumpIfFalse));
|
||||
self.stack_depth -= 1;
|
||||
}
|
||||
self.visit(body);
|
||||
|
@ -1098,23 +1090,22 @@ impl<'a> Compiler<'a> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
while self.stack_depth > stack_depth {
|
||||
self.pop();
|
||||
}
|
||||
self.emit_op(Op::Jump);
|
||||
jump_idxes.push(self.len());
|
||||
self.emit_byte(0xff);
|
||||
self.pop_n(self.stack_depth - stack_depth);
|
||||
jump_idxes.push(self.stub_jump(Op::Jump));
|
||||
for idx in no_match_jumps {
|
||||
self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1;
|
||||
self.patch_jump(idx, self.len() - idx - 3);
|
||||
}
|
||||
}
|
||||
self.emit_op(Op::PanicNoMatch);
|
||||
|
||||
for idx in jump_idxes {
|
||||
self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1;
|
||||
}
|
||||
while self.stack_depth > stack_depth {
|
||||
self.pop();
|
||||
self.patch_jump(idx, self.len() - idx - 3);
|
||||
// self.chunk.bytecode[idx] = (self.len() - idx) as u8 - 1;
|
||||
}
|
||||
self.pop_n(self.stack_depth - stack_depth);
|
||||
// while self.stack_depth > stack_depth {
|
||||
// self.pop();
|
||||
// }
|
||||
self.emit_op(Op::Load);
|
||||
self.stack_depth += 1;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,12 @@ pub fn run(src: &'static str) {
|
|||
pub fn main() {
|
||||
// env::set_var("RUST_BACKTRACE", "1");
|
||||
let src = "
|
||||
let #{:a 1, :b (2, #{:c 3})} = #{:a 1, :b (1, #{:c 3})}
|
||||
match :foo with {
|
||||
:foo if false -> :bar
|
||||
:bar -> :baz
|
||||
:foo if true -> :quux
|
||||
:thing -> :oops
|
||||
}
|
||||
";
|
||||
run(src);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user