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

pull/1/head
trivernis 5 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 |
| 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 |
| label (rgl) | creates a label with rgd as the name | 0x07 |
| goto (rgl) | goes to the label with name rgd | 0x08 |
| label <byte> | creates a label at the current position. | 0x07 |
| goto (rgl) | goes to the label with name rgl | 0x08 |
| 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 |
| sub (rgd, rgi, rgo) | substracts rgi from rgd and writes the result into rgo | 0x11 |
@ -53,3 +53,12 @@ A virtual machine for controlling a wifi led strip.
- the rgo register stores the result of operations
- the rgl register stores as label name that can be jumped to
- 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!(
"Failed to parse the hex value into a u8: {}.",
line
)),
)) as u8,
register: get_register_code_by_name(instr_parts.next()?)?,
}),
"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()?)?,
}),
"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),
"debug" => some_box!(DebugToken),
"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)
/// 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") {
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 {
value.parse::<u8>()
value.parse::<u32>()
}
}

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

@ -1,6 +1,7 @@
use crate::registers::{Register, RCS};
use crate::runtime::Runtime;
use std::io;
use std::mem;
use std::thread::sleep;
use std::time::Duration;
@ -242,23 +243,30 @@ impl FromBytecode for WriteToken {
}
#[derive(Debug, Clone)]
pub struct LabelToken;
pub struct LabelToken {
pub value: u32,
}
impl Token for LabelToken {
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<()> {
runtime.create_label(runtime.rgl.get());
runtime.create_label(self.value);
Ok(())
}
}
impl FromBytecode for LabelToken {
fn from_bytecode(_: &[&u8]) -> Self {
Self
fn from_bytecode(code: &[&u8]) -> 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!("rgl: {}", runtime.rgl.get());
println!("\n--- Runtime ---");
println!("Labels: {:?}", runtime.labels);
println!("Memory: {:?}", runtime.memory);
println!();

Loading…
Cancel
Save