From 318836115884d478b9afdf8a1be508ff67c6ea45 Mon Sep 17 00:00:00 2001 From: afonya2 Date: Sun, 1 Jun 2025 15:33:42 +0200 Subject: [PATCH] begin VM --- src/main.rs | 6 +- src/virtualmachine.rs | 205 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/virtualmachine.rs diff --git a/src/main.rs b/src/main.rs index 122014a..e298e6f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,15 @@ use std::fs; use executor::Executor; use parser::ASTPart; +use virtualmachine::Machine; + mod lexer; mod parser; mod executor; mod enviroment; mod compiler; +mod virtualmachine; fn log_ast_part(part: &ASTPart, prefix: String) { match part { @@ -125,7 +128,8 @@ fn main() { } let compiled = compiler::compile(ast); println!("Compiled output: {:?}", compiled); - fs::write("./compiled.asx", compiled).expect("Failed to write compiled file"); + let mut vm = Machine::new(); + vm.load(compiled); /*let mut executor = Executor::new(ast, 100); executor.resume(); println!("\nFinished!"); diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs new file mode 100644 index 0000000..7aea60f --- /dev/null +++ b/src/virtualmachine.rs @@ -0,0 +1,205 @@ +use std::collections::HashMap; + +const ASXVERSION: [u8; 3] = [0,1,0]; + +enum VMMemory { + String(VMMemoryString), + Number(VMMemoryNumber), + Boolean(VMMemoryBoolean), + Null, +} + +struct VMMemoryString { + value: String, + variable_id: u32, +} +struct VMMemoryNumber { + value: i64, + variable_id: u32, +} +struct VMMemoryBoolean { + value: bool, + variable_id: u32, +} + +#[derive(Debug)] +struct DecompiledFile { + name: String, + functions: Vec, +} +#[derive(Debug)] +struct DecompiledFunction { + name: String, + body: Vec, + var_ids: HashMap, + strings: HashMap, + functions: HashMap +} +#[derive(Debug)] +struct DecompiledOperation { + opcode: u8, + arg1: u8, + arg2: i64, + arg3: u8, +} + +#[derive(Debug)] +struct Register { + id: u8, + pointer: usize +} + +pub struct Machine { + memory: Vec, + files: Vec, + stack: Vec, + registers: Vec, + pc: usize, +} + +fn read_be_num(input: &[u8]) -> usize { + let mut result: usize = 0; + for i in 0..input.len() { + result <<= 8; + result |= input[i] as usize; + } + return result; +} + +fn read_str(input: &[u8]) -> String { + let mut result = String::new(); + for &byte in input { + result.push(byte as char); + } + return result; +} + +fn read_bin(input: &[u8]) -> String { + let mut result = String::new(); + for &byte in input { + result.push_str(&format!("{:08b}", byte)); + } + return result; +} + +fn bin_to_num(bin: String) -> usize { + let mut result: usize = 0; + for (i, c) in bin.chars().rev().enumerate() { + if c == '1' { + result += 1 << i; + } + } + return result; +} + +fn bin_to_snum(bin: String) -> i64 { + let mut result: i64 = 0; + let mut is_negative = false; + for (i, c) in bin.chars().rev().enumerate() { + if c == '1' { + if i == bin.len() - 1 { + is_negative = true; + } else { + result += 1 << i; + } + } + } + if is_negative { + result = -result; + } + return result; +} + +impl Machine { + pub fn new() -> Self { + let mut registers = Vec::new(); + for i in 1..17 { + registers.push(Register { + id: i, + pointer: 0, + }); + } + return Machine { + memory: Vec::new(), + files: Vec::new(), + stack: Vec::new(), + registers: registers, + pc: 0, + }; + } + + pub fn load(&mut self, data: Vec) { + if data[0..3] != *"ASX".as_bytes() { + panic!("Invalid ASX file header"); + } + if data[3..6] != ASXVERSION { + panic!("Unsupported ASX version"); + } + let filename_len = read_be_num(&data[6..10]); + let filename = read_str(&data[10..10 + filename_len]); + let mut offset = 10 + filename_len; + let func_name_len = read_be_num(&data[offset..offset + 4]); + offset += 4; + let func_name = read_str(&data[offset..offset + func_name_len]); + offset += func_name_len; + let var_id_len = read_be_num(&data[offset..offset + 4]); + offset += 4; + let mut var_ids: HashMap = HashMap::new(); + for _ in 0..var_id_len { + let name_len = read_be_num(&data[offset..offset + 4]); + offset += 4; + let name = read_str(&data[offset..offset + name_len]); + offset += name_len; + let var_id = read_be_num(&data[offset..offset + 3]) as u32; + offset += 3; + var_ids.insert(name, var_id); + } + let mut strings: HashMap = HashMap::new(); + let string_count = read_be_num(&data[offset..offset + 4]); + offset += 4; + for _ in 0..string_count { + let str_id = read_be_num(&data[offset..offset + 3]) as u32; + offset += 3; + let str_len = read_be_num(&data[offset..offset + 4]); + offset += 4; + let str_value = read_str(&data[offset..offset + str_len]); + offset += str_len; + strings.insert(str_id, str_value); + } + let mut functions: HashMap = HashMap::new(); + let _function_count = read_be_num(&data[offset..offset + 4]); + offset += 4; + for _ in 0.._function_count { + let func_id = read_be_num(&data[offset..offset + 3]) as u32; + offset += 3; + let func_pos = read_be_num(&data[offset..offset + 4]) as u32; + offset += 4; + functions.insert(func_id, func_pos); + } + let mut body: Vec = Vec::new(); + let instr_len: usize = read_be_num(&data[offset..offset + 4]); + offset += 4; + for _ in 0..instr_len { + let op = read_bin(&data[offset..offset + 10]); + offset += 10; + println!("{}", op); + let op_code = bin_to_num(op[0..5].to_string()); + let arg1 = bin_to_num(op[5..9].to_string()); + let arg2 = bin_to_snum(op[9..73].to_string()); + let arg3 = bin_to_num(op[73..77].to_string()); + body.push(DecompiledOperation { + opcode: op_code as u8, + arg1: arg1 as u8, + arg2: arg2, + arg3: arg3 as u8, + }); + } + let mut file_functions: Vec = Vec::new(); + file_functions.push(DecompiledFunction { name: func_name, body: body, var_ids: var_ids, strings: strings, functions: functions }); + self.files.push(DecompiledFile { + name: filename, + functions: file_functions + }); + println!("Decompiled: {:?}", self.files[0]); + } +} \ No newline at end of file