Compare commits

..

No commits in common. "5ae47428404cb4199291b29ec6351de6f2fa55e0" and "2ce2e2c2d3a8a169048dc2dc02ecaa0964df8e90" have entirely different histories.

2 changed files with 56 additions and 49 deletions

View File

@ -5,7 +5,6 @@ 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;
@ -912,41 +911,61 @@ 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);
no_match_jumps.push(self.len()); let jnm_jump_idx = self.len();
self.emit_byte(0xff); self.emit_byte(0xff);
if guard.is_some() { // conditional compilation of guards
let guard_expr: &'static Spanned<Ast> = // hard to DRY out
Box::leak(Box::new(guard.clone().unwrap())); match guard.as_ref() {
self.visit(guard_expr); Some(_) => todo!(),
self.emit_op(Op::JumpIfFalse); // Some(expr) => {
no_match_jumps.push(self.len()); // self.visit(expr);
self.emit_byte(0xff); // self.emit_op(Op::JumpIfFalse);
self.stack_depth -= 1; // let jif_idx = self.len();
} // self.emit_byte(0xff);
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.bindings.pop(); // self.pop();
} else { // // self.emit_op(Op::Pop);
break; // 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.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);
self.chunk.bytecode[jnm_jump_idx] =
self.len() as u8 - jnm_jump_idx as u8 - 1;
} }
} }
while self.stack_depth > stack_depth {
self.pop();
}
self.emit_op(Op::Jump);
jump_idxes.push(self.len());
self.emit_byte(0xff);
for idx in no_match_jumps {
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
}
} }
self.emit_op(Op::PanicNoMatch); self.emit_op(Op::PanicNoMatch);
for idx in jump_idxes { for idx in jump_idxes {
@ -972,7 +991,7 @@ impl<'a> Compiler<'a> {
let mut upvalues = vec![]; let mut upvalues = vec![];
for clause in fn_body { for clause in fn_body {
let MatchClause(pattern, guard, clause_body) = &clause.0 else { let MatchClause(pattern, _, clause_body) = &clause.0 else {
unreachable!() unreachable!()
}; };
let TuplePattern(pattern) = &pattern.0 else { let TuplePattern(pattern) = &pattern.0 else {
@ -1021,20 +1040,9 @@ impl<'a> Compiler<'a> {
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.chunk.bytecode[jump_idx] = compiler.len() as u8 - jump_idx as u8 - 1;
let mut no_match_jumps = vec![];
compiler.emit_op(Op::JumpIfNoMatch); 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); 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.visit(clause_body);
compiler.emit_op(Op::Store); compiler.emit_op(Op::Store);
compiler.scope_depth -= 1; compiler.scope_depth -= 1;
@ -1050,10 +1058,7 @@ impl<'a> Compiler<'a> {
} }
compiler.stack_depth = 0; compiler.stack_depth = 0;
compiler.emit_op(Op::Return); compiler.emit_op(Op::Return);
for idx in no_match_jumps { compiler.chunk.bytecode[jnm_idx] = compiler.len() as u8 - jnm_idx as u8 - 1;
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; compiler.scope_depth -= 1;
std::mem::swap(&mut compiler.upvalues, &mut upvalues); std::mem::swap(&mut compiler.upvalues, &mut upvalues);
@ -1083,6 +1088,7 @@ impl<'a> Compiler<'a> {
self.emit_constant(init_val); self.emit_constant(init_val);
self.bind(name); self.bind(name);
// TODO: close over everything accessed in the function
for upvalue in upvalues { for upvalue in upvalues {
self.emit_op(Op::SetUpvalue); self.emit_op(Op::SetUpvalue);
self.emit_byte(upvalue.stack_pos); self.emit_byte(upvalue.stack_pos);

View File

@ -76,11 +76,12 @@ 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 = "
fn foo () -> :foo let bar = 42
let foo = {
let (1, 2, 3) = (1, 2, 3)
}
foo foo
"; ";
run(src); run(src);
} }