begin executor
This commit is contained in:
parent
eae6c61c24
commit
c880366eb0
3 changed files with 252 additions and 19 deletions
243
src/executor.rs
Normal file
243
src/executor.rs
Normal file
|
@ -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<ASTPart>,
|
||||
pub pos: usize,
|
||||
pub memory: Vec<Vec<MemoryData>>,
|
||||
pub state: State,
|
||||
pub breakpoints: Vec<usize>,
|
||||
pub max_oppr: usize
|
||||
}
|
||||
|
||||
struct Processed {
|
||||
ret: ASTPart,
|
||||
yld: bool,
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
pub fn new(code: Vec<ASTPart>, 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
20
test.as
20
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)
|
||||
}
|
||||
gethelj b = 2
|
Loading…
Add table
Add a link
Reference in a new issue