upgrade the variable system

This commit is contained in:
afonya2 2025-06-03 17:08:32 +02:00
parent 431b04cf2a
commit a8e174af7f
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
3 changed files with 131 additions and 83 deletions

View file

@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, vec};
use crate::parser::ASTPart;
@ -29,11 +29,20 @@ struct AllocateResult {
#[derive(Debug, Clone)]
struct Compiled {
operations: Vec<Operation>,
var_ids: HashMap<String, u32>,
variables: Vec<Variable>,
strings: HashMap<u32, String>,
functions: HashMap<u32, Compiled>
}
#[derive(Debug, Clone)]
struct Variable {
name: String,
id: u32,
start: usize,
end: usize,
no_end: bool
}
fn get_register_by_id(registers: &Vec<RegisterState>, id: u8) -> RegisterState {
for register in registers {
if register.id == id {
@ -48,9 +57,9 @@ fn get_register_by_id(registers: &Vec<RegisterState>, id: u8) -> RegisterState {
};
}
fn get_register_by_variable(registers: &Vec<RegisterState>, variable: u32) -> RegisterState {
fn get_register_by_variable(registers: &Vec<RegisterState>, variable: Variable) -> RegisterState {
for register in registers {
if register.variable == variable {
if register.variable == variable.id {
return register.clone();
}
}
@ -119,7 +128,18 @@ fn garbage_collect_registers(registers: &mut Vec<RegisterState>) {
}
}
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, var_ids: &mut HashMap<String, u32>, next_var_id: &mut u32, strings: &mut HashMap<u32, String>, next_string_id: &mut u32, functions: &mut HashMap<u32, Compiled>, next_function_id: &mut u32, registers: &mut Vec<RegisterState>) -> u8 {
fn get_variable_by_name(variables: &Vec<Variable>, name: &str, position: usize) -> Option<Variable> {
for variable in variables {
if variable.name == name {
if variable.start <= position && (variable.no_end || variable.end >= position) {
return Some(variable.clone());
}
}
}
None
}
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, variables: &mut Vec<Variable>, next_var_id: &mut u32, strings: &mut HashMap<u32, String>, next_string_id: &mut u32, functions: &mut HashMap<u32, Compiled>, next_function_id: &mut u32, registers: &mut Vec<RegisterState>) -> u8 {
*op_count += 1;
match ast_op {
ASTPart::Number(num) => {
@ -162,17 +182,17 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return reg.register;
},
ASTPart::VarRead(var_read) => {
if !var_ids.contains_key(&var_read.variable) {
if get_variable_by_name(variables, &var_read.variable, ops.len()).is_none() {
panic!("Variable {} does not exist", var_read.variable);
}
let reg = get_register_by_variable(registers, var_ids[&var_read.variable]);
let reg = get_register_by_variable(registers, get_variable_by_name(variables, &var_read.variable, ops.len()).expect("Variable should exist"));
if reg.id == 0 {
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
}
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(var_ids[&var_read.variable] as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: var_ids[&var_read.variable], last_used: *op_count });
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, &var_read.variable, ops.len()).expect("Variable should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, &var_read.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
return reg.register;
} else {
return reg.id;
@ -180,7 +200,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
},
ASTPart::Function(func) => {
let func_id = *next_function_id;
functions.insert(func_id, compile_function(func.body, Some(func.args), registers));
functions.insert(func_id, compile_function(func.body, Some(func.args), registers, next_var_id));
*next_function_id += 1;
let reg = allocate_register(registers);
if reg.unbind_before {
@ -190,30 +210,34 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
},
ASTPart::Call(call) => {
let func = do_ast_op(*call.function, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
for arg in call.args {
let arg_reg = do_ast_op(arg, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let arg_reg = do_ast_op(arg, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 28, arg1: Some(arg_reg), arg2: None, arg3: None });
set_register(registers, RegisterState { id: arg_reg, used: false, variable: 0, last_used: 0 });
}
ops.push(Operation { opcode: 27, arg1: Some(func), arg2: None, arg3: None });
},
ASTPart::If(if_part) => {
let condition_reg = do_ast_op(*if_part.condition, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let condition_reg = do_ast_op(*if_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
//Update the lastif variable
if !var_ids.contains_key("__LASTIF") {
var_ids.insert(String::from("__LASTIF"), *next_var_id);
if get_variable_by_name(variables, "__LASTIF", ops.len()).is_none() {
variables.push(Variable { name: String::from("__LASTIF"), id: *next_var_id, start: ops.len(), end: 0, no_end: true });
*next_var_id += 1;
}
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(var_ids["__LASTIF"] as i64), arg3: None });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: var_ids["__LASTIF"], last_used: *op_count });
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
let mut fake_vars: Vec<Variable> = vec![];
for if_op in if_part.body {
do_ast_op(if_op, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(if_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers);
}
for fake_var in fake_vars {
variables.push(Variable { name: fake_var.name, id: fake_var.id, start: fake_var.start, end: ops.len()-1, no_end: false });
}
ops[op_placeholder] = Operation {
opcode: 26,
@ -223,22 +247,25 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
};
//Unbind the lastif variable
if get_register_by_id(registers, condition_reg).variable == var_ids["__LASTIF"] {
if get_register_by_id(registers, condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id {
ops.push(Operation { opcode: 8, arg1: Some(condition_reg), arg2: None, arg3: None });
set_register(registers, RegisterState { id: condition_reg, used: false, variable: 0, last_used: 0 });
}
garbage_collect_registers(registers);
},
ASTPart::Else(else_part) => {
let reg = get_register_by_variable(registers, var_ids["__LASTIF"]);
if get_variable_by_name(variables, "__LASTIF", ops.len()).is_none() {
panic!("Else used without an if statement before it");
}
let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").clone());
let else_condition_reg;
if reg.id == 0 {
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
}
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(var_ids["__LASTIF"] as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: var_ids["__LASTIF"], last_used: *op_count });
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
else_condition_reg = reg.register;
} else {
else_condition_reg = reg.id;
@ -247,8 +274,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
let mut fake_vars: Vec<Variable> = vec![];
for else_op in else_part.body {
do_ast_op(else_op, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(else_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers);
}
for fake_var in fake_vars {
variables.push(Variable { name: fake_var.name, id: fake_var.id, start: fake_var.start, end: ops.len()-1, no_end: false });
}
ops[op_placeholder] = Operation {
opcode: 26,
@ -257,44 +288,47 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg3: None,
};
//Unbind the lastif variable
if get_register_by_id(registers, else_condition_reg).variable == var_ids["__LASTIF"] {
if get_register_by_id(registers, else_condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id {
ops.push(Operation { opcode: 8, arg1: Some(else_condition_reg), arg2: None, arg3: None });
set_register(registers, RegisterState { id: else_condition_reg, used: false, variable: 0, last_used: 0 });
}
garbage_collect_registers(registers);
},
ASTPart::ElseIf(elseif_part) => {
let reg = get_register_by_variable(registers, var_ids["__LASTIF"]);
if get_variable_by_name(variables, "__LASTIF", ops.len()).is_none() {
panic!("Else if used without an if statement before it");
}
let reg = get_register_by_variable(registers, get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").clone());
let else_condition_reg;
if reg.id == 0 {
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
}
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(var_ids["__LASTIF"] as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: var_ids["__LASTIF"], last_used: *op_count });
ops.push(Operation { opcode: 2, arg1: Some(reg.register), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: reg.register, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
else_condition_reg = reg.register;
} else {
else_condition_reg = reg.id;
}
ops.push(Operation { opcode: 24, arg1: Some(else_condition_reg), arg2: Some(else_condition_reg as i64), arg3: None });
let condition_reg = do_ast_op(*elseif_part.condition, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let condition_reg = do_ast_op(*elseif_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 16, arg1: Some(else_condition_reg), arg2: Some(condition_reg as i64), arg3: Some(condition_reg) });
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
//Update the lastif variable
if !var_ids.contains_key("__LASTIF") {
var_ids.insert(String::from("__LASTIF"), *next_var_id);
*next_var_id += 1;
}
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(var_ids["__LASTIF"] as i64), arg3: None });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: var_ids["__LASTIF"], last_used: *op_count });
ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: condition_reg, used: true, variable: get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id, last_used: *op_count });
let op_placeholder = ops.len();
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
let mut fake_vars: Vec<Variable> = vec![];
for elseif_op in elseif_part.body {
do_ast_op(elseif_op, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(elseif_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers);
}
for fake_var in fake_vars {
variables.push(Variable { name: fake_var.name, id: fake_var.id, start: fake_var.start, end: ops.len()-1, no_end: false });
}
ops[op_placeholder] = Operation {
opcode: 26,
@ -303,7 +337,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
arg3: None,
};
//Unbind the lastif variable
if get_register_by_id(registers, condition_reg).variable == var_ids["__LASTIF"] {
if get_register_by_id(registers, condition_reg).variable == get_variable_by_name(variables, "__LASTIF", ops.len()).expect("__LASTIF should exist").id {
ops.push(Operation { opcode: 8, arg1: Some(condition_reg), arg2: None, arg3: None });
set_register(registers, RegisterState { id: condition_reg, used: false, variable: 0, last_used: 0 });
}
@ -311,7 +345,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
},
ASTPart::While(while_part) => {
let start = ops.len();
let condition_reg = do_ast_op(*while_part.condition, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let condition_reg = do_ast_op(*while_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
let op_placeholder = ops.len();
@ -329,7 +363,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
},
_ => {
do_ast_op(while_op, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(while_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
}
}
}
@ -364,9 +398,9 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
panic!("Unexpected continue outside of loop at {}", op_count);
},
ASTPart::For(for_part) => {
do_ast_op(*for_part.init, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(*for_part.init, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let start = ops.len();
let condition_reg = do_ast_op(*for_part.condition, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let condition_reg = do_ast_op(*for_part.condition, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None });
let op_placeholder = ops.len();
@ -384,11 +418,11 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None });
},
_ => {
do_ast_op(for_op, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(for_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
}
}
}
do_ast_op(*for_part.update, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
do_ast_op(*for_part.update, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as i64), arg3: None });
ops[op_placeholder] = Operation {
@ -415,12 +449,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
}
},
ASTPart::Return(ret) => {
let ret_reg = do_ast_op(*ret.value, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let ret_reg = do_ast_op(*ret.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 29, arg1: Some(ret_reg), arg2: None, arg3: None });
},
ASTPart::Operation(op) => {
let left_reg = do_ast_op(*op.left, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let right_reg = do_ast_op(*op.right, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let left_reg = do_ast_op(*op.left, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let right_reg = do_ast_op(*op.right, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
let reg = allocate_register(registers);
if reg.unbind_before {
ops.push(Operation { opcode: 8, arg1: Some(reg.register), arg2: None, arg3: None });
@ -452,28 +486,28 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return reg.register;
},
ASTPart::VarUpdate(upd) => {
if !var_ids.contains_key(&upd.variable) {
if get_variable_by_name(variables, &upd.variable, ops.len()).is_none() {
panic!("Variable {} does not exist", upd.variable);
}
let reg = get_register_by_variable(registers, var_ids[&upd.variable]);
let reg = get_register_by_variable(registers, get_variable_by_name(variables, &upd.variable, ops.len()).expect("Variable should exist").clone());
if reg.id != 0 {
ops.push(Operation { opcode: 8, arg1: Some(reg.id), arg2: None, arg3: None });
set_register(registers, RegisterState { id: reg.id, used: false, variable: 0, last_used: 0 });
}
let value_reg = do_ast_op(*upd.value, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 7, arg1: Some(value_reg), arg2: Some(var_ids[&upd.variable] as i64), arg3: None });
set_register(registers, RegisterState { id: value_reg, used: true, variable: var_ids[&upd.variable], last_used: *op_count });
let value_reg = do_ast_op(*upd.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 7, arg1: Some(value_reg), arg2: Some(get_variable_by_name(variables, &upd.variable, ops.len()).expect("Variable should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: value_reg, used: true, variable: get_variable_by_name(variables, &upd.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
garbage_collect_registers(registers);
},
ASTPart::Assigment(asign) => {
if var_ids.contains_key(&asign.variable) {
if get_variable_by_name(variables, &asign.variable, ops.len()).is_some() {
panic!("Variable {} already exists", asign.variable);
}
var_ids.insert(asign.variable.clone(), *next_var_id);
let reg = do_ast_op(*asign.value, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
variables.push(Variable { name: asign.variable.clone(), id: *next_var_id, start: ops.len(), end: 0, no_end: true });
*next_var_id += 1;
let reg = do_ast_op(*asign.value, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers);
ops.push(Operation { opcode: 7, arg1: Some(reg), arg2: Some(var_ids[&asign.variable.clone()] as i64), arg3: None });
set_register(registers, RegisterState { id: reg, used: true, variable: var_ids[&asign.variable.clone()], last_used: *op_count });
ops.push(Operation { opcode: 7, arg1: Some(reg), arg2: Some(get_variable_by_name(variables, &asign.variable, ops.len()).expect("Variable should exist").id as i64), arg3: None });
set_register(registers, RegisterState { id: reg, used: true, variable: get_variable_by_name(variables, &asign.variable, ops.len()).expect("Variable should exist").id, last_used: *op_count });
garbage_collect_registers(registers);
},
_ => {}
@ -481,11 +515,10 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
return 0;
}
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>) -> Compiled {
fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mut Vec<RegisterState>, next_var_id: &mut u32) -> Compiled {
let mut ops: Vec<Operation> = vec![];
let mut var_ids: HashMap<String, u32> = HashMap::new();
let mut next_var_id: u32 = 1;
let mut variables: Vec<Variable> = vec![];
let mut strings: HashMap<u32, String> = HashMap::new();
let mut next_string_id: u32 = 1;
let mut functions: HashMap<u32, Compiled> = HashMap::new();
@ -494,11 +527,11 @@ fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mu
match args {
Some(arg_list) => {
for arg in arg_list {
if var_ids.contains_key(&arg) {
if get_variable_by_name(&variables, &arg, 0).is_some() {
panic!("Argument {} already exists", arg);
}
var_ids.insert(arg, next_var_id);
next_var_id += 1;
variables.push( Variable { name: arg, id: *next_var_id, start: 0, end: 0, no_end: true });
*next_var_id += 1;
}
},
None => {}
@ -506,18 +539,23 @@ fn compile_function(ast: Vec<ASTPart>, args: Option<Vec<String>>, registers: &mu
let mut op_count = 0;
for ast_op in ast {
do_ast_op(ast_op, &mut op_count, &mut ops, &mut var_ids, &mut next_var_id, &mut strings, &mut next_string_id, &mut functions, &mut next_function_id, registers);
do_ast_op(ast_op, &mut op_count, &mut ops, &mut variables, next_var_id, &mut strings, &mut next_string_id, &mut functions, &mut next_function_id, registers);
}
ops.push(Operation { opcode: 29, arg1: Some(0), arg2: None, arg3: None });
for var in &mut variables {
if var.no_end {
var.end = ops.len() - 1;
}
}
println!("Operations: {:?}\n", ops);
println!("Registers: {:?}\n", registers);
println!("Variable IDs: {:?}", var_ids);
println!("Variable IDs: {:?}", variables);
println!("Strings: {:?}", strings);
println!("==========================");
return Compiled {
operations: ops,
var_ids,
variables,
strings,
functions,
};
@ -569,6 +607,7 @@ fn bin_to_num(bin: String) -> usize {
}
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
let mut next_var_id: u32 = 1;
let mut registers: Vec<RegisterState> = vec![];
for i in 0..17 {
registers.push(RegisterState {
@ -579,7 +618,7 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
});
}
let compiled = compile_function(ast, None, &mut registers);
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id);
println!("Compiled: {:?}", compiled);
let mut output: Vec<u8> = vec![];
@ -594,10 +633,12 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
//function
append_string(&mut output, String::from("main"), true);
//function headers
append_be_num(&mut output, 4, compiled.var_ids.len());
for var_id in compiled.var_ids.keys() {
append_string(&mut output, var_id.clone(), true);
append_be_num(&mut output, 3, compiled.var_ids[var_id] as usize);
append_be_num(&mut output, 4, compiled.variables.len());
for var in compiled.variables {
append_string(&mut output, var.name, true);
append_be_num(&mut output, 3, var.id as usize);
append_be_num(&mut output, 4, var.start);
append_be_num(&mut output, 4, var.end);
}
append_be_num(&mut output, 4, compiled.strings.len());
for strs in compiled.strings.keys() {

View file

@ -45,7 +45,7 @@ struct DecompiledFile {
struct DecompiledFunction {
name: String,
body: Vec<DecompiledOperation>,
var_ids: HashMap<String, u32>,
variables: Vec<Variable>,
strings: HashMap<u32, String>,
functions: HashMap<u32, u32>
}
@ -63,9 +63,17 @@ pub struct Register {
pointer: usize
}
#[derive(Debug, Clone)]
struct Variable {
name: String,
id: u32,
start: usize,
end: usize
}
pub struct Machine {
pub memory: Vec<VMMemory>,
pub files: Vec<DecompiledFile>,
files: Vec<DecompiledFile>,
pub stack: Vec<VMMemory>,
pub registers: Vec<Register>,
pub pc: usize,
@ -362,7 +370,7 @@ impl Machine {
offset += func_name_len;
let var_id_len = read_be_num(&data[offset..offset + 4]);
offset += 4;
let mut var_ids: HashMap<String, u32> = HashMap::new();
let mut variables: Vec<Variable> = vec![];
for _ in 0..var_id_len {
let name_len = read_be_num(&data[offset..offset + 4]);
offset += 4;
@ -370,7 +378,11 @@ impl Machine {
offset += name_len;
let var_id = read_be_num(&data[offset..offset + 3]) as u32;
offset += 3;
var_ids.insert(name, var_id);
let start = read_be_num(&data[offset..offset + 4]);
offset += 4;
let end = read_be_num(&data[offset..offset + 4]);
offset += 4;
variables.push(Variable { name: name, id: var_id, start: start, end: end });
}
let mut strings: HashMap<u32, String> = HashMap::new();
let string_count = read_be_num(&data[offset..offset + 4]);
@ -413,7 +425,7 @@ impl Machine {
});
}
let mut file_functions: Vec<DecompiledFunction> = Vec::new();
file_functions.push(DecompiledFunction { name: func_name, body: body, var_ids: var_ids, strings: strings, functions: functions });
file_functions.push(DecompiledFunction { name: func_name, body: body, variables: variables, strings: strings, functions: functions });
self.files.push(DecompiledFile {
name: filename,
functions: file_functions

11
test.as
View file

@ -1,9 +1,4 @@
gethelj a = 1
gethelj b = (a + 2) * 3
gethelj c = piszv & nem piszv
ha geny (a < b) {
gethelj d = 69
} ha nem geny {
gethelj de = 420
ha geny (1 == 1) {
gethelj d = 1
}
d = d + 1
gethelj d = 2