Compare commits

..

3 Commits

Author SHA1 Message Date
Scott Richmond
4f7ba56d1f properly compile when expressions? 2025-05-23 17:59:09 -04:00
Scott Richmond
ce1612a30c compiler: decouple stack & bindings resetting 2025-05-23 13:43:35 -04:00
Scott Richmond
1ef0da5dd1 compiler: decouple stack & bindings resetting 2025-05-23 13:42:29 -04:00
3 changed files with 47 additions and 45 deletions

View File

@ -355,6 +355,7 @@ impl Compiler {
}
Block(lines) => {
self.scope_depth += 1;
let stack_depth = self.stack_depth;
for expr in lines.iter().take(lines.len() - 1) {
if is_binding(expr) {
self.visit(expr);
@ -365,6 +366,7 @@ impl Compiler {
}
}
let last_expr = lines.last().unwrap();
// TODO: make sure this actually returns the RHS of the expression
if is_binding(last_expr) {
self.visit(last_expr);
self.emit_op(Op::Duplicate);
@ -375,17 +377,19 @@ impl Compiler {
}
self.emit_op(Op::Store);
self.scope_depth -= 1;
// reset bindings
while let Some(binding) = self.bindings.last() {
if binding.depth > self.scope_depth {
self.pop();
// self.emit_op(Op::Pop);
self.bindings.pop();
let binding = self.bindings.pop().unwrap();
println!("popping: {:?}", binding);
} else {
break;
}
}
// reset stack
while self.stack_depth > stack_depth + 1 {
self.pop();
// self.emit_op(Op::Pop);
}
self.emit_op(Op::Load);
}
If(cond, then, r#else) => {
@ -600,24 +604,24 @@ impl Compiler {
When(clauses) => {
let mut jump_idxes = vec![];
let mut clauses = clauses.iter();
let stack_depth = self.stack_depth;
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);
self.stack_depth -= 1;
self.visit(body);
self.emit_op(Op::Jump);
jump_idxes.push(self.len());
self.emit_byte(0xff);
self.chunk.bytecode[jif_jump_idx] = self.len() as u8 - jif_jump_idx as u8 - 1;
self.stack_depth = stack_depth;
self.stack_depth -= 1;
}
self.stack_depth += 1;
self.emit_op(Op::PanicNoWhen);
for idx in jump_idxes {
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 + 1;
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
}
self.stack_depth += 1;
}
WhenClause(..) => unreachable!(),
Match(scrutinee, clauses) => {
@ -635,43 +639,45 @@ impl Compiler {
// conditional compilation of guards
// hard to DRY out
match guard.as_ref() {
Some(expr) => {
self.visit(expr);
self.emit_op(Op::JumpIfFalse);
let jif_idx = self.len();
self.emit_byte(0xff);
self.visit(body);
self.emit_op(Op::Store);
self.scope_depth -= 1;
while let Some(binding) = self.bindings.last() {
if binding.depth > self.scope_depth {
self.pop();
// self.emit_op(Op::Pop);
self.bindings.pop();
} else {
break;
}
}
self.emit_op(Op::Jump);
jump_idxes.push(self.len());
self.emit_byte(0xff);
self.chunk.bytecode[jnm_jump_idx] =
self.len() as u8 - jnm_jump_idx as u8 - 1;
self.chunk.bytecode[jif_idx] = self.len() as u8 - jif_idx as u8 - 1;
}
Some(_) => todo!(),
// Some(expr) => {
// self.visit(expr);
// self.emit_op(Op::JumpIfFalse);
// let jif_idx = self.len();
// self.emit_byte(0xff);
// self.visit(body);
// self.emit_op(Op::Store);
// self.scope_depth -= 1;
// while let Some(binding) = self.bindings.last() {
// if binding.depth > self.scope_depth {
// self.pop();
// // self.emit_op(Op::Pop);
// self.bindings.pop();
// } else {
// break;
// }
// }
// self.emit_op(Op::Jump);
// jump_idxes.push(self.len());
// self.emit_byte(0xff);
// self.chunk.bytecode[jnm_jump_idx] =
// self.len() as u8 - jnm_jump_idx as u8 - 1;
// self.chunk.bytecode[jif_idx] = self.len() as u8 - jif_idx as u8 - 1;
// }
None => {
self.visit(body);
self.emit_op(Op::Store);
self.scope_depth -= 1;
while let Some(binding) = self.bindings.last() {
if binding.depth > self.scope_depth {
self.pop();
// self.emit_op(Op::Pop);
self.bindings.pop();
} else {
break;
}
}
while self.stack_depth > stack_depth {
self.pop();
}
self.emit_op(Op::Jump);
jump_idxes.push(self.len());
self.emit_byte(0xff);
@ -679,14 +685,14 @@ impl Compiler {
self.len() as u8 - jnm_jump_idx as u8 - 1;
}
}
self.stack_depth = stack_depth;
}
self.emit_op(Op::PanicNoMatch);
for idx in jump_idxes {
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
}
while self.stack_depth > stack_depth {
self.pop();
// self.emit_op(Op::Pop);
}
self.emit_op(Op::Load);
self.stack_depth += 1;
}

View File

@ -67,18 +67,14 @@ pub fn run(src: &'static str) {
Ok(val) => val.show(&compiler.chunk),
Err(panic) => format!("{:?}", panic),
};
vm.print_stack();
println!("{output}");
}
pub fn main() {
env::set_var("RUST_BACKTRACE", "1");
let src = "
match (-1, (2)) with {
(0) -> :nope
(1) -> :yup
(x, (1)) -> :thing
(x, (y)) -> y
}
";
run(src);
}

View File

@ -65,7 +65,7 @@ impl<'a> Vm<'a> {
self.stack.last().unwrap()
}
fn print_stack(&self) {
pub fn print_stack(&self) {
let inner = self
.stack
.iter()