maybe properly compile functions? need to start work on fn calls to test

This commit is contained in:
Scott Richmond 2025-06-01 20:01:42 -04:00
parent b6f9b35b4c
commit de3d7e834c
2 changed files with 41 additions and 47 deletions

View File

@ -62,6 +62,7 @@ pub enum Op {
Stringify,
Call,
Return,
Eq,
Add,
@ -183,6 +184,7 @@ impl std::fmt::Display for Op {
Not => "not",
Call => "call",
Return => "return",
};
write!(f, "{rep}")
}
@ -204,31 +206,42 @@ pub struct Chunk {
}
impl Chunk {
pub fn dissasemble_instr(&self, i: usize) {
let op = Op::from_u8(self.bytecode[i]).unwrap();
pub fn dissasemble_instr(&self, i: &mut usize) {
let op = Op::from_u8(self.bytecode[*i]).unwrap();
use Op::*;
match op {
Pop | Store | Stash | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch
| TypeOf | Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq
| Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic
| EmptyString | ConcatStrings | Stringify | MatchType => {
| EmptyString | ConcatStrings | Stringify | MatchType | Return => {
println!("{i:04}: {op}")
}
Constant | MatchConstant => {
let next = self.bytecode[i + 1];
let next = self.bytecode[*i + 1];
let value = &self.constants[next as usize].show(self);
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
*i += 1;
}
PushBinding | MatchTuple | MatchList | MatchDict | LoadDictValue | PushTuple
| PushDict | PushList | PushBox | Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch
| JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN | StoreAt | Call => {
let next = self.bytecode[i + 1];
let next = self.bytecode[*i + 1];
println!("{i:04}: {:16} {next:04}", op.to_string());
*i += 1;
}
}
}
pub fn dissasemble(&self) {
println!("IDX | CODE | INFO");
let mut i = 0;
while i < self.bytecode.len() {
self.dissasemble_instr(&mut i);
i += 1;
}
}
pub fn kw_from(&self, kw: &str) -> Option<Value> {
self.kw_index_from(kw).map(Value::Keyword)
}
@ -840,6 +853,7 @@ impl Compiler {
}
}
self.emit_op(Op::Call);
self.emit_byte(args.len());
}
},
_ => unreachable!(),
@ -1015,17 +1029,10 @@ impl Compiler {
compiler.pop();
}
compiler.stack_depth = 0;
compiler.emit_op(Op::Jump);
compiler.emit_byte(0xff);
compiler.emit_op(Op::Return);
compiler.chunk.bytecode[jnm_idx] = compiler.len() as u8 - jnm_idx as u8;
compiler.scope_depth -= 1;
}
if crate::DEBUG_COMPILE {
for (arity, compiler) in compilers.iter() {
println!("==function clause: {name}/{arity}==");
compiler.disassemble();
}
}
// let mut the_chunks = vec![];
@ -1046,8 +1053,14 @@ impl Compiler {
//
let mut the_chunks = vec![];
for (arity, compiler) in compilers.into_iter() {
the_chunks.push((arity as u8, compiler.chunk));
for (arity, mut compiler) in compilers.into_iter() {
compiler.emit_op(Op::PanicNoMatch);
let mut chunk = compiler.chunk;
if crate::DEBUG_COMPILE {
println!("=== function chuncktion: {name}/{arity} ===");
chunk.dissasemble();
}
the_chunks.push((arity as u8, chunk));
}
let lfn = crate::value::LFn {
@ -1071,11 +1084,16 @@ impl Compiler {
self.emit_constant(lfn);
self.bind(name);
}
FnBody(clauses) => {
self.emit_op(Op::ResetMatch);
todo!();
}
FnBody(_) => unreachable!(),
// TODO: add a check to make sure times >= 0
// TODO: fix this so that the algorithm is actually correct
// * truncate
// * check that it's 0 or more, panic if not
// * jump if 0 to end of loop
// * body
// * pop
// * decrement counter (which is now at the top of the stack)
// * jump back to jump if 0 instruction
Repeat(times, body) => {
self.visit(times);
self.emit_op(Op::Truncate);
@ -1241,32 +1259,6 @@ impl Compiler {
pub fn disassemble(&self) {
println!("=== chunk: {} ===", self.name);
println!("IDX | CODE | INFO");
let mut codes = self.chunk.bytecode.iter().enumerate();
while let Some((i, byte)) = codes.next() {
let op = Op::from_u8(*byte).unwrap();
use Op::*;
match op {
Noop | Pop | Store | Stash | Load | Nil | True | False | MatchNil | MatchTrue
| MatchFalse | MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen
| PanicNoMatch | TypeOf | Duplicate | Truncate | Decrement | LoadTuple
| LoadList | Eq | Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At
| Not | Panic | EmptyString | ConcatStrings | Stringify | MatchType => {
println!("{i:04}: {op}")
}
Constant | MatchConstant => {
let (_, next) = codes.next().unwrap();
let value = &self.chunk.constants[*next as usize].show(&self.chunk);
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
}
PushBinding | MatchTuple | MatchList | PushTuple | PushDict | PushList
| MatchDict | LoadDictValue | PushBox | Jump | JumpIfFalse | JumpIfTrue
| JumpIfNoMatch | JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN
| StoreAt | Call => {
let (_, next) = codes.next().unwrap();
println!("{i:04}: {:16} {next:04}", op.to_string());
}
}
}
self.chunk.dissasemble();
}
}

View File

@ -104,7 +104,8 @@ impl<'a> Vm<'a> {
fn print_debug(&self) {
self.print_stack();
self.chunk.dissasemble_instr(self.ip);
let mut ip = self.ip;
self.chunk.dissasemble_instr(&mut ip);
}
pub fn run(&mut self) -> &Result<Value, Panic> {
@ -611,6 +612,7 @@ impl<'a> Vm<'a> {
self.ip += 1;
}
Call => todo!(),
Return => todo!(),
}
}
}