From 35e8dd18b718d85af6f2402bb7f0714c8bf5da1c Mon Sep 17 00:00:00 2001 From: afonya2 Date: Thu, 29 May 2025 21:23:30 +0200 Subject: [PATCH] begin compiler --- src/compiler.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 7 ++- test.as | 6 +-- 3 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 src/compiler.rs diff --git a/src/compiler.rs b/src/compiler.rs new file mode 100644 index 0000000..86015f3 --- /dev/null +++ b/src/compiler.rs @@ -0,0 +1,132 @@ +use std::{collections::HashMap}; + +use crate::parser::ASTPart; + +#[derive(Debug, Clone)] +pub struct Opeartion { + pub opcode: u8, + pub arg1: Option, + pub arg2: Option, + pub arg3: Option, +} + +#[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, 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, 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, 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) -> 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, var_ids: &mut HashMap, next_var_id: &mut u32, registers: &mut Vec) -> 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) -> Vec { + let mut ops: Vec = vec![]; + + let mut var_ids: HashMap = HashMap::new(); + let mut next_var_id: u32 = 1; + let mut registers: Vec = 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![]; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 2adfc40..e1539bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod lexer; mod parser; mod executor; mod enviroment; +mod compiler; fn log_ast_part(part: &ASTPart, prefix: String) { match part { @@ -117,12 +118,14 @@ fn main() { for part in &ast { 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(); println!("\nFinished!"); println!("State: {:?}", executor.state); println!("Position: {}", executor.pos); - println!("Memory: {:?}", executor.memory); + println!("Memory: {:?}", executor.memory);*/ }, Result::Err(err) => { panic!("Error while reading file: {}", err) diff --git a/test.as b/test.as index 491d8a3..fcae62f 100644 --- a/test.as +++ b/test.as @@ -1,5 +1 @@ -ha geny (1 == 1) { - gethelj a = 1 - ugass(szaft"test"szaft) - printMemory() -} \ No newline at end of file +gethelj a = 69 \ No newline at end of file