summaryrefslogtreecommitdiffstats
path: root/src/forth/vm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/forth/vm.rs')
-rw-r--r--src/forth/vm.rs41
1 files changed, 28 insertions, 13 deletions
diff --git a/src/forth/vm.rs b/src/forth/vm.rs
index b4ce674..fe034a6 100644
--- a/src/forth/vm.rs
+++ b/src/forth/vm.rs
@@ -2,7 +2,7 @@ use log::debug;
use std::ops::Index;
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub enum OpCode {
Num(i32),
Str(usize, usize),
@@ -27,7 +27,7 @@ pub enum OpCode {
Ret,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ByteCode(pub Vec<OpCode>);
impl std::ops::Deref for ByteCode {
type Target = Vec<OpCode>;
@@ -40,6 +40,19 @@ impl ByteCode {
pub fn len(&self) -> usize {
self.0.len()
}
+
+ pub fn is_empty(&self) -> bool {
+ self.0.is_empty()
+ }
+}
+
+// really just to make unit testing look nicer. should probably move
+// it there.
+impl PartialEq<Vec<OpCode>> for &ByteCode {
+ fn eq(&self, other: &Vec<OpCode>) -> bool {
+ self.0.len() == other.len() &&
+ std::iter::zip(&self.0, other).all(|(a, b)| a == b)
+ }
}
impl Index<usize> for ByteCode {
@@ -65,6 +78,12 @@ impl InstructionPointer {
}
}
+impl Default for InstructionPointer {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
#[derive(Debug)]
pub struct DataStack(pub Vec<i32>);
@@ -119,7 +138,7 @@ impl VM {
let bc = &self.wordlist.0[self.ip.word];
match bc[self.ip.offset] {
OpCode::Num(n) => self.stack.0.push(n),
- OpCode::Str(start, end) => debug!("got str: {} to {}", start, end),
+ OpCode::Str(start, end) => debug!("got str: {start} to {end}"),
OpCode::Add => {
let n1 = self.stack.0.pop().ok_or(RuntimeError::StackUnderflow)?;
let n2 = self.stack.0.pop().ok_or(RuntimeError::StackUnderflow)?;
@@ -511,21 +530,17 @@ mod tests {
let mut vm = VM::new(wordlist);
vm.tick()?;
- assert_eq!(vm.stack.0.len(), 0, "call(1) stack len");
+ assert_eq!(vm.stack.0, vec![], "call(1) 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");
vm.tick()?;
- assert_eq!(vm.stack.0.len(), 0, "tif stack len");
+ assert_eq!(vm.stack.0, vec![], "tif stack");
vm.tick()?;
- assert_eq!(vm.stack.0.len(), 1, "push 2 stack len");
- assert_eq!(vm.stack.0[0], 2, "push 2 val");
+ assert_eq!(vm.stack.0, vec![2], "push 2 stack");
vm.tick()?;
- assert_eq!(vm.stack.0.len(), 1, "ret stack len");
- assert_eq!(vm.stack.0[0], 2, "ret val");
+ assert_eq!(vm.stack.0, vec![2], "ret stack");
vm.tick()?;
- assert_eq!(vm.stack.0.len(), 2, "push -2 stack len");
- assert_eq!(vm.stack.0[1], -2, "push -2 val");
+ assert_eq!(vm.stack.0, vec![2, -2], "push -2 stack");
Ok(())
}