Change label token to accept a 32 bit number instead of reading rgl

pull/1/head
trivernis 4 years ago
parent e5489e49a5
commit 2692d0640d

@ -14,8 +14,8 @@ A virtual machine for controlling a wifi led strip.
| load (rgp, rgd) | loads the value the pointer register points to into the data register | 0x04 | | load (rgp, rgd) | loads the value the pointer register points to into the data register | 0x04 |
| clear \<rg> | clears a register (sets it to 0x00) | 0x05 | | clear \<rg> | clears a register (sets it to 0x00) | 0x05 |
| write (rgd, rgp) | writes the value in the data register to the address of the pointer register | 0x06 | | write (rgd, rgp) | writes the value in the data register to the address of the pointer register | 0x06 |
| label (rgl) | creates a label with rgd as the name | 0x07 | | label <byte> | creates a label at the current position. | 0x07 |
| goto (rgl) | goes to the label with name rgd | 0x08 | | goto (rgl) | goes to the label with name rgl | 0x08 |
| debug (*) | prints out the state for debug information | 0x09 | | debug (*) | prints out the state for debug information | 0x09 |
| add (rgd, rgi, rgo) | adds the value of rgi to the value of rgd and writes the result into rgo | 0x10 | | add (rgd, rgi, rgo) | adds the value of rgi to the value of rgd and writes the result into rgo | 0x10 |
| sub (rgd, rgi, rgo) | substracts rgi from rgd and writes the result into rgo | 0x11 | | sub (rgd, rgi, rgo) | substracts rgi from rgd and writes the result into rgo | 0x11 |
@ -52,4 +52,13 @@ A virtual machine for controlling a wifi led strip.
- the rgi register stores the input for operations that require two input values - the rgi register stores the input for operations that require two input values
- the rgo register stores the result of operations - the rgo register stores the result of operations
- the rgl register stores as label name that can be jumped to - the rgl register stores as label name that can be jumped to
- comments start with # - comments start with #
## The Runtime
The runtime works in three stages.
1. Connect to the led strip
2. Parse the bytecode into a vector of tokens
- if the instruction creates a label, add the label to the map of labels
3. Execute the token vector

