guards work in match forms

This commit is contained in:
Scott Richmond 2025-06-04 18:51:07 -04:00
parent 2ce2e2c2d3
commit 01ce043379
2 changed files with 32 additions and 53 deletions

View File

@ -5,6 +5,7 @@ use crate::value::*;
use chumsky::prelude::SimpleSpan; use chumsky::prelude::SimpleSpan;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use std::borrow::Borrow;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@ -911,41 +912,22 @@ impl<'a> Compiler<'a> {
let mut jump_idxes = vec![]; let mut jump_idxes = vec![];
let mut clauses = clauses.iter(); let mut clauses = clauses.iter();
while let Some((MatchClause(pattern, guard, body), _)) = clauses.next() { while let Some((MatchClause(pattern, guard, body), _)) = clauses.next() {
let mut no_match_jumps = vec![];
self.scope_depth += 1; self.scope_depth += 1;
self.match_depth = 0; self.match_depth = 0;
self.visit(pattern); self.visit(pattern);
self.emit_op(Op::JumpIfNoMatch); self.emit_op(Op::JumpIfNoMatch);
let jnm_jump_idx = self.len(); no_match_jumps.push(self.len());
self.emit_byte(0xff); self.emit_byte(0xff);
// conditional compilation of guards if guard.is_some() {
// hard to DRY out let guard_expr: &'static Spanned<Ast> =
match guard.as_ref() { Box::leak(Box::new(guard.clone().unwrap()));
Some(_) => todo!(), self.visit(guard_expr);
// Some(expr) => { self.emit_op(Op::JumpIfFalse);
// self.visit(expr); no_match_jumps.push(self.len());
// self.emit_op(Op::JumpIfFalse); self.emit_byte(0xff);
// let jif_idx = self.len(); self.stack_depth -= 1;
// 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.visit(body);
self.emit_op(Op::Store); self.emit_op(Op::Store);
self.scope_depth -= 1; self.scope_depth -= 1;
@ -962,9 +944,8 @@ impl<'a> Compiler<'a> {
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[jnm_jump_idx] = for idx in no_match_jumps {
self.len() as u8 - jnm_jump_idx as u8 - 1; self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
}
} }
} }
self.emit_op(Op::PanicNoMatch); self.emit_op(Op::PanicNoMatch);

View File

@ -76,12 +76,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 = "
let bar = 42 match :foo with {
let foo = { :foo if eq? (1, 2) -> :no
let (1, 2, 3) = (1, 2, 3) x if eq? (x, :foo) -> :yes
} }
foo
"; ";
run(src); run(src);
} }