guards work in match forms

This commit is contained in:
Scott Richmond 2025-06-04 18:55:40 -04:00
parent 01ce043379
commit 0f8645d2eb
2 changed files with 22 additions and 6 deletions

View File

@ -972,7 +972,7 @@ impl<'a> Compiler<'a> {
let mut upvalues = vec![];
for clause in fn_body {
let MatchClause(pattern, _, clause_body) = &clause.0 else {
let MatchClause(pattern, guard, clause_body) = &clause.0 else {
unreachable!()
};
let TuplePattern(pattern) = &pattern.0 else {
@ -1021,9 +1021,20 @@ impl<'a> Compiler<'a> {
compiler.emit_op(Op::Pop);
}
compiler.chunk.bytecode[jump_idx] = compiler.len() as u8 - jump_idx as u8 - 1;
let mut no_match_jumps = vec![];
compiler.emit_op(Op::JumpIfNoMatch);
let jnm_idx = compiler.len();
// let jnm_idx = compiler.len();
no_match_jumps.push(compiler.len());
compiler.emit_byte(0xff);
if guard.is_some() {
let guard_expr: &'static Spanned<Ast> =
Box::leak(Box::new(guard.clone().unwrap()));
compiler.visit(guard_expr);
compiler.emit_op(Op::JumpIfFalse);
no_match_jumps.push(self.len());
compiler.emit_byte(0xff);
compiler.stack_depth -= 1;
}
compiler.visit(clause_body);
compiler.emit_op(Op::Store);
compiler.scope_depth -= 1;
@ -1039,7 +1050,10 @@ impl<'a> Compiler<'a> {
}
compiler.stack_depth = 0;
compiler.emit_op(Op::Return);
compiler.chunk.bytecode[jnm_idx] = compiler.len() as u8 - jnm_idx as u8 - 1;
for idx in no_match_jumps {
compiler.chunk.bytecode[idx] = compiler.len() as u8 - idx as u8 - 1;
}
// compiler.chunk.bytecode[jnm_idx] = compiler.len() as u8 - jnm_idx as u8 - 1;
compiler.scope_depth -= 1;
std::mem::swap(&mut compiler.upvalues, &mut upvalues);

View File

@ -76,10 +76,12 @@ pub fn run(src: &'static str) {
pub fn main() {
env::set_var("RUST_BACKTRACE", "1");
let src = "
match :foo with {
:foo if eq? (1, 2) -> :no
x if eq? (x, :foo) -> :yes
fn foo {
() if false -> :no
() if true -> :yes
}
foo ()
";
run(src);
}