From 3ff7aac2d2eb2cbf2f854793fc0d7bc6f1f7d927 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sun, 9 Jan 2022 08:40:09 -0800 Subject: Initial commit. Not sure if everything here will be needed eventually, but we have a working bytecode interpreter. Next I will write the linker, then the core compiler, and finish with the macro expander. --- bytecode/src/encoding.rs | 225 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 bytecode/src/encoding.rs (limited to 'bytecode/src/encoding.rs') diff --git a/bytecode/src/encoding.rs b/bytecode/src/encoding.rs new file mode 100644 index 0000000..b3a7983 --- /dev/null +++ b/bytecode/src/encoding.rs @@ -0,0 +1,225 @@ +use crate::bytecode::Op; +use std::io::Read; + +fn read_tag(prog: &mut T) -> Result { + let mut buf = [0; 8]; + match prog.read_exact(&mut buf) { + Ok(()) => (), + Err(_) => { + return Err(String::from("error reading input")); + } + }; + Ok(u64::from_le_bytes(buf)) +} + +fn read_i64(prog: &mut T) -> Result { + let mut buf = [0; 8]; + match prog.read_exact(&mut buf) { + Ok(()) => (), + Err(_) => { + return Err(String::from("error reading input")); + } + }; + Ok(i64::from_le_bytes(buf)) +} + +fn read_u8(prog: &mut T) -> Result { + let mut buf = vec![0]; + match prog.read_exact(&mut buf) { + Ok(()) => (), + Err(_) => { + return Err(String::from("error reading input")); + } + }; + Ok(buf[0]) +} + +fn op_decoding(prog: &mut T) -> Result { + let op = match read_tag(prog)? { + 1010 => Op::Const(read_i64(prog)?), + 1020 => Op::Add, + 1030 => Op::Sub, + 1040 => Op::Mul, + 1050 => Op::Div, + 1060 => Op::Mod, + 2010 => Op::Alloc, + 2020 => Op::Peek(read_u8(prog)?), + 2030 => Op::Poke(read_u8(prog)?), + 2040 => Op::PeekByte, + 2050 => Op::PokeByte, + 3010 => Op::Pop, + 3020 => Op::Local(read_u8(prog)?), + 4010 => Op::If(read_i64(prog)?), + 4020 => Op::Call(read_u8(prog)?), + 4030 => Op::Ret, + 4040 => Op::Exit, + 5010 => Op::PutC, + 5020 => Op::GetC, + _ => { + return Err(String::from("invalid opcode")); + } + }; + Ok(op) +} + +pub fn decode(prog: &[u8]) -> Result, String> { + let mut reader = prog; + let mut out = Vec::new(); + while reader.len() > 0 { + out.push(op_decoding(&mut reader)?); + } + Ok(out) +} + +mod tests { + use super::*; + + #[test] + fn decode_const() { + assert_eq!( + Ok(vec![Op::Const(10)]), + decode(&vec![0xf2, 0x3, 0, 0, 0, 0, 0, 0, 0xa, 0, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_add() { + assert_eq!( + Ok(vec![Op::Add]), + decode(&vec![0xfc, 0x3, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_sub() { + assert_eq!(Ok(vec![Op::Sub]), decode(&vec![0x6, 0x4, 0, 0, 0, 0, 0, 0])); + } + + #[test] + fn decode_mul() { + assert_eq!( + Ok(vec![Op::Mul]), + decode(&vec![0x10, 0x4, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_div() { + assert_eq!( + Ok(vec![Op::Div]), + decode(&vec![0x1a, 0x4, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_mod() { + assert_eq!( + Ok(vec![Op::Mod]), + decode(&vec![0x24, 0x4, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_alloc() { + assert_eq!( + Ok(vec![Op::Alloc]), + decode(&vec![0xda, 0x7, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_peek() { + assert_eq!( + Ok(vec![Op::Peek(10)]), + decode(&vec![0xe4, 0x7, 0, 0, 0, 0, 0, 0, 0xa]) + ); + } + + #[test] + fn decode_poke() { + assert_eq!( + Ok(vec![Op::Poke(10)]), + decode(&vec![0xee, 0x7, 0, 0, 0, 0, 0, 0, 0xa]) + ); + } + + #[test] + fn decode_peek_byte() { + assert_eq!( + Ok(vec![Op::PeekByte]), + decode(&vec![0xf8, 0x7, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_poke_byte() { + assert_eq!( + Ok(vec![Op::PokeByte]), + decode(&vec![0x2, 0x8, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_pop() { + assert_eq!( + Ok(vec![Op::Pop]), + decode(&vec![0xc2, 0xb, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_local() { + assert_eq!( + Ok(vec![Op::Local(10)]), + decode(&vec![0xcc, 0xb, 0, 0, 0, 0, 0, 0, 0xa]) + ); + } + + #[test] + fn decode_if() { + assert_eq!( + Ok(vec![Op::If(10)]), + decode(&vec![0xaa, 0xf, 0, 0, 0, 0, 0, 0, 0xa, 0, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_call() { + assert_eq!( + Ok(vec![Op::Call(10)]), + decode(&vec![0xb4, 0xf, 0, 0, 0, 0, 0, 0, 0xa]) + ); + } + + #[test] + fn decode_ret() { + assert_eq!( + Ok(vec![Op::Ret]), + decode(&vec![0xbe, 0xf, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_exit() { + assert_eq!( + Ok(vec![Op::Exit]), + decode(&vec![0xc8, 0xf, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_putc() { + assert_eq!( + Ok(vec![Op::PutC]), + decode(&vec![0x92, 0x13, 0, 0, 0, 0, 0, 0]) + ); + } + + #[test] + fn decode_getc() { + assert_eq!( + Ok(vec![Op::GetC]), + decode(&vec![0x9c, 0x13, 0, 0, 0, 0, 0, 0]) + ); + } +} -- cgit v1.3.1