diff --git a/src/bytecode.rs b/src/bytecode.rs index faf1e7a..51146d2 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -14,6 +14,8 @@ pub struct FnBlock<'bc> { #[derive(Debug, Clone, Copy)] pub enum Instr { + Nop, + /// Store the current value on the stack to the stack location with the local offset `usize` Store(usize), /// Load the variable value from the local offset `usize` onto the stack @@ -39,8 +41,8 @@ pub enum Instr { /// Println the value on top of the stack Print, - /// If the current stack value is true, skip `usize` instructions. - JumpFalse(usize), + /// If the current stack value is true, skip `usize` instructions. When jumping backwards + JumpFalse(isize), /// Same as `JumpCond`, but unconditional - Jmp(usize), + Jmp(isize), } diff --git a/src/compile.rs b/src/compile.rs index 8158cea..4dd614b 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -87,6 +87,10 @@ impl<'ast, 'bc, 'gc> Compiler<'ast, 'bc, 'gc> { }; self.blocks.push(global_block); self.current_block = self.blocks.len() - 1; + + // padding for backwards jumps + self.push_instr(Instr::Nop, StackChange::None, Span::dummy()); + self.compile_stmts(&ast.0)?; Ok(()) } @@ -169,7 +173,7 @@ impl<'ast, 'bc, 'gc> Compiler<'ast, 'bc, 'gc> { let block = &mut self.blocks[self.current_block]; let next_index = block.code.len(); let jmp_pos = (next_index - 1) - jmp_idx; - block.code[jmp_idx] = Instr::JumpFalse(jmp_pos); + block.code[jmp_idx] = Instr::JumpFalse(jmp_pos as isize); match else_part { ElsePart::Else(block, _) => { @@ -183,19 +187,35 @@ impl<'ast, 'bc, 'gc> Compiler<'ast, 'bc, 'gc> { let block = &mut self.blocks[self.current_block]; let next_index = block.code.len(); let jmp_pos = (next_index - else_skip_jmp_idx) - 1; - block.code[else_skip_jmp_idx] = Instr::Jmp(jmp_pos); + block.code[else_skip_jmp_idx] = Instr::Jmp(jmp_pos as isize); } else { let block = &mut self.blocks[self.current_block]; let next_index = block.code.len(); let jmp_pos = (next_index - 1) - jmp_idx; - block.code[jmp_idx] = Instr::JumpFalse(jmp_pos); + block.code[jmp_idx] = Instr::JumpFalse(jmp_pos as isize); } Ok(()) } - fn compile_loop(&mut self, _: &Block, _: Span) -> CResult<()> { - todo!() + fn compile_loop(&mut self, ast_block: &'ast Block, span: Span) -> CResult<()> { + /* + ╭>0 // do things + ╰─1 JMP (-2), + */ + + let block = &self.blocks[self.current_block]; + let first_stmt_idx = block.code.len() as isize; + self.compile_block(ast_block)?; + + let block = &self.blocks[self.current_block]; + let jmp_index = block.code.len() as isize; + + let jmp_offset = -(jmp_index - first_stmt_idx + 1); + + self.push_instr(Instr::Jmp(jmp_offset), StackChange::None, span); + + Ok(()) } fn compile_while(&mut self, _: &WhileStmt) -> CResult<()> { diff --git a/src/vm.rs b/src/vm.rs index 56b18e6..b19a21e 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -68,6 +68,7 @@ impl<'bc> Vm<'bc, '_> { fn dispatch_instr(&mut self, instr: Instr) -> VmResult { match instr { + Instr::Nop => {} Instr::Store(index) => { let val = self.stack.pop().unwrap(); self.stack.insert(index, val); @@ -153,12 +154,12 @@ impl<'bc> Vm<'bc, '_> { Instr::JumpFalse(pos) => { let val = self.stack.pop().unwrap(); match val { - Value::Bool(false) => self.pc += pos, + Value::Bool(false) => self.pc = (self.pc as isize + pos) as usize, Value::Bool(true) => {} _ => return Err("bad type"), } } - Instr::Jmp(pos) => self.pc += pos, + Instr::Jmp(pos) => self.pc = (self.pc as isize + pos) as usize, } Ok(()) diff --git a/test.dil b/test.dil index e5f5db3..314fd76 100644 --- a/test.dil +++ b/test.dil @@ -1,11 +1,3 @@ -let x = 5; - -let y = 0; - -if x < 0 { - y = x; -} else { - y = "hello it is smaller"; -} - -print y; \ No newline at end of file +if 54 > 53 { + print "hallo conny"; +} \ No newline at end of file