From 70950e0bc77e4fba253ac23d36978c89061275a8 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Mon, 31 Jan 2022 15:30:37 -0500 Subject: [PATCH] Reduce usage of OpGetter by making RuntimeError (de)composable --- mps-interpreter/src/lang/error.rs | 32 ++++++++ mps-interpreter/src/lang/filter.rs | 78 +++++++++---------- mps-interpreter/src/lang/filter_replace.rs | 69 ++++++++-------- mps-interpreter/src/lang/lookup.rs | 16 ++-- mps-interpreter/src/lang/mod.rs | 2 +- mps-interpreter/src/lang/sorter.rs | 15 +--- .../lang/vocabulary/filters/empty_filter.rs | 12 +-- .../lang/vocabulary/filters/field_filter.rs | 31 +++----- .../vocabulary/filters/field_like_filter.rs | 31 +++----- .../lang/vocabulary/filters/index_filter.rs | 31 ++------ .../lang/vocabulary/filters/range_filter.rs | 31 +++----- .../vocabulary/sorters/bliss_next_sorter.rs | 24 +++--- .../lang/vocabulary/sorters/bliss_sorter.rs | 18 ++--- .../lang/vocabulary/sorters/empty_sorter.rs | 6 +- .../lang/vocabulary/sorters/field_sorter.rs | 6 +- .../src/lang/vocabulary/sorters/shuffle.rs | 6 +- .../src/lang/vocabulary/variable_assign.rs | 52 +++++++------ mps-interpreter/src/processing/variables.rs | 65 ++++++---------- 18 files changed, 222 insertions(+), 303 deletions(-) diff --git a/mps-interpreter/src/lang/error.rs b/mps-interpreter/src/lang/error.rs index b8e3830..0906dee 100644 --- a/mps-interpreter/src/lang/error.rs +++ b/mps-interpreter/src/lang/error.rs @@ -40,6 +40,12 @@ pub struct RuntimeError { pub msg: String, } +impl RuntimeError { + pub fn decompose(self) -> (RuntimeOp, RuntimeMsg) { + (RuntimeOp(self.op), RuntimeMsg(self.msg)) + } +} + impl Display for RuntimeError { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "{} (line {}): {}", &self.msg, &self.line, &self.op) @@ -55,3 +61,29 @@ impl MpsLanguageError for RuntimeError { pub trait MpsLanguageError: Display + Debug { fn set_line(&mut self, line: usize); } + +// RuntimeError builder components + +pub struct RuntimeMsg(pub String); + +impl RuntimeMsg { + pub fn with(self, op: RuntimeOp) -> RuntimeError { + RuntimeError { + line: 0, + op: op.0, + msg: self.0, + } + } +} + +pub struct RuntimeOp(pub PseudoOp); + +impl RuntimeOp { + pub fn with(self, msg: RuntimeMsg) -> RuntimeError { + RuntimeError { + line: 0, + op: self.0, + msg: msg.0, + } + } +} diff --git a/mps-interpreter/src/lang/filter.rs b/mps-interpreter/src/lang/filter.rs index c5023dc..18de8a0 100644 --- a/mps-interpreter/src/lang/filter.rs +++ b/mps-interpreter/src/lang/filter.rs @@ -8,9 +8,8 @@ use crate::lang::MpsFilterReplaceStatement; use crate::lang::MpsLanguageDictionary; use crate::lang::SingleItem; use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, PseudoOp}; -use crate::lang::{RuntimeError, SyntaxError}; +use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError}; use crate::processing::general::MpsType; -use crate::processing::OpGetter; use crate::tokens::MpsToken; use crate::MpsContext; use crate::MpsItem; @@ -18,16 +17,11 @@ use crate::MpsItem; const INNER_VARIABLE_NAME: &str = "[inner variable]"; pub trait MpsFilterPredicate: Clone + Debug + Display { - fn matches( - &mut self, - item: &MpsItem, - ctx: &mut MpsContext, - op: &mut OpGetter, - ) -> Result; + fn matches(&mut self, item: &MpsItem, ctx: &mut MpsContext) -> Result; fn is_complete(&self) -> bool; - fn reset(&mut self) -> Result<(), RuntimeError>; + fn reset(&mut self) -> Result<(), RuntimeMsg>; } pub trait MpsFilterFactory { @@ -125,17 +119,19 @@ impl MpsOp for MpsFilterStatement

{ fn reset(&mut self) -> Result<(), RuntimeError> { let fake = PseudoOp::Fake(format!("{}", self)); - self.predicate.reset()?; + self.predicate + .reset() + .map_err(|x| x.with(RuntimeOp(fake.clone())))?; match &mut self.iterable { VariableOrOp::Variable(s) => { if self.context.as_mut().unwrap().variables.exists(s) { - let fake_getter = &mut move || fake.clone(); let mut var = self .context .as_mut() .unwrap() .variables - .remove(s, fake_getter)?; + .remove(s) + .map_err(|e| e.with(RuntimeOp(fake.clone())))?; let result = if let MpsType::Op(var) = &mut var { var.enter(self.context.take().unwrap()); let result = var.reset(); @@ -144,7 +140,7 @@ impl MpsOp for MpsFilterStatement

{ } else { Err(RuntimeError { line: 0, - op: fake_getter(), + op: fake.clone(), msg: "Cannot reset non-iterable filter variable".to_string(), }) }; @@ -152,7 +148,8 @@ impl MpsOp for MpsFilterStatement

{ .as_mut() .unwrap() .variables - .declare(s, var, fake_getter)?; + .declare(s, var) + .map_err(|e| e.with(RuntimeOp(fake)))?; result } else { Ok(()) @@ -190,7 +187,7 @@ impl Iterator for MpsFilterStatement

{ } let self_clone = self.clone(); let self_clone2 = self_clone.clone(); - let mut op_getter = move || (Box::new(self_clone.clone()) as Box).into(); + let fake = PseudoOp::Fake(format!("{}", self)); //let ctx = self.context.as_mut().unwrap(); match &mut self.iterable { VariableOrOp::Op(op) => match op.try_real() { @@ -208,11 +205,10 @@ impl Iterator for MpsFilterStatement

{ break; } Ok(item) => { - let matches_result = - self.predicate.matches(&item, &mut ctx, &mut op_getter); + let matches_result = self.predicate.matches(&item, &mut ctx); let matches = match matches_result { Err(e) => { - maybe_result = Some(Err(e)); + maybe_result = Some(Err(e.with(RuntimeOp(fake.clone())))); self.context = Some(ctx); break; } @@ -225,12 +221,12 @@ impl Iterator for MpsFilterStatement

{ match ctx.variables.declare( INNER_VARIABLE_NAME, MpsType::Op(Box::new(single_op)), - &mut op_getter, ) { Ok(x) => x, Err(e) => { //self.context = Some(op.escape()); - maybe_result = Some(Err(e)); + maybe_result = + Some(Err(e.with(RuntimeOp(fake.clone())))); self.context = Some(ctx); break; } @@ -249,13 +245,14 @@ impl Iterator for MpsFilterStatement

{ Some(item) => { maybe_result = Some(item); ctx = inner_real.escape(); - match ctx - .variables - .remove(INNER_VARIABLE_NAME, &mut op_getter) - { + match ctx.variables.remove(INNER_VARIABLE_NAME) { Ok(_) => {} Err(e) => match maybe_result { - Some(Ok(_)) => maybe_result = Some(Err(e)), + Some(Ok(_)) => { + maybe_result = Some(Err( + e.with(RuntimeOp(fake.clone())) + )) + } Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error, None => {} // impossible }, @@ -265,14 +262,12 @@ impl Iterator for MpsFilterStatement

{ } None => { ctx = inner_real.escape(); // move ctx back to expected spot - match ctx - .variables - .remove(INNER_VARIABLE_NAME, &mut op_getter) - { + match ctx.variables.remove(INNER_VARIABLE_NAME) { Ok(_) => {} Err(e) => { //self.context = Some(op.escape()); - maybe_result = Some(Err(e)); + maybe_result = + Some(Err(e.with(RuntimeOp(fake.clone())))); self.context = Some(ctx); break; } @@ -303,7 +298,7 @@ impl Iterator for MpsFilterStatement

{ .as_mut() .unwrap() .variables - .remove(variable_name, &mut op_getter) + .remove(variable_name) { Ok(MpsType::Op(op)) => op, Ok(x) => { @@ -316,7 +311,7 @@ impl Iterator for MpsFilterStatement

{ ), })) } - Err(e) => return Some(Err(e)), + Err(e) => return Some(Err(e.with(RuntimeOp(fake.clone())))), }; let mut maybe_result = None; let ctx = self.context.take().unwrap(); @@ -330,11 +325,10 @@ impl Iterator for MpsFilterStatement

{ break; } Ok(item) => { - let matches_result = - self.predicate.matches(&item, &mut ctx, &mut op_getter); + let matches_result = self.predicate.matches(&item, &mut ctx); let matches = match matches_result { Err(e) => { - maybe_result = Some(Err(e)); + maybe_result = Some(Err(e.with(RuntimeOp(fake.clone())))); self.context = Some(ctx); break; } @@ -352,12 +346,14 @@ impl Iterator for MpsFilterStatement

{ if self.context.is_none() { self.context = Some(variable.escape()); } - match self.context.as_mut().unwrap().variables.declare( - variable_name, - MpsType::Op(variable), - &mut op_getter, - ) { - Err(e) => Some(Err(e)), + match self + .context + .as_mut() + .unwrap() + .variables + .declare(variable_name, MpsType::Op(variable)) + { + Err(e) => Some(Err(e.with(RuntimeOp(fake.clone())))), Ok(_) => maybe_result, } } diff --git a/mps-interpreter/src/lang/filter_replace.rs b/mps-interpreter/src/lang/filter_replace.rs index e6bf36b..6a2f6b7 100644 --- a/mps-interpreter/src/lang/filter_replace.rs +++ b/mps-interpreter/src/lang/filter_replace.rs @@ -2,12 +2,11 @@ use std::collections::VecDeque; use std::fmt::{Debug, Display, Error, Formatter}; use std::iter::Iterator; -use crate::lang::RuntimeError; use crate::lang::SingleItem; use crate::lang::{filter::VariableOrOp, MpsFilterPredicate}; use crate::lang::{MpsIteratorItem, MpsOp, PseudoOp}; +use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp}; use crate::processing::general::MpsType; -use crate::processing::OpGetter; use crate::MpsContext; use crate::MpsItem; @@ -91,17 +90,19 @@ impl MpsOp for MpsFilterReplaceStatement

{ fn reset(&mut self) -> Result<(), RuntimeError> { self.item_cache.clear(); let fake = PseudoOp::Fake(format!("{}", self)); - self.predicate.reset()?; + self.predicate + .reset() + .map_err(|x| x.with(RuntimeOp(fake.clone())))?; match &mut self.iterable { VariableOrOp::Variable(s) => { if self.context.as_mut().unwrap().variables.exists(s) { - let fake_getter = &mut move || fake.clone(); let mut var = self .context .as_mut() .unwrap() .variables - .remove(s, fake_getter)?; + .remove(s) + .map_err(|e| e.with(RuntimeOp(fake.clone())))?; let result = if let MpsType::Op(var) = &mut var { var.enter(self.context.take().unwrap()); let result = var.reset(); @@ -110,7 +111,7 @@ impl MpsOp for MpsFilterReplaceStatement

{ } else { Err(RuntimeError { line: 0, - op: fake_getter(), + op: fake.clone(), msg: "Cannot reset non-iterable filter variable".to_string(), }) }; @@ -118,7 +119,8 @@ impl MpsOp for MpsFilterReplaceStatement

{ .as_mut() .unwrap() .variables - .declare(s, var, fake_getter)?; + .declare(s, var) + .map_err(|e| e.with(RuntimeOp(fake)))?; result } else { Ok(()) @@ -146,8 +148,7 @@ impl Iterator for MpsFilterReplaceStatement

if !self.item_cache.is_empty() { return self.item_cache.pop_front(); } - let self_clone = self.clone(); - let mut op_getter = move || (Box::new(self_clone.clone()) as Box).into(); + let fake = PseudoOp::Fake(format!("{}", self)); // get next item in iterator let next_item = match &mut self.iterable { VariableOrOp::Op(op) => match op.try_real() { @@ -166,31 +167,33 @@ impl Iterator for MpsFilterReplaceStatement

.as_mut() .unwrap() .variables - .remove(variable_name, &mut op_getter) + .remove(variable_name) { Ok(MpsType::Op(op)) => op, Ok(x) => { return Some(Err(RuntimeError { line: 0, - op: op_getter(), + op: fake.clone(), msg: format!( "Expected operation/iterable type in variable {}, got {}", &variable_name, x ), })) } - Err(e) => return Some(Err(e)), + Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), }; let ctx = self.context.take().unwrap(); variable.enter(ctx); let item = variable.next(); self.context = Some(variable.escape()); - match self.context.as_mut().unwrap().variables.declare( - variable_name, - MpsType::Op(variable), - &mut op_getter, - ) { - Err(e) => return Some(Err(e)), + match self + .context + .as_mut() + .unwrap() + .variables + .declare(variable_name, MpsType::Op(variable)) + { + Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), Ok(_) => {} } item @@ -202,7 +205,7 @@ impl Iterator for MpsFilterReplaceStatement

//println!("item is now: `{}`", &item.filename); match self .predicate - .matches(&item, self.context.as_mut().unwrap(), &mut op_getter) + .matches(&item, self.context.as_mut().unwrap()) { Ok(is_match) => { if is_match { @@ -214,11 +217,10 @@ impl Iterator for MpsFilterReplaceStatement

//println!("Declaring item variable"); let old_item = match declare_or_replace_item( single_op, - &mut op_getter, self.context.as_mut().unwrap(), ) { Ok(x) => x, - Err(e) => return Some(Err(e)), // probably shouldn't occur + Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), // probably shouldn't occur }; // invoke inner op real_op.enter(self.context.take().unwrap()); @@ -236,11 +238,10 @@ impl Iterator for MpsFilterReplaceStatement

//println!("Removing item variable"); match remove_or_replace_item( old_item, - &mut op_getter, self.context.as_mut().unwrap(), ) { Ok(_) => {} - Err(e) => return Some(Err(e)), + Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), } } Err(e) => return Some(Err(e)), // probably shouldn't occur @@ -261,11 +262,10 @@ impl Iterator for MpsFilterReplaceStatement

//println!("Declaring item variable"); let old_item = match declare_or_replace_item( single_op, - &mut op_getter, self.context.as_mut().unwrap(), ) { Ok(x) => x, - Err(e) => return Some(Err(e)), // probably shouldn't occur + Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), // probably shouldn't occur }; // invoke inner operation real_op.enter(self.context.take().unwrap()); @@ -283,11 +283,10 @@ impl Iterator for MpsFilterReplaceStatement

//println!("Removing item variable"); match remove_or_replace_item( old_item, - &mut op_getter, self.context.as_mut().unwrap(), ) { Ok(_) => {} - Err(e) => return Some(Err(e)), + Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), } } Err(e) => return Some(Err(e)), // probably shouldn't occur @@ -303,7 +302,7 @@ impl Iterator for MpsFilterReplaceStatement

Some(Ok(item)) } } - Err(e) => Some(Err(e)), + Err(e) => Some(Err(e.with(RuntimeOp(fake.clone())))), } } Some(Err(e)) => Some(Err(e)), @@ -329,28 +328,26 @@ impl Iterator for MpsFilterReplaceStatement

fn declare_or_replace_item( single: SingleItem, - op: &mut OpGetter, ctx: &mut MpsContext, -) -> Result, RuntimeError> { +) -> Result, RuntimeMsg> { let old_item: Option; if ctx.variables.exists(ITEM_VARIABLE_NAME) { - old_item = Some(ctx.variables.remove(ITEM_VARIABLE_NAME, op)?); + old_item = Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?); } else { old_item = None; } ctx.variables - .declare(ITEM_VARIABLE_NAME, MpsType::Op(Box::new(single)), op)?; + .declare(ITEM_VARIABLE_NAME, MpsType::Op(Box::new(single)))?; Ok(old_item) } fn remove_or_replace_item( old_item: Option, - op: &mut OpGetter, ctx: &mut MpsContext, -) -> Result<(), RuntimeError> { - ctx.variables.remove(ITEM_VARIABLE_NAME, op)?; +) -> Result<(), RuntimeMsg> { + ctx.variables.remove(ITEM_VARIABLE_NAME)?; if let Some(old_item) = old_item { - ctx.variables.declare(ITEM_VARIABLE_NAME, old_item, op)?; + ctx.variables.declare(ITEM_VARIABLE_NAME, old_item)?; } Ok(()) } diff --git a/mps-interpreter/src/lang/lookup.rs b/mps-interpreter/src/lang/lookup.rs index 7fa3981..b6a9626 100644 --- a/mps-interpreter/src/lang/lookup.rs +++ b/mps-interpreter/src/lang/lookup.rs @@ -3,9 +3,8 @@ use std::fmt::{Display, Error, Formatter}; //use super::MpsTypePrimitive; use super::utility::{assert_token, assert_type, check_is_type}; -use crate::lang::{RuntimeError, SyntaxError}; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::processing::general::MpsType; -use crate::processing::OpGetter; use crate::tokens::MpsToken; use crate::MpsContext; @@ -43,22 +42,17 @@ impl Lookup { pub fn get_mut<'a, 'b: 'a>( &'b mut self, ctx: &'a mut MpsContext, - op: &mut OpGetter, - ) -> Result<&'a mut MpsType, RuntimeError> { + ) -> Result<&'a mut MpsType, RuntimeMsg> { match self { Self::Static(var) => Ok(var), - Self::Variable(name) => ctx.variables.get_mut(name, op), + Self::Variable(name) => ctx.variables.get_mut(name), } } - pub fn get<'a, 'b: 'a>( - &'b self, - ctx: &'a MpsContext, - op: &mut OpGetter, - ) -> Result<&'a MpsType, RuntimeError> { + pub fn get<'a, 'b: 'a>(&'b self, ctx: &'a MpsContext) -> Result<&'a MpsType, RuntimeMsg> { match self { Self::Static(var) => Ok(var), - Self::Variable(name) => ctx.variables.get(name, op), + Self::Variable(name) => ctx.variables.get(name), } } } diff --git a/mps-interpreter/src/lang/mod.rs b/mps-interpreter/src/lang/mod.rs index 213f01a..f3e30e0 100644 --- a/mps-interpreter/src/lang/mod.rs +++ b/mps-interpreter/src/lang/mod.rs @@ -15,7 +15,7 @@ mod type_primitives; pub(crate) mod utility; pub use dictionary::MpsLanguageDictionary; -pub use error::{MpsLanguageError, RuntimeError, SyntaxError}; +pub use error::{MpsLanguageError, RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError}; pub use filter::{ MpsFilterFactory, MpsFilterPredicate, MpsFilterStatement, MpsFilterStatementFactory, }; diff --git a/mps-interpreter/src/lang/sorter.rs b/mps-interpreter/src/lang/sorter.rs index ffecba6..87deb72 100644 --- a/mps-interpreter/src/lang/sorter.rs +++ b/mps-interpreter/src/lang/sorter.rs @@ -6,8 +6,7 @@ use std::marker::PhantomData; use crate::lang::utility::{assert_name, assert_token_raw, check_name}; use crate::lang::MpsLanguageDictionary; use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, PseudoOp}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::OpGetter; +use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError}; use crate::tokens::MpsToken; use crate::MpsContext; @@ -18,8 +17,7 @@ pub trait MpsSorter: Clone + Debug + Display { &mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque, - op: &'a mut OpGetter, - ) -> Result<(), RuntimeError>; + ) -> Result<(), RuntimeMsg>; fn reset(&mut self) {} } @@ -86,18 +84,13 @@ impl Iterator for MpsSortStatement { type Item = MpsIteratorItem; fn next(&mut self) -> Option { - let pseudo_self = PseudoOp::from_printable(self); let real_op = match self.iterable.try_real() { Ok(op) => op, Err(e) => return Some(Err(e)), }; - match self - .orderer - .sort(real_op.as_mut(), &mut self.item_cache, &mut move || { - pseudo_self.clone() - }) { + match self.orderer.sort(real_op.as_mut(), &mut self.item_cache) { Ok(_) => {} - Err(e) => return Some(Err(e)), + Err(e) => return Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), } self.item_cache.pop_front() } diff --git a/mps-interpreter/src/lang/vocabulary/filters/empty_filter.rs b/mps-interpreter/src/lang/vocabulary/filters/empty_filter.rs index 25a2b64..96904e7 100644 --- a/mps-interpreter/src/lang/vocabulary/filters/empty_filter.rs +++ b/mps-interpreter/src/lang/vocabulary/filters/empty_filter.rs @@ -3,8 +3,7 @@ use std::fmt::{Debug, Display, Error, Formatter}; use crate::lang::MpsLanguageDictionary; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::OpGetter; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::tokens::MpsToken; use crate::MpsContext; use crate::MpsItem; @@ -19,12 +18,7 @@ impl Display for EmptyFilter { } impl MpsFilterPredicate for EmptyFilter { - fn matches( - &mut self, - _item: &MpsItem, - _ctx: &mut MpsContext, - _op: &mut OpGetter, - ) -> Result { + fn matches(&mut self, _item: &MpsItem, _ctx: &mut MpsContext) -> Result { Ok(true) } @@ -32,7 +26,7 @@ impl MpsFilterPredicate for EmptyFilter { false } - fn reset(&mut self) -> Result<(), RuntimeError> { + fn reset(&mut self) -> Result<(), RuntimeMsg> { Ok(()) } } diff --git a/mps-interpreter/src/lang/vocabulary/filters/field_filter.rs b/mps-interpreter/src/lang/vocabulary/filters/field_filter.rs index 4dd62c5..aea737c 100644 --- a/mps-interpreter/src/lang/vocabulary/filters/field_filter.rs +++ b/mps-interpreter/src/lang/vocabulary/filters/field_filter.rs @@ -6,9 +6,8 @@ use crate::lang::utility::{assert_token, assert_type, check_is_type}; use crate::lang::MpsLanguageDictionary; use crate::lang::MpsTypePrimitive; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; -use crate::lang::{RuntimeError, SyntaxError}; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::processing::general::MpsType; -use crate::processing::OpGetter; use crate::tokens::MpsToken; use crate::MpsContext; use crate::MpsItem; @@ -65,16 +64,11 @@ impl MpsFilterPredicate for FieldFilter { &mut self, music_item_lut: &MpsItem, ctx: &mut MpsContext, - op: &mut OpGetter, - ) -> Result { + ) -> Result { let variable = match &self.val { - VariableOrValue::Variable(name) => match ctx.variables.get(name, op)? { + VariableOrValue::Variable(name) => match ctx.variables.get(name)? { MpsType::Primitive(t) => Ok(t), - _ => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Variable {} is not comparable", name), - }), + _ => Err(RuntimeMsg(format!("Variable {} is not comparable", name))), }, VariableOrValue::Value(val) => Ok(val), }?; @@ -82,11 +76,7 @@ impl MpsFilterPredicate for FieldFilter { let compare_res = field.compare(variable); if let Err(e) = compare_res { match self.comparison_errors { - FieldFilterErrorHandling::Error => Err(RuntimeError { - line: 0, - op: op(), - msg: e, - }), + FieldFilterErrorHandling::Error => Err(RuntimeMsg(e)), FieldFilterErrorHandling::Ignore => Ok(false), FieldFilterErrorHandling::Include => Ok(true), } @@ -103,11 +93,10 @@ impl MpsFilterPredicate for FieldFilter { } } else { match self.field_errors { - FieldFilterErrorHandling::Error => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Field {} does not exist", &self.field_name), - }), + FieldFilterErrorHandling::Error => Err(RuntimeMsg(format!( + "Field {} does not exist", + &self.field_name + ))), FieldFilterErrorHandling::Ignore => Ok(false), FieldFilterErrorHandling::Include => Ok(true), } @@ -118,7 +107,7 @@ impl MpsFilterPredicate for FieldFilter { false } - fn reset(&mut self) -> Result<(), RuntimeError> { + fn reset(&mut self) -> Result<(), RuntimeMsg> { Ok(()) } } diff --git a/mps-interpreter/src/lang/vocabulary/filters/field_like_filter.rs b/mps-interpreter/src/lang/vocabulary/filters/field_like_filter.rs index 6a5b43e..99e03dd 100644 --- a/mps-interpreter/src/lang/vocabulary/filters/field_like_filter.rs +++ b/mps-interpreter/src/lang/vocabulary/filters/field_like_filter.rs @@ -6,9 +6,8 @@ use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_na use crate::lang::MpsLanguageDictionary; use crate::lang::MpsTypePrimitive; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; -use crate::lang::{RuntimeError, SyntaxError}; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::processing::general::MpsType; -use crate::processing::OpGetter; use crate::tokens::MpsToken; use crate::MpsContext; use crate::MpsItem; @@ -34,35 +33,25 @@ impl MpsFilterPredicate for FieldLikeFilter { &mut self, music_item_lut: &MpsItem, ctx: &mut MpsContext, - op: &mut OpGetter, - ) -> Result { + ) -> Result { let variable = match &self.val { - VariableOrValue::Variable(name) => match ctx.variables.get(name, op)? { + VariableOrValue::Variable(name) => match ctx.variables.get(name)? { MpsType::Primitive(MpsTypePrimitive::String(s)) => Ok(s), - _ => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Variable {} is not comparable", name), - }), + _ => Err(RuntimeMsg(format!("Variable {} is not comparable", name))), }, VariableOrValue::Value(MpsTypePrimitive::String(s)) => Ok(s), // non-string values will be stopped at parse-time, so this should never occur - _ => Err(RuntimeError { - line: 0, - op: op(), - msg: "Value is not type String".to_string(), - }), + _ => Err(RuntimeMsg("Value is not type String".to_string())), }?; if let Some(field) = music_item_lut.field(&self.field_name) { let field_str = field.as_str().to_lowercase(); Ok(field_str.contains(&variable.to_lowercase())) } else { match self.field_errors { - FieldFilterErrorHandling::Error => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Field {} does not exist", &self.field_name), - }), + FieldFilterErrorHandling::Error => Err(RuntimeMsg(format!( + "Field {} does not exist", + &self.field_name + ))), FieldFilterErrorHandling::Ignore => Ok(false), FieldFilterErrorHandling::Include => Ok(true), } @@ -73,7 +62,7 @@ impl MpsFilterPredicate for FieldLikeFilter { false } - fn reset(&mut self) -> Result<(), RuntimeError> { + fn reset(&mut self) -> Result<(), RuntimeMsg> { Ok(()) } } diff --git a/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs b/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs index bf56422..9deea5e 100644 --- a/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs +++ b/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs @@ -4,8 +4,8 @@ use std::fmt::{Debug, Display, Error, Formatter}; use crate::lang::{utility::assert_token_raw, Lookup}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::{general::MpsType, OpGetter}; +use crate::lang::{RuntimeMsg, SyntaxError}; +use crate::processing::general::MpsType; use crate::tokens::MpsToken; use crate::MpsContext; use crate::MpsItem; @@ -26,32 +26,15 @@ impl Display for IndexFilter { } impl MpsFilterPredicate for IndexFilter { - fn matches( - &mut self, - _item: &MpsItem, - ctx: &mut MpsContext, - op: &mut OpGetter, - ) -> Result { - let index: u64 = match self.index.get(ctx, op)? { + fn matches(&mut self, _item: &MpsItem, ctx: &mut MpsContext) -> Result { + let index: u64 = match self.index.get(ctx)? { MpsType::Primitive(val) => match val { MpsTypePrimitive::Int(i) => *i as u64, MpsTypePrimitive::UInt(u) => *u, MpsTypePrimitive::Float(f) => *f as u64, - val => { - return Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot use {} as index", val), - }) - } + val => return Err(RuntimeMsg(format!("Cannot use {} as index", val))), }, - val => { - return Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot use {} as index", val), - }) - } + val => return Err(RuntimeMsg(format!("Cannot use {} as index", val))), }; if self.current == index && !self.is_opposite { self.current += 1; @@ -70,7 +53,7 @@ impl MpsFilterPredicate for IndexFilter { self.complete } - fn reset(&mut self) -> Result<(), RuntimeError> { + fn reset(&mut self) -> Result<(), RuntimeMsg> { self.current = 0; self.complete = false; Ok(()) diff --git a/mps-interpreter/src/lang/vocabulary/filters/range_filter.rs b/mps-interpreter/src/lang/vocabulary/filters/range_filter.rs index fcefe78..28e229b 100644 --- a/mps-interpreter/src/lang/vocabulary/filters/range_filter.rs +++ b/mps-interpreter/src/lang/vocabulary/filters/range_filter.rs @@ -5,8 +5,8 @@ use crate::lang::utility::assert_token_raw; use crate::lang::Lookup; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::{general::MpsType, OpGetter}; +use crate::lang::{RuntimeMsg, SyntaxError}; +use crate::processing::general::MpsType; use crate::tokens::MpsToken; use crate::MpsContext; use crate::MpsItem; @@ -42,14 +42,9 @@ impl Display for RangeFilter { } impl MpsFilterPredicate for RangeFilter { - fn matches( - &mut self, - _item: &MpsItem, - ctx: &mut MpsContext, - op: &mut OpGetter, - ) -> Result { + fn matches(&mut self, _item: &MpsItem, ctx: &mut MpsContext) -> Result { let start_index = if let Some(start) = &self.start { - lookup_to_index(start.get(ctx, op)?, op)? + lookup_to_index(start.get(ctx)?)? } else { 0 }; @@ -57,7 +52,7 @@ impl MpsFilterPredicate for RangeFilter { self.current += 1; if current >= start_index { if let Some(end) = &self.end { - let end_index = lookup_to_index(end.get(ctx, op)?, op)?; + let end_index = lookup_to_index(end.get(ctx)?)?; if self.inclusive_end && current <= end_index { if current == end_index { self.complete = true; @@ -83,30 +78,22 @@ impl MpsFilterPredicate for RangeFilter { self.complete } - fn reset(&mut self) -> Result<(), RuntimeError> { + fn reset(&mut self) -> Result<(), RuntimeMsg> { self.current = 0; self.complete = false; Ok(()) } } -fn lookup_to_index(item: &MpsType, op: &mut OpGetter) -> Result { +fn lookup_to_index(item: &MpsType) -> Result { match item { MpsType::Primitive(val) => match val { MpsTypePrimitive::Int(i) => Ok(*i as u64), MpsTypePrimitive::UInt(u) => Ok(*u), MpsTypePrimitive::Float(f) => Ok(*f as u64), - val => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot use {} as index", val), - }), + val => Err(RuntimeMsg(format!("Cannot use {} as index", val))), }, - val => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot use {} as index", val), - }), + val => Err(RuntimeMsg(format!("Cannot use {} as index", val))), } } diff --git a/mps-interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs b/mps-interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs index 68311ef..4d41432 100644 --- a/mps-interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs +++ b/mps-interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs @@ -10,10 +10,8 @@ use bliss_audio::Song; use crate::lang::utility::{assert_name, check_name}; use crate::lang::SyntaxError; #[cfg(feature = "bliss-audio")] -use crate::lang::{MpsIteratorItem, MpsOp, MpsSorter, MpsTypePrimitive, RuntimeError}; +use crate::lang::{MpsIteratorItem, MpsOp, MpsSorter, MpsTypePrimitive, RuntimeMsg}; use crate::lang::{MpsLanguageDictionary, MpsSortStatementFactory, MpsSorterFactory}; -#[cfg(feature = "bliss-audio")] -use crate::processing::OpGetter; use crate::tokens::MpsToken; #[cfg(feature = "bliss-audio")] use crate::MpsItem; @@ -28,11 +26,11 @@ pub struct BlissNextSorter { #[cfg(feature = "bliss-audio")] impl BlissNextSorter { - fn get_maybe(&mut self, op: &mut OpGetter) -> Option { + fn get_maybe(&mut self) -> Option> { if self.algorithm_done { None } else if let Ok(Some(item)) = self.rx.as_ref().unwrap().recv() { - Some(item.map_err(|e| bliss_err(e, op))) + Some(item.map_err(|e| bliss_err(e))) } else { self.algorithm_done = true; None @@ -157,8 +155,7 @@ impl MpsSorter for BlissNextSorter { &mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque, - op: &mut OpGetter, - ) -> Result<(), RuntimeError> { + ) -> Result<(), RuntimeMsg> { if self.rx.is_none() { // first run let mut items = VecDeque::new(); @@ -176,8 +173,8 @@ impl MpsSorter for BlissNextSorter { std::thread::spawn(move || Self::algorithm(items, tx)); self.rx = Some(rx); } - if let Some(item) = self.get_maybe(op) { - item_buf.push_back(item); + if let Some(item) = self.get_maybe() { + item_buf.push_back(Ok(item?)); } Ok(()) } @@ -189,12 +186,9 @@ impl MpsSorter for BlissNextSorter { } #[cfg(feature = "bliss-audio")] -fn bliss_err(error: D, op: &mut OpGetter) -> RuntimeError { - RuntimeError { - line: 0, - op: op(), - msg: format!("Bliss error: {}", error), - } +#[inline] +fn bliss_err(error: D) -> RuntimeMsg { + RuntimeMsg(format!("Bliss error: {}", error)) } #[cfg(not(feature = "bliss-audio"))] diff --git a/mps-interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs b/mps-interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs index 347c02e..9282102 100644 --- a/mps-interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs +++ b/mps-interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs @@ -13,10 +13,8 @@ use bliss_audio::Song; use crate::lang::utility::{assert_name, check_name}; use crate::lang::SyntaxError; #[cfg(feature = "bliss-audio")] -use crate::lang::{MpsIteratorItem, MpsOp, MpsSorter, MpsTypePrimitive, RuntimeError}; +use crate::lang::{MpsIteratorItem, MpsOp, MpsSorter, MpsTypePrimitive, RuntimeMsg}; use crate::lang::{MpsLanguageDictionary, MpsSortStatementFactory, MpsSorterFactory}; -#[cfg(feature = "bliss-audio")] -use crate::processing::OpGetter; use crate::tokens::MpsToken; #[cfg(feature = "bliss-audio")] @@ -102,8 +100,7 @@ impl MpsSorter for BlissSorter { &mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque, - op: &mut OpGetter, - ) -> Result<(), RuntimeError> { + ) -> Result<(), RuntimeMsg> { let buf_len_old = item_buf.len(); // save buffer length before modifying buffer if item_buf.len() < self.up_to { for item in iterator { @@ -182,18 +179,15 @@ impl MpsSorter for BlissSorter { if self.errors.is_empty() { Ok(()) } else { - Err(bliss_err(self.errors.pop().unwrap(), op)) + Err(bliss_err(self.errors.pop().unwrap())) } } } #[cfg(feature = "bliss-audio")] -fn bliss_err(error: D, op: &mut OpGetter) -> RuntimeError { - RuntimeError { - line: 0, - op: op(), - msg: format!("Bliss error: {}", error), - } +#[inline] +fn bliss_err(error: D) -> RuntimeMsg { + RuntimeMsg(format!("Bliss error: {}", error)) } #[cfg(not(feature = "bliss-audio"))] diff --git a/mps-interpreter/src/lang/vocabulary/sorters/empty_sorter.rs b/mps-interpreter/src/lang/vocabulary/sorters/empty_sorter.rs index f2a2cc7..857dd2a 100644 --- a/mps-interpreter/src/lang/vocabulary/sorters/empty_sorter.rs +++ b/mps-interpreter/src/lang/vocabulary/sorters/empty_sorter.rs @@ -3,8 +3,7 @@ use std::fmt::{Debug, Display, Error, Formatter}; use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp}; use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::OpGetter; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::tokens::MpsToken; #[derive(Debug, Clone, Default)] @@ -15,8 +14,7 @@ impl MpsSorter for EmptySorter { &mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque, - _op: &mut OpGetter, - ) -> Result<(), RuntimeError> { + ) -> Result<(), RuntimeMsg> { if let Some(item) = iterator.next() { item_buf.push_back(item) } diff --git a/mps-interpreter/src/lang/vocabulary/sorters/field_sorter.rs b/mps-interpreter/src/lang/vocabulary/sorters/field_sorter.rs index 7764229..1b239a6 100644 --- a/mps-interpreter/src/lang/vocabulary/sorters/field_sorter.rs +++ b/mps-interpreter/src/lang/vocabulary/sorters/field_sorter.rs @@ -5,8 +5,7 @@ use std::fmt::{Debug, Display, Error, Formatter}; use crate::lang::utility::assert_token; use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp}; use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::OpGetter; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::tokens::MpsToken; #[derive(Debug, Clone)] @@ -21,8 +20,7 @@ impl MpsSorter for FieldSorter { &mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque, - _op: &mut OpGetter, - ) -> Result<(), RuntimeError> { + ) -> Result<(), RuntimeMsg> { let buf_len_old = item_buf.len(); // save buffer length before modifying buffer if item_buf.len() < self.up_to { for item in iterator { diff --git a/mps-interpreter/src/lang/vocabulary/sorters/shuffle.rs b/mps-interpreter/src/lang/vocabulary/sorters/shuffle.rs index 467b621..0e0c235 100644 --- a/mps-interpreter/src/lang/vocabulary/sorters/shuffle.rs +++ b/mps-interpreter/src/lang/vocabulary/sorters/shuffle.rs @@ -6,8 +6,7 @@ use rand::{thread_rng, Rng}; use crate::lang::utility::{assert_name, check_name}; use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp}; use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory}; -use crate::lang::{RuntimeError, SyntaxError}; -use crate::processing::OpGetter; +use crate::lang::{RuntimeMsg, SyntaxError}; use crate::tokens::MpsToken; const RNG_LIMIT_BITMASK: usize = 0xffff; // bits to preserve in RNG @@ -22,8 +21,7 @@ impl MpsSorter for ShuffleSorter { &mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque, - _op: &mut OpGetter, - ) -> Result<(), RuntimeError> { + ) -> Result<(), RuntimeMsg> { // iterative shuffling algorithm // // choose a random number r diff --git a/mps-interpreter/src/lang/vocabulary/variable_assign.rs b/mps-interpreter/src/lang/vocabulary/variable_assign.rs index 89b1d1c..f2d5cb5 100644 --- a/mps-interpreter/src/lang/vocabulary/variable_assign.rs +++ b/mps-interpreter/src/lang/vocabulary/variable_assign.rs @@ -10,7 +10,7 @@ use crate::lang::MpsLanguageDictionary; use crate::lang::{ BoxedMpsOpFactory, MpsIteratorItem, MpsOp, MpsOpFactory, MpsTypePrimitive, PseudoOp, }; -use crate::lang::{RuntimeError, SyntaxError}; +use crate::lang::{RuntimeError, RuntimeOp, SyntaxError}; use crate::processing::general::MpsType; #[derive(Debug)] @@ -67,24 +67,25 @@ impl Iterator for AssignStatement { Ok(real) => real, Err(e) => return Some(Err(e)), }; - let pseudo_clone = self.clone(); let result; if self.is_declaration { - result = self.context.as_mut().unwrap().variables.declare( - &self.variable_name, - MpsType::Op(real), - &mut move || (Box::new(pseudo_clone.clone()) as Box).into(), - ); + result = self + .context + .as_mut() + .unwrap() + .variables + .declare(&self.variable_name, MpsType::Op(real)); } else { - result = self.context.as_mut().unwrap().variables.assign( - &self.variable_name, - MpsType::Op(real), - &mut move || (Box::new(pseudo_clone.clone()) as Box).into(), - ); + result = self + .context + .as_mut() + .unwrap() + .variables + .assign(&self.variable_name, MpsType::Op(real)); } match result { Ok(_) => None, - Err(e) => Some(Err(e)), + Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), } } } else if !self.is_simple { @@ -99,24 +100,25 @@ impl Iterator for AssignStatement { }))*/ } else { let assign_type = self.assign_type.clone().unwrap(); - let pseudo_clone = self.clone(); let result; if self.is_declaration { - result = self.context.as_mut().unwrap().variables.declare( - &self.variable_name, - MpsType::Primitive(assign_type), - &mut move || (Box::new(pseudo_clone.clone()) as Box).into(), - ); + result = self + .context + .as_mut() + .unwrap() + .variables + .declare(&self.variable_name, MpsType::Primitive(assign_type)); } else { - result = self.context.as_mut().unwrap().variables.assign( - &self.variable_name, - MpsType::Primitive(assign_type), - &mut move || (Box::new(pseudo_clone.clone()) as Box).into(), - ); + result = self + .context + .as_mut() + .unwrap() + .variables + .assign(&self.variable_name, MpsType::Primitive(assign_type)); } match result { Ok(_) => None, - Err(e) => Some(Err(e)), + Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), } } } diff --git a/mps-interpreter/src/processing/variables.rs b/mps-interpreter/src/processing/variables.rs index 4a14e3c..28c4b7c 100644 --- a/mps-interpreter/src/processing/variables.rs +++ b/mps-interpreter/src/processing/variables.rs @@ -4,9 +4,7 @@ use std::collections::HashMap; use crate::lang::MpsOp; use crate::lang::MpsTypePrimitive; -use crate::lang::RuntimeError; - -use super::OpGetter; +use crate::lang::RuntimeMsg; #[derive(Debug)] pub enum MpsType { @@ -24,43 +22,29 @@ impl Display for MpsType { } pub trait MpsVariableStorer: Debug { - fn get(&self, name: &str, op: &mut OpGetter) -> Result<&'_ MpsType, RuntimeError> { + fn get(&self, name: &str) -> Result<&'_ MpsType, RuntimeMsg> { match self.get_opt(name) { Some(item) => Ok(item), - None => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Variable '{}' not found", name), - }), + None => Err(RuntimeMsg(format!("Variable '{}' not found", name))), } } fn get_opt(&self, name: &str) -> Option<&'_ MpsType>; - fn get_mut(&mut self, name: &str, op: &mut OpGetter) -> Result<&'_ mut MpsType, RuntimeError> { + fn get_mut(&mut self, name: &str) -> Result<&'_ mut MpsType, RuntimeMsg> { match self.get_mut_opt(name) { Some(item) => Ok(item), - None => Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Variable '{}' not found", name), - }), + None => Err(RuntimeMsg(format!("Variable '{}' not found", name))), } } fn get_mut_opt(&mut self, name: &str) -> Option<&'_ mut MpsType>; - fn assign(&mut self, name: &str, value: MpsType, op: &mut OpGetter) - -> Result<(), RuntimeError>; + fn assign(&mut self, name: &str, value: MpsType) -> Result<(), RuntimeMsg>; - fn declare( - &mut self, - name: &str, - value: MpsType, - op: &mut OpGetter, - ) -> Result<(), RuntimeError>; + fn declare(&mut self, name: &str, value: MpsType) -> Result<(), RuntimeMsg>; - fn remove(&mut self, name: &str, op: &mut OpGetter) -> Result; + fn remove(&mut self, name: &str) -> Result; fn exists(&self, name: &str) -> bool { self.get_opt(name).is_some() @@ -81,41 +65,38 @@ impl MpsVariableStorer for MpsOpStorage { self.storage.get_mut(key) } - fn assign(&mut self, key: &str, item: MpsType, op: &mut OpGetter) -> Result<(), RuntimeError> { + fn assign(&mut self, key: &str, item: MpsType) -> Result<(), RuntimeMsg> { if !self.storage.contains_key(key) { - Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot assign to non-existent variable '{}'", key), - }) + Err(RuntimeMsg(format!( + "Cannot assign to non-existent variable '{}'", + key + ))) } else { self.storage.insert(key.to_string(), item); Ok(()) } } - fn declare(&mut self, key: &str, item: MpsType, op: &mut OpGetter) -> Result<(), RuntimeError> { + fn declare(&mut self, key: &str, item: MpsType) -> Result<(), RuntimeMsg> { if self.storage.contains_key(key) { - Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot overwrite existing variable '{}'", key), - }) + Err(RuntimeMsg(format!( + "Cannot overwrite existing variable '{}'", + key + ))) } else { self.storage.insert(key.to_string(), item); Ok(()) } } - fn remove(&mut self, key: &str, op: &mut OpGetter) -> Result { + fn remove(&mut self, key: &str) -> Result { if self.storage.contains_key(key) { Ok(self.storage.remove(key).unwrap()) } else { - Err(RuntimeError { - line: 0, - op: op(), - msg: format!("Cannot remove non-existing variable '{}'", key), - }) + Err(RuntimeMsg(format!( + "Cannot remove non-existing variable '{}'", + key + ))) } } }