diff --git a/src/internal/interpreter/execution_engine.rs b/src/internal/interpreter/execution_engine.rs index fae5b78..efb6ded 100644 --- a/src/internal/interpreter/execution_engine.rs +++ b/src/internal/interpreter/execution_engine.rs @@ -166,7 +166,14 @@ impl ExecutionEngine for Interpreter { } Instruction::StackPush(ref register, ref reference) => { - self.push_on_stack(register, reference) + let res = self.push_on_stack(register, reference); + if let Err(mut err) = res { + let context = err.context.get_or_insert_with(|| create_context!(self, vec![], vec![])); + context.instruction.push(operation); + context.instruction_pointer.push(index); + create_new_trace!(err); + return Err(err); + } } Instruction::StackMov(ref register, ref reference) => { let res = self.stack_mov(register, reference); diff --git a/src/internal/interpreter/instruction/cpy.rs b/src/internal/interpreter/instruction/cpy.rs index 9e5006c..f65fed8 100644 --- a/src/internal/interpreter/instruction/cpy.rs +++ b/src/internal/interpreter/instruction/cpy.rs @@ -30,7 +30,11 @@ impl Interpreter { (RegisterLocation::Accumulator, RegisterLocation::Global) => { // Start doing the move if src_register is not None let src_register = self.cpy_global(src_index_usize); // take the value from global memory - match src_register { + if let Err(mut err) = src_register { + create_new_trace!(err); + return Err(err); + } + match src_register.unwrap() { Constant::Int(src_int) => { self.accumulator = src_int as f64; } @@ -68,7 +72,12 @@ impl Interpreter { self.global[dst_index_usize] = Some(create_constant_double(&self.accumulator)); }, (RegisterLocation::Global, RegisterLocation::Global) => { - self.global[dst_index_usize] = Some(self.cpy_global(src_index_usize)); + let src_reg = self.cpy_global(src_index_usize); + if let Err(mut err) = src_reg { + create_new_trace!(err); + return Err(err); + } + self.global[dst_index_usize] = Some(src_reg.unwrap()); }, (RegisterLocation::Global, RegisterLocation::Local) => { self.global[dst_index_usize] = Some(self.cpy_local(src_index_usize)); @@ -85,9 +94,13 @@ impl Interpreter { stack_frame.registers[dst_index_usize] = accumulator; }, (RegisterLocation::Local, RegisterLocation::Global) => { - let global_value = Some(self.cpy_global(src_index_usize)); + let global_value = self.cpy_global(src_index_usize); let stack_frame = self.ref_stack_frame(); - stack_frame.registers[dst_index_usize] = global_value; + if let Err(mut err) = global_value { + create_new_trace!(err); + return Err(err); + } + stack_frame.registers[dst_index_usize] = Some(global_value.unwrap()); }, (RegisterLocation::Local, RegisterLocation::Local) => { let stack_frame = self.ref_stack_frame(); diff --git a/src/internal/interpreter/instruction/mov.rs b/src/internal/interpreter/instruction/mov.rs index c945e59..4873e38 100644 --- a/src/internal/interpreter/instruction/mov.rs +++ b/src/internal/interpreter/instruction/mov.rs @@ -30,7 +30,11 @@ impl Interpreter { (RegisterLocation::Accumulator, RegisterLocation::Global) => { // Start doing the move if src_register is not None let src_register = self.mov_global(src_index_usize); // take the value from global memory - match src_register { + if let Err(mut err) = src_register { + create_new_trace!(err); + return Err(err); + } + match src_register.unwrap() { Constant::Int(src_int) => { self.accumulator = src_int as f64; } @@ -62,7 +66,14 @@ impl Interpreter { }, (RegisterLocation::Global, RegisterLocation::Accumulator) => self.global[dst_index_usize] = Some(create_constant_double(&self.accumulator)), - (RegisterLocation::Global, RegisterLocation::Global) => self.global[dst_index_usize] = Some(self.mov_global(src_index_usize)), + (RegisterLocation::Global, RegisterLocation::Global) => { + let src_reg = self.mov_global(src_index_usize); + if let Err(mut err) = src_reg { + create_new_trace!(err); + return Err(err); + } + self.global[dst_index_usize] = Some(src_reg.unwrap()); + }, (RegisterLocation::Global, RegisterLocation::Local) => self.global[dst_index_usize] = Some(self.mov_local(src_index_usize)), (RegisterLocation::Local, RegisterLocation::Accumulator) => { @@ -71,9 +82,14 @@ impl Interpreter { stack_frame.registers[dst_index_usize] = Some(create_constant_double(&accumulator)); }, (RegisterLocation::Local, RegisterLocation::Global) => { - let global_value = Some(self.mov_global(src_index_usize)); + let global_value = self.mov_global(src_index_usize); let stack_frame = self.ref_stack_frame(); - stack_frame.registers[dst_index_usize] = global_value; + + if let Err(mut err) = global_value { + create_new_trace!(err); + return Err(err); + } + stack_frame.registers[dst_index_usize] = Some(global_value.unwrap()); }, (RegisterLocation::Local, RegisterLocation::Local) => { let stack_frame = self.ref_stack_frame(); diff --git a/src/internal/interpreter/instruction/stk_push.rs b/src/internal/interpreter/instruction/stk_push.rs index 69a6f50..8252e86 100644 --- a/src/internal/interpreter/instruction/stk_push.rs +++ b/src/internal/interpreter/instruction/stk_push.rs @@ -1,8 +1,8 @@ -use crate::{objects::{register::{Register, RegisterReference, RegisterLocation}, constant::create_constant_double}, Interpreter}; +use crate::{objects::{register::{Register, RegisterReference, RegisterLocation}, constant::create_constant_double}, Interpreter, create_new_trace, ResurgenceError}; impl Interpreter { - pub(crate) fn push_on_stack(&mut self, register: &Register, reference: &RegisterReference) { + pub(crate) fn push_on_stack(&mut self, register: &Register, reference: &RegisterReference) -> Result<(), ResurgenceError> { let Register(mut reg_index, mut reg_loc) = register; let mut reg_index_usize = reg_index as usize; if *reference == RegisterReference::Dereference { Register(reg_index, reg_loc) = self.dereference_register(reg_index_usize, ®_loc); reg_index_usize = reg_index as usize; @@ -13,12 +13,17 @@ impl Interpreter { RegisterLocation::Accumulator => self.stack.push(create_constant_double(&self.accumulator)), RegisterLocation::Global => { let val = self.mov_global(reg_index_usize); - self.stack.push(val); + if let Err(mut err) = val { + create_new_trace!(err); + return Err(err); + } + self.stack.push(val.unwrap()); }, RegisterLocation::Local => { let val = self.mov_local(reg_index_usize); self.stack.push(val); }, } + Ok(()) } } diff --git a/src/internal/interpreter/utils/mod.rs b/src/internal/interpreter/utils/mod.rs index a718e99..afc8acf 100644 --- a/src/internal/interpreter/utils/mod.rs +++ b/src/internal/interpreter/utils/mod.rs @@ -2,24 +2,46 @@ use crate::{ objects::{ constant::Constant, register::{Register, RegisterLocation}, - stackframe::StackFrame, + stackframe::StackFrame, resurgence_error::ResurgenceErrorKind, }, - Interpreter, + Interpreter, ResurgenceError, create_new_trace, }; impl Interpreter { - /// Moves the value of a global register - /// - /// `index` (`usize`): index of register - pub(crate) fn mov_global(&mut self, index: usize) -> Constant { - self.global[index].take().expect("Non-existant register!") + /// Moves a value from a global register and returns that value, or an error if: + /// - Register is beyond bounds + /// - Register contains a `Option::None` instead of `Option::Some` + pub(crate) fn mov_global(&mut self, index: usize) -> Result { + if index >= self.global.len() { + let mut err = ResurgenceError::from(ResurgenceErrorKind::REGISTER_OUT_OF_BOUNDS, "Register beyond bounds!"); + create_new_trace!(err); + return Err(err); + } + let reg = self.global[index].take(); + if let None = reg { + let mut err = ResurgenceError::from(ResurgenceErrorKind::MEMORY_ADDRESS_NONE, "Global register None!"); + create_new_trace!(err); + return Err(err); + } + Ok(reg.unwrap()) } - /// Returns a copy of a global register - /// - /// `index` (`usize`): index of register - pub(crate) fn cpy_global(&mut self, index: usize) -> Constant { - self.global[index].clone().expect("Non-existant register!") + /// Copies a value from a global register and returns that value, or an error if: + /// - Register is beyond bounds + /// - Register contains a `Option::None` instead of `Option::Some` + pub(crate) fn cpy_global(&mut self, index: usize) -> Result { + if index >= self.global.len() { + let mut err = ResurgenceError::from(ResurgenceErrorKind::REGISTER_OUT_OF_BOUNDS, "Register beyond bounds!"); + create_new_trace!(err); + return Err(err); + } + let reg = self.global[index].clone(); + if let None = reg { + let mut err = ResurgenceError::from(ResurgenceErrorKind::MEMORY_ADDRESS_NONE, "Global register None!"); + create_new_trace!(err); + return Err(err); + } + Ok(reg.unwrap()) } /// Returns a reference to a global register