From 1d3b54ff7ffbc2d56e2e3e761d927da584c7c46e Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 2 May 2020 12:59:11 +0200 Subject: [PATCH] Add invocation code for tokens --- src/bin/lsambler.rs | 12 +-- src/registers.rs | 2 +- src/runtime.rs | 67 ++++++++++++++++- src/tokens.rs | 175 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 247 insertions(+), 9 deletions(-) diff --git a/src/bin/lsambler.rs b/src/bin/lsambler.rs index cb81417..afef969 100644 --- a/src/bin/lsambler.rs +++ b/src/bin/lsambler.rs @@ -1,4 +1,4 @@ -use ledstrip_vm::registers::get_register_by_name; +use ledstrip_vm::registers::get_register_code_by_name; use ledstrip_vm::tokens::{ AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, GotoToken, JeToken, JgToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SetToken, @@ -60,22 +60,22 @@ fn get_token(line: &str) -> Option> { match instr_parts.next()? { "exit" => some_box!(ExitToken { - register: get_register_by_name(instr_parts.next()?)?, + register: get_register_code_by_name(instr_parts.next()?)?, }), "set" => some_box!(SetToken { value: parse_value(instr_parts.next()?).expect(&format!( "Failed to parse the hex value into a u8: {}.", line )), - register: get_register_by_name(instr_parts.next()?)?, + register: get_register_code_by_name(instr_parts.next()?)?, }), "copy" => some_box!(CopyToken { - register_1: get_register_by_name(instr_parts.next()?)?, - register_2: get_register_by_name(instr_parts.next()?)?, + register_1: get_register_code_by_name(instr_parts.next()?)?, + register_2: get_register_code_by_name(instr_parts.next()?)?, }), "load" => some_box!(LoadToken), "clear" => some_box!(ClearToken { - register: get_register_by_name(instr_parts.next()?)?, + register: get_register_code_by_name(instr_parts.next()?)?, }), "write" => some_box!(WriteToken), "label" => some_box!(LabelToken), diff --git a/src/registers.rs b/src/registers.rs index 3cae33d..a1c418c 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -13,7 +13,7 @@ pub const RGO: u8 = 0x08; pub const RGL: u8 = 0x09; /// Maps a register name to the bytecode value -pub fn get_register_by_name(name: &str) -> Option { +pub fn get_register_code_by_name(name: &str) -> Option { let item = [ ("rcs", RCS), ("rcr", RCR), diff --git a/src/runtime.rs b/src/runtime.rs index d8bd376..33ae0f5 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1,8 +1,13 @@ use crate::ledstrip_controller::LedStripController; -use crate::registers::{Rcb, Rcg, Rcr, Rcs, Rgd, Rgi, Rgl, Rgo, Rgp}; +use crate::ledstrip_controller::ProgramStripCommand::RedGradual; +use crate::registers::{ + Rcb, Rcg, Rcr, Rcs, Register, Rgd, Rgi, Rgl, Rgo, Rgp, RCB, RCG, RCR, RCS, RGD, RGI, RGL, RGO, + RGP, +}; use crate::tokens::Token; -use std::cell::RefCell; +use std::cell::{Ref, RefCell}; use std::collections::HashMap; +use std::io; use std::rc::Rc; pub struct Runtime { @@ -19,6 +24,8 @@ pub struct Runtime { text: Vec>, labels: HashMap, strip_controller: Rc>, + exit: Option, + current_index: u128, } impl Runtime { @@ -41,6 +48,62 @@ impl Runtime { text: Vec::new(), labels: HashMap::new(), strip_controller: controller, + exit: None, + current_index: 0, } } + + pub fn exit(&mut self, code: u8) { + self.exit = Some(code); + } + + /* + pub fn get_register(&mut self, code: u8) -> Option<&mut impl Register> { + match code { + RCS => Some(&mut self.rcs), + RCR => Some(&mut self.rcr), + RCG => Some(&mut self.rcg), + RCB => Some(&mut self.rcb), + RGD => Some(&mut self.rgd), + RGP => Some(&mut self.rgp), + RGI => Some(&mut self.rgi), + RGO => Some(&mut self.rgo), + RGL => Some(&mut self.rgl), + _ => None, + } + }*/ + + pub fn get_1byte_register(&mut self, code: u8) -> Option>> { + match code { + RCR => Some(Box::new(&mut self.rcr)), + RCG => Some(Box::new(&mut self.rcg)), + RCB => Some(Box::new(&mut self.rcb)), + _ => None, + } + } + + pub fn get_4byte_register(&mut self, code: u8) -> Option>> { + match code { + RGD => Some(Box::new(&mut self.rgd)), + RGP => Some(Box::new(&mut self.rgp)), + RGI => Some(Box::new(&mut self.rgi)), + RGO => Some(Box::new(&mut self.rgo)), + RGL => Some(Box::new(&mut self.rgl)), + _ => None, + } + } + + /// Creates a new label at the current position + pub fn create_label(&mut self, id: u32) { + self.labels.insert(id, self.current_index + 1); + } + + pub fn jump(&mut self, label: u32) -> io::Result<()> { + self.current_index = *self + .labels + .get(&label) + .expect(&format!("The label {} does not exist", label)); + + Ok(()) + } } diff --git a/src/tokens.rs b/src/tokens.rs index 532b5c1..d4cc3b0 100644 --- a/src/tokens.rs +++ b/src/tokens.rs @@ -1,3 +1,11 @@ +use crate::registers::{Register, RCS}; +use crate::runtime::Runtime; +use std::borrow::BorrowMut; +use std::io; +use std::panic::resume_unwind; +use std::thread::sleep; +use std::time::Duration; + const T_NOP: u8 = 0x00; const T_EXIT: u8 = 0x01; const T_SET: u8 = 0x02; @@ -22,6 +30,7 @@ const T_CMD: u8 = 0xF1; pub trait Token { fn to_bytecode(&self) -> Vec; + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()>; } pub trait FromBytecode { @@ -34,6 +43,9 @@ impl Token for NopToken { fn to_bytecode(&self) -> Vec { vec![T_NOP] } + fn invoke(&self, _: &mut Runtime) -> io::Result<()> { + Ok(()) + } } impl FromBytecode for NopToken { @@ -50,6 +62,20 @@ impl Token for ExitToken { fn to_bytecode(&self) -> Vec { vec![T_EXIT, self.register] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + let mut exit_code = 0; + if let Some(rg) = runtime.get_1byte_register(self.register) { + exit_code = rg.get(); + } else if let Some(rg) = runtime.get_4byte_register(self.register) { + exit_code = rg.get() as u8; + } else if self.register == RCS { + exit_code = runtime.rcs.get() as u8; + } + runtime.exit(exit_code); + + Ok(()) + } } impl FromBytecode for ExitToken { @@ -67,6 +93,18 @@ impl Token for SetToken { fn to_bytecode(&self) -> Vec { vec![T_SET, self.value, self.register] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + if let Some(mut rg) = runtime.get_1byte_register(self.register) { + rg.set(self.value); + } else if let Some(mut rg) = runtime.get_4byte_register(self.register) { + rg.set(self.value as u32); + } else if self.register == RCS { + runtime.rcs.set(self.value == 0); + } + + Ok(()) + } } impl FromBytecode for SetToken { @@ -87,6 +125,26 @@ impl Token for CopyToken { fn to_bytecode(&self) -> Vec { vec![T_COPY, self.register_1, self.register_2] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + let mut value = 0u32; + if let Some(rg) = runtime.get_1byte_register(self.register_1) { + value = rg.get() as u32; + } else if let Some(rg) = runtime.get_4byte_register(self.register_1) { + value = rg.get(); + } else if self.register_1 == RCS { + value = runtime.rcs.get() as u32; + } + if let Some(mut rg) = runtime.get_1byte_register(self.register_2) { + rg.set(value as u8); + } else if let Some(mut rg) = runtime.get_4byte_register(self.register_2) { + rg.set(value); + } else if self.register_2 == RCS { + runtime.rcs.set(value == 0); + } + + Ok(()) + } } impl FromBytecode for CopyToken { @@ -104,6 +162,17 @@ impl Token for LoadToken { fn to_bytecode(&self) -> Vec { vec![T_LOAD] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + let pointer = runtime.rgp.get(); + if let Some(value) = runtime.memory.get(&pointer) { + runtime.rgd.set(*value); + } else { + runtime.rgd.set(0); + } + + Ok(()) + } } impl FromBytecode for LoadToken { @@ -120,6 +189,18 @@ impl Token for ClearToken { fn to_bytecode(&self) -> Vec { vec![T_CLEAR, self.register] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + if let Some(mut rg) = runtime.get_1byte_register(self.register) { + rg.set(0u8); + } else if let Some(mut rg) = runtime.get_4byte_register(self.register) { + rg.set(0u32); + } else if self.register == RCS { + runtime.rcs.set(false); + } + + Ok(()) + } } impl FromBytecode for ClearToken { @@ -134,6 +215,12 @@ impl Token for WriteToken { fn to_bytecode(&self) -> Vec { vec![T_WRITE] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.memory.insert(runtime.rgp.get(), runtime.rgd.get()); + + Ok(()) + } } impl FromBytecode for WriteToken { @@ -148,6 +235,12 @@ impl Token for LabelToken { fn to_bytecode(&self) -> Vec { vec![T_LABEL] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.create_label(runtime.rgl.get()); + + Ok(()) + } } impl FromBytecode for LabelToken { @@ -162,6 +255,10 @@ impl Token for GotoToken { fn to_bytecode(&self) -> Vec { vec![T_GOTO] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.jump(runtime.rgl.get()) + } } impl FromBytecode for GotoToken { @@ -176,6 +273,12 @@ impl Token for AddToken { fn to_bytecode(&self) -> Vec { vec![T_ADD] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgo.get() + runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for AddToken { @@ -190,6 +293,12 @@ impl Token for SubToken { fn to_bytecode(&self) -> Vec { vec![T_SUB] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgd.get() - runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for SubToken { @@ -204,6 +313,12 @@ impl Token for MulToken { fn to_bytecode(&self) -> Vec { vec![T_MUL] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgd.get() * runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for MulToken { @@ -218,6 +333,12 @@ impl Token for DivToken { fn to_bytecode(&self) -> Vec { vec![T_DIV] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgd.get() / runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for DivToken { @@ -232,6 +353,12 @@ impl Token for ModToken { fn to_bytecode(&self) -> Vec { vec![T_MOD] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgd.get() % runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for ModToken { @@ -246,6 +373,12 @@ impl Token for LshToken { fn to_bytecode(&self) -> Vec { vec![T_LSH] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgd.get() << runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for LshToken { @@ -260,6 +393,12 @@ impl Token for RshToken { fn to_bytecode(&self) -> Vec { vec![T_RSH] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + runtime.rgo.set(runtime.rgd.get() >> runtime.rgi.get()); + + Ok(()) + } } impl FromBytecode for RshToken { @@ -274,6 +413,14 @@ impl Token for JgToken { fn to_bytecode(&self) -> Vec { vec![T_JG] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + if runtime.rgd.get() > runtime.rgi.get() { + runtime.jump(runtime.rgl.get())?; + } + + Ok(()) + } } impl FromBytecode for JgToken { @@ -288,6 +435,14 @@ impl Token for JlToken { fn to_bytecode(&self) -> Vec { vec![T_JL] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + if runtime.rgd.get() < runtime.rgi.get() { + runtime.jump(runtime.rgl.get())?; + } + + Ok(()) + } } impl FromBytecode for JlToken { @@ -302,6 +457,14 @@ impl Token for JeToken { fn to_bytecode(&self) -> Vec { vec![T_JE] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + if runtime.rgd.get() == runtime.rgi.get() { + runtime.jump(runtime.rgl.get())?; + } + + Ok(()) + } } impl FromBytecode for JeToken { @@ -316,6 +479,12 @@ impl Token for PauseToken { fn to_bytecode(&self) -> Vec { vec![T_PAUSE] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + sleep(Duration::from_millis(runtime.rgd.get() as u64)); + + Ok(()) + } } impl FromBytecode for PauseToken { @@ -330,6 +499,12 @@ impl Token for CmdToken { fn to_bytecode(&self) -> Vec { vec![T_CMD] } + + fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { + unimplemented!(); + + Ok(()) + } } impl FromBytecode for CmdToken {