diff options
| author | Brian Cully <bjc@spork.org> | 2025-12-15 11:05:17 -0500 |
|---|---|---|
| committer | Brian Cully <bjc@spork.org> | 2025-12-15 11:05:17 -0500 |
| commit | ffadffdcf944ec198bdc44bd9bbbf8ab19ef7485 (patch) | |
| tree | 2f505c2cdb274e346973797c0583846fe00054cd /src | |
| parent | c41113223429c92a1f42b317ac4545208b507be7 (diff) | |
| download | automathon-ffadffdcf944ec198bdc44bd9bbbf8ab19ef7485.tar.gz automathon-ffadffdcf944ec198bdc44bd9bbbf8ab19ef7485.zip | |
vm: add support for robo stuff: velocity, heading, doppler, say
Diffstat (limited to 'src')
| -rw-r--r-- | src/forth/vm.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/forth/vm.rs b/src/forth/vm.rs index ad4b78c..e7c3794 100644 --- a/src/forth/vm.rs +++ b/src/forth/vm.rs @@ -33,6 +33,17 @@ pub enum OpCode { // which are bounded, so running of the end can be treated as an // implicit ‘ret’. Ret, + + // robo-specific stuff + // + // todo: figure out how to split this out of the compiler/vm and + // provide it as some kind of plugin. + Say, + Heading, + SetHeading, + Velocity, + SetVelocity, + Doppler, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -110,6 +121,11 @@ pub struct VM { pub callstack: CallStack, pub wordlist: WordList, pub ip: InstructionPointer, + + pub out: Vec<String>, + pub heading: DataStackType, + pub velocity: DataStackType, + pub doppler: DataStackType, } #[derive(Debug, PartialEq, Eq)] @@ -132,6 +148,11 @@ impl VM { callstack: CallStack(Vec::new()), ip: InstructionPointer::new(), wordlist, + + out: vec![], + heading: 0, + velocity: 0, + doppler: 0, } } @@ -286,6 +307,25 @@ impl VM { self.ip = self.callstack.0.pop().ok_or(RuntimeError::StackUnderflow)?; } } + OpCode::Say => { + let v = self.stack.0.pop().ok_or(RuntimeError::StackUnderflow)?; + self.out.push(format!("{}", v)); + } + OpCode::Heading => { + self.stack.0.push(self.heading); + } + OpCode::SetHeading => { + self.heading = self.stack.0.pop().ok_or(RuntimeError::StackUnderflow)?; + } + OpCode::Velocity => { + self.stack.0.push(self.velocity); + } + OpCode::SetVelocity => { + self.velocity = self.stack.0.pop().ok_or(RuntimeError::StackUnderflow)?; + } + OpCode::Doppler => { + self.stack.0.push(self.doppler); + } } self.ip.offset += 1; Ok(self.ip.offset < self.wordlist.0[self.ip.word].len()) @@ -767,4 +807,75 @@ mod tests { assert_eq!(vm.stack.0, vec![res]); } } + + + #[test] + fn opcode_say() { + let wordlist = wl_for(vec![vec![ + OpCode::Num(-1), OpCode::Say + ]]); + let mut vm = VM::new(wordlist); + vm.run().expect("should run to completion"); + assert_eq!(vm.stack.0.len(), 0, "empty stack"); + assert_eq!(vm.out.len(), 1, "output length"); + assert_eq!(vm.out[0], "-1", "output value"); + } + + #[test] + fn opcode_heading() { + let wordlist = wl_for(vec![vec![ + OpCode::Heading + ]]); + let mut vm = VM::new(wordlist); + vm.heading = 12; + vm.run().expect("should run to completion"); + assert_eq!(vm.stack.0.len(), 1, "stack size"); + assert_eq!(vm.stack.0[0], 12, "heading value"); + } + + #[test] + fn opcode_setheading() { + let wordlist = wl_for(vec![vec![ + OpCode::Num(3), OpCode::SetHeading + ]]); + let mut vm = VM::new(wordlist); + vm.run().expect("should run to completion"); + assert_eq!(vm.stack.0.len(), 0, "empty stack"); + assert_eq!(vm.heading, 3, "heading value"); + } + + #[test] + fn opcode_velocity() { + let wordlist = wl_for(vec![vec![ + OpCode::Velocity + ]]); + let mut vm = VM::new(wordlist); + vm.velocity = 12; + vm.run().expect("should run to completion"); + assert_eq!(vm.stack.0.len(), 1, "stack size"); + assert_eq!(vm.stack.0[0], 12, "velocity value"); + } + + #[test] + fn opcode_setvelocity() { + let wordlist = wl_for(vec![vec![ + OpCode::Num(3), OpCode::SetVelocity + ]]); + let mut vm = VM::new(wordlist); + vm.run().expect("should run to completion"); + assert_eq!(vm.stack.0.len(), 0, "empty stack"); + assert_eq!(vm.velocity, 3, "velocity value"); + } + + #[test] + fn opcode_doppler() { + let wordlist = wl_for(vec![vec![ + OpCode::Doppler + ]]); + let mut vm = VM::new(wordlist); + vm.doppler = 12; + vm.run().expect("should run to completion"); + assert_eq!(vm.stack.0.len(), 1, "stack size"); + assert_eq!(vm.stack.0[0], 12, "doppler value"); + } } |