@ -68,7 +68,7 @@ fn get_token(line: &str) -> Option<Box<dyn Token>> {
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
)), )) as u8,
register: get_register_code_by_name(instr_parts.next()?)?, register: get_register_code_by_name(instr_parts.next()?)?,
}), }),
"copy" => some_box!(CopyToken { "copy" => some_box!(CopyToken {
@ -80,7 +80,9 @@ fn get_token(line: &str) -> Option<Box<dyn Token>> {
register: get_register_code_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 {
value: parse_value(instr_parts.next()?).expect("Failed to parse label name")
}),
"goto" => some_box!(GotoToken), "goto" => some_box!(GotoToken),
"debug" => some_box!(DebugToken), "debug" => some_box!(DebugToken),
"add" => some_box!(AddToken), "add" => some_box!(AddToken),
@ -102,11 +104,11 @@ fn get_token(line: &str) -> Option<Box<dyn Token>> {
/// Parses a value depending on if it starts with 0x (as a hex value) /// Parses a value depending on if it starts with 0x (as a hex value)
/// or just is a plain base-10 number /// or just is a plain base-10 number
fn parse_value(value: &str) -> Result<u8, ParseIntError> { fn parse_value(value: &str) -> Result<u32, ParseIntError> {
if value.starts_with("0x") { if value.starts_with("0x") {
let value = value.trim_start_matches("0x"); let value = value.trim_start_matches("0x");
Ok(i64::from_str_radix(value, 16)? as u8) Ok(i64::from_str_radix(value, 16)? as u32)
} else { } else {
value.parse::<u8>() value.parse::<u32>()
} }
} }

@ -27,7 +27,7 @@ pub struct Runtime {
pub rgl: Rgl, pub rgl: Rgl,
pub memory: HashMap<u32, u32>, pub memory: HashMap<u32, u32>,
text: Rc<RefCell<Vec<Box<dyn Token>>>>, text: Rc<RefCell<Vec<Box<dyn Token>>>>,
labels: HashMap<u32, usize>, pub labels: HashMap<u32, usize>,
pub strip_controller: Rc<RefCell<LedStripController>>, pub strip_controller: Rc<RefCell<LedStripController>>,
exit: Option<u8>, exit: Option<u8>,
current_index: usize, current_index: usize,
@ -63,6 +63,7 @@ impl Runtime {
pub fn parse_bytecode(&mut self, bytecode: Vec<u8>) { pub fn parse_bytecode(&mut self, bytecode: Vec<u8>) {
let mut code_iter = bytecode.iter(); let mut code_iter = bytecode.iter();
let mut text = self.text.borrow_mut(); let mut text = self.text.borrow_mut();
let mut index = 0;
while let Some(instruction) = code_iter.next() { while let Some(instruction) = code_iter.next() {
match *instruction { match *instruction {
@ -86,7 +87,17 @@ impl Runtime {
code_iter.next().unwrap(), code_iter.next().unwrap(),
]))), ]))),
T_WRITE => text.push(Box::new(WriteToken)), T_WRITE => text.push(Box::new(WriteToken)),
T_LABEL => text.push(Box::new(LabelToken)), T_LABEL => {
let token = LabelToken::from_bytecode(&[
instruction,
code_iter.next().unwrap(),
code_iter.next().unwrap(),
code_iter.next().unwrap(),
code_iter.next().unwrap(),
]);
self.labels.insert(token.value, index);
text.push(Box::new(token));
}
T_GOTO => text.push(Box::new(GotoToken)), T_GOTO => text.push(Box::new(GotoToken)),
T_DEBUG => text.push(Box::new(DebugToken)), T_DEBUG => text.push(Box::new(DebugToken)),
T_ADD => text.push(Box::new(AddToken)), T_ADD => text.push(Box::new(AddToken)),
@ -104,6 +115,7 @@ impl Runtime {
T_SEND => text.push(Box::new(SendToken)), T_SEND => text.push(Box::new(SendToken)),
_ => panic!("unknown instruction {}", instruction), _ => panic!("unknown instruction {}", instruction),
}; };
index += 1;
} }
} }

@ -1,6 +1,7 @@
use crate::registers::{Register, RCS}; use crate::registers::{Register, RCS};
use crate::runtime::Runtime; use crate::runtime::Runtime;
use std::io; use std::io;
use std::mem;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
@ -242,23 +243,30 @@ impl FromBytecode for WriteToken {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LabelToken; pub struct LabelToken {
pub value: u32,
}
impl Token for LabelToken { impl Token for LabelToken {
fn to_bytecode(&self) -> Vec<u8> { fn to_bytecode(&self) -> Vec<u8> {
vec![T_LABEL] let mut bytecode = vec![T_LABEL];
bytecode.append(&mut self.value.to_be_bytes().to_vec());
bytecode
} }
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> { fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.create_label(runtime.rgl.get()); runtime.create_label(self.value);
Ok(()) Ok(())
} }
} }
impl FromBytecode for LabelToken { impl FromBytecode for LabelToken {
fn from_bytecode(_: &[&u8]) -> Self { fn from_bytecode(code: &[&u8]) -> Self {
Self Self {
value: u32::from_be_bytes([*code[1], *code[2], *code[3], *code[4]]),
}
} }
} }
@ -295,6 +303,7 @@ impl Token for DebugToken {
println!("rgo: {}", runtime.rgo.get()); println!("rgo: {}", runtime.rgo.get());
println!("rgl: {}", runtime.rgl.get()); println!("rgl: {}", runtime.rgl.get());
println!("\n--- Runtime ---"); println!("\n--- Runtime ---");
println!("Labels: {:?}", runtime.labels);
println!("Memory: {:?}", runtime.memory); println!("Memory: {:?}", runtime.memory);
println!(); println!();

Loading…
Cancel
Save