diff --git a/src/compiler.rs b/src/compiler.rs index a0b3b02..45425fb 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -679,8 +679,12 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va } }, ASTPart::TryCatch(tc) => { - let catch_f = compile_function(tc.catch_block.body, None, registers, next_var_id, ctx, traceback, None); - let mut try_f = compile_function(tc.try_block.body, None, registers, next_var_id, ctx, traceback, Some(0)); + let self_tb = PrevFunc { + variables: variables.clone(), + previous: Some(Box::new(traceback.clone())), + }; + let catch_f = compile_function(tc.catch_block.body, Some(tc.catch_block.args), registers, next_var_id, ctx, &self_tb, None); + let mut try_f = compile_function(tc.try_block.body, None, registers, next_var_id, ctx, &self_tb, Some(0)); let mut nextt_f = 1; for (fid, _) in &try_f.functions { if fid >= &nextt_f { diff --git a/src/errors.rs b/src/errors.rs index c77071c..1fe38ad 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -54,7 +54,7 @@ pub struct ASLError { pub code: String, } -fn convert_types_to_string(typ: &ErrorType) -> String { +pub fn convert_types_to_string(typ: &ErrorType) -> String { match typ { ErrorType::SyntaxError => String::from("Syntax Error: "), ErrorType::TypeError => String::from("Type Error: "), @@ -85,7 +85,7 @@ pub fn reverse_type_short(str: String) -> ErrorType { _ => panic!("Unknown error type short: {}", str), } } -fn convert_subtypes_to_string(stype: &ErrorSubType) -> String { +pub fn convert_subtypes_to_string(stype: &ErrorSubType) -> String { match stype { ErrorSubType::UnexpectedEnd => String::from("Unexpected end"), ErrorSubType::UnexpectedOperation => String::from("Unexpected operation"), diff --git a/src/main.rs b/src/main.rs index 7ead5cd..00e2567 100644 --- a/src/main.rs +++ b/src/main.rs @@ -143,11 +143,11 @@ fn main() { 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() { + if decompiled.func_count <= errcode_data[2].parse().unwrap() { println!("Error code {} is invalid for this file.", args[3]); return; } - let func_ctx = contexts[errcode_data[3].parse::().unwrap()].clone(); + let func_ctx = contexts[errcode_data[2].parse::().unwrap()].clone(); let error = create_error("", errcode_data[3].parse().unwrap(), reverse_type_short(errcode_data[0].to_string()), reverse_subtype_short(errcode_data[1].to_string()), &func_ctx); print_error(&error, &func_ctx); return; diff --git a/src/virtualmachine.rs b/src/virtualmachine.rs index c02206d..34484fe 100644 --- a/src/virtualmachine.rs +++ b/src/virtualmachine.rs @@ -1,5 +1,5 @@ -use std::{any::Any, collections::HashMap, process, vec}; -use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{create_error, print_error, ASLError, ErrorSubType, ErrorType}, Context}; +use std::{any::Any, collections::HashMap, vec}; +use crate::{decompiler::{operation_to_name, process, DecompiledFunction, DecompiledOperation}, enviroment, errors::{convert_subtypes_to_string, convert_types_to_string, create_error, print_error, ASLError, ErrorSubType, ErrorType}, Context}; #[derive(Debug, Clone)] pub enum VMMemory { @@ -184,22 +184,81 @@ fn set_var_id(var: &mut VMMemory, target: u32) { } } -fn do_operation_operation(registers: &mut Vec, memory: &mut Vec, operation: &DecompiledOperation, ctx: &Context) { - let reg_clone = registers.clone(); +fn fallback_to_catch(memory: &mut Vec, state: &mut VMState, functions: &mut Vec, call_stack: &mut Vec, executed_stack: &mut usize, executed_func: &DecompiledFunction, err: ASLError) { + call_stack.pop(); + if call_stack.len() < 1 { + *state = VMState::Finished; + return; + } + let catchf = match executed_func.functions.get(&executed_func.try_catch) { + Some(f) => f, + None => { + panic!("Try/Catch function not found!"); + } + }; + call_stack.push(CallStack { func: *catchf as usize, return_reg: 0, pc: 0 }); + *executed_stack = call_stack.len() - 1; + let func = &functions[*catchf as usize]; + let err_tbl: Vec = vec![ + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("message"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: err.message, variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("position"), variable_id: 0 }), + value: VMMemory::Number(VMMemoryNumber { value: err.position as f64, variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("type"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: convert_types_to_string(&err.typ), variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("subtype"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: convert_subtypes_to_string(&err.subtype), variable_id: 0 }) + }, + TableValue { + key: VMMemory::String(VMMemoryString { value: String::from("code"), variable_id: 0 }), + value: VMMemory::String(VMMemoryString { value: err.code, variable_id: 0 }) + }, + ]; + if func.variables.len() < 1 || func.variables[0].start != 0 { + return; + } + memory.push(VMMemory::Table(VMMemoryTable { values: err_tbl, variable_id: func.variables[0].id })); +} + +fn do_operation_operation(machine: &mut Machine, operation: &DecompiledOperation, executed_stack: &mut usize, executed_func: &DecompiledFunction) { + let registers = &mut machine.registers; + let memory = &mut machine.memory; + let ctx = &machine.ctx[machine.call_stack[*executed_stack].func].clone(); + let func = machine.functions[machine.call_stack[*executed_stack].func].clone(); + let reg_clone: Vec = registers.clone(); let reg1 = get_register_by_id(®_clone, operation.arg1); let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); let reg3 = get_register_by_id(®_clone, operation.arg3); if reg1.is_none() || reg2.is_none() || reg3.is_none() { let err = create_error(&format!("One or more registers not found for operation"), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } let mem1 = reg1.unwrap().pointer; let mem2 = reg2.unwrap().pointer; if mem1 >= memory.len() || mem2 >= memory.len() || mem1 < 1 || mem2 < 1 { let err = create_error(&format!("Memory location out of bounds `{}` or `{}`", mem1, mem2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } let mut result: VMMemory; match (&memory[mem1], &memory[mem2]) { @@ -217,8 +276,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { if num2.value == 0.0 { let err = create_error(&format!("Division by zero"), operation.pos, ErrorType::MathError, ErrorSubType::DivisionByZero, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } result = VMMemory::Number(VMMemoryNumber { value: num1.value / num2.value, variable_id: 0 }); }, @@ -248,8 +313,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for number operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, @@ -266,8 +337,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for string operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, @@ -287,8 +364,14 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for boolean operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, @@ -302,15 +385,27 @@ fn do_operation_operation(registers: &mut Vec, memory: &mut Vec { let err = create_error(&format!("Unknown operation code for null operation: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } }; }, _ => { let err = create_error(&format!("Wrong memory types for operation: `{}`, position: `{}` and `{}`", operation_to_name(operation.opcode), mem1, mem2), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, ctx); - print_error(&err, &ctx); - process::exit(1); + if func.try_catch > 0 { + fallback_to_catch(memory, &mut machine.state, &mut machine.functions, &mut machine.call_stack, executed_stack, executed_func, err); + return; + } else { + print_error(&err, &ctx); + machine.state = VMState::Error(err); + return; + } } } let mut reg3_pointer = reg3.unwrap().pointer; @@ -372,9 +467,7 @@ impl Machine { let executed_func = func_clone.get(self.call_stack[self.call_stack.len()-1].func); let mut executed_stack = self.call_stack.len()-1; if executed_func.is_none() { - let err = create_error(&format!("Current function not found"), 1, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + panic!("Unable to resume VM, current function not found in function list"); } let mut executed_func = executed_func.unwrap(); self.state = VMState::Running; @@ -390,6 +483,7 @@ impl Machine { match operation.opcode { 0 => { //HLT + self.state = VMState::Finished; return; }, 1 => { @@ -397,8 +491,15 @@ impl Machine { let str = executed_func.strings.get(&(operation.arg2 as u32)); if str.is_none() { let err = create_error(&format!("String with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownString, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let str = str.unwrap(); self.memory.push(VMMemory::String(VMMemoryString { value: str.clone(), variable_id: 0 })); @@ -409,14 +510,28 @@ impl Machine { let mem = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32); if mem.is_none() { let err = create_error(&format!("Memory with variable ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap(); if mem >= self.memory.len() || mem < 1 { let err = create_error(&format!("Memory location out of bounds for variable ID `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mut nmem = self.memory[mem].clone(); match &mut nmem { @@ -460,15 +575,29 @@ impl Machine { let func_pos = executed_func.functions.get(&(operation.arg2 as u32)); if func_pos.is_none() { let err = create_error(&format!("Function with ID `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let func_pos = func_pos.unwrap(); let func = self.functions.get(*func_pos as usize); if func.is_none() { let err = create_error(&format!("Function with position `{}` not found", func_pos), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownFunction, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } self.memory.push(VMMemory::Function(VMMemoryFunction { id: *func_pos as usize, @@ -491,14 +620,28 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); if reg.pointer >= self.memory.len() || reg.pointer < 1 { let err = create_error(&format!("Register `{}` points to an invalid memory location", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let used_var = get_mem_pos_by_var_id(&self.memory, operation.arg2 as u32); if let Some(pos) = used_var { @@ -516,14 +659,22 @@ impl Machine { let reg1 = get_register_by_id(&temp_regs, operation.arg1); if reg1.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg1 = reg1.unwrap(); set_register(&mut self.registers, Register { id: operation.arg2 as u8, pointer: reg1.pointer }); }, 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 => { - do_operation_operation(&mut self.registers, &mut self.memory, operation, &self.ctx[self.call_stack[executed_stack].func].clone()); + do_operation_operation(self, operation, &mut executed_stack, executed_func); + executed_func = &func_clone[self.call_stack[executed_stack].func]; }, 24 => { //NOT @@ -532,14 +683,28 @@ impl Machine { let reg2 = get_register_by_id(®_clone, operation.arg2 as u8); if reg1.is_none() || reg2.is_none() { let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = reg1.unwrap().pointer; if mem1 >= self.memory.len() || mem1 < 1 { let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mut result: VMMemory; match &self.memory[mem1] { @@ -548,8 +713,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Wrong memory type for NOT operation, position: `{}`", mem1), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } let mut reg2_pointer = reg2.unwrap().pointer; @@ -571,15 +743,29 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap(); match &mem { @@ -590,8 +776,15 @@ impl Machine { } _ => { let err = create_error(&format!("Wrong memory type for CJP operation, position: `{}`", reg.pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } }, } }, @@ -600,15 +793,29 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownMemoryLocation, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap().clone(); match mem { @@ -617,9 +824,7 @@ impl Machine { for i in &self.stack { let mut new_mem = i.clone(); if self.functions[func.id].variables.len() <= arg || self.functions[func.id].variables[arg].start != 0 { - let err = create_error(&format!("Too many arguments supplied for function: `{}`", func.id), operation.pos, ErrorType::SemanticError, ErrorSubType::TooManyArguments, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + break; } set_var_id(&mut new_mem, self.functions[func.id].variables[arg].id); self.memory.push(new_mem); @@ -635,8 +840,15 @@ impl Machine { let ret_reg = get_register_by_id(&self.registers, operation.arg2 as u8); if ret_reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mut ret_pointer = ret_reg.unwrap().pointer; if ret_pointer >= self.memory.len() || ret_pointer < 1 { @@ -652,8 +864,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Unable to call non-function type"), operation.pos, ErrorType::MachineError, ErrorSubType::NonFunctionCall, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } }, @@ -662,15 +881,29 @@ impl Machine { let reg = get_register_by_id(&self.registers, operation.arg1); if reg.is_none() { let err = create_error(&format!("Register `{}` not found", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let reg = reg.unwrap(); let mem = self.memory.get(reg.pointer); if mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem = mem.unwrap(); self.stack.push(mem.clone()); @@ -681,14 +914,28 @@ impl Machine { let ret_reg = get_register_by_id(&self.registers, operation.arg1); if target_reg.is_none() || ret_reg.is_none() { let err = create_error(&format!("Register `{}` or `{}` not found", self.call_stack[executed_stack].return_reg, operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let ret_mem = self.memory.get(ret_reg.unwrap().pointer); if ret_mem.is_none() { let err = create_error(&format!("Memory location not found for register `{}`", operation.arg1), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let return_value = ret_mem.unwrap().clone(); let target_reg_pointer = self.memory.len(); @@ -697,6 +944,7 @@ impl Machine { self.memory[target_reg_pointer] = return_value; self.call_stack.pop(); if self.call_stack.len() < 1 { + self.state = VMState::Finished; return; } executed_stack = self.call_stack.len() - 1; @@ -711,14 +959,28 @@ impl Machine { let reg3 = get_register_by_id(®_clone, operation.arg3); if reg2.is_none() || reg3.is_none() { let err = create_error(&format!("Register `{}` or `{}` not found", operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem2 = self.memory.get(reg2.unwrap().pointer); if mem2.is_none() { let err = create_error(&format!("Memory location out of bounds for register `{}`", operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem2 = mem2.unwrap().clone(); let mut result: VMMemory; @@ -733,8 +995,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Only string keys are allowed for GET enviroment"), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } let mut reg3_pointer = reg3.unwrap().pointer; @@ -753,15 +1022,29 @@ impl Machine { let reg3 = get_register_by_id(®_clone, operation.arg3); if reg.is_none() || reg2.is_none() || reg3.is_none() { let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = self.memory.get(reg.unwrap().pointer); let mem2 = self.memory.get(reg2.unwrap().pointer); if mem1.is_none() || mem2.is_none() { let err = create_error(&format!("Memory location not found for register `{}` or `{}`", operation.arg1, operation.arg2), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = mem1.unwrap().clone(); let mem2 = mem2.unwrap().clone(); @@ -777,8 +1060,15 @@ impl Machine { }, _ => { let err = create_error(&format!("Wrong memory type for GET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } let mut reg3_pointer = reg3.unwrap().pointer; @@ -798,16 +1088,30 @@ impl Machine { let reg3 = get_register_by_id(&self.registers, operation.arg3); if reg.is_none() || reg2.is_none() || reg3.is_none() { let err = create_error(&format!("Register `{}` or `{}` or `{}` not found", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::RegisterNotFound, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem1 = self.memory.get(reg.unwrap().pointer); let mem2 = self.memory.get(reg2.unwrap().pointer); let mem3 = self.memory.get(reg3.unwrap().pointer); if mem1.is_none() || mem2.is_none() || mem3.is_none() { let err = create_error(&format!("Memory location not found for register `{}` or `{}` or `{}`", operation.arg1, operation.arg2, operation.arg3), operation.pos, ErrorType::MachineError, ErrorSubType::MemoryOutOfBounds, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } let mem2 = mem2.unwrap().clone(); let mem3 = mem3.unwrap().clone(); @@ -818,15 +1122,29 @@ impl Machine { }, _ => { let err = create_error(&format!("Wrong memory type for SET operation, position: `{}`", reg.unwrap().pointer), operation.pos, ErrorType::TypeError, ErrorSubType::WrongType, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } }, _ => { let err = create_error(&format!("Unknown operation code: `{}`", operation.opcode), operation.pos, ErrorType::MachineError, ErrorSubType::UnknownOPCode, &self.ctx[self.call_stack[executed_stack].func].clone()); - print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); - process::exit(1); + if executed_func.try_catch > 0 { + fallback_to_catch(&mut self.memory, &mut self.state, &mut self.functions, &mut self.call_stack, &mut executed_stack, executed_func, err); + executed_func = &func_clone[self.call_stack[executed_stack].func]; + continue; + } else { + print_error(&err, &self.ctx[self.call_stack[executed_stack].func].clone()); + self.state = VMState::Error(err); + return; + } } } } diff --git a/test.asl b/test.asl index 60adf39..008de33 100644 --- a/test.asl +++ b/test.asl @@ -1,5 +1,8 @@ +gethelj a = 1 piszolj { + ugass(a) gethelj test = szaft"a"szaft+1 } csecs(err) { - ugass(szaft"Hibás bemb"szaft) -} \ No newline at end of file + ugass(szaft"Hibás bemb"szaft, err) +} +ugass(test) \ No newline at end of file