begin compiler
This commit is contained in:
parent
7399a6d2ef
commit
35e8dd18b7
3 changed files with 138 additions and 7 deletions
132
src/compiler.rs
Normal file
132
src/compiler.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
use std::{collections::HashMap};
|
||||||
|
|
||||||
|
use crate::parser::ASTPart;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Opeartion {
|
||||||
|
pub opcode: u8,
|
||||||
|
pub arg1: Option<u8>,
|
||||||
|
pub arg2: Option<u32>,
|
||||||
|
pub arg3: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct RegisterState {
|
||||||
|
id: u8,
|
||||||
|
used: bool,
|
||||||
|
variable: u32,
|
||||||
|
last_used: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct AllocateResult {
|
||||||
|
register: u8,
|
||||||
|
unbind_before: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_register_by_id(registers: &Vec<RegisterState>, id: u8) -> RegisterState {
|
||||||
|
for register in registers {
|
||||||
|
if register.id == id {
|
||||||
|
return register.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic!("Register with id {} not found", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_register_by_variable(registers: &Vec<RegisterState>, variable: u32) -> RegisterState {
|
||||||
|
for register in registers {
|
||||||
|
if register.variable == variable {
|
||||||
|
return register.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic!("Register with variable {} not found", variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_register(registers: &mut Vec<RegisterState>, new_state: RegisterState) {
|
||||||
|
if new_state.id == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for i in 0..registers.len() {
|
||||||
|
if registers[i].id == new_state.id {
|
||||||
|
registers[i] = new_state;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocate_register(registers: &Vec<RegisterState>) -> AllocateResult {
|
||||||
|
for register in registers {
|
||||||
|
if register.id != 0 && !register.used {
|
||||||
|
return AllocateResult {
|
||||||
|
register: register.id,
|
||||||
|
unbind_before: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Find the one that wasn't used for the longest time
|
||||||
|
let mut oldest: usize = 0;
|
||||||
|
let mut oldest_register: u8 = 0;
|
||||||
|
for register in registers {
|
||||||
|
if ((register.last_used < oldest) || (oldest == 0)) && register.id != 0 {
|
||||||
|
oldest = register.last_used;
|
||||||
|
oldest_register = register.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AllocateResult {
|
||||||
|
register: oldest_register,
|
||||||
|
unbind_before: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Opeartion>, var_ids: &mut HashMap<String, u32>, next_var_id: &mut u32, registers: &mut Vec<RegisterState>) -> u8 {
|
||||||
|
*op_count += 1;
|
||||||
|
match ast_op {
|
||||||
|
ASTPart::Number(num) => {
|
||||||
|
let reg = allocate_register(registers);
|
||||||
|
if reg.unbind_before {
|
||||||
|
ops.push(Opeartion { opcode: 0x08, arg1: Some(reg.register), arg2: None, arg3: None });
|
||||||
|
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
|
||||||
|
}
|
||||||
|
ops.push(Opeartion { opcode: 0x03, arg1: Some(reg.register), arg2: Some(num.value as u32), arg3: None });
|
||||||
|
return reg.register;
|
||||||
|
},
|
||||||
|
ASTPart::Assigment(asign) => {
|
||||||
|
if var_ids.contains_key(&asign.variable) {
|
||||||
|
panic!("Variable {} already exists", asign.variable);
|
||||||
|
}
|
||||||
|
var_ids.insert(asign.variable.clone(), *next_var_id);
|
||||||
|
*next_var_id += 1;
|
||||||
|
let reg = do_ast_op(*asign.value, op_count, ops, var_ids, next_var_id, registers);
|
||||||
|
ops.push(Opeartion { opcode: 0x07, arg1: Some(reg), arg2: Some(var_ids[&asign.variable.clone()]), arg3: None });
|
||||||
|
set_register(registers, RegisterState { id: reg, used: true, variable: var_ids[&asign.variable.clone()], last_used: *op_count });
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
|
||||||
|
let mut ops: Vec<Opeartion> = vec![];
|
||||||
|
|
||||||
|
let mut var_ids: HashMap<String, u32> = HashMap::new();
|
||||||
|
let mut next_var_id: u32 = 1;
|
||||||
|
let mut registers: Vec<RegisterState> = vec![];
|
||||||
|
for i in 0..17 {
|
||||||
|
registers.push(RegisterState {
|
||||||
|
id: i as u8,
|
||||||
|
used: false,
|
||||||
|
variable: 0,
|
||||||
|
last_used: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 registers);
|
||||||
|
println!("Operations: {:?}", ops);
|
||||||
|
println!("Registers: {:?}", registers);
|
||||||
|
println!("Variable IDs: {:?}", var_ids);
|
||||||
|
println!("==========================");
|
||||||
|
}
|
||||||
|
return vec![];
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ mod lexer;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod executor;
|
mod executor;
|
||||||
mod enviroment;
|
mod enviroment;
|
||||||
|
mod compiler;
|
||||||
|
|
||||||
fn log_ast_part(part: &ASTPart, prefix: String) {
|
fn log_ast_part(part: &ASTPart, prefix: String) {
|
||||||
match part {
|
match part {
|
||||||
|
@ -117,12 +118,14 @@ fn main() {
|
||||||
for part in &ast {
|
for part in &ast {
|
||||||
log_ast_part(part, String::from(" "));
|
log_ast_part(part, String::from(" "));
|
||||||
}
|
}
|
||||||
let mut executor = Executor::new(ast, 100);
|
let compiled = compiler::compile(ast);
|
||||||
|
println!("Compiled output: {:?}", compiled);
|
||||||
|
/*let mut executor = Executor::new(ast, 100);
|
||||||
executor.resume();
|
executor.resume();
|
||||||
println!("\nFinished!");
|
println!("\nFinished!");
|
||||||
println!("State: {:?}", executor.state);
|
println!("State: {:?}", executor.state);
|
||||||
println!("Position: {}", executor.pos);
|
println!("Position: {}", executor.pos);
|
||||||
println!("Memory: {:?}", executor.memory);
|
println!("Memory: {:?}", executor.memory);*/
|
||||||
},
|
},
|
||||||
Result::Err(err) => {
|
Result::Err(err) => {
|
||||||
panic!("Error while reading file: {}", err)
|
panic!("Error while reading file: {}", err)
|
||||||
|
|
6
test.as
6
test.as
|
@ -1,5 +1 @@
|
||||||
ha geny (1 == 1) {
|
gethelj a = 69
|
||||||
gethelj a = 1
|
|
||||||
ugass(szaft"test"szaft)
|
|
||||||
printMemory()
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue