fixed multiple variable issues, added a way to view an ASX file

This commit is contained in:
afonya 2025-06-17 19:33:09 +02:00
parent 8f967fc172
commit bf82ead8a8
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
4 changed files with 123 additions and 19 deletions

View file

@ -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<RegisterState>) -> 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<Operation>, 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<Variable> = 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<Operation>, 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<Variable> = 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<Operation>, 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<Variable> = 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<Operation>, va
let mut breaks: Vec<usize> = vec![];
let mut continues: Vec<usize> = 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<Variable> = 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<Operation>, 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<Operation>, va
let mut breaks: Vec<usize> = vec![];
let mut continues: Vec<usize> = 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<Variable> = 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<Operation>, 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 });

View file

@ -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<DecompiledFunction>,
pub func_count: usize,
pub version: String,
}
pub fn operation_to_name(opcode: u8) -> String {
@ -175,8 +177,10 @@ pub fn process(data: &Vec<u8>) -> 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::<Vec<String>>().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<u8>) -> DecompiledData {
return DecompiledData {
functions: functions,
func_count: func_count,
version: ver_str,
};
}

View file

@ -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<usize> = 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();

View file

@ -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))
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)