Add invocation code for tokens

pull/1/head
trivernis 5 years ago
parent d7c689f7d2
commit 1d3b54ff7f

@ -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::{ use ledstrip_vm::tokens::{
AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, GotoToken, JeToken, JgToken, AddToken, ClearToken, CmdToken, CopyToken, DivToken, ExitToken, GotoToken, JeToken, JgToken,
JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SetToken, JlToken, LabelToken, LoadToken, LshToken, ModToken, MulToken, PauseToken, RshToken, SetToken,
@ -60,22 +60,22 @@ fn get_token(line: &str) -> Option<Box<dyn Token>> {
match instr_parts.next()? { match instr_parts.next()? {
"exit" => some_box!(ExitToken { "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 { "set" => some_box!(SetToken {
value: parse_value(instr_parts.next()?).expect(&format!( value: parse_value(instr_parts.next()?).expect(&format!(
"Failed to parse the hex value into a u8: {}.", "Failed to parse the hex value into a u8: {}.",
line line
)), )),
register: get_register_by_name(instr_parts.next()?)?, register: get_register_code_by_name(instr_parts.next()?)?,
}), }),
"copy" => some_box!(CopyToken { "copy" => some_box!(CopyToken {
register_1: get_register_by_name(instr_parts.next()?)?, register_1: get_register_code_by_name(instr_parts.next()?)?,
register_2: get_register_by_name(instr_parts.next()?)?, register_2: get_register_code_by_name(instr_parts.next()?)?,
}), }),
"load" => some_box!(LoadToken), "load" => some_box!(LoadToken),
"clear" => some_box!(ClearToken { "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), "write" => some_box!(WriteToken),
"label" => some_box!(LabelToken), "label" => some_box!(LabelToken),

@ -13,7 +13,7 @@ pub const RGO: u8 = 0x08;
pub const RGL: u8 = 0x09; pub const RGL: u8 = 0x09;
/// Maps a register name to the bytecode value /// Maps a register name to the bytecode value
pub fn get_register_by_name(name: &str) -> Option<u8> { pub fn get_register_code_by_name(name: &str) -> Option<u8> {
let item = [ let item = [
("rcs", RCS), ("rcs", RCS),
("rcr", RCR), ("rcr", RCR),

@ -1,8 +1,13 @@
use crate::ledstrip_controller::LedStripController; 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 crate::tokens::Token;
use std::cell::RefCell; use std::cell::{Ref, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::io;
use std::rc::Rc; use std::rc::Rc;
pub struct Runtime { pub struct Runtime {
@ -19,6 +24,8 @@ pub struct Runtime {
text: Vec<Box<dyn Token>>, text: Vec<Box<dyn Token>>,
labels: HashMap<u32, u128>, labels: HashMap<u32, u128>,
strip_controller: Rc<RefCell<LedStripController>>, strip_controller: Rc<RefCell<LedStripController>>,
exit: Option<u8>,
current_index: u128,
} }
impl Runtime { impl Runtime {
@ -41,6 +48,62 @@ impl Runtime {
text: Vec::new(), text: Vec::new(),
labels: HashMap::new(), labels: HashMap::new(),
strip_controller: controller, strip_controller: controller,
exit: None,
current_index: 0,
} }
} }
pub fn exit(&mut self, code: u8) {
self.exit = Some(code);
}
/*
pub fn get_register<T>(&mut self, code: u8) -> Option<&mut impl Register<T>> {
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<Box<&mut dyn Register<u8>>> {
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<Box<&mut dyn Register<u32>>> {
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(())
}
} }

@ -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_NOP: u8 = 0x00;
const T_EXIT: u8 = 0x01; const T_EXIT: u8 = 0x01;
const T_SET: u8 = 0x02; const T_SET: u8 = 0x02;
@ -22,6 +30,7 @@ const T_CMD: u8 = 0xF1;
pub trait Token { pub trait Token {
fn to_bytecode(&self) -> Vec<u8>; fn to_bytecode(&self) -> Vec<u8>;
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()>;
} }
pub trait FromBytecode { pub trait FromBytecode {
@ -34,6 +43,9 @@ impl Token for NopToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_NOP] vec![T_NOP]
} }
fn invoke(&self, _: &mut Runtime) -> io::Result<()> {
Ok(())
}
} }
impl FromBytecode for NopToken { impl FromBytecode for NopToken {
@ -50,6 +62,20 @@ impl Token for ExitToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_EXIT, self.register] 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 { impl FromBytecode for ExitToken {
@ -67,6 +93,18 @@ impl Token for SetToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_SET, self.value, self.register] 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 { impl FromBytecode for SetToken {
@ -87,6 +125,26 @@ impl Token for CopyToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_COPY, self.register_1, self.register_2] 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 { impl FromBytecode for CopyToken {
@ -104,6 +162,17 @@ impl Token for LoadToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_LOAD] 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 { impl FromBytecode for LoadToken {
@ -120,6 +189,18 @@ impl Token for ClearToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_CLEAR, self.register] 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 { impl FromBytecode for ClearToken {
@ -134,6 +215,12 @@ impl Token for WriteToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_WRITE] 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 { impl FromBytecode for WriteToken {
@ -148,6 +235,12 @@ impl Token for LabelToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_LABEL] vec![T_LABEL]
} }
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.create_label(runtime.rgl.get());
Ok(())
}
} }
impl FromBytecode for LabelToken { impl FromBytecode for LabelToken {
@ -162,6 +255,10 @@ impl Token for GotoToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_GOTO] vec![T_GOTO]
} }
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.jump(runtime.rgl.get())
}
} }
impl FromBytecode for GotoToken { impl FromBytecode for GotoToken {
@ -176,6 +273,12 @@ impl Token for AddToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_ADD] 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 { impl FromBytecode for AddToken {
@ -190,6 +293,12 @@ impl Token for SubToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_SUB] 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 { impl FromBytecode for SubToken {
@ -204,6 +313,12 @@ impl Token for MulToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_MUL] 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 { impl FromBytecode for MulToken {
@ -218,6 +333,12 @@ impl Token for DivToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_DIV] 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 { impl FromBytecode for DivToken {
@ -232,6 +353,12 @@ impl Token for ModToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_MOD] 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 { impl FromBytecode for ModToken {
@ -246,6 +373,12 @@ impl Token for LshToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_LSH] 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 { impl FromBytecode for LshToken {
@ -260,6 +393,12 @@ impl Token for RshToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_RSH] 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 { impl FromBytecode for RshToken {
@ -274,6 +413,14 @@ impl Token for JgToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_JG] 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 { impl FromBytecode for JgToken {
@ -288,6 +435,14 @@ impl Token for JlToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_JL] 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 { impl FromBytecode for JlToken {
@ -302,6 +457,14 @@ impl Token for JeToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_JE] 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 { impl FromBytecode for JeToken {
@ -316,6 +479,12 @@ impl Token for PauseToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_PAUSE] 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 { impl FromBytecode for PauseToken {
@ -330,6 +499,12 @@ impl Token for CmdToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_CMD] vec![T_CMD]
} }
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
unimplemented!();
Ok(())
}
} }
impl FromBytecode for CmdToken { impl FromBytecode for CmdToken {

Loading…
Cancel
Save