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

View File

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