start major work on function compilation
This commit is contained in:
parent
34ab24c4c9
commit
b6f9b35b4c
104
src/compiler.rs
104
src/compiler.rs
|
@ -6,8 +6,8 @@ use chumsky::prelude::SimpleSpan;
|
|||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::FromPrimitive;
|
||||
use std::cell::OnceCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::string;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
pub enum Op {
|
||||
|
@ -948,40 +948,120 @@ impl Compiler {
|
|||
Fn(name, body, doc) => {
|
||||
// first, declare the function
|
||||
// TODO: or, check if the function has already been declared!
|
||||
let init_val = Value::Fn(Rc::new(OnceCell::new()));
|
||||
self.emit_constant(init_val);
|
||||
self.bind(name);
|
||||
|
||||
let FnBody(fn_body) = &body.as_ref().0 else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let mut chunks = vec![];
|
||||
let mut compilers: HashMap<usize, Compiler> = HashMap::new();
|
||||
|
||||
for clause in fn_body {
|
||||
let MatchClause(pattern, guard, clause_body) = &clause.0 else {
|
||||
let MatchClause(pattern, _, clause_body) = &clause.0 else {
|
||||
unreachable!()
|
||||
};
|
||||
let TuplePattern(pattern) = &pattern.0 else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let arity = pattern.len();
|
||||
|
||||
let compiler = match compilers.get_mut(&arity) {
|
||||
Some(compiler) => compiler,
|
||||
None => {
|
||||
let mut compiler = Compiler::new(clause, self.name, self.src);
|
||||
compiler.emit_op(Op::Load);
|
||||
compiler.stack_depth += arity;
|
||||
compiler.scope_depth += 1;
|
||||
compiler.emit_op(Op::ResetMatch);
|
||||
compiler.match_depth = arity;
|
||||
compilers.insert(arity, compiler);
|
||||
compilers.get_mut(&arity).unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let mut tup_jump_idxes = vec![];
|
||||
for member in pattern {
|
||||
compiler.match_depth -= 1;
|
||||
compiler.emit_op(Op::MatchDepth);
|
||||
compiler.emit_byte(compiler.match_depth);
|
||||
compiler.visit(member);
|
||||
compiler.emit_op(Op::JumpIfNoMatch);
|
||||
tup_jump_idxes.push(compiler.len());
|
||||
compiler.emit_byte(0xff);
|
||||
}
|
||||
compiler.emit_op(Op::Jump);
|
||||
let jump_idx = compiler.len();
|
||||
compiler.emit_byte(0xff);
|
||||
for idx in tup_jump_idxes {
|
||||
compiler.chunk.bytecode[idx] = compiler.len() as u8 - idx as u8 - 2;
|
||||
}
|
||||
for _ in 0..arity {
|
||||
compiler.emit_op(Op::Pop);
|
||||
}
|
||||
compiler.chunk.bytecode[jump_idx] = compiler.len() as u8 - jump_idx as u8 - 1;
|
||||
compiler.emit_op(Op::JumpIfNoMatch);
|
||||
let jnm_idx = compiler.len();
|
||||
compiler.emit_byte(0xff);
|
||||
compiler.visit(clause_body);
|
||||
compiler.emit_op(Op::Store);
|
||||
compiler.scope_depth -= 1;
|
||||
while let Some(binding) = compiler.bindings.last() {
|
||||
if binding.depth > compiler.scope_depth {
|
||||
compiler.bindings.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while compiler.stack_depth > arity {
|
||||
compiler.pop();
|
||||
}
|
||||
compiler.stack_depth = 0;
|
||||
compiler.emit_op(Op::Jump);
|
||||
compiler.emit_byte(0xff);
|
||||
compiler.chunk.bytecode[jnm_idx] = compiler.len() as u8 - jnm_idx as u8;
|
||||
compiler.scope_depth -= 1;
|
||||
}
|
||||
// compile the function
|
||||
let mut compiler = Compiler::new(body, self.name, self.src);
|
||||
compiler.compile();
|
||||
if crate::DEBUG_COMPILE {
|
||||
println!("==function: {name}==");
|
||||
for (arity, compiler) in compilers.iter() {
|
||||
println!("==function clause: {name}/{arity}==");
|
||||
compiler.disassemble();
|
||||
}
|
||||
}
|
||||
|
||||
// let mut the_chunks = vec![];
|
||||
|
||||
// for (arity, chunks) in chunks.iter() {
|
||||
// let mut jump_len: u8 = 0;
|
||||
// for chunk in chunks.iter().rev() {
|
||||
// let chunk_len = chunk.bytecode.len();
|
||||
// chunk.bytecode[chunk_len - 1] = jump_len;
|
||||
// jump_len += chunk_len as u8;
|
||||
// }
|
||||
// let the_chunk = chunks.into_iter().fold(vec![], |chunks, chunk| {
|
||||
// chunks.append();
|
||||
// chunks
|
||||
// });
|
||||
// the_chunks.push((arity, the_chunk))
|
||||
// }
|
||||
//
|
||||
//
|
||||
let mut the_chunks = vec![];
|
||||
|
||||
for (arity, compiler) in compilers.into_iter() {
|
||||
the_chunks.push((arity as u8, compiler.chunk));
|
||||
}
|
||||
|
||||
let lfn = crate::value::LFn {
|
||||
name,
|
||||
doc: *doc,
|
||||
chunks,
|
||||
chunks: the_chunks,
|
||||
closed: vec![],
|
||||
};
|
||||
|
||||
let cell = OnceCell::new();
|
||||
let _ = cell.set(lfn);
|
||||
let init_val = Value::Fn(Rc::new(cell));
|
||||
self.emit_constant(init_val);
|
||||
self.bind(name);
|
||||
// TODO: close over everything accessed in the function
|
||||
|
||||
// TODO: pull the function off the stack, and set the OnceCell.
|
||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -57,25 +57,26 @@ pub fn run(src: &'static str) {
|
|||
println!("\n\n")
|
||||
}
|
||||
|
||||
if DEBUG_RUN {
|
||||
println!("=== vm run: test ===");
|
||||
}
|
||||
// if DEBUG_RUN {
|
||||
// println!("=== vm run: test ===");
|
||||
// }
|
||||
|
||||
let mut vm = Vm::new(&compiler.chunk);
|
||||
let result = vm.run();
|
||||
let output = match result {
|
||||
Ok(val) => val.show(&compiler.chunk),
|
||||
Err(panic) => format!("Ludus panicked! {panic}"),
|
||||
};
|
||||
vm.print_stack();
|
||||
println!("{output}");
|
||||
// let mut vm = Vm::new(&compiler.chunk);
|
||||
// let result = vm.run();
|
||||
// let output = match result {
|
||||
// Ok(val) => val.show(&compiler.chunk),
|
||||
// Err(panic) => format!("Ludus panicked! {panic}"),
|
||||
// };
|
||||
// vm.print_stack();
|
||||
// println!("{output}");
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
let src = "
|
||||
let (x as :keyword, y as :number) = (:ok, 42)
|
||||
[x, y]
|
||||
fn foo () -> :bar
|
||||
|
||||
foo ()
|
||||
";
|
||||
run(src);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user