diff options
Diffstat (limited to 'src/forth/vm.rs')
| -rw-r--r-- | src/forth/vm.rs | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/src/forth/vm.rs b/src/forth/vm.rs index 7ce9c03..9c7f203 100644 --- a/src/forth/vm.rs +++ b/src/forth/vm.rs @@ -254,6 +254,8 @@ impl VM { } else if let Some(false_clause) = false_clause { self.jmp(false_clause); return Ok(true) + } else { + self.ip = self.callstack.0.pop().ok_or(RuntimeError::StackUnderflow)?; } }, } @@ -501,24 +503,21 @@ mod tests { #[test] fn tail_if_then_false() -> Result<(), RuntimeError> { - let mut wordlist = WordList(vec![]); - wordlist.0.push(ByteCode(vec![OpCode::Call(1), OpCode::Num(0)])); - wordlist.0.push(ByteCode(vec![OpCode::Num(0), OpCode::TIf(2, None), OpCode::Ret])); - wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret])); + let wordlist = wl_for(vec![ + vec![OpCode::Call(1), OpCode::Num(0)], + vec![OpCode::Num(0), OpCode::TIf(2, None)], + vec![OpCode::Num(1), OpCode::Ret], + ]); let mut vm = VM::new(wordlist); vm.tick()?; assert_eq!(vm.stack.0.len(), 0, "call(1) stack len"); vm.tick()?; - assert_eq!(vm.stack.0.len(), 1, "push 0 stack len"); - assert_eq!(vm.stack.0[0], 0, "push 0 val"); - vm.tick()?; - assert_eq!(vm.stack.0.len(), 0, "tif stack len"); + assert_eq!(vm.stack.0, vec![0], "push 0 stack"); vm.tick()?; - assert_eq!(vm.stack.0.len(), 0, "ret stack len"); + assert_eq!(vm.stack.0, vec![], "tif stack"); vm.tick()?; - assert_eq!(vm.stack.0.len(), 1, "push 0 stack len"); - assert_eq!(vm.stack.0[0], 0, "push 0 val"); + assert_eq!(vm.stack.0, vec![0], "push 0 stack"); Ok(()) } @@ -599,4 +598,17 @@ mod tests { assert_eq!(vm.stack.0, vec![2, 3, 1]); Ok(()) } + + #[test] + fn tif_no_ret() -> Result<(), RuntimeError> { + let wordlist = wl_for(vec![ + vec![OpCode::Call(1)], + vec![OpCode::Num(0), OpCode::TIf(2, None), OpCode::Num(3)], + vec![OpCode::Num(-2)], + ]); + let mut vm = VM::new(wordlist); + vm.run()?; + assert_eq!(vm.stack.0, vec![]); + Ok(()) + } } |
