From 25e794f77968db0068b85f3e0d9a904c0dbf1181 Mon Sep 17 00:00:00 2001 From: nils <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 20 Jun 2022 14:36:11 +0200 Subject: [PATCH] interpret --- src/interpret.rs | 165 +++++++++++++++++++++++++++++++++++++++++++++++ src/ir.rs | 4 +- src/main.rs | 5 +- 3 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 src/interpret.rs diff --git a/src/interpret.rs b/src/interpret.rs new file mode 100644 index 0000000..d95a971 --- /dev/null +++ b/src/interpret.rs @@ -0,0 +1,165 @@ +//! +//! The interpreter is little endian +//! +//! ```text +//! | 0 | 1 | 2 | 3 +//! --------------- +//! 1 0 0 0 +//! -------------- +//! Decimal 1 +//! ``` + +use logos::Span; + +use crate::{ + error::Result, + ir::{Place, Register, Stmt, Value}, +}; + +impl Register { + fn as_index(self) -> usize { + self.0.into() + } +} + +struct InterpretCtx { + memory: Vec, + registers: [u64; 16], + flag: bool, + stmts: Vec, + spans: Vec, + ip: usize, +} + +impl InterpretCtx { + fn interpret(&mut self) -> Result<()> { + let stmt_i = self.ip; + while stmt_i < self.stmts.len() { + self.ip += 1; + self.interpret_stmt(stmt_i)? + } + Ok(()) + } + + fn interpret_stmt(&mut self, stmt_i: usize) -> Result<()> { + let stmt = &self.stmts[stmt_i]; + match stmt { + Stmt::Mov { from, to } => { + let value = self.read_value(from); + self.write_place(to, value); + } + Stmt::Add { to, value } => { + let old = self.read_place(to); + let value = self.read_value(value); + let new = old.wrapping_add(value); + self.write_place(to, new); + } + Stmt::Sub { to, value } => { + let old = self.read_place(to); + let value = self.read_value(value); + let new = old.wrapping_sub(value); + self.write_place(to, new); + } + Stmt::Mul { to, value } => { + let old = self.read_place(to); + let value = self.read_value(value); + let new = old.wrapping_mul(value); + self.write_place(to, new); + } + Stmt::Div { to, value } => { + let old = self.read_place(to); + let value = self.read_value(value); + let new = old.wrapping_div(value); + self.write_place(to, new); + } + Stmt::Jmp { to } => { + let index = to.index; + self.ip = index; + } + Stmt::Cmp { lhs, rhs } => { + let lhs = self.read_value(lhs); + let rhs = self.read_value(rhs); + self.flag = lhs == rhs; + } + Stmt::Je { to } => { + let index = to.index; + if self.flag { + self.ip = index; + } + } + } + Ok(()) + } + + fn read_value(&self, value: &Value) -> u64 { + match value { + Value::Literal(n) => *n, + Value::Place(place) => self.read_place(place), + } + } + + fn read_place(&self, place: &Place) -> u64 { + match place { + Place::Register(reg) => self.registers[reg.as_index()], + Place::AddrRegister(reg) => { + let addr = self.registers[reg.as_index()] as usize; + self.read_addr(addr) + } + Place::AddrLiteral(addr) => { + let addr = *addr as usize; + self.read_addr(addr) + } + } + } + + fn write_place(&mut self, place: &Place, value: u64) { + match place { + Place::Register(reg) => { + let r = &mut self.registers[reg.as_index()]; + *r = value; + } + Place::AddrRegister(reg) => { + let addr = self.registers[reg.as_index()] as usize; + self.write_addr(addr, value); + } + Place::AddrLiteral(addr) => { + let addr = *addr as usize; + self.write_addr(addr, value); + } + } + } + + fn read_addr(&self, addr: usize) -> u64 { + u64::from_le_bytes([ + self.memory[addr], + self.memory[addr + 1], + self.memory[addr + 2], + self.memory[addr + 3], + self.memory[addr + 4], + self.memory[addr + 5], + self.memory[addr + 6], + self.memory[addr + 7], + ]) + } + + fn write_addr(&mut self, addr: usize, value: u64) { + assert!(addr + 7 < self.memory.len()); + let bytes = value.to_le_bytes(); + for i in 0..8 { + self.memory[addr + i] = bytes[i]; + } + } +} + +pub fn interpret(stmts: Vec, spans: Vec) -> Result<()> { + let mut ctx = InterpretCtx { + memory: vec![0; 100_000], + registers: [0; 16], + flag: false, + stmts, + spans, + ip: 0, + }; + + ctx.interpret() +} diff --git a/src/ir.rs b/src/ir.rs index 5a2f1ed..e053d70 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -11,7 +11,7 @@ use crate::{ }; #[derive(Debug, Clone, Copy, DebugPls)] -pub struct Register(u8); +pub struct Register(pub u8); #[derive(Debug, Clone, Copy, DebugPls)] pub enum Place { @@ -30,7 +30,7 @@ pub enum Value { #[derive(Debug, Clone, Copy, DebugPls)] pub struct Location { - index: usize, + pub index: usize, } #[derive(Debug, Clone, Copy, DebugPls)] diff --git a/src/main.rs b/src/main.rs index c78c3fe..da55f39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::{io, process}; use crate::error::CompilerError; mod error; +mod interpret; mod ir; mod parser; @@ -13,7 +14,9 @@ fn main() -> Result<(), io::Error> { let ast = result.unwrap_or_else(|e| report_and_exit(&file, e)); dbg_pls::color!(&ast); let stmts = ir::compile(ast.into_iter()).unwrap_or_else(|e| report_and_exit(&file, e)); - dbg_pls::color!(stmts.0); + dbg_pls::color!(&stmts.0); + + interpret::interpret(stmts.0, stmts.1).unwrap_or_else(|e| report_and_exit(&file, e)); Ok(()) }