diff --git a/.gitignore b/.gitignore index ea8c4bf..e45e974 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +compiled.asx \ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index 6c3463c..9800d8f 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -689,7 +689,6 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu var.end = ops.len() - 1; } } - println!("Compiled operations: {:?}", ops); return Compiled { operations: ops, diff --git a/src/decompiler.rs b/src/decompiler.rs new file mode 100644 index 0000000..da294b9 --- /dev/null +++ b/src/decompiler.rs @@ -0,0 +1,206 @@ +use std::collections::HashMap; + +const ASXVERSION: [u8; 3] = [0,1,0]; + +#[derive(Debug, Clone)] +pub struct DecompiledFunction { + pub body: Vec, + pub variables: Vec, + pub strings: HashMap, + pub functions: HashMap +} +#[derive(Debug, Clone)] +pub struct DecompiledOperation { + pub opcode: u8, + pub arg1: u8, + pub arg2: i64, + pub arg3: u8, + pub pos: usize, +} + +#[derive(Debug, Clone)] +pub struct Variable { + pub name: String, + pub id: u32, + pub start: usize, + pub end: usize +} + +pub struct DecompiledData { + pub functions: Vec, + pub func_count: usize, +} + +pub fn operation_to_name(opcode: u8) -> String { + match opcode { + 0 => "HLT".to_string(), + 1 => "LDS".to_string(), + 2 => "LDM".to_string(), + 3 => "LDI".to_string(), + 4 => "LDB".to_string(), + 5 => "LDF".to_string(), + 6 => "LDN".to_string(), + 7 => "ASS".to_string(), + 8 => "UNB".to_string(), + 9 => "MOV".to_string(), + 10 => "ADD".to_string(), + 11 => "SUB".to_string(), + 12 => "MUL".to_string(), + 13 => "DIV".to_string(), + 14 => "POW".to_string(), + 15 => "MOD".to_string(), + 16 => "AND".to_string(), + 17 => "OR".to_string(), + 18 => "EQ".to_string(), + 19 => "NEQ".to_string(), + 20 => "GRE".to_string(), + 21 => "GRQ".to_string(), + 22 => "LES".to_string(), + 23 => "LEQ".to_string(), + 24 => "NOT".to_string(), + 25 => "JMP".to_string(), + 26 => "CJP".to_string(), + 27 => "CAL".to_string(), + 28 => "PSH".to_string(), + 29 => "RET".to_string(), + 30 => "GET".to_string(), + 31 => "SET".to_string(), + _ => panic!("Unknown operation code: {}", opcode), + } +} + +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 { + String::from_utf8(input.to_vec()).expect("Invalid UTF-8 sequence") +} + +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; +} + +fn load_func(data: Vec, offset: &mut usize) -> DecompiledFunction { + let var_id_len = read_be_num(&data[*offset..*offset + 4]); + *offset += 4; + let mut variables: Vec = vec![]; + 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; + let start = read_be_num(&data[*offset..*offset + 4]); + *offset += 4; + let end = read_be_num(&data[*offset..*offset + 4]); + *offset += 4; + variables.push(Variable { name: name, id: var_id, start: start, end: end }); + } + 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; + 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()); + let pos = read_be_num(&data[*offset..*offset + 4]); + *offset += 4; + body.push(DecompiledOperation { + opcode: op_code as u8, + arg1: arg1 as u8, + arg2: arg2, + arg3: arg3 as u8, + pos: pos, + }); + } + return DecompiledFunction { + body: body, + variables: variables, + strings: strings, + functions: functions, + }; +} + +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 func_count = read_be_num(&data[6..10]); + let mut offset = 10; + let mut functions: Vec = Vec::new(); + while offset < data.len() { + let func = load_func(data.clone(), &mut offset); + functions.push(func); + } + return DecompiledData { + functions: functions, + func_count: func_count, + }; +} \ No newline at end of file diff --git a/src/enviroment.rs b/src/enviroment.rs index bfe514c..38da895 100644 --- a/src/enviroment.rs +++ b/src/enviroment.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, io::{BufReader, Read, Write}, net::{self, TcpListener, TcpStream}, process, thread::sleep, time::Duration, vec}; -use crate::{errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{DecompiledOperation, Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable}}; +use crate::{decompiler::DecompiledOperation, errors::{create_error, print_error, ErrorSubType, ErrorType}, virtualmachine::{Machine, TableValue, VMMemory, VMMemoryBoolean, VMMemoryNativeFunction, VMMemoryNull, VMMemoryNumber, VMMemoryString, VMMemoryTable}}; fn get_string_from_vmmem(mem: &VMMemory) -> String { let mut out = String::new(); diff --git a/src/errors.rs b/src/errors.rs index 7440c67..3f547dc 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -70,6 +70,17 @@ fn convert_types_to_short(typ: &ErrorType) -> String { ErrorType::IOError => String::from("IO:"), } } +pub fn reverse_type_short(str: String) -> ErrorType { + match str.as_str() { + "ST" => ErrorType::SyntaxError, + "TP" => ErrorType::TypeError, + "MT" => ErrorType::MathError, + "SM" => ErrorType::SemanticError, + "MC" => ErrorType::MachineError, + "IO" => ErrorType::IOError, + _ => panic!("Unknown error type short: {}", str), + } +} fn convert_subtypes_to_string(stype: &ErrorSubType) -> String { match stype { ErrorSubType::UnexpectedEnd => String::from("Unexpected end"), @@ -126,6 +137,35 @@ fn convert_subtypes_to_short(stype: &ErrorSubType) -> String { ErrorSubType::RuntimeError => String::from("RE:"), } } +pub fn reverse_subtype_short(str: String) -> ErrorSubType { + match str.as_str() { + "UE" => ErrorSubType::UnexpectedEnd, + "UP" => ErrorSubType::UnexpectedOperation, + "EX" => ErrorSubType::Expected, + "UN" => ErrorSubType::Unexpected, + "IK" => ErrorSubType::InvalidTableKeys, + "UC" => ErrorSubType::Unclosed, + "EW" => ErrorSubType::ElseWithoutIf, + "BC" => ErrorSubType::BreakContinueWithoutLoop, + "UO" => ErrorSubType::UnknownOperation, + "VN" => ErrorSubType::VariableNotFound, + "VE" => ErrorSubType::VariableAlreadyExists, + "AD" => ErrorSubType::ArgumentDuplication, + "RF" => ErrorSubType::RegisterNotFound, + "MO" => ErrorSubType::MemoryOutOfBounds, + "OC" => ErrorSubType::UnknownOPCode, + "UF" => ErrorSubType::UnknownFunction, + "US" => ErrorSubType::UnknownString, + "UM" => ErrorSubType::UnknownMemoryLocation, + "NF" => ErrorSubType::NonFunctionCall, + "DZ" => ErrorSubType::DivisionByZero, + "WT" => ErrorSubType::WrongType, + "TA" => ErrorSubType::TooManyArguments, + "FE" => ErrorSubType::FileError, + "RE" => ErrorSubType::RuntimeError, + _ => panic!("Unknown error subtype short: {}", str), + } +} pub fn create_error(message: &str, position: usize, typ: ErrorType, stype: ErrorSubType) -> ASLError { let mut code = convert_types_to_short(&typ); diff --git a/src/main.rs b/src/main.rs index f08197a..dbb3d1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ -use std::fs; - -use parser::ASTPart; +use std::{env, fs, time::Instant}; use virtualmachine::Machine; +use crate::{decompiler::process, errors::{create_error, print_error, reverse_subtype_short, reverse_type_short}}; mod lexer; mod parser; @@ -9,133 +8,9 @@ mod enviroment; mod compiler; mod virtualmachine; mod errors; +mod decompiler; -fn log_ast_part(part: &ASTPart, prefix: String) { - match part { - ASTPart::Number(number) => println!("{}{}: Number: {}", prefix, number.pos, number.value), - ASTPart::String(str) => println!("{}{}: String: {}", prefix, str.pos, str.value), - ASTPart::Boolean(bool) => println!("{}{}: Boolean: {}", prefix, bool.pos, bool.value), - ASTPart::Null(null) => println!("{}{}: Null", prefix, null.pos), - ASTPart::Assigment(assigment) => { - println!("{}{}: Assigment: {}", prefix, assigment.pos, assigment.variable); - println!("{} Value:", prefix); - log_ast_part(&assigment.value, format!("{} ", prefix)); - }, - ASTPart::VarUpdate(v_update) => { - println!("{}{}: Update: {}", prefix, v_update.pos, v_update.variable); - println!("{} Value:", prefix); - log_ast_part(&v_update.value, format!("{} ", prefix)); - }, - ASTPart::Operation(operation) => { - println!("{}{}: Operation: {}", prefix, operation.pos, operation.operator); - println!("{} Left:", prefix); - log_ast_part(&operation.left, format!("{} ", prefix)); - println!("{} Right:", prefix); - log_ast_part(&operation.right, format!("{} ", prefix)); - }, - ASTPart::VarRead(var_read) => println!("{}{}: Variable Read: {}", prefix, var_read.pos, var_read.variable), - ASTPart::Call(call) => { - println!("{}{}: Call:", prefix, call.pos); - println!("{} Function:", prefix); - log_ast_part(&call.function, format!("{} ", prefix)); - println!("{} Args:", prefix); - for arg in &call.args { - log_ast_part(&arg, format!("{} ", prefix)); - } - }, - ASTPart::Function(func) => { - println!("{}{}: Function:", prefix, func.pos); - println!("{} Args: {}", prefix, func.args.join(", ")); - println!("{} Body:", prefix); - for part in &func.body { - log_ast_part(part, format!("{} ", prefix)); - } - }, - ASTPart::If(if_part) => { - println!("{}{}: If:", prefix, if_part.pos); - println!("{} Condition:", prefix); - log_ast_part(&if_part.condition, format!("{} ", prefix)); - println!("{} Body:", prefix); - for part in &if_part.body { - log_ast_part(part, format!("{} ", prefix)); - } - }, - ASTPart::ElseIf(elif) => { - println!("{}{}: Else If:", prefix, elif.pos); - println!("{} Condition:", prefix); - log_ast_part(&elif.condition, format!("{} ", prefix)); - println!("{} Body:", prefix); - for part in &elif.body { - log_ast_part(part, format!("{} ", prefix)); - } - }, - ASTPart::Else(els) => { - println!("{}{}: Else:", prefix, els.pos); - println!("{} Body:", prefix); - for part in &els.body { - log_ast_part(part, format!("{} ", prefix)); - } - }, - ASTPart::While(while_part) => { - println!("{}{}: While:", prefix, while_part.pos); - println!("{} Condition:", prefix); - log_ast_part(&while_part.condition, format!("{} ", prefix)); - println!("{} Body:", prefix); - for part in &while_part.body { - log_ast_part(part, format!("{} ", prefix)); - } - }, - ASTPart::Break(brk) => println!("{}{}: Break", prefix, brk.pos), - ASTPart::For(fr) => { - println!("{}{}: For:", prefix, fr.pos); - println!("{} Init:", prefix); - log_ast_part(&fr.init, format!("{} ", prefix)); - println!("{} Condition:", prefix); - log_ast_part(&fr.condition, format!("{} ", prefix)); - println!("{} Update:", prefix); - log_ast_part(&fr.update, format!("{} ", prefix)); - println!("{} Body:", prefix); - for part in &fr.body { - log_ast_part(part, format!("{} ", prefix)); - } - }, - ASTPart::Continue(cnt) => println!("{}{}: Continue", prefix, cnt.pos), - ASTPart::Return(ret) => { - println!("{}{}: Return", prefix, ret.pos); - println!("{} Value:", prefix); - log_ast_part(&ret.value, format!("{} ", prefix)); - }, - ASTPart::Table(tbl) => { - println!("{}{}: Table:", prefix, tbl.pos); - for table_value in &tbl.values { - println!("{} Key:", prefix); - log_ast_part(&table_value.key, format!("{} ", prefix)); - println!("{} Value:", prefix); - log_ast_part(&table_value.value, format!("{} ", prefix)); - } - }, - ASTPart::TableGet(tbl_get) => { - println!("{}{}: Table Get:", prefix, tbl_get.pos); - println!("{} Table:", prefix); - log_ast_part(&tbl_get.table, format!("{} ", prefix)); - println!("{} Key:", prefix); - log_ast_part(&tbl_get.key, format!("{} ", prefix)); - }, - ASTPart::TableSet(tbl_set) => { - println!("{}{}: Table Set:", prefix, tbl_set.pos); - println!("{} Table:", prefix); - log_ast_part(&tbl_set.table, format!("{} ", prefix)); - println!("{} Key:", prefix); - log_ast_part(&tbl_set.key, format!("{} ", prefix)); - println!("{} Value:", prefix); - log_ast_part(&tbl_set.value, format!("{} ", prefix)); - }, - ASTPart::Import(imp) => { - println!("{}{}: Import: {}", prefix, imp.pos, imp.path); - }, - ASTPart::NOOP => println!("{}NOOP", prefix) - } -} +const CLIVER: [u8; 3] = [0, 1, 0]; #[derive(Clone)] struct Context { @@ -145,37 +20,146 @@ struct Context { known: bool } +fn print_help() { + println!("Usage: ASL []"); + println!("Commands:"); + 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"); +} + fn main() { - let inp = fs::read_to_string("./test.asl"); - match inp { - Result::Ok(data) => { - let ctx = Context { - file: String::from("./test.asl"), - raw_file: data.clone(), - c_funcid: 0, - known: true - }; - let lexed = lexer::lex(data, &ctx); - println!("Lexer output: "); - for token in &lexed { - println!(" {}: {:?}: {}", token.pos, token.typ, token.value); + let msg = format!("Astro Lang (ASL) CLI v{}.{}.{}", CLIVER[0], CLIVER[1], CLIVER[2]); + println!("{}", msg); + println!("{}", "=".repeat(msg.len())); + let args: Vec = env::args().collect(); + if args.len() < 3 { + println!("Not enough arguments provided."); + print_help(); + return; + } + if args[1] == "run" { + let file = &args[2]; + if file.ends_with(".asl") { + let inp = fs::read_to_string(file); + let time = Instant::now(); + match inp { + Result::Ok(data) => { + let ctx = Context { + file: String::from(file), + raw_file: data.clone(), + c_funcid: 0, + known: true + }; + let lexed = lexer::lex(data, &ctx); + let ast = parser::parse(lexed, &ctx); + let (compiled, contexts) = compiler::compile(ast, &ctx); + let ntime = time.elapsed(); + println!("Build successful. Took: {}ms", ntime.as_millis()); + let mut vm = Machine::new(contexts); + vm.load(&compiled); + vm.run(); + }, + Result::Err(err) => { + panic!("Can't read file: {}", err); + } } - let ast = parser::parse(lexed, &ctx); - println!("AST: "); - for part in &ast { - log_ast_part(part, String::from(" ")); + } else if file.ends_with(".asx") { + let inp = fs::read(file); + match inp { + Result::Ok(data) => { + let decompiled = process(&data); + let mut contexts: Vec = Vec::new(); + for i in 0..decompiled.func_count { + contexts.push(Context { file: String::from(file), raw_file: String::from("Unknown"), c_funcid: i, known: false }); + } + let mut vm = Machine::new(contexts); + vm.load(&data); + vm.run(); + }, + Result::Err(err) => { + panic!("Can't read file: {}", err); + } } - let (compiled, contexts) = compiler::compile(ast, &ctx); - println!("Compiled output: {:?}", compiled); - let mut vm = Machine::new(contexts); - vm.load(compiled); - vm.run(); - println!("Registers: {:?}", vm.registers); - println!("Stack: {:?}", vm.stack); - println!("Memory: {:?}", vm.memory); - }, - Result::Err(err) => { - panic!("Error while reading file: {}", err) + } else { + println!("Unknown file type. Please use .asl or .asx files."); } + } else if args[1] == "compile" { + let file = &args[2]; + if file.ends_with(".asl") { + let inp = fs::read_to_string(file); + let time = Instant::now(); + match inp { + Result::Ok(data) => { + let ctx = Context { + file: String::from(file), + raw_file: data.clone(), + c_funcid: 0, + known: true + }; + let lexed = lexer::lex(data, &ctx); + let ast = parser::parse(lexed, &ctx); + let (compiled, _contexts) = compiler::compile(ast, &ctx); + match fs::write("compiled.asx", compiled) { + Ok(_) => { + let ntime = time.elapsed(); + println!("Build successful. Took: {}ms", ntime.as_millis()); + }, + Err(err) => { + panic!("Can't write compiled file: {}", err); + } + } + }, + Result::Err(err) => { + panic!("Can't read file: {}", err); + } + } + } else { + println!("Unknown file type. Please use .asl files."); + } + } else if args[1] == "traceback" { + if args.len() < 4 { + println!("Not enough arguments provided for traceback."); + print_help(); + return; + } + let file = &args[2]; + if file.ends_with(".asl") { + let inp = fs::read_to_string(file); + let time = Instant::now(); + match inp { + Result::Ok(data) => { + let ctx = Context { + file: String::from(file), + raw_file: data.clone(), + c_funcid: 0, + known: true + }; + let lexed = lexer::lex(data, &ctx); + let ast = parser::parse(lexed, &ctx); + let (compiled, contexts) = compiler::compile(ast, &ctx); + let ntime = time.elapsed(); + println!("Build successful. Took: {}ms", ntime.as_millis()); + let decompiled = process(&compiled); + let errcode_data: Vec<&str> = args[3].split(":").collect(); + if decompiled.func_count <= errcode_data[3].parse().unwrap() { + println!("Error code {} is invalid for this file.", args[3]); + return; + } + let error = create_error("", errcode_data[2].parse().unwrap(), reverse_type_short(errcode_data[0].to_string()), reverse_subtype_short(errcode_data[1].to_string())); + let func_ctx = contexts[errcode_data[3].parse::().unwrap()].clone(); + print_error(&error, &func_ctx); + return; + }, + Result::Err(err) => { + panic!("Can't read file: {}", err); + } + } + } else { + println!("Unknown file type. Please use .asl files."); + } + } else { + println!("Invalid command."); + print_help(); } } \ No newline at end of file diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index 2ed4d7d..acb990f 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -1,7 +1,5 @@ use std::{any::Any, collections::HashMap, process, vec}; -use crate::{enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context}; - -const ASXVERSION: [u8; 3] = [0,1,0]; +use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{create_error, print_error, ErrorSubType, ErrorType}, Context}; #[derive(Debug, Clone)] pub enum VMMemory { @@ -54,36 +52,12 @@ pub struct VMMemoryNativeFunction { pub variable_id: u32, } -#[derive(Debug, Clone)] -struct DecompiledFunction { - body: Vec, - variables: Vec, - strings: HashMap, - functions: HashMap -} -#[derive(Debug, Clone)] -pub struct DecompiledOperation { - pub opcode: u8, - pub arg1: u8, - pub arg2: i64, - pub arg3: u8, - pub pos: usize, -} - #[derive(Debug, Clone)] pub struct Register { id: u8, pointer: usize } -#[derive(Debug, Clone)] -struct Variable { - name: String, - id: u32, - start: usize, - end: usize -} - pub struct CallStack { pub func: usize, pub return_reg: usize, @@ -101,55 +75,6 @@ pub struct Machine { pub storage: Vec>, } -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 { - String::from_utf8(input.to_vec()).expect("Invalid UTF-8 sequence") -} - -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; -} - fn get_register_by_id(registers: &Vec, id: u8) -> Option<&Register> { for reg in registers { if reg.id == id { @@ -226,44 +151,6 @@ fn get_mem_tbl_val(tbl: &VMMemoryTable, key: VMMemory) -> Option<&VMMemory> { None } -fn operation_to_name(opcode: u8) -> String { - match opcode { - 0 => "HLT".to_string(), - 1 => "LDS".to_string(), - 2 => "LDM".to_string(), - 3 => "LDI".to_string(), - 4 => "LDB".to_string(), - 5 => "LDF".to_string(), - 6 => "LDN".to_string(), - 7 => "ASS".to_string(), - 8 => "UNB".to_string(), - 9 => "MOV".to_string(), - 10 => "ADD".to_string(), - 11 => "SUB".to_string(), - 12 => "MUL".to_string(), - 13 => "DIV".to_string(), - 14 => "POW".to_string(), - 15 => "MOD".to_string(), - 16 => "AND".to_string(), - 17 => "OR".to_string(), - 18 => "EQ".to_string(), - 19 => "NEQ".to_string(), - 20 => "GRE".to_string(), - 21 => "GRQ".to_string(), - 22 => "LES".to_string(), - 23 => "LEQ".to_string(), - 24 => "NOT".to_string(), - 25 => "JMP".to_string(), - 26 => "CJP".to_string(), - 27 => "CAL".to_string(), - 28 => "PSH".to_string(), - 29 => "RET".to_string(), - 30 => "GET".to_string(), - 31 => "SET".to_string(), - _ => panic!("Unknown operation code: {}", opcode), - } -} - fn get_var_id(var: &VMMemory) -> u32 { match var { VMMemory::String(str) => str.variable_id, @@ -428,76 +315,6 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec, offset: &mut usize) -> DecompiledFunction { - let var_id_len = read_be_num(&data[*offset..*offset + 4]); - *offset += 4; - let mut variables: Vec = vec![]; - 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; - let start = read_be_num(&data[*offset..*offset + 4]); - *offset += 4; - let end = read_be_num(&data[*offset..*offset + 4]); - *offset += 4; - variables.push(Variable { name: name, id: var_id, start: start, end: end }); - } - 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; - 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()); - let pos = read_be_num(&data[*offset..*offset + 4]); - *offset += 4; - body.push(DecompiledOperation { - opcode: op_code as u8, - arg1: arg1 as u8, - arg2: arg2, - arg3: arg3 as u8, - pos: pos, - }); - } - println!("Variables: {:?}", variables); - println!("Strings: {:?}", strings); - println!("Functions: {:?}", functions); - return DecompiledFunction { - body: body, - variables: variables, - strings: strings, - functions: functions, - }; -} - impl Machine { pub fn new(ctx: Vec) -> Self { let mut registers = Vec::new(); @@ -525,19 +342,9 @@ impl Machine { }; } - 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 _func_count = read_be_num(&data[6..10]); - let mut offset = 10; - while offset < data.len() { - let func = load_func(data.clone(), &mut offset); - self.functions.push(func); - } + pub fn load(&mut self, data: &Vec) { + let dec = process(data); + self.functions = dec.functions; } pub fn run(&mut self) { diff --git a/test.asl b/test.asl index 3aa93d5..7c4dd83 100644 --- a/test.asl +++ b/test.asl @@ -3,4 +3,5 @@ a = tábla.hozzáad(a, 1) ugass(a) a = tábla.töröl(a, 0) ugass(a) -ugass(tábla.kulcsok(a)) \ No newline at end of file +ugass(tábla.kulcsok(a)) +ugass(a+1) \ No newline at end of file