summaryrefslogtreecommitdiffstats
path: root/src/forth/vm.rs
diff options
context:
space:
mode:
authorBrian Cully <bjc@spork.org>2025-08-25 12:25:30 -0400
committerBrian Cully <bjc@spork.org>2025-08-25 12:25:30 -0400
commit8275403e955e8998c61ecaa07d70949e3bd53a66 (patch)
tree3f0989d16931d889a4938f742f8da68d3e6e362b /src/forth/vm.rs
parent1c81d26b706abb43ba71eb36cdb622dae03e95cd (diff)
downloadautomathon-8275403e955e8998c61ecaa07d70949e3bd53a66.tar.gz
automathon-8275403e955e8998c61ecaa07d70949e3bd53a66.zip
tail-position if no longer needs ret
Diffstat (limited to 'src/forth/vm.rs')
-rw-r--r--src/forth/vm.rs34
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(())
+ }
}