summaryrefslogtreecommitdiffstats
path: root/src/forth
diff options
context:
space:
mode:
authorBrian Cully <bjc@spork.org>2025-08-24 14:22:48 -0400
committerBrian Cully <bjc@spork.org>2025-08-24 15:36:55 -0400
commit0efb15a9eb706896cdabb9ca5d2b0c295c2dffcf (patch)
treed4bb89acd2ab1dd45ee40d9dffed5a4b73554b12 /src/forth
parent57f32dc1d36650a5f282f1ba3906e9772b89709d (diff)
downloadautomathon-0efb15a9eb706896cdabb9ca5d2b0c295c2dffcf.tar.gz
automathon-0efb15a9eb706896cdabb9ca5d2b0c295c2dffcf.zip
rename parser → compiler, interp → vm
reflects reality better
Diffstat (limited to 'src/forth')
-rw-r--r--src/forth/compiler.rs (renamed from src/forth/parser.rs)126
-rw-r--r--[-rwxr-xr-x]src/forth/mod.rs24
-rw-r--r--src/forth/vm.rs (renamed from src/forth/interp.rs)356
3 files changed, 253 insertions, 253 deletions
diff --git a/src/forth/parser.rs b/src/forth/compiler.rs
index c934c4a..9120506 100644
--- a/src/forth/parser.rs
+++ b/src/forth/compiler.rs
@@ -1,18 +1,18 @@
-use super::interp::{ByteCode, OpCode, WordList};
+use super::vm::{ByteCode, OpCode, WordList};
use std::collections::HashMap;
use std::iter::{Enumerate, Iterator};
use std::str::Chars;
#[derive(Debug)]
-pub enum ParseError {
+pub enum CompileError {
EOF,
DefStackEmpty,
MissingIf,
MissingQuote,
UnknownWord(String),
}
-impl std::fmt::Display for ParseError {
+impl std::fmt::Display for CompileError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::EOF => write!(f, "premature end-of-file"),
@@ -23,9 +23,9 @@ impl std::fmt::Display for ParseError {
}
}
}
-impl std::error::Error for ParseError {}
+impl std::error::Error for CompileError {}
-type ParseResult<T> = Result<T, ParseError>;
+type CompileResult<T> = Result<T, CompileError>;
// todo: the annotations should be directly tied to the wordlist so
// they can't get out of sync.
@@ -45,7 +45,7 @@ pub enum IfClauses {
}
#[derive(Debug)]
-pub struct Parser<'a> {
+pub struct Compiler<'a> {
text: &'a str,
enumerator: Enumerate<Chars<'a>>,
// list of all word definitions, in the order defined. the main
@@ -64,7 +64,7 @@ pub struct Parser<'a> {
if_stack: Vec<(IfClauses, Annotation)>,
}
-impl<'a> Parser<'a> {
+impl<'a> Compiler<'a> {
pub fn new(text: &'a str) -> Self {
let mut wl = vec![];
// main routine is always the first entry.
@@ -115,7 +115,7 @@ impl<'a> Parser<'a> {
self.anno_mut().push(anno);
}
- pub fn parse(&mut self) -> ParseResult<()> {
+ pub fn compile(&mut self) -> CompileResult<()> {
while let Some((word, start, end)) = self.next_word() {
let anno = Annotation { loc: (start, end) };
if let Ok(i) = word.parse::<i32>() {
@@ -128,11 +128,11 @@ impl<'a> Parser<'a> {
let (s_end, _) =
self.enumerator
.find(|(_i, c)| return *c == '"')
- .ok_or(ParseError::MissingQuote)?;
+ .ok_or(CompileError::MissingQuote)?;
self.bc_push(OpCode::Str(end+1, s_end), anno);
},
":" => {
- let (name, _, _) = self.next_word().ok_or(ParseError::EOF)?;
+ let (name, _, _) = self.next_word().ok_or(CompileError::EOF)?;
self.wordalog.0.insert(name, self.wordlist.0.len());
self.defstack.push(self.wordlist.0.len());
self.wordlist.0.push(ByteCode(vec![]));
@@ -155,7 +155,7 @@ impl<'a> Parser<'a> {
},
_ => self.bc_push(OpCode::Ret, anno),
}
- self.defstack.pop().ok_or(ParseError::DefStackEmpty)?;
+ self.defstack.pop().ok_or(CompileError::DefStackEmpty)?;
},
"if" => {
let i = self.wordlist.0.len();
@@ -175,8 +175,8 @@ impl<'a> Parser<'a> {
self.defstack.push(i);
let (true_clause, anno) = match self.if_stack.pop() {
- None => return Err(ParseError::MissingIf),
- Some((IfClauses::TrueFalse(_, _), _)) => return Err(ParseError::MissingIf),
+ None => return Err(CompileError::MissingIf),
+ Some((IfClauses::TrueFalse(_, _), _)) => return Err(CompileError::MissingIf),
Some((IfClauses::True(cl), anno)) => (cl, anno),
};
self.if_stack.push((IfClauses::TrueFalse(true_clause, i), anno));
@@ -186,7 +186,7 @@ impl<'a> Parser<'a> {
self.defstack.pop();
match self.if_stack.pop() {
- None => return Err(ParseError::MissingIf),
+ None => return Err(CompileError::MissingIf),
Some((IfClauses::True(true_clause), anno)) => {
self.bc_push(OpCode::If(true_clause, None), anno);
},
@@ -206,7 +206,7 @@ impl<'a> Parser<'a> {
">=" => self.bc_push(OpCode::GTE, anno),
"<" => self.bc_push(OpCode::LT, anno),
"<=" => self.bc_push(OpCode::LTE, anno),
- other => return Err(ParseError::UnknownWord(String::from(other))),
+ other => return Err(CompileError::UnknownWord(String::from(other))),
}
}
}
@@ -217,11 +217,11 @@ impl<'a> Parser<'a> {
#[cfg(test)]
mod tests {
use super::*;
- use super::super::interp::OpCode;
+ use super::super::vm::OpCode;
- fn parser_for(text: &str) -> Parser {
- let mut p = Parser::new(text);
- p.parse().expect("badparse");
+ fn compiler_for(text: &str) -> Compiler {
+ let mut p = Compiler::new(text);
+ p.compile().expect("badparse");
p
}
@@ -233,42 +233,42 @@ mod tests {
#[test]
fn literal_num() {
- let p = parser_for("1\n");
- let main = &p.wordlist.0[0];
+ let comp = compiler_for("1\n");
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Num(1));
}
#[test]
fn literal_string() {
- let p = parser_for(r#"s" hello there""#);
- let main = &p.wordlist.0[0];
+ let comp = compiler_for(r#"s" hello there""#);
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Str(3, 14));
}
#[test]
fn add_opcode() {
- let p = parser_for("+\n");
- let main = &p.wordlist.0[0];
+ let comp = compiler_for("+\n");
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Add);
}
#[test]
fn sub_opcode() {
- let p = parser_for("-\n");
- let main = &p.wordlist.0[0];
+ let comp = compiler_for("-\n");
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Sub);
}
#[test]
fn def_word() {
- let p = parser_for(": add2 2 + ; 3 add2\n");
- let main = &p.wordlist.0[0];
- let add2_index = p.wordalog.0.get("add2").expect("add2 has entry in wordlist");
- let add2 = &p.wordlist.0[*add2_index];
+ let comp = compiler_for(": add2 2 + ; 3 add2\n");
+ let main = &comp.wordlist.0[0];
+ let add2_index = comp.wordalog.0.get("add2").expect("add2 has entry in wordlist");
+ let add2 = &comp.wordlist.0[*add2_index];
assert_eq!(main.len(), 2);
assert_eq!(main[0], OpCode::Num(3));
assert_eq!(main[1], OpCode::Call(*add2_index));
@@ -280,13 +280,13 @@ mod tests {
#[test]
fn if_then() {
- let p = parser_for("if 1 2 + then\n");
- eprintwordlist(&p.wordlist);
- assert_eq!(p.wordlist.0.len(), 2);
- let main = &p.wordlist.0[0];
+ let comp = compiler_for("if 1 2 + then\n");
+ eprintwordlist(&comp.wordlist);
+ assert_eq!(comp.wordlist.0.len(), 2);
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::If(1, None));
- let tr = &p.wordlist.0[1];
+ let tr = &comp.wordlist.0[1];
assert_eq!(tr.len(), 4);
assert_eq!(tr[0], OpCode::Num(1));
assert_eq!(tr[1], OpCode::Num(2));
@@ -296,19 +296,19 @@ mod tests {
#[test]
fn if_else_then() {
- let p = parser_for("if 1 2 + else 1 2 - then\n");
- eprintwordlist(&p.wordlist);
- assert_eq!(p.wordlist.0.len(), 3, "wordlist length");
- let main = &p.wordlist.0[0];
+ let comp = compiler_for("if 1 2 + else 1 2 - then\n");
+ eprintwordlist(&comp.wordlist);
+ assert_eq!(comp.wordlist.0.len(), 3, "wordlist length");
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::If(1, Some(2)));
- let tr = &p.wordlist.0[1];
+ let tr = &comp.wordlist.0[1];
assert_eq!(tr.len(), 4);
assert_eq!(tr[0], OpCode::Num(1));
assert_eq!(tr[1], OpCode::Num(2));
assert_eq!(tr[2], OpCode::Add);
assert_eq!(tr[3], OpCode::Ret);
- let fl = &p.wordlist.0[2];
+ let fl = &comp.wordlist.0[2];
assert_eq!(fl.len(), 4);
assert_eq!(fl[0], OpCode::Num(1));
assert_eq!(fl[1], OpCode::Num(2));
@@ -318,24 +318,24 @@ mod tests {
#[test]
fn tail_call() {
- let p = parser_for(": first + ; : second 3 first ; 1 second\n");
- assert_eq!(p.wordlist.0.len(), 3, "wordlist length");
- eprintwordlist(&p.wordlist);
+ let comp = compiler_for(": first + ; : second 3 first ; 1 second\n");
+ assert_eq!(comp.wordlist.0.len(), 3, "wordlist length");
+ eprintwordlist(&comp.wordlist);
}
#[test]
fn tail_if() {
- let p = parser_for(": t if 1 2 + then ; t\n");
- eprintwordlist(&p.wordlist);
- assert_eq!(p.wordlist.0.len(), 3);
- let main = &p.wordlist.0[0];
+ let comp = compiler_for(": t if 1 2 + then ; t\n");
+ eprintwordlist(&comp.wordlist);
+ assert_eq!(comp.wordlist.0.len(), 3);
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Call(1));
- let t = &p.wordlist.0[1];
+ let t = &comp.wordlist.0[1];
assert_eq!(t.len(), 2);
assert_eq!(t[0], OpCode::TIf(2, None));
assert_eq!(t[1], OpCode::Ret);
- let tr = &p.wordlist.0[2];
+ let tr = &comp.wordlist.0[2];
assert_eq!(tr.len(), 4);
assert_eq!(tr[0], OpCode::Num(1));
assert_eq!(tr[1], OpCode::Num(2));
@@ -345,23 +345,23 @@ mod tests {
#[test]
fn tail_if_else() {
- let p = parser_for(": t if 1 2 + else 1 2 - then ; t\n");
- eprintwordlist(&p.wordlist);
- assert_eq!(p.wordlist.0.len(), 4, "wordlist length");
- let main = &p.wordlist.0[0];
+ let comp = compiler_for(": t if 1 2 + else 1 2 - then ; t\n");
+ eprintwordlist(&comp.wordlist);
+ assert_eq!(comp.wordlist.0.len(), 4, "wordlist length");
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Call(1));
- let t = &p.wordlist.0[1];
+ let t = &comp.wordlist.0[1];
assert_eq!(t.len(), 2);
assert_eq!(t[0], OpCode::TIf(2, Some(3)));
assert_eq!(t[1], OpCode::Ret);
- let tr = &p.wordlist.0[2];
+ let tr = &comp.wordlist.0[2];
assert_eq!(tr.len(), 4);
assert_eq!(tr[0], OpCode::Num(1));
assert_eq!(tr[1], OpCode::Num(2));
assert_eq!(tr[2], OpCode::Add);
assert_eq!(tr[3], OpCode::Ret);
- let fl = &p.wordlist.0[3];
+ let fl = &comp.wordlist.0[3];
assert_eq!(fl.len(), 4);
assert_eq!(fl[0], OpCode::Num(1));
assert_eq!(fl[1], OpCode::Num(2));
@@ -371,13 +371,13 @@ mod tests {
#[test]
fn recursion() {
- let p = parser_for(": foo foo ; foo\n");
- eprintwordlist(&p.wordlist);
- assert_eq!(p.wordlist.0.len(), 2);
- let main = &p.wordlist.0[0];
+ let comp = compiler_for(": foo foo ; foo\n");
+ eprintwordlist(&comp.wordlist);
+ assert_eq!(comp.wordlist.0.len(), 2);
+ let main = &comp.wordlist.0[0];
assert_eq!(main.len(), 1);
assert_eq!(main[0], OpCode::Call(1));
- let foo = &p.wordlist.0[1];
+ let foo = &comp.wordlist.0[1];
assert_eq!(foo.len(), 1);
assert_eq!(foo[0], OpCode::TCall(1));
}
diff --git a/src/forth/mod.rs b/src/forth/mod.rs
index 063b40e..f244ef4 100755..100644
--- a/src/forth/mod.rs
+++ b/src/forth/mod.rs
@@ -1,16 +1,16 @@
-pub mod interp;
-pub mod parser;
+pub mod compiler;
+pub mod vm;
#[cfg(test)]
mod tests {
use super::{
- interp::{Interp, WordList},
- parser::Parser
+ vm::{VM, WordList},
+ compiler::Compiler,
};
- fn parser_for(text: &str) -> Parser {
- let mut p = Parser::new(text);
- p.parse().expect("badparse");
+ fn parser_for(text: &str) -> Compiler {
+ let mut p = Compiler::new(text);
+ p.compile().expect("badparse");
p
}
@@ -26,10 +26,10 @@ mod tests {
let prog = ": fac dup 1 > if dup 1 - fac * then ; 5 fac\n";
let p = parser_for(prog);
eprintwordlist(&p.wordlist);
- let mut interp = Interp::new(p.wordlist);
- interp.run().expect("should run to completion");
- eprintln!("stack: {:?}", interp.stack);
- assert_eq!(interp.stack.0.len(), 1, "factorial result stack len");
- assert_eq!(interp.stack.0[0], 120, "factorial result value");
+ let mut vm = VM::new(p.wordlist);
+ vm.run().expect("should run to completion");
+ eprintln!("stack: {:?}", vm.stack);
+ assert_eq!(vm.stack.0.len(), 1, "factorial result stack len");
+ assert_eq!(vm.stack.0[0], 120, "factorial result value");
}
}
diff --git a/src/forth/interp.rs b/src/forth/vm.rs
index 512c022..b4ce674 100644
--- a/src/forth/interp.rs
+++ b/src/forth/vm.rs
@@ -81,7 +81,7 @@ impl std::ops::Deref for WordList {
}
#[derive(Debug)]
-pub struct Interp {
+pub struct VM {
// todo: don't be pub, probably
pub stack: DataStack,
pub callstack: CallStack,
@@ -94,7 +94,7 @@ pub enum RuntimeError {
StackUnderflow,
}
-impl Interp {
+impl VM {
pub fn new(wordlist: WordList) -> Self {
Self {
stack: DataStack(Vec::new()),
@@ -232,22 +232,22 @@ mod tests {
fn simple_ticks() -> Result<(), RuntimeError> {
let mut wordlist = WordList(vec![]);
wordlist.0.push(ByteCode(vec![OpCode::Num(2), OpCode::Num(3), OpCode::Add]));
- let mut interp = Interp::new(wordlist);
- assert_eq!(interp.tick()?, true, "first arg running");
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 1);
- assert_eq!(interp.stack.0.len(), 1);
- assert_eq!(interp.stack.0[0], 2, "first argument");
- assert_eq!(interp.tick()?, true, "second arg running");
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 2);
- assert_eq!(interp.stack.0.len(), 2);
- assert_eq!(interp.stack.0[1], 3, "second argument");
- assert_eq!(interp.tick()?, false, "stopped after addition");
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 3);
- assert_eq!(interp.stack.0.len(), 1);
- assert_eq!(interp.stack.0[0], 5, "result of addition");
+ let mut vm = VM::new(wordlist);
+ assert_eq!(vm.tick()?, true, "first arg running");
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 1);
+ assert_eq!(vm.stack.0.len(), 1);
+ assert_eq!(vm.stack.0[0], 2, "first argument");
+ assert_eq!(vm.tick()?, true, "second arg running");
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 2);
+ assert_eq!(vm.stack.0.len(), 2);
+ assert_eq!(vm.stack.0[1], 3, "second argument");
+ assert_eq!(vm.tick()?, false, "stopped after addition");
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 3);
+ assert_eq!(vm.stack.0.len(), 1);
+ assert_eq!(vm.stack.0[0], 5, "result of addition");
Ok(())
}
@@ -259,50 +259,50 @@ mod tests {
OpCode::Num(2), OpCode::Num(3), OpCode::Call(1), OpCode::Num(-2), OpCode::Add,
OpCode::Sub, OpCode::Ret,
]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
// "sub" definition
- interp.wordlist.0.push(ByteCode(vec![
+ vm.wordlist.0.push(ByteCode(vec![
OpCode::Sub, OpCode::Ret,
]));
- interp.tick()?;
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 1);
- assert_eq!(interp.stack.0.len(), 1);
- assert_eq!(interp.stack.0[0], 2, "first argument");
- interp.tick()?;
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 2);
- assert_eq!(interp.stack.0.len(), 2);
- assert_eq!(interp.stack.0[1], 3, "second argument");
+ vm.tick()?;
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 1);
+ assert_eq!(vm.stack.0.len(), 1);
+ assert_eq!(vm.stack.0[0], 2, "first argument");
+ vm.tick()?;
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 2);
+ assert_eq!(vm.stack.0.len(), 2);
+ assert_eq!(vm.stack.0[1], 3, "second argument");
- interp.tick()?; // call sub
- assert_eq!(interp.ip.word, 1);
- assert_eq!(interp.ip.offset, 0);
- assert_eq!(interp.stack.0.len(), 2);
+ vm.tick()?; // call sub
+ assert_eq!(vm.ip.word, 1);
+ assert_eq!(vm.ip.offset, 0);
+ assert_eq!(vm.stack.0.len(), 2);
- interp.tick()?; // -
- assert_eq!(interp.ip.word, 1);
- assert_eq!(interp.ip.offset, 1);
- assert_eq!(interp.stack.0.len(), 1);
+ vm.tick()?; // -
+ assert_eq!(vm.ip.word, 1);
+ assert_eq!(vm.ip.offset, 1);
+ assert_eq!(vm.stack.0.len(), 1);
- interp.tick()?; // ret
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 3);
- assert_eq!(interp.stack.0.len(), 1);
- assert_eq!(interp.stack.0[0], -1, "result of sub word");
+ vm.tick()?; // ret
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 3);
+ assert_eq!(vm.stack.0.len(), 1);
+ assert_eq!(vm.stack.0[0], -1, "result of sub word");
- interp.tick()?; // 2
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 4);
- assert_eq!(interp.stack.0.len(), 2);
- assert_eq!(interp.stack.0[1], -2, "post sub arg");
+ vm.tick()?; // 2
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 4);
+ assert_eq!(vm.stack.0.len(), 2);
+ assert_eq!(vm.stack.0[1], -2, "post sub arg");
- interp.tick()?; // -
- assert_eq!(interp.ip.word, 0);
- assert_eq!(interp.ip.offset, 5);
- assert_eq!(interp.stack.0.len(), 1);
- assert_eq!(interp.stack.0[0], -3, "add opcode result");
+ vm.tick()?; // -
+ assert_eq!(vm.ip.word, 0);
+ assert_eq!(vm.ip.offset, 5);
+ assert_eq!(vm.stack.0.len(), 1);
+ assert_eq!(vm.stack.0[0], -3, "add opcode result");
Ok(())
}
@@ -313,14 +313,14 @@ mod tests {
wordlist.0.push(ByteCode(vec![OpCode::Call(1)]));
wordlist.0.push(ByteCode(vec![OpCode::TCall(2), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?; // call
- assert_eq!(interp.callstack.0.len(), 1, "callstack after call");
- interp.tick()?; // tcall
- assert_eq!(interp.callstack.0.len(), 1, "callstack after tcall");
- interp.tick()?; // ret
- assert_eq!(interp.callstack.0.len(), 0, "callstack after ret");
+ vm.tick()?; // call
+ assert_eq!(vm.callstack.0.len(), 1, "callstack after call");
+ vm.tick()?; // tcall
+ assert_eq!(vm.callstack.0.len(), 1, "callstack after tcall");
+ vm.tick()?; // ret
+ assert_eq!(vm.callstack.0.len(), 0, "callstack after ret");
Ok(())
}
@@ -329,22 +329,22 @@ mod tests {
let mut wordlist = WordList(vec![]);
wordlist.0.push(ByteCode(vec![OpCode::Num(-1), OpCode::If(1, None), OpCode::Num(0)]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push -1 stack len");
- assert_eq!(interp.stack.0[0], -1, "push -1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "if stack ");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 1 stack len");
- assert_eq!(interp.stack.0[0], 1, "push 1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "ret stack len");
- assert_eq!(interp.stack.0[0], 1, "ret stack val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 2, "push 0 stack len");
- assert_eq!(interp.stack.0[1], 0, "push 0 stack val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push -1 stack len");
+ assert_eq!(vm.stack.0[0], -1, "push -1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "if stack ");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push 1 stack len");
+ assert_eq!(vm.stack.0[0], 1, "push 1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "ret stack len");
+ assert_eq!(vm.stack.0[0], 1, "ret stack val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 2, "push 0 stack len");
+ assert_eq!(vm.stack.0[1], 0, "push 0 stack val");
Ok(())
}
@@ -354,16 +354,16 @@ mod tests {
let mut wordlist = WordList(vec![]);
wordlist.0.push(ByteCode(vec![OpCode::Num(0), OpCode::If(1, None), OpCode::Num(-1)]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 0 stack len");
- assert_eq!(interp.stack.0[0], 0, "push 0 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "if stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push -1 stack len");
- assert_eq!(interp.stack.0[0], -1, "push -1 val");
+ 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, "if stack len");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push -1 stack len");
+ assert_eq!(vm.stack.0[0], -1, "push -1 val");
Ok(())
}
@@ -374,22 +374,22 @@ mod tests {
wordlist.0.push(ByteCode(vec![OpCode::Num(-1), OpCode::If(1, Some(2)), OpCode::Num(-2)]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(2), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push -1 stack len");
- assert_eq!(interp.stack.0[0], -1, "push -1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "if stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 1 stack len");
- assert_eq!(interp.stack.0[0], 1, "push 1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "ret stack len");
- assert_eq!(interp.stack.0[0], 1, "ret val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 2, "push -2 stack len");
- assert_eq!(interp.stack.0[1], -2, "push -2 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push -1 stack len");
+ assert_eq!(vm.stack.0[0], -1, "push -1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "if stack len");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push 1 stack len");
+ assert_eq!(vm.stack.0[0], 1, "push 1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "ret stack len");
+ assert_eq!(vm.stack.0[0], 1, "ret val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 2, "push -2 stack len");
+ assert_eq!(vm.stack.0[1], -2, "push -2 val");
Ok(())
}
@@ -400,22 +400,22 @@ mod tests {
wordlist.0.push(ByteCode(vec![OpCode::Num(0), OpCode::If(1, Some(2)), OpCode::Num(-2)]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(2), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 0 stack len");
- assert_eq!(interp.stack.0[0], 0, "push 0 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "if");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 2 stack len");
- assert_eq!(interp.stack.0[0], 2, "push 2 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "ret");
- assert_eq!(interp.stack.0[0], 2, "ret");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 2, "push -2 stack len");
- assert_eq!(interp.stack.0[1], -2, "push -2 val");
+ 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, "if");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push 2 stack len");
+ assert_eq!(vm.stack.0[0], 2, "push 2 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "ret");
+ assert_eq!(vm.stack.0[0], 2, "ret");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 2, "push -2 stack len");
+ assert_eq!(vm.stack.0[1], -2, "push -2 val");
Ok(())
}
@@ -426,24 +426,24 @@ mod tests {
wordlist.0.push(ByteCode(vec![OpCode::Call(1), OpCode::Num(0)]));
wordlist.0.push(ByteCode(vec![OpCode::Num(-1), OpCode::TIf(2, None), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "call(1) stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push -1 stack len");
- assert_eq!(interp.stack.0[0], -1, "push -1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "tif stack ");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 1 stack len");
- assert_eq!(interp.stack.0[0], 1, "push 1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "ret stack len");
- assert_eq!(interp.stack.0[0], 1, "ret stack val");
- interp.tick()?; // no ret on wordlist[1] since it's ‘tif’
- assert_eq!(interp.stack.0.len(), 2, "push 0 stack len");
- assert_eq!(interp.stack.0[1], 0, "push 0 stack val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "call(1) stack len");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push -1 stack len");
+ assert_eq!(vm.stack.0[0], -1, "push -1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "tif stack ");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push 1 stack len");
+ assert_eq!(vm.stack.0[0], 1, "push 1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "ret stack len");
+ assert_eq!(vm.stack.0[0], 1, "ret stack val");
+ vm.tick()?; // no ret on wordlist[1] since it's ‘tif’
+ assert_eq!(vm.stack.0.len(), 2, "push 0 stack len");
+ assert_eq!(vm.stack.0[1], 0, "push 0 stack val");
Ok(())
}
@@ -454,20 +454,20 @@ mod tests {
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 mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "call(1) stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 0 stack len");
- assert_eq!(interp.stack.0[0], 0, "push 0 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "tif stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "ret stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 0 stack len");
- assert_eq!(interp.stack.0[0], 0, "push 0 val");
+ 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");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "ret 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");
Ok(())
}
@@ -479,24 +479,24 @@ mod tests {
wordlist.0.push(ByteCode(vec![OpCode::Num(-1), OpCode::TIf(2, Some(3)), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(2), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "call(1) stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push -1 stack len");
- assert_eq!(interp.stack.0[0], -1, "push -1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "tif stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 1 stack len");
- assert_eq!(interp.stack.0[0], 1, "push 1 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "ret stack len");
- assert_eq!(interp.stack.0[0], 1, "ret val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 2, "push -2 stack len");
- assert_eq!(interp.stack.0[1], -2, "push -2 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "call(1) stack len");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push -1 stack len");
+ assert_eq!(vm.stack.0[0], -1, "push -1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 0, "tif stack len");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push 1 stack len");
+ assert_eq!(vm.stack.0[0], 1, "push 1 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "ret stack len");
+ assert_eq!(vm.stack.0[0], 1, "ret val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 2, "push -2 stack len");
+ assert_eq!(vm.stack.0[1], -2, "push -2 val");
Ok(())
}
@@ -508,24 +508,24 @@ mod tests {
wordlist.0.push(ByteCode(vec![OpCode::Num(0), OpCode::TIf(2, Some(3)), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(1), OpCode::Ret]));
wordlist.0.push(ByteCode(vec![OpCode::Num(2), OpCode::Ret]));
- let mut interp = Interp::new(wordlist);
+ let mut vm = VM::new(wordlist);
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "call(1) stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 0 stack len");
- assert_eq!(interp.stack.0[0], 0, "push 0 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 0, "tif stack len");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "push 2 stack len");
- assert_eq!(interp.stack.0[0], 2, "push 2 val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 1, "ret stack len");
- assert_eq!(interp.stack.0[0], 2, "ret val");
- interp.tick()?;
- assert_eq!(interp.stack.0.len(), 2, "push -2 stack len");
- assert_eq!(interp.stack.0[1], -2, "push -2 val");
+ 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");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "push 2 stack len");
+ assert_eq!(vm.stack.0[0], 2, "push 2 val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 1, "ret stack len");
+ assert_eq!(vm.stack.0[0], 2, "ret val");
+ vm.tick()?;
+ assert_eq!(vm.stack.0.len(), 2, "push -2 stack len");
+ assert_eq!(vm.stack.0[1], -2, "push -2 val");
Ok(())
}