use log::trace;
use crate::runtime::error::state_error;
use crate::runtime::utilities::next_ref;
use garnish_lang_traits::{GarnishDataType, GarnishData, RuntimeError};
pub(crate) fn jump<Data: GarnishData>(this: &mut Data, index: Data::Size) -> Result<Option<Data::Size>, RuntimeError<Data::Error>> {
match this.get_jump_point(index.clone()) {
None => state_error(format!("No jump point at index {:?}", index))?,
Some(point) => {
trace!("Jumping to point {:?}", point);
return Ok(Some(point));
}
}
Ok(None)
}
pub(crate) fn jump_if_true<Data: GarnishData>(
this: &mut Data,
index: Data::Size,
) -> Result<Option<Data::Size>, RuntimeError<Data::Error>> {
let point = match this.get_jump_point(index.clone()) {
None => state_error(format!("No jump point at index {:?}", index))?,
Some(point) => point,
};
let d = next_ref(this)?;
match this.get_data_type(d.clone())? {
GarnishDataType::False | GarnishDataType::Unit => {
trace!("Not jumping from value of type {:?} with addr {:?}", this.get_data_type(d.clone())?, d);
Ok(None)
}
t => {
trace!("Jumping from value of type {:?} with addr {:?} to point {:?}", t, d, point);
Ok(Some(point))
}
}
}
pub(crate) fn jump_if_false<Data: GarnishData>(
this: &mut Data,
index: Data::Size,
) -> Result<Option<Data::Size>, RuntimeError<Data::Error>> {
let point = match this.get_jump_point(index.clone()) {
None => state_error(format!("No jump point at index {:?}", index))?,
Some(point) => point,
};
let d = next_ref(this)?;
match this.get_data_type(d.clone())? {
GarnishDataType::False | GarnishDataType::Unit => {
trace!(
"Jumping from value of type {:?} with addr {:?} to point {:?}",
this.get_data_type(d.clone())?,
d,
point
);
Ok(Some(point))
}
t => {
trace!("Not jumping from value of type {:?} with addr {:?}", t, d);
Ok(None)
}
}
}
pub(crate) fn end_expression<Data: GarnishData>(this: &mut Data) -> Result<Option<Data::Size>, RuntimeError<Data::Error>> {
match this.pop_jump_path() {
None => {
let r = next_ref(this)?;
trace!(
"No remaining return points. Pushing {:?} to values. Setting cursor to instruction length {:?}.",
r,
this.get_instruction_len()
);
match this.get_current_value_mut() {
None => state_error(format!("No inputs available to update during end expression operation."))?,
Some(v) => *v = r,
}
Ok(Some(this.get_instruction_len()))
}
Some(jump_point) => {
trace!("Setting cursor to {:?}", jump_point);
this.pop_value_stack();
Ok(Some(jump_point))
}
}
}