+++ /dev/null
-use sorel_ir::*;
-
-use std::collections::HashMap;
-
-use syscalls::*;
-use anyhow::{Result, anyhow};
-
-pub struct Interpreter<'a> {
- module: &'a IRObject,
- data_stack: Vec<u64>,
- instruction_pointer: usize,
- return_stack: Vec<usize>,
- labels: HashMap<String, usize>,
- strings: HashMap<String, String>,
-}
-
-impl<'a> Interpreter<'a> {
- pub fn new(ir_mod: &'a IRObject) -> Result<Self> {
- let mut index = 0;
- let mut labels = HashMap::new();
- for token in ir_mod.text.iter() {
- if let IR::Label(name) = token {
- labels.insert(name.clone(), index);
- }
- index += 1;
- }
- let instruction_pointer = *labels.get("main").ok_or(anyhow!("no main word found!"))?;
-
- let mut strings = HashMap::new();
- ir_mod.data.iter().for_each(|s| {
- match s {
- IR::StringDef(label, string) => {
- strings.insert(label.clone(), string.clone());
- },
- _ => {}
- }
- });
-
- Ok(Self {
- module: ir_mod,
- data_stack: vec![],
- instruction_pointer,
- return_stack: vec![],
- labels,
- strings
- })
- }
-
- fn process_syscall_result(&mut self, result: Result<usize, Errno>) {
- match result {
- Ok(result) => {
- self.data_stack.push(result as u64);
- self.data_stack.push(0);
- }
- Err(err) => {
- self.data_stack.push(0);
- self.data_stack.push(err.into_raw() as u64);
- }
- }
- }
-
- fn ds_pop(&mut self) -> Result<u64> {
- self.data_stack.pop().ok_or(anyhow!("popping from empty data stack"))
- }
-
- pub fn run(&mut self) -> Result<()> {
- let mut looking_for_endif = false;
- loop {
- if looking_for_endif {
- match &self.module.text[self.instruction_pointer] {
- IR::EndIf => {
- looking_for_endif = false;
- },
- IR::Else => {
- looking_for_endif = false;
- }
- _ => {}
- }
- } else {
- match &self.module.text[self.instruction_pointer] {
- IR::Label(_) => {},
- IR::Call(name) => {
- self.return_stack.push(self.instruction_pointer);
- self.instruction_pointer = *self.labels.get(name).ok_or(anyhow!("calling undefined word `{}`", name))?;
- },
- IR::Ret => {
- if self.return_stack.len() == 0 {
- return Ok(());
- }
- self.instruction_pointer = self.return_stack.pop().ok_or(anyhow!("returning from top level"))?;
- },
- IR::StackPush(num) => {
- self.data_stack.push(*num);
- },
- IR::AddU64 => {
- let a = self.ds_pop()?;
- let b = self.ds_pop()?;
- self.data_stack.push(a + b);
- },
- IR::SubtractU64 => {
- let b = self.ds_pop()?;
- let a = self.ds_pop()?;
- self.data_stack.push(a - b);
- },
- IR::Dup => {
- self.data_stack.push(*self.data_stack.last().ok_or(anyhow!("empty data stack"))?);
- },
- IR::Swap => {
- let a = self.ds_pop()?;
- let b = self.ds_pop()?;
- self.data_stack.push(a);
- self.data_stack.push(b);
- },
- IR::Drop => {
- self.data_stack.pop();
- },
- IR::Equals => {
- let a = self.ds_pop()?;
- let b = self.ds_pop()?;
- self.data_stack.push(if a == b {
- 0
- } else {
- -1 as i64 as u64
- });
- },
- IR::GreaterThan => {
- let b = self.ds_pop()?;
- let a = self.ds_pop()?;
- self.data_stack.push(if a > b {
- 0
- } else {
- -1 as i64 as u64
- });
-
- },
- IR::BitwiseOr => {
- let b = self.ds_pop()?;
- let a = self.ds_pop()?;
- self.data_stack.push(a | b);
- }
- IR::If => {
- if self.ds_pop()? != 0 {
- looking_for_endif = true;
- }
- },
- IR::EndIf => {},
- IR::Sys0 => {
- let call_num = Sysno::from(self.ds_pop()? as i32);
- self.process_syscall_result(unsafe { syscall!(call_num) });
- },
- IR::Sys1 => {
- let call_num = Sysno::from(self.ds_pop()? as i32);
- let a1 = self.ds_pop()?;
- self.process_syscall_result(unsafe { syscall!(call_num, a1) });
- },
- IR::Sys2 => {
- let call_num = Sysno::from(self.ds_pop()? as i32);
- let a2 = self.ds_pop()?;
- let a1 = self.ds_pop()?;
- self.process_syscall_result(unsafe { syscall!(call_num, a1, a2) });
- },
- IR::Sys3 => {
- let call_num = Sysno::from(self.ds_pop()? as i32);
- let a3 = self.ds_pop()?;
- let a2 = self.ds_pop()?;
- let a1 = self.ds_pop()?;
- self.process_syscall_result(unsafe { syscall!(call_num, a1, a2, a3) });
- },
- IR::Sys4 => {
- let call_num = Sysno::from(self.ds_pop()? as i32);
- let a4 = self.ds_pop()?;
- let a3 = self.ds_pop()?;
- let a2 = self.ds_pop()?;
- let a1 = self.ds_pop()?;
- self.process_syscall_result(unsafe { syscall!(call_num, a1, a2, a3, a4) });
- },
- IR::Sys5 => {
- let call_num = Sysno::from(self.ds_pop()? as i32);
- let a5 = self.ds_pop()?;
- let a4 = self.ds_pop()?;
- let a3 = self.ds_pop()?;
- let a2 = self.ds_pop()?;
- let a1 = self.ds_pop()?;
- self.process_syscall_result(unsafe { syscall!(call_num, a1, a2, a3, a4, a5) });
- },
- IR::Sys6 => {
- println!("stack: {:?}", self.data_stack);
- let call_num = Sysno::from(self.ds_pop()? as i32);
- let a6 = self.ds_pop()?;
- let a5 = self.ds_pop()?;
- let a4 = self.ds_pop()?;
- let a3 = self.ds_pop()?;
- let a2 = self.ds_pop()?;
- let a1 = self.ds_pop()?;
- self.process_syscall_result(unsafe { syscall!(call_num, a1, a2, a3, a4, a5, a6) });
- },
- _ => {
- println!("Instruction not implemented.");
- },
- }
- }
- self.instruction_pointer += 1;
- }
- }
-}