You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

654 lines
14 KiB
Rust

use crate::registers::{Register, RCS};
use crate::runtime::Runtime;
use num_integer::Roots;
use std::io;
use std::mem;
use std::ops::BitXor;
use std::thread::sleep;
use std::time::Duration;
pub const T_NOP: u8 = 0x00;
pub const T_EXIT: u8 = 0x01;
pub const T_SET: u8 = 0x02;
pub const T_COPY: u8 = 0x03;
pub const T_LOAD: u8 = 0x04;
pub const T_CLEAR: u8 = 0x05;
pub const T_WRITE: u8 = 0x06;
pub const T_LABEL: u8 = 0x07;
pub const T_GOTO: u8 = 0x08;
pub const T_DEBUG: u8 = 0x09;
pub const T_PRINT: u8 = 0x0A;
pub const T_ADD: u8 = 0x10;
pub const T_SUB: u8 = 0x11;
pub const T_MUL: u8 = 0x12;
pub const T_DIV: u8 = 0x13;
pub const T_MOD: u8 = 0x14;
pub const T_LSH: u8 = 0x15;
pub const T_RSH: u8 = 0x16;
pub const T_AND: u8 = 0x17;
pub const T_OR: u8 = 0x18;
pub const T_NOT: u8 = 0x19;
pub const T_XOR: u8 = 0x1A;
pub const T_POW: u8 = 0x1B;
pub const T_NRT: u8 = 0x1C;
pub const T_JG: u8 = 0x20;
pub const T_JL: u8 = 0x21;
pub const T_JE: u8 = 0x22;
pub const T_PAUSE: u8 = 0xF0;
pub const T_CMD: u8 = 0xF1;
pub const T_SEND: u8 = 0xF2;
pub trait Token {
fn to_bytecode(&self) -> Vec<u8>;
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()>;
}
pub trait FromBytecode {
fn from_bytecode(code: &[&u8]) -> Self;
}
#[derive(Debug, Clone)]
pub struct NopToken;
impl Token for NopToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_NOP]
}
fn invoke(&self, _: &mut Runtime) -> io::Result<()> {
Ok(())
}
}
impl FromBytecode for NopToken {
fn from_bytecode(_: &[&u8]) -> Self {
Self
}
}
#[derive(Debug, Clone)]
pub struct ExitToken {
pub register: u8,
}
impl Token for ExitToken {
fn to_bytecode(&self) -> Vec<u8> {
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 {
fn from_bytecode(code: &[&u8]) -> Self {
Self { register: *code[1] }
}
}
#[derive(Debug, Clone)]
pub struct SetToken {
pub value: u8,
pub register: u8,
}
impl Token for SetToken {
fn to_bytecode(&self) -> Vec<u8> {
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 {
fn from_bytecode(code: &[&u8]) -> Self {
Self {
value: *code[1],
register: *code[2],
}
}
}
#[derive(Debug, Clone)]
pub struct CopyToken {
pub register_1: u8,
pub register_2: u8,
}
impl Token for CopyToken {
fn to_bytecode(&self) -> Vec<u8> {
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;
} else {
panic!("unknown register {}", self.register_1);
}
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);
} else {
panic!("unknown register {}", self.register_2);
}
Ok(())
}
}
impl FromBytecode for CopyToken {
fn from_bytecode(code: &[&u8]) -> Self {
Self {
register_1: *code[1],
register_2: *code[2],
}
}
}
#[derive(Debug, Clone)]
pub struct LoadToken;
impl Token for LoadToken {
fn to_bytecode(&self) -> Vec<u8> {
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 {
fn from_bytecode(_: &[&u8]) -> Self {
Self
}
}
#[derive(Debug, Clone)]
pub struct ClearToken {
pub register: u8,
}
impl Token for ClearToken {
fn to_bytecode(&self) -> Vec<u8> {
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 {
fn from_bytecode(code: &[&u8]) -> Self {
Self { register: *code[1] }
}
}
#[derive(Debug, Clone)]
pub struct WriteToken;
impl Token for WriteToken {
fn to_bytecode(&self) -> Vec<u8> {
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 {
fn from_bytecode(_: &[&u8]) -> Self {
Self
}
}
#[derive(Debug, Clone)]
pub struct LabelToken {
pub value: u32,
}
impl Token for LabelToken {
fn to_bytecode(&self) -> Vec<u8> {
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(self.value);
Ok(())
}
}
impl FromBytecode for LabelToken {
fn from_bytecode(code: &[&u8]) -> Self {
Self {
value: u32::from_be_bytes([*code[1], *code[2], *code[3], *code[4]]),
}
}
}
#[derive(Debug, Clone)]
pub struct GotoToken;
impl Token for GotoToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_GOTO]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.jump(runtime.rgl.get())
}
}
#[derive(Debug, Clone)]
pub struct DebugToken;
impl Token for DebugToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_DEBUG]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
println!("--- Registers --");
println!("rcs: {}", runtime.rcs.get());
println!("rcr: {}", runtime.rcr.get());
println!("rcg: {}", runtime.rcg.get());
println!("rcb: {}", runtime.rcb.get());
println!("rgd: {}", runtime.rgd.get());
println!("rgp: {}", runtime.rgp.get());
println!("rgi: {}", runtime.rgi.get());
println!("rgo: {}", runtime.rgo.get());
println!("rgl: {}", runtime.rgl.get());
println!("\n--- Runtime ---");
println!("Labels: {:?}", runtime.labels);
println!("Memory: {:?}", runtime.memory);
println!();
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct PrintToken {
pub register: u8,
}
impl Token for PrintToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_PRINT, self.register]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
let mut value = if let Some(rg) = runtime.get_1byte_register(self.register) {
rg.get() as u32
} else if let Some(rg) = runtime.get_4byte_register(self.register) {
rg.get()
} else if self.register == RCS {
runtime.rcs.get() as u32
} else {
0
};
println!("{}", value);
Ok(())
}
}
impl FromBytecode for PrintToken {
fn from_bytecode(code: &[&u8]) -> Self {
Self { register: *code[1] }
}
}
#[derive(Debug, Clone)]
pub struct AddToken;
impl Token for AddToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_ADD]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() + runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct SubToken;
impl Token for SubToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_SUB]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() - runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct MulToken;
impl Token for MulToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_MUL]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() * runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct DivToken;
impl Token for DivToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_DIV]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() / runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct ModToken;
impl Token for ModToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_MOD]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() % runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct LshToken;
impl Token for LshToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_LSH]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() << runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct RshToken;
impl Token for RshToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_RSH]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() >> runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct AndToken;
impl Token for AndToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_AND]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() & runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct OrToken;
impl Token for OrToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_OR]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get() | runtime.rgi.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct NotToken;
impl Token for NotToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_NOT]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(!runtime.rgd.get());
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct XorToken;
impl Token for XorToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_XOR]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(runtime.rgd.get().bitxor(runtime.rgi.get()));
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct PowToken;
impl Token for PowToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_POW]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime.rgo.set(
(runtime.rgd.get() as f32)
.powi(runtime.rgi.get() as i32)
.round() as u32,
);
Ok(())
}
}
pub struct NrtToken;
impl Token for NrtToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_NRT]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
runtime
.rgo
.set(runtime.rgd.get().nth_root(runtime.rgi.get()));
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct JgToken;
impl Token for JgToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_JG]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
if runtime.rgd.get() > runtime.rgi.get() {
runtime.jump(runtime.rgl.get())?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct JlToken;
impl Token for JlToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_JL]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
if runtime.rgd.get() < runtime.rgi.get() {
runtime.jump(runtime.rgl.get())?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct JeToken;
impl Token for JeToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_JE]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
if runtime.rgd.get() == runtime.rgi.get() {
runtime.jump(runtime.rgl.get())?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct PauseToken;
impl Token for PauseToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_PAUSE]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
sleep(Duration::from_millis(runtime.rgd.get() as u64));
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct CmdToken;
impl Token for CmdToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_CMD]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
unimplemented!();
Ok(())
}
}
pub struct SendToken;
impl Token for SendToken {
fn to_bytecode(&self) -> Vec<u8> {
vec![T_SEND]
}
fn invoke(&self, runtime: &mut Runtime) -> io::Result<()> {
let r = runtime.rcr.get();
let g = runtime.rcg.get();
let b = runtime.rcb.get();
runtime
.strip_controller
.borrow_mut()
.send_rgb_color(r, g, b)
}
}