From bf82ead8a84d43f5974310582b2ac53567603c28 Mon Sep 17 00:00:00 2001 From: afonya Date: Tue, 17 Jun 2025 19:33:09 +0200 Subject: [PATCH] fixed multiple variable issues, added a way to view an ASX file --- src/compiler.rs | 44 +++++++++++++++++++++++++++------ src/decompiler.rs | 11 ++++++--- src/main.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++-- test.asl | 24 +++++++++++++----- 4 files changed, 123 insertions(+), 19 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index d5b82ce..5431925 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, fs, process, vec}; use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, lexer::lex, parser::{parse, ASTPart}, Context}; -const ASXVERSION: [u8; 3] = [0,1,0]; +const ASXVERSION: [u8; 3] = [0,2,0]; #[derive(Debug, Clone)] pub struct Operation { @@ -113,12 +113,12 @@ fn allocate_register(registers: &Vec) -> AllocateResult { oldest_temp_register = register.id; } } - if oldest_temp_register != 0 { + /*if oldest_temp_register != 0 { return AllocateResult { register: oldest_temp_register, unbind_before: false, }; - } + }*/ return AllocateResult { register: oldest_register, unbind_before: true, @@ -277,8 +277,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va let op_placeholder = ops.len(); ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: if_part.pos as u32 }); let mut fake_vars: Vec = vec![]; + let tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; for if_op in if_part.body { - do_ast_op(if_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); + do_ast_op(if_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, &tb); } 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 }); @@ -321,9 +325,13 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va let op_placeholder = ops.len(); ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: else_part.pos as u32 }); + let tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; let mut fake_vars: Vec = vec![]; for else_op in else_part.body { - do_ast_op(else_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); + do_ast_op(else_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, &tb); } 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 }); @@ -373,9 +381,13 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va let op_placeholder = ops.len(); ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: elseif_part.pos as u32 }); + let tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; let mut fake_vars: Vec = vec![]; for elseif_op in elseif_part.body { - do_ast_op(elseif_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); + do_ast_op(elseif_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, &tb); } 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 }); @@ -403,6 +415,11 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va let mut breaks: Vec = vec![]; let mut continues: Vec = vec![]; ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: while_part.pos as u32 }); + let tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; + let mut fake_vars: Vec = vec![]; for while_op in while_part.body { match while_op { ASTPart::Break(_) => { @@ -414,10 +431,13 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: while_part.pos as u32 }); }, _ => { - do_ast_op(while_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); + do_ast_op(while_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, &tb); } } } + 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.push(Operation { opcode: 25, arg1: None, arg2: Some(start as f64), arg3: None, pos: while_part.pos as u32 }); ops[op_placeholder] = Operation { opcode: 26, @@ -465,6 +485,11 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va let mut breaks: Vec = vec![]; let mut continues: Vec = vec![]; ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: for_part.pos as u32 }); + let tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; + let mut fake_vars: Vec = vec![]; for for_op in for_part.body { match for_op { ASTPart::Break(_) => { @@ -476,10 +501,13 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None, pos: for_part.pos as u32 }); }, _ => { - do_ast_op(for_op, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); + do_ast_op(for_op, op_count, ops, &mut fake_vars, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, &tb); } } } + 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 }); + } do_ast_op(*for_part.update, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers, ctx, traceback); ops.push(Operation { opcode: 25, arg1: None, arg2: Some(start as f64), arg3: None, pos: for_part.pos as u32 }); diff --git a/src/decompiler.rs b/src/decompiler.rs index aaffa16..ae39057 100644 --- a/src/decompiler.rs +++ b/src/decompiler.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -const ASXVERSION: [u8; 3] = [0,1,0]; +const ASXVERSION: [u8; 3] = [0,2,0]; #[derive(Debug, Clone)] pub struct DecompiledFunction { @@ -26,9 +26,11 @@ pub struct Variable { pub end: usize } +#[derive(Debug, Clone)] pub struct DecompiledData { pub functions: Vec, pub func_count: usize, + pub version: String, } pub fn operation_to_name(opcode: u8) -> String { @@ -175,8 +177,10 @@ pub fn process(data: &Vec) -> DecompiledData { if data[0..3] != *"ASX".as_bytes() { panic!("Invalid ASX file header"); } - if data[3..6] != ASXVERSION { - panic!("Unsupported ASX version"); + let ver = &data[3..6].to_vec(); + let ver_str: String = ver.iter().map(|b| b.to_string()).collect::>().join("."); + if *ver != ASXVERSION { + panic!("Unsupported ASX version ({})", ver_str); } let func_count = read_be_num(&data[6..10]); let mut offset = 10; @@ -188,5 +192,6 @@ pub fn process(data: &Vec) -> DecompiledData { return DecompiledData { functions: functions, func_count: func_count, + version: ver_str, }; } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index dbb3d1d..bf38df7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::{env, fs, time::Instant}; use virtualmachine::Machine; -use crate::{decompiler::process, errors::{create_error, print_error, reverse_subtype_short, reverse_type_short}}; +use crate::{decompiler::{operation_to_name, process}, errors::{create_error, print_error, reverse_subtype_short, reverse_type_short}}; mod lexer; mod parser; @@ -10,7 +10,7 @@ mod virtualmachine; mod errors; mod decompiler; -const CLIVER: [u8; 3] = [0, 1, 0]; +const CLIVER: [u8; 3] = [0, 2, 0]; #[derive(Clone)] struct Context { @@ -26,6 +26,7 @@ fn print_help() { println!(" run - Run an ASL/ASX file"); println!(" compile - Compile the ASL file to bytecode"); println!(" traceback - Traceback an error based on an error code"); + println!(" viewx- - View the contents of an ASX file"); } fn main() { @@ -158,6 +159,64 @@ fn main() { } else { println!("Unknown file type. Please use .asl files."); } + } else if args[1] == "viewx" { + let file = &args[2]; + if file.ends_with(".asx") { + let inp = fs::read(file); + match inp { + Result::Ok(data) => { + let decompiled = process(&data); + println!("ASX Verion: {}", decompiled.version); + println!("Function Count: {}", decompiled.func_count); + for i in 0..decompiled.func_count { + println!("Function {}:", i); + let func = &decompiled.functions[i]; + println!(" Variables:"); + for var in &func.variables { + println!(" {}: {} ({}:{})", var.id, var.name, var.start, var.end); + } + println!(" Strings:"); + for (id, string) in &func.strings { + println!(" {}: {}", id, string); + } + println!(" Functions:"); + for (id, pos) in &func.functions { + println!(" {}: {}", id, pos); + } + println!(" Body:"); + //Print these under each other like when you tabulate + let mut longest_cols: Vec = vec![0, 0, 0, 0]; + for op in &func.body { + longest_cols[0] = longest_cols[0].max(operation_to_name(op.opcode).len()); + longest_cols[1] = longest_cols[1].max(op.arg1.to_string().len()); + longest_cols[2] = longest_cols[2].max(op.arg2.to_string().len()); + longest_cols[3] = longest_cols[3].max(op.arg3.to_string().len()); + } + let mut longest = 0; + for op in &func.body { + let op_name = operation_to_name(op.opcode); + let str = format!(" {}{} {}{} {}{} {} at {}", + op_name, + " ".repeat(longest_cols[0] - op_name.len()), + op.arg1, + " ".repeat(longest_cols[1] - op.arg1.to_string().len()), + op.arg2, + " ".repeat(longest_cols[2] - op.arg2.to_string().len()), + op.arg3, + op.pos); + longest = longest.max(str.len()+4); + println!("{}", str); + } + println!("{}", "=".repeat(longest)); + } + }, + Result::Err(err) => { + panic!("Can't read file: {}", err); + } + } + } else { + println!("Unknown file type. Please use .asx files."); + } } else { println!("Invalid command."); print_help(); diff --git a/test.asl b/test.asl index 0c58aa7..005e58d 100644 --- a/test.asl +++ b/test.asl @@ -1,6 +1,18 @@ -gethelj a = -6.5 -ugass(nerd.abs(a)) -ugass(nerd.kerek(a, szaft"fel"szaft)) -ugass(nerd.sqrt(16)) -ugass(nerd.legnagyobb(3,56,66,1,12,55,6)) -ugass(nerd.legkisebb(3,56,66,1,12,55,6)) \ No newline at end of file +gethelj a = 125 +gethelj b = 567 +gethelj c = 8765 +gethelj d = 123 +gethelj e = 123 +gethelj f = 123 +gethelj g = 123 +gethelj h = 123 +gethelj i = 123 +gethelj j = 123 +gethelj k = 123 +gethelj l = 123 +gethelj m = 123 +gethelj n = 123 +gethelj o = 123 +gethelj p = 123 +gethelj q = 123 +ugass(a+b+c) \ No newline at end of file