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

View File

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

View File

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