update repeat w/ new jumps
This commit is contained in:
parent
ffe5d2ad61
commit
f6bfe0975b
|
@ -1112,8 +1112,7 @@ impl<'a> Compiler<'a> {
|
||||||
MatchClause(..) => unreachable!(),
|
MatchClause(..) => unreachable!(),
|
||||||
Fn(name, body, doc) => {
|
Fn(name, body, doc) => {
|
||||||
let name = if name.is_empty() { "anonymous" } else { name };
|
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 {
|
let FnBody(fn_body) = &body.as_ref().0 else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -1155,35 +1154,26 @@ impl<'a> Compiler<'a> {
|
||||||
compiler.emit_op(Op::MatchDepth);
|
compiler.emit_op(Op::MatchDepth);
|
||||||
compiler.emit_byte(compiler.match_depth);
|
compiler.emit_byte(compiler.match_depth);
|
||||||
compiler.visit(member);
|
compiler.visit(member);
|
||||||
compiler.emit_op(Op::JumpIfNoMatch);
|
tup_jump_idxes.push(compiler.stub_jump(Op::JumpIfNoMatch));
|
||||||
tup_jump_idxes.push(compiler.len());
|
|
||||||
compiler.emit_byte(0xff);
|
|
||||||
}
|
}
|
||||||
if pattern.is_empty() {
|
if pattern.is_empty() {
|
||||||
compiler.emit_op(Op::Match);
|
compiler.emit_op(Op::Match);
|
||||||
}
|
}
|
||||||
compiler.emit_op(Op::Jump);
|
let jump_idx = compiler.stub_jump(Op::Jump);
|
||||||
let jump_idx = compiler.len();
|
|
||||||
compiler.emit_byte(0xff);
|
|
||||||
for idx in tup_jump_idxes {
|
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 {
|
for _ in 0..arity {
|
||||||
compiler.emit_op(Op::Pop);
|
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![];
|
let mut no_match_jumps = vec![];
|
||||||
compiler.emit_op(Op::JumpIfNoMatch);
|
no_match_jumps.push(compiler.stub_jump(Op::JumpIfNoMatch));
|
||||||
// let jnm_idx = compiler.len();
|
|
||||||
no_match_jumps.push(compiler.len());
|
|
||||||
compiler.emit_byte(0xff);
|
|
||||||
if guard.is_some() {
|
if guard.is_some() {
|
||||||
let guard_expr: &'static Spanned<Ast> =
|
let guard_expr: &'static Spanned<Ast> =
|
||||||
Box::leak(Box::new(guard.clone().unwrap()));
|
Box::leak(Box::new(guard.clone().unwrap()));
|
||||||
compiler.visit(guard_expr);
|
compiler.visit(guard_expr);
|
||||||
compiler.emit_op(Op::JumpIfFalse);
|
no_match_jumps.push(compiler.stub_jump(Op::JumpIfFalse));
|
||||||
no_match_jumps.push(self.len());
|
|
||||||
compiler.emit_byte(0xff);
|
|
||||||
compiler.stack_depth -= 1;
|
compiler.stack_depth -= 1;
|
||||||
}
|
}
|
||||||
compiler.visit(clause_body);
|
compiler.visit(clause_body);
|
||||||
|
@ -1196,15 +1186,12 @@ impl<'a> Compiler<'a> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while compiler.stack_depth > 0 {
|
compiler.pop_n(compiler.stack_depth);
|
||||||
compiler.pop();
|
|
||||||
}
|
|
||||||
compiler.stack_depth = 0;
|
compiler.stack_depth = 0;
|
||||||
compiler.emit_op(Op::Return);
|
compiler.emit_op(Op::Return);
|
||||||
for idx in no_match_jumps {
|
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;
|
compiler.scope_depth -= 1;
|
||||||
|
|
||||||
std::mem::swap(&mut compiler.upvalues, &mut upvalues);
|
std::mem::swap(&mut compiler.upvalues, &mut upvalues);
|
||||||
|
@ -1245,42 +1232,27 @@ impl<'a> Compiler<'a> {
|
||||||
self.bind(name);
|
self.bind(name);
|
||||||
}
|
}
|
||||||
FnBody(_) => unreachable!(),
|
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) => {
|
Repeat(times, body) => {
|
||||||
self.visit(times);
|
self.visit(times);
|
||||||
self.emit_op(Op::Truncate);
|
self.emit_op(Op::Truncate);
|
||||||
// skip the decrement the first time
|
// skip the decrement the first time
|
||||||
self.emit_op(Op::Jump);
|
self.emit_op(Op::Jump);
|
||||||
|
self.emit_byte(0);
|
||||||
self.emit_byte(1);
|
self.emit_byte(1);
|
||||||
// begin repeat
|
// begin repeat
|
||||||
self.emit_op(Op::Decrement);
|
self.emit_op(Op::Decrement);
|
||||||
let repeat_begin = self.len();
|
let repeat_begin = self.len();
|
||||||
self.emit_op(Op::Duplicate);
|
self.emit_op(Op::Duplicate);
|
||||||
// self.stack_depth += 1;
|
let jiz_idx = self.stub_jump(Op::JumpIfZero);
|
||||||
self.emit_op(Op::JumpIfZero);
|
|
||||||
self.emit_byte(0xff);
|
|
||||||
// compile the body
|
// compile the body
|
||||||
self.visit(body);
|
self.visit(body);
|
||||||
// pop whatever value the body returns
|
// pop whatever value the body returns
|
||||||
self.pop();
|
self.pop();
|
||||||
// self.emit_op(Op::Pop);
|
let jump_back = self.stub_jump(Op::JumpBack);
|
||||||
self.emit_op(Op::JumpBack);
|
|
||||||
// set jump points
|
// set jump points
|
||||||
let repeat_end = self.len();
|
self.patch_jump(jump_back, self.len() - repeat_begin - 2);
|
||||||
self.emit_byte(repeat_end - repeat_begin);
|
self.patch_jump(jiz_idx, self.len() - repeat_begin - 4);
|
||||||
self.chunk.bytecode[repeat_begin + 2] = (repeat_end - repeat_begin - 2) as u8;
|
self.pop();
|
||||||
// pop the counter
|
|
||||||
// self.pop();
|
|
||||||
// self.emit_op(Op::Pop);
|
|
||||||
// and emit nil
|
|
||||||
self.emit_constant(Value::Nil);
|
self.emit_constant(Value::Nil);
|
||||||
}
|
}
|
||||||
Loop(value, clauses) => {
|
Loop(value, clauses) => {
|
||||||
|
|
|
@ -73,13 +73,10 @@ pub fn run(src: &'static str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
// env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
let src = "
|
let src = "
|
||||||
match :foo with {
|
repeat 4 {
|
||||||
:foo if false -> :bar
|
:foo
|
||||||
:bar -> :baz
|
|
||||||
:foo if true -> :quux
|
|
||||||
:thing -> :oops
|
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user