mirror of
https://github.com/Noratrieb/crapderive.git
synced 2026-01-16 17:45:07 +01:00
interpret
This commit is contained in:
parent
86f7d33c13
commit
25e794f779
3 changed files with 171 additions and 3 deletions
165
src/interpret.rs
Normal file
165
src/interpret.rs
Normal file
|
|
@ -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<u8>,
|
||||||
|
registers: [u64; 16],
|
||||||
|
flag: bool,
|
||||||
|
stmts: Vec<Stmt>,
|
||||||
|
spans: Vec<Span>,
|
||||||
|
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<Stmt>, spans: Vec<Span>) -> Result<()> {
|
||||||
|
let mut ctx = InterpretCtx {
|
||||||
|
memory: vec![0; 100_000],
|
||||||
|
registers: [0; 16],
|
||||||
|
flag: false,
|
||||||
|
stmts,
|
||||||
|
spans,
|
||||||
|
ip: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.interpret()
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, DebugPls)]
|
#[derive(Debug, Clone, Copy, DebugPls)]
|
||||||
pub struct Register(u8);
|
pub struct Register(pub u8);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, DebugPls)]
|
#[derive(Debug, Clone, Copy, DebugPls)]
|
||||||
pub enum Place {
|
pub enum Place {
|
||||||
|
|
@ -30,7 +30,7 @@ pub enum Value {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, DebugPls)]
|
#[derive(Debug, Clone, Copy, DebugPls)]
|
||||||
pub struct Location {
|
pub struct Location {
|
||||||
index: usize,
|
pub index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, DebugPls)]
|
#[derive(Debug, Clone, Copy, DebugPls)]
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::{io, process};
|
||||||
use crate::error::CompilerError;
|
use crate::error::CompilerError;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
mod interpret;
|
||||||
mod ir;
|
mod ir;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
|
|
@ -13,7 +14,9 @@ fn main() -> Result<(), io::Error> {
|
||||||
let ast = result.unwrap_or_else(|e| report_and_exit(&file, e));
|
let ast = result.unwrap_or_else(|e| report_and_exit(&file, e));
|
||||||
dbg_pls::color!(&ast);
|
dbg_pls::color!(&ast);
|
||||||
let stmts = ir::compile(ast.into_iter()).unwrap_or_else(|e| report_and_exit(&file, e));
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue