added function to the ASX standard
This commit is contained in:
parent
a8e174af7f
commit
598f4a0cdb
3 changed files with 126 additions and 136 deletions
|
@ -208,6 +208,7 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec<Operation>, va
|
||||||
}
|
}
|
||||||
ops.push(Operation { opcode: 5, arg1: Some(reg.register), arg2: Some(func_id as i64), arg3: None });
|
ops.push(Operation { opcode: 5, arg1: Some(reg.register), arg2: Some(func_id as i64), arg3: None });
|
||||||
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
|
set_register(registers, RegisterState { id: reg.register, used: true, variable: 0, last_used: *op_count });
|
||||||
|
return reg.register;
|
||||||
},
|
},
|
||||||
ASTPart::Call(call) => {
|
ASTPart::Call(call) => {
|
||||||
let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
|
let func = do_ast_op(*call.function, op_count, ops, variables, next_var_id, strings, next_string_id, functions, next_function_id, registers);
|
||||||
|
@ -606,32 +607,10 @@ fn bin_to_num(bin: String) -> usize {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
|
fn compile_body(compiled: Compiled, fpos: &mut usize) -> Vec<u8> {
|
||||||
let mut next_var_id: u32 = 1;
|
|
||||||
let mut registers: Vec<RegisterState> = vec![];
|
|
||||||
for i in 0..17 {
|
|
||||||
registers.push(RegisterState {
|
|
||||||
id: i as u8,
|
|
||||||
used: false,
|
|
||||||
variable: 0,
|
|
||||||
last_used: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id);
|
|
||||||
println!("Compiled: {:?}", compiled);
|
|
||||||
|
|
||||||
let mut output: Vec<u8> = vec![];
|
let mut output: Vec<u8> = vec![];
|
||||||
//doctype specifier
|
let mut additional: Vec<Vec<u8>> = vec![];
|
||||||
append_string(&mut output, String::from("ASX"), false);
|
|
||||||
//version
|
|
||||||
output.push(ASXVERSION[0]);
|
|
||||||
output.push(ASXVERSION[1]);
|
|
||||||
output.push(ASXVERSION[2]);
|
|
||||||
//file name
|
|
||||||
append_string(&mut output, String::from("main.asl"), true);
|
|
||||||
//function
|
//function
|
||||||
append_string(&mut output, String::from("main"), true);
|
|
||||||
//function headers
|
//function headers
|
||||||
append_be_num(&mut output, 4, compiled.variables.len());
|
append_be_num(&mut output, 4, compiled.variables.len());
|
||||||
for var in compiled.variables {
|
for var in compiled.variables {
|
||||||
|
@ -645,10 +624,13 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
|
||||||
append_be_num(&mut output, 3, *strs as usize);
|
append_be_num(&mut output, 3, *strs as usize);
|
||||||
append_string(&mut output, compiled.strings[strs].clone(), true);
|
append_string(&mut output, compiled.strings[strs].clone(), true);
|
||||||
}
|
}
|
||||||
append_be_num(&mut output, 4, 0);
|
append_be_num(&mut output, 4, compiled.functions.len());
|
||||||
/*for funcs in compiled.functions.keys() {
|
for funcs in compiled.functions.keys() {
|
||||||
//not implemented yet
|
*fpos += 1;
|
||||||
}*/
|
append_be_num(&mut output, 3, *funcs as usize);
|
||||||
|
append_be_num(&mut output, 4, *fpos);
|
||||||
|
additional.push(compile_body(compiled.functions[funcs].clone(), fpos));
|
||||||
|
}
|
||||||
//function body
|
//function body
|
||||||
append_be_num(&mut output, 4, compiled.operations.len());
|
append_be_num(&mut output, 4, compiled.operations.len());
|
||||||
for ops in compiled.operations {
|
for ops in compiled.operations {
|
||||||
|
@ -672,6 +654,39 @@ pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
|
||||||
println!("{}", op_bin);
|
println!("{}", op_bin);
|
||||||
append_binary(&mut output, op_bin);
|
append_binary(&mut output, op_bin);
|
||||||
}
|
}
|
||||||
|
for addition in additional {
|
||||||
|
output.extend_from_slice(&addition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile(ast: Vec<ASTPart>) -> Vec<u8> {
|
||||||
|
let mut next_var_id: u32 = 1;
|
||||||
|
let mut registers: Vec<RegisterState> = vec![];
|
||||||
|
for i in 0..17 {
|
||||||
|
registers.push(RegisterState {
|
||||||
|
id: i as u8,
|
||||||
|
used: false,
|
||||||
|
variable: 0,
|
||||||
|
last_used: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let compiled = compile_function(ast, None, &mut registers, &mut next_var_id);
|
||||||
|
println!("Compiled: {:?}", compiled);
|
||||||
|
|
||||||
|
let mut output: Vec<u8> = vec![];
|
||||||
|
//doctype specifier
|
||||||
|
append_string(&mut output, String::from("ASX"), false);
|
||||||
|
//version
|
||||||
|
output.push(ASXVERSION[0]);
|
||||||
|
output.push(ASXVERSION[1]);
|
||||||
|
output.push(ASXVERSION[2]);
|
||||||
|
//functions
|
||||||
|
let mut fpos = 0;
|
||||||
|
let body = compile_body(compiled, &mut fpos);
|
||||||
|
output.extend_from_slice(&body);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
|
@ -28,7 +28,7 @@ pub struct VMMemoryBoolean {
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct VMMemoryFunction {
|
pub struct VMMemoryFunction {
|
||||||
pub function: DecompiledFunction,
|
function: DecompiledFunction,
|
||||||
pub variable_id: u32,
|
pub variable_id: u32,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -36,14 +36,8 @@ pub struct VMMemoryNull {
|
||||||
pub variable_id: u32,
|
pub variable_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct DecompiledFile {
|
|
||||||
name: String,
|
|
||||||
functions: Vec<DecompiledFunction>,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct DecompiledFunction {
|
struct DecompiledFunction {
|
||||||
name: String,
|
|
||||||
body: Vec<DecompiledOperation>,
|
body: Vec<DecompiledOperation>,
|
||||||
variables: Vec<Variable>,
|
variables: Vec<Variable>,
|
||||||
strings: HashMap<u32, String>,
|
strings: HashMap<u32, String>,
|
||||||
|
@ -73,7 +67,7 @@ struct Variable {
|
||||||
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
pub memory: Vec<VMMemory>,
|
pub memory: Vec<VMMemory>,
|
||||||
files: Vec<DecompiledFile>,
|
functions: Vec<DecompiledFunction>,
|
||||||
pub stack: Vec<VMMemory>,
|
pub stack: Vec<VMMemory>,
|
||||||
pub registers: Vec<Register>,
|
pub registers: Vec<Register>,
|
||||||
pub pc: usize,
|
pub pc: usize,
|
||||||
|
@ -132,24 +126,6 @@ fn bin_to_snum(bin: String) -> i64 {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_file_by_name(files: &Vec<DecompiledFile>, name: &str) -> Option<DecompiledFile> {
|
|
||||||
for file in files {
|
|
||||||
if file.name == name {
|
|
||||||
return Some(file.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_function_by_name(file: &DecompiledFile, name: &str) -> Option<DecompiledFunction> {
|
|
||||||
for function in &file.functions {
|
|
||||||
if function.name == name {
|
|
||||||
return Some(function.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_register_by_id(registers: &Vec<Register>, id: u8) -> Option<&Register> {
|
fn get_register_by_id(registers: &Vec<Register>, id: u8) -> Option<&Register> {
|
||||||
for reg in registers {
|
for reg in registers {
|
||||||
if reg.id == id {
|
if reg.id == id {
|
||||||
|
@ -334,6 +310,74 @@ fn do_operation_operation(registers: &mut Vec<Register>, memory: &mut Vec<VMMemo
|
||||||
memory[reg3_pointer] = result;
|
memory[reg3_pointer] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_func(data: Vec<u8>, offset: &mut usize) -> DecompiledFunction {
|
||||||
|
let var_id_len = read_be_num(&data[*offset..*offset + 4]);
|
||||||
|
*offset += 4;
|
||||||
|
let mut variables: Vec<Variable> = 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<u32, String> = 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<u32, u32> = 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);
|
||||||
|
}
|
||||||
|
println!("Variables: {:?}", variables);
|
||||||
|
println!("Strings: {:?}", strings);
|
||||||
|
println!("Functions: {:?}", functions);
|
||||||
|
let mut body: Vec<DecompiledOperation> = 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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return DecompiledFunction {
|
||||||
|
body: body,
|
||||||
|
variables: variables,
|
||||||
|
strings: strings,
|
||||||
|
functions: functions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut registers = Vec::new();
|
let mut registers = Vec::new();
|
||||||
|
@ -347,7 +391,7 @@ impl Machine {
|
||||||
memory: vec![
|
memory: vec![
|
||||||
VMMemory::Null(VMMemoryNull { variable_id: 0 })
|
VMMemory::Null(VMMemoryNull { variable_id: 0 })
|
||||||
],
|
],
|
||||||
files: Vec::new(),
|
functions: Vec::new(),
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
registers: registers,
|
registers: registers,
|
||||||
pc: 0,
|
pc: 0,
|
||||||
|
@ -361,87 +405,18 @@ impl Machine {
|
||||||
if data[3..6] != ASXVERSION {
|
if data[3..6] != ASXVERSION {
|
||||||
panic!("Unsupported ASX version");
|
panic!("Unsupported ASX version");
|
||||||
}
|
}
|
||||||
let filename_len = read_be_num(&data[6..10]);
|
let mut offset = 6;
|
||||||
let filename = read_str(&data[10..10 + filename_len]);
|
while offset < data.len() {
|
||||||
let mut offset = 10 + filename_len;
|
let func = load_func(data.clone(), &mut offset);
|
||||||
let func_name_len = read_be_num(&data[offset..offset + 4]);
|
self.functions.push(func);
|
||||||
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 variables: Vec<Variable> = 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<u32, String> = HashMap::new();
|
println!("Decompiled: {:?}", self.functions);
|
||||||
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<u32, u32> = 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<DecompiledOperation> = 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<DecompiledFunction> = Vec::new();
|
|
||||||
file_functions.push(DecompiledFunction { name: func_name, body: body, variables: variables, strings: strings, functions: functions });
|
|
||||||
self.files.push(DecompiledFile {
|
|
||||||
name: filename,
|
|
||||||
functions: file_functions
|
|
||||||
});
|
|
||||||
println!("Decompiled: {:?}", self.files[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let main = get_file_by_name(&self.files, "main.asl");
|
let main_func = self.functions.get(0);
|
||||||
if main.is_none() {
|
|
||||||
panic!("Main file not found");
|
|
||||||
}
|
|
||||||
let main = main.unwrap();
|
|
||||||
let main_func = get_function_by_name(&main, "main");
|
|
||||||
if main_func.is_none() {
|
if main_func.is_none() {
|
||||||
panic!("Main function not found");
|
panic!("No main function found!");
|
||||||
}
|
}
|
||||||
let main_func = main_func.unwrap();
|
let main_func = main_func.unwrap();
|
||||||
while self.pc < main_func.body.len() {
|
while self.pc < main_func.body.len() {
|
||||||
|
@ -488,7 +463,7 @@ impl Machine {
|
||||||
panic!("Function with ID {} not found", operation.arg2);
|
panic!("Function with ID {} not found", operation.arg2);
|
||||||
}
|
}
|
||||||
let func_pos = func_pos.unwrap();
|
let func_pos = func_pos.unwrap();
|
||||||
let func = main.functions.get(*func_pos as usize);
|
let func = self.functions.get(*func_pos as usize);
|
||||||
if func.is_none() {
|
if func.is_none() {
|
||||||
panic!("Function with position {} not found", func_pos);
|
panic!("Function with position {} not found", func_pos);
|
||||||
}
|
}
|
||||||
|
|
6
test.as
6
test.as
|
@ -1,4 +1,4 @@
|
||||||
ha geny (1 == 1) {
|
gethelj a = 1
|
||||||
gethelj d = 1
|
gethelj b = lőcsve() {
|
||||||
|
gethelj a = 2
|
||||||
}
|
}
|
||||||
gethelj d = 2
|
|
Loading…
Add table
Add a link
Reference in a new issue