diff --git a/src/compiler.rs b/src/compiler.rs index 965052b..1184630 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -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 { 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(); } } diff --git a/src/vm.rs b/src/vm.rs index 405ada7..b5d32df 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -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 { @@ -611,6 +612,7 @@ impl<'a> Vm<'a> { self.ip += 1; } Call => todo!(), + Return => todo!(), } } }