From c880366eb0b527945df2429a3375a7a9ee77aebf Mon Sep 17 00:00:00 2001 From: afonya2 Date: Sat, 24 May 2025 18:01:07 +0200 Subject: [PATCH] begin executor --- src/executor.rs | 243 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 8 ++ test.as | 20 +--- 3 files changed, 252 insertions(+), 19 deletions(-) create mode 100644 src/executor.rs diff --git a/src/executor.rs b/src/executor.rs new file mode 100644 index 0000000..6fd8410 --- /dev/null +++ b/src/executor.rs @@ -0,0 +1,243 @@ +use crate::parser::{ASTPart, AstBool, AstNull, AstNumber, AstString}; + +#[derive(Debug, PartialEq)] +pub enum State { + Running, + Paused, + Finished, + Error(String) +} + +#[derive(Debug, Clone, PartialEq)] +pub enum MemoryData { + Number(MemoryNumber), + String(MemoryString), + Boolean(MemoryBoolean), + Null(MemoryNull) +} +#[derive(Debug, Clone, PartialEq)] +pub struct MemoryNumber { + pub key: String, + pub value: i64 +} +#[derive(Debug, Clone, PartialEq)] +pub struct MemoryString { + pub key: String, + pub value: String +} +#[derive(Debug, Clone, PartialEq)] +pub struct MemoryBoolean { + pub key: String, + pub value: bool +} +#[derive(Debug, Clone, PartialEq)] +pub struct MemoryNull { + pub key: String, +} + +pub struct Executor { + pub code: Vec, + pub pos: usize, + pub memory: Vec>, + pub state: State, + pub breakpoints: Vec, + pub max_oppr: usize +} + +struct Processed { + ret: ASTPart, + yld: bool, +} + +impl Executor { + pub fn new(code: Vec, max_oppr: usize) -> Executor { + return Executor { + code, + pos: 0, + memory: vec![ + vec![] + ], + breakpoints: vec![], + state: State::Paused, + max_oppr, + }; + } + + fn read_memory(&mut self, key: String, check_mode: bool) -> ASTPart { + let current_scope = self.memory.len() - 1; + for scope in current_scope..0 { + for data in &self.memory[scope] { + match data { + MemoryData::Number(num) => { + if num.key == key { + return ASTPart::Number(AstNumber { value: num.value, pos: 0 }); + } + }, + MemoryData::String(str) => { + if str.key == key { + return ASTPart::String(AstString { value: str.value.clone(), pos: 0 }); + } + }, + MemoryData::Boolean(bool_data) => { + if bool_data.key == key { + return ASTPart::Boolean(AstBool { value: bool_data.value, pos: 0 }); + } + }, + MemoryData::Null(null_data) => { + if null_data.key == key { + return ASTPart::Null(AstNull { pos: 0 }); + } + } + } + } + if check_mode { + return ASTPart::NOOP; + } + } + return ASTPart::Null(AstNull { pos: 0 }); + } + + fn delete_memory(&mut self, key: String) -> bool { + let current_scope = self.memory.len() - 1; + for data in 0..self.memory[current_scope].len() { + match &self.memory[current_scope][data] { + MemoryData::Number(num) => { + if num.key == key { + self.memory[current_scope].remove(data); + return true; + } + }, + MemoryData::String(str) => { + if str.key == key { + self.memory[current_scope].remove(data); + return true; + } + }, + MemoryData::Boolean(bool_data) => { + if bool_data.key == key { + self.memory[current_scope].remove(data); + return true; + } + }, + MemoryData::Null(null_data) => { + if null_data.key == key { + self.memory[current_scope].remove(data); + return true; + } + } + } + } + return false; + } + + fn write_memory(&mut self, key: String, value: ASTPart, update: bool) { + if !update { + self.delete_memory(key.clone()); + } else { + let red = self.read_memory(key.clone(), true); + match red { + ASTPart::NOOP => { + self.delete_memory(key.clone()); + }, + _ => { + panic!("Uanble to update non-existing memory key: {}", key); + } + } + } + match value { + ASTPart::Number(num) => { + let current_scope = self.memory.len() - 1; + self.memory[current_scope].push(MemoryData::Number(MemoryNumber { key: key, value: num.value })); + }, + ASTPart::String(str) => { + let current_scope = self.memory.len() - 1; + self.memory[current_scope].push(MemoryData::String(MemoryString { key: key, value: str.value })); + }, + ASTPart::Boolean(bool_data) => { + let current_scope = self.memory.len() - 1; + self.memory[current_scope].push(MemoryData::Boolean(MemoryBoolean { key: key, value: bool_data.value })); + }, + ASTPart::Null(_) => { + let current_scope = self.memory.len() - 1; + self.delete_memory(key.clone()); + self.memory[current_scope].push(MemoryData::Null(MemoryNull { key: key })); + }, + _ => { + panic!("Unable to write to memory: {:?}", value); + } + } + } + + fn process_code(&mut self, code: &ASTPart, op_count: &mut usize) -> Processed { + println!("Processing code: {:?}", code); + if *op_count >= self.max_oppr { + return Processed { + ret: ASTPart::NOOP, + yld: false, + }; + } + *op_count += 1; + match code { + ASTPart::String(_) => { + return Processed { + ret: code.clone(), + yld: false, + }; + }, + ASTPart::Number(_) => { + return Processed { + ret: code.clone(), + yld: false, + }; + }, + ASTPart::Boolean(_) => { + return Processed { + ret: code.clone(), + yld: false, + }; + }, + ASTPart::Assigment(assign) => { + let value = self.process_code(&assign.value, op_count); + self.write_memory(assign.variable.clone(), value.ret, false); + return Processed { + ret: ASTPart::NOOP, + yld: false, + }; + } + _ => { + return Processed { + ret: ASTPart::NOOP, + yld: true, + }; + } + } + } + + pub fn resume(&mut self) { + if self.state != State::Paused { + panic!("Cannot resume executor, it is not paused."); + } + self.state = State::Running; + let mut op_count: usize = 0; + while self.pos < self.code.len() { + if self.breakpoints.len() > 0 && self.breakpoints[0] == self.pos { + self.state = State::Paused; + self.breakpoints.remove(0); + break; + } + let proc = self.process_code(&self.code[self.pos].clone(), &mut op_count); + if proc.yld { + self.state = State::Paused; + break; + } + if op_count >= self.max_oppr { + self.state = State::Error(String::from("Too long without yielding!")); + break; + } + self.pos += 1; + } + if self.pos >= self.code.len() { + self.state = State::Finished; + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a3d45aa..ece85fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ use std::fs; +use executor::Executor; use parser::ASTPart; mod lexer; mod parser; +mod executor; fn log_ast_part(part: &ASTPart, prefix: String) { match part { @@ -113,6 +115,12 @@ fn main() { for part in &ast { log_ast_part(part, String::from(" ")); } + let mut executor = Executor::new(ast, 100); + executor.resume(); + println!("\nFinished!"); + println!("State: {:?}", executor.state); + println!("Position: {}", executor.pos); + println!("Memory: {:?}", executor.memory); }, Result::Err(err) => { panic!("Error while reading file: {}", err) diff --git a/test.as b/test.as index 5793560..394ee8c 100644 --- a/test.as +++ b/test.as @@ -1,20 +1,2 @@ gethelj a = 1 -gethelj b = (a + 2) * 3 -ugass(a,b) -gethelj c = piszv & nem piszv -gethelj d = lőcsve(e,f) { - ugass(a,b) -} -ha geny (1 == 1) { - ugass(1) -} ha nem geny { - ugass(2) -} ha nem geny akkor geny (1 == 2) { - ugass(3) -} -amíg geny (1 == 1) { - kraf -} -kopva (gethelj i = 0; i < 10; i = i + 1) { - ugass(i) -} \ No newline at end of file +gethelj b = 2 \ No newline at end of file