Skip to content

Commit

Permalink
Added error handling for global operations
Browse files Browse the repository at this point in the history
Now global operations (or at least cpy_global and mov_global) have error
handling, which allows us to better introduce better error handling to
more places. This in turn should make it easier for us to port
Resurgence from a panic system to a proper error handling system.
  • Loading branch information
StandingPadAnimations committed Mar 26, 2023
1 parent cb885c3 commit 4c936ef
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 24 deletions.
9 changes: 8 additions & 1 deletion src/internal/interpreter/execution_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
21 changes: 17 additions & 4 deletions src/internal/interpreter/instruction/cpy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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));
Expand All @@ -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();
Expand Down
24 changes: 20 additions & 4 deletions src/internal/interpreter/instruction/mov.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) => {
Expand All @@ -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();
Expand Down
11 changes: 8 additions & 3 deletions src/internal/interpreter/instruction/stk_push.rs
Original file line number Diff line number Diff line change
@@ -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, &reg_loc); reg_index_usize = reg_index as usize;
Expand All @@ -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(())
}
}
46 changes: 34 additions & 12 deletions src/internal/interpreter/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Constant, ResurgenceError> {
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<Constant, ResurgenceError> {
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
Expand Down

0 comments on commit 4c936ef

Please sign in to comment.