From 71a6db55a67fe7c2b3357e58306ebdfe09a30ad9 Mon Sep 17 00:00:00 2001 From: Mateusz Russak Date: Sun, 3 Dec 2023 01:18:54 +0100 Subject: [PATCH] feat: addition and subtraction works on VM --- crates/compiler/src/lib.rs | 98 +++++++++------------------------- crates/vm/src/instr.rs | 1 - crates/vm/src/lib.rs | 3 -- crates/vm/src/vm.rs | 3 +- tests/compute_compiled_test.rs | 12 +++-- 5 files changed, 35 insertions(+), 82 deletions(-) diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs index faa715b..d6cee0d 100644 --- a/crates/compiler/src/lib.rs +++ b/crates/compiler/src/lib.rs @@ -2,56 +2,11 @@ use std::{fmt::{Display, Formatter}}; use lexer::PError; use parser::{Node, Op, Value}; -use vm::OpCode; - -struct Instruction { - op_code: OpCode, - arg0: Option, - arg1: Option, - arg2: Option, -} - - -impl Instruction { - pub fn new(op_code: OpCode) -> Instruction { - Instruction { - op_code, - arg0: None, - arg1: None, - arg2: None, - } - } - pub fn with_arg0(mut self, arg0: u8) -> Instruction { - self.arg0 = Some(arg0); - self - } - pub fn with_arg1(mut self, arg1: u8) -> Instruction { - self.arg1 = Some(arg1); - self - } - pub fn with_arg2(mut self, arg2: u8) -> Instruction { - self.arg2 = Some(arg2); - self - } - pub fn to_bytes(&self) -> Vec { - let mut bytes = Vec::new(); - bytes.push(self.op_code as u8); - if let Some(arg0) = self.arg0 { - bytes.push(arg0); - } - if let Some(arg1) = self.arg1 { - bytes.push(arg1); - } - if let Some(arg2) = self.arg2 { - bytes.push(arg2); - } - bytes - } -} +use vm::{Instr, Instrs, OpCode}; struct Code { - code: Vec, + code: Vec, } impl Code { @@ -60,11 +15,11 @@ impl Code { code: Vec::new(), } } - pub fn push(&mut self, inst: Instruction) { + pub fn push(&mut self, inst: Instr) { self.code.push(inst); } pub fn to_bytes(&self) -> Vec { - self.code.iter().flat_map(|i| i.to_bytes()).collect::>() + Instrs(self.code.iter().map(|c| c.byte_description()).collect()).into() } } @@ -104,18 +59,24 @@ pub fn compile_node(node: &Node, mut consts: &mut Mem, inst: &mut Code) -> Resul match node.op { Op::Add => { compile_node(&node.children[0], &mut consts, inst)?; + inst.push(Instr::Mov(2, 0)); + compile_node(&node.children[1], &mut consts, inst)?; + inst.push(Instr::Mov(1, 0)); + inst.push(Instr::Add(0,1,2)); + }, + Op::Sub => { + compile_node(&node.children[0], &mut consts, inst)?; + inst.push(Instr::Mov(2, 0)); compile_node(&node.children[1], &mut consts, inst)?; - inst.push(Instruction::new(OpCode::Add)); + inst.push(Instr::Mov(1, 0)); + inst.push(Instr::Sub(0,2,1)); }, Op::Value => { match &node.value { - Some(Value::Number(0)) => inst.push(Instruction::new(OpCode::Load0)), - Some(Value::Number(1)) => inst.push(Instruction::new(OpCode::Load1)), + Some(Value::Number(0)) => inst.push(Instr::Load0(0)), + Some(Value::Number(1)) => inst.push(Instr::Load1(0)), Some(Value::Number(val)) => { - let addr = consts.write(*val as u32); - if addr < 256 { - inst.push(Instruction::new(OpCode::Load).with_arg0(addr.try_into().unwrap())); - } + inst.push(Instr::Load(0, *val as u16)); }, Some(..) => { panic!("Unknown value: {}", node); @@ -123,14 +84,15 @@ pub fn compile_node(node: &Node, mut consts: &mut Mem, inst: &mut Code) -> Resul None => panic!("No value"), } }, - Op::Scope => { + Op::Scope | Op::Paren => { for child in &node.children { + println!("child: {}", child.op); compile_node(child, &mut consts, inst)?; } - inst.push(Instruction::new(OpCode::Exit)); + inst.push(Instr::Exit); }, _ => { - panic!("Unknown op: {}", node); + panic!("Unknown op: {} {}", node, node.op); } } Ok(()) @@ -141,11 +103,7 @@ pub fn compile(node: &Node) -> Result, PError> { let mut consts = Mem::new(); compile_node(node, &mut consts, &mut inst)?; let code = inst.to_bytes(); - let mem = consts.to_bytes(); - let mut bytes = Vec::new(); - bytes.extend_from_slice(&code); - bytes.extend_from_slice(&mem); - Ok(bytes) + Ok(code) } #[cfg(test)] @@ -155,21 +113,13 @@ mod tests { use super::*; + #[test] fn compile_simple() { let mut node = Node::new(Op::Scope, Location::Eof); node.add(Node::new(Op::Value, Location::Eof).set_value(1.into())); let bytes = compile(&node).unwrap(); - assert_eq!(bytes, vec![3, 5]); + assert_eq!(bytes, vec![OpCode::Load1.into(), 0, OpCode::Exit.into()]); } - fn compile_binary_op() { - let mut node = Node::new(Op::Scope, Location::Eof); - let mut add = Node::new(Op::Add, Location::Eof); - add.add(Node::new(Op::Value, Location::Eof).set_value(1.into())); - add.add(Node::new(Op::Value, Location::Eof).set_value(2.into())); - node.add(add); - let bytes = compile(&node).unwrap(); - assert_eq!(bytes, vec![3, 2, 0, 6, 5]); - } } diff --git a/crates/vm/src/instr.rs b/crates/vm/src/instr.rs index 5f67c21..76c31e7 100644 --- a/crates/vm/src/instr.rs +++ b/crates/vm/src/instr.rs @@ -169,7 +169,6 @@ impl Instr { bytes[i] = data[pc+i]; } - println!("val: {:?}", bytes); let val = u32::from_be_bytes(bytes.try_into().unwrap()); match code { OpCode::Load => parse_instr!(val; tr value -> Load), diff --git a/crates/vm/src/lib.rs b/crates/vm/src/lib.rs index 47db332..77a68fb 100644 --- a/crates/vm/src/lib.rs +++ b/crates/vm/src/lib.rs @@ -8,9 +8,6 @@ extern crate num_derive; #[macro_use] extern crate enum_display; -use std::{fmt::{Display, Formatter}}; - -use lexer::PError; pub use instr::{Instr, Instrs}; pub use op_code::OpCode; pub use vm::VM; diff --git a/crates/vm/src/vm.rs b/crates/vm/src/vm.rs index 65338de..da93f5e 100644 --- a/crates/vm/src/vm.rs +++ b/crates/vm/src/vm.rs @@ -60,7 +60,7 @@ impl VM { pub fn new(prog: Vec) -> VM { VM { prog, - regs: vec![0; 32], + regs: vec![0; 16], stack: Vec::new(), pc: 0, } @@ -79,6 +79,7 @@ impl VM { while let Some(inst) = self.next() { xx -= 1; if xx < 0 {break;} + println!("regs: {:?}", self.regs); println!("inst: {}", inst); match inst { Instr::Sub(target, v1, v2) => { diff --git a/tests/compute_compiled_test.rs b/tests/compute_compiled_test.rs index 0078e2d..8da0565 100644 --- a/tests/compute_compiled_test.rs +++ b/tests/compute_compiled_test.rs @@ -15,11 +15,11 @@ macro_rules! test_return_code{ let node = parse(text).unwrap_or_else(|e| { panic!("\nError:\n{}\n", e.format_error($i, "file.lum", false)); }); - //println!("{}", node); + println!("{}", node); let bytes = compiler::compile(&node).unwrap_or_else(|e| { panic!("\nError:\n{}\n", e.format_error($i, "file.lum", false)); }); - + println!("{:?}", bytes); let mut vm = vm::VM::new(bytes); let val = vm.run().unwrap_or_else(|e| { panic!("\nError:\n{}\n", e.format_error($i, "file.lum", false)); @@ -29,7 +29,13 @@ macro_rules! test_return_code{ }; } -//test_return_code!(simple, "1", 1); +test_return_code!(vm_return_1, "1", 1); +test_return_code!(vm_compute_add, "1+2", 3); +test_return_code!(vm_compute_add_2, "1+2+2", 5); +test_return_code!(vm_compute_sub, "4-2", 2); +test_return_code!(vm_compute_sub_overflow, "2-4", (-2i32) as u32); +test_return_code!(vm_compute_add_and_sub, "1+2-2", 1); +test_return_code!(vm_compute_branch, "if(1){2}else{3}", 2); /* test_return_code!(simple, "1 + 2", 3); test_return_code!(with_braces, "2 * (3 + 4) ", 14);