Reduce usage of OpGetter by making RuntimeError (de)composable

This commit is contained in:
NGnius (Graham) 2022-01-31 15:30:37 -05:00
parent 46459c7da1
commit 70950e0bc7
18 changed files with 222 additions and 303 deletions

View file

@ -40,6 +40,12 @@ pub struct RuntimeError {
pub msg: String, pub msg: String,
} }
impl RuntimeError {
pub fn decompose(self) -> (RuntimeOp, RuntimeMsg) {
(RuntimeOp(self.op), RuntimeMsg(self.msg))
}
}
impl Display for RuntimeError { impl Display for RuntimeError {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{} (line {}): {}", &self.msg, &self.line, &self.op) write!(f, "{} (line {}): {}", &self.msg, &self.line, &self.op)
@ -55,3 +61,29 @@ impl MpsLanguageError for RuntimeError {
pub trait MpsLanguageError: Display + Debug { pub trait MpsLanguageError: Display + Debug {
fn set_line(&mut self, line: usize); 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,
}
}
}

View file

@ -8,9 +8,8 @@ use crate::lang::MpsFilterReplaceStatement;
use crate::lang::MpsLanguageDictionary; use crate::lang::MpsLanguageDictionary;
use crate::lang::SingleItem; use crate::lang::SingleItem;
use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, PseudoOp}; 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::general::MpsType;
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -18,16 +17,11 @@ use crate::MpsItem;
const INNER_VARIABLE_NAME: &str = "[inner variable]"; const INNER_VARIABLE_NAME: &str = "[inner variable]";
pub trait MpsFilterPredicate: Clone + Debug + Display { pub trait MpsFilterPredicate: Clone + Debug + Display {
fn matches( fn matches(&mut self, item: &MpsItem, ctx: &mut MpsContext) -> Result<bool, RuntimeMsg>;
&mut self,
item: &MpsItem,
ctx: &mut MpsContext,
op: &mut OpGetter,
) -> Result<bool, RuntimeError>;
fn is_complete(&self) -> bool; fn is_complete(&self) -> bool;
fn reset(&mut self) -> Result<(), RuntimeError>; fn reset(&mut self) -> Result<(), RuntimeMsg>;
} }
pub trait MpsFilterFactory<P: MpsFilterPredicate + 'static> { pub trait MpsFilterFactory<P: MpsFilterPredicate + 'static> {
@ -125,17 +119,19 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeError> {
let fake = PseudoOp::Fake(format!("{}", self)); let fake = PseudoOp::Fake(format!("{}", self));
self.predicate.reset()?; self.predicate
.reset()
.map_err(|x| x.with(RuntimeOp(fake.clone())))?;
match &mut self.iterable { match &mut self.iterable {
VariableOrOp::Variable(s) => { VariableOrOp::Variable(s) => {
if self.context.as_mut().unwrap().variables.exists(s) { if self.context.as_mut().unwrap().variables.exists(s) {
let fake_getter = &mut move || fake.clone();
let mut var = self let mut var = self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.remove(s, fake_getter)?; .remove(s)
.map_err(|e| e.with(RuntimeOp(fake.clone())))?;
let result = if let MpsType::Op(var) = &mut var { let result = if let MpsType::Op(var) = &mut var {
var.enter(self.context.take().unwrap()); var.enter(self.context.take().unwrap());
let result = var.reset(); let result = var.reset();
@ -144,7 +140,7 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
} else { } else {
Err(RuntimeError { Err(RuntimeError {
line: 0, line: 0,
op: fake_getter(), op: fake.clone(),
msg: "Cannot reset non-iterable filter variable".to_string(), msg: "Cannot reset non-iterable filter variable".to_string(),
}) })
}; };
@ -152,7 +148,8 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.declare(s, var, fake_getter)?; .declare(s, var)
.map_err(|e| e.with(RuntimeOp(fake)))?;
result result
} else { } else {
Ok(()) Ok(())
@ -190,7 +187,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
} }
let self_clone = self.clone(); let self_clone = self.clone();
let self_clone2 = self_clone.clone(); let self_clone2 = self_clone.clone();
let mut op_getter = move || (Box::new(self_clone.clone()) as Box<dyn MpsOp>).into(); let fake = PseudoOp::Fake(format!("{}", self));
//let ctx = self.context.as_mut().unwrap(); //let ctx = self.context.as_mut().unwrap();
match &mut self.iterable { match &mut self.iterable {
VariableOrOp::Op(op) => match op.try_real() { VariableOrOp::Op(op) => match op.try_real() {
@ -208,11 +205,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
break; break;
} }
Ok(item) => { Ok(item) => {
let matches_result = let matches_result = self.predicate.matches(&item, &mut ctx);
self.predicate.matches(&item, &mut ctx, &mut op_getter);
let matches = match matches_result { let matches = match matches_result {
Err(e) => { Err(e) => {
maybe_result = Some(Err(e)); maybe_result = Some(Err(e.with(RuntimeOp(fake.clone()))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -225,12 +221,12 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
match ctx.variables.declare( match ctx.variables.declare(
INNER_VARIABLE_NAME, INNER_VARIABLE_NAME,
MpsType::Op(Box::new(single_op)), MpsType::Op(Box::new(single_op)),
&mut op_getter,
) { ) {
Ok(x) => x, Ok(x) => x,
Err(e) => { Err(e) => {
//self.context = Some(op.escape()); //self.context = Some(op.escape());
maybe_result = Some(Err(e)); maybe_result =
Some(Err(e.with(RuntimeOp(fake.clone()))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -249,13 +245,14 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
Some(item) => { Some(item) => {
maybe_result = Some(item); maybe_result = Some(item);
ctx = inner_real.escape(); ctx = inner_real.escape();
match ctx match ctx.variables.remove(INNER_VARIABLE_NAME) {
.variables
.remove(INNER_VARIABLE_NAME, &mut op_getter)
{
Ok(_) => {} Ok(_) => {}
Err(e) => match maybe_result { 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, Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error,
None => {} // impossible None => {} // impossible
}, },
@ -265,14 +262,12 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
} }
None => { None => {
ctx = inner_real.escape(); // move ctx back to expected spot ctx = inner_real.escape(); // move ctx back to expected spot
match ctx match ctx.variables.remove(INNER_VARIABLE_NAME) {
.variables
.remove(INNER_VARIABLE_NAME, &mut op_getter)
{
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
//self.context = Some(op.escape()); //self.context = Some(op.escape());
maybe_result = Some(Err(e)); maybe_result =
Some(Err(e.with(RuntimeOp(fake.clone()))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -303,7 +298,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.remove(variable_name, &mut op_getter) .remove(variable_name)
{ {
Ok(MpsType::Op(op)) => op, Ok(MpsType::Op(op)) => op,
Ok(x) => { Ok(x) => {
@ -316,7 +311,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
), ),
})) }))
} }
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e.with(RuntimeOp(fake.clone())))),
}; };
let mut maybe_result = None; let mut maybe_result = None;
let ctx = self.context.take().unwrap(); let ctx = self.context.take().unwrap();
@ -330,11 +325,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
break; break;
} }
Ok(item) => { Ok(item) => {
let matches_result = let matches_result = self.predicate.matches(&item, &mut ctx);
self.predicate.matches(&item, &mut ctx, &mut op_getter);
let matches = match matches_result { let matches = match matches_result {
Err(e) => { Err(e) => {
maybe_result = Some(Err(e)); maybe_result = Some(Err(e.with(RuntimeOp(fake.clone()))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -352,12 +346,14 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
if self.context.is_none() { if self.context.is_none() {
self.context = Some(variable.escape()); self.context = Some(variable.escape());
} }
match self.context.as_mut().unwrap().variables.declare( match self
variable_name, .context
MpsType::Op(variable), .as_mut()
&mut op_getter, .unwrap()
) { .variables
Err(e) => Some(Err(e)), .declare(variable_name, MpsType::Op(variable))
{
Err(e) => Some(Err(e.with(RuntimeOp(fake.clone())))),
Ok(_) => maybe_result, Ok(_) => maybe_result,
} }
} }

View file

@ -2,12 +2,11 @@ use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter}; use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator; use std::iter::Iterator;
use crate::lang::RuntimeError;
use crate::lang::SingleItem; use crate::lang::SingleItem;
use crate::lang::{filter::VariableOrOp, MpsFilterPredicate}; use crate::lang::{filter::VariableOrOp, MpsFilterPredicate};
use crate::lang::{MpsIteratorItem, MpsOp, PseudoOp}; use crate::lang::{MpsIteratorItem, MpsOp, PseudoOp};
use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp};
use crate::processing::general::MpsType; use crate::processing::general::MpsType;
use crate::processing::OpGetter;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -91,17 +90,19 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeError> {
self.item_cache.clear(); self.item_cache.clear();
let fake = PseudoOp::Fake(format!("{}", self)); let fake = PseudoOp::Fake(format!("{}", self));
self.predicate.reset()?; self.predicate
.reset()
.map_err(|x| x.with(RuntimeOp(fake.clone())))?;
match &mut self.iterable { match &mut self.iterable {
VariableOrOp::Variable(s) => { VariableOrOp::Variable(s) => {
if self.context.as_mut().unwrap().variables.exists(s) { if self.context.as_mut().unwrap().variables.exists(s) {
let fake_getter = &mut move || fake.clone();
let mut var = self let mut var = self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.remove(s, fake_getter)?; .remove(s)
.map_err(|e| e.with(RuntimeOp(fake.clone())))?;
let result = if let MpsType::Op(var) = &mut var { let result = if let MpsType::Op(var) = &mut var {
var.enter(self.context.take().unwrap()); var.enter(self.context.take().unwrap());
let result = var.reset(); let result = var.reset();
@ -110,7 +111,7 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
} else { } else {
Err(RuntimeError { Err(RuntimeError {
line: 0, line: 0,
op: fake_getter(), op: fake.clone(),
msg: "Cannot reset non-iterable filter variable".to_string(), msg: "Cannot reset non-iterable filter variable".to_string(),
}) })
}; };
@ -118,7 +119,8 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.declare(s, var, fake_getter)?; .declare(s, var)
.map_err(|e| e.with(RuntimeOp(fake)))?;
result result
} else { } else {
Ok(()) Ok(())
@ -146,8 +148,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
if !self.item_cache.is_empty() { if !self.item_cache.is_empty() {
return self.item_cache.pop_front(); return self.item_cache.pop_front();
} }
let self_clone = self.clone(); let fake = PseudoOp::Fake(format!("{}", self));
let mut op_getter = move || (Box::new(self_clone.clone()) as Box<dyn MpsOp>).into();
// get next item in iterator // get next item in iterator
let next_item = match &mut self.iterable { let next_item = match &mut self.iterable {
VariableOrOp::Op(op) => match op.try_real() { VariableOrOp::Op(op) => match op.try_real() {
@ -166,31 +167,33 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.remove(variable_name, &mut op_getter) .remove(variable_name)
{ {
Ok(MpsType::Op(op)) => op, Ok(MpsType::Op(op)) => op,
Ok(x) => { Ok(x) => {
return Some(Err(RuntimeError { return Some(Err(RuntimeError {
line: 0, line: 0,
op: op_getter(), op: fake.clone(),
msg: format!( msg: format!(
"Expected operation/iterable type in variable {}, got {}", "Expected operation/iterable type in variable {}, got {}",
&variable_name, x &variable_name, x
), ),
})) }))
} }
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e.with(RuntimeOp(fake)))),
}; };
let ctx = self.context.take().unwrap(); let ctx = self.context.take().unwrap();
variable.enter(ctx); variable.enter(ctx);
let item = variable.next(); let item = variable.next();
self.context = Some(variable.escape()); self.context = Some(variable.escape());
match self.context.as_mut().unwrap().variables.declare( match self
variable_name, .context
MpsType::Op(variable), .as_mut()
&mut op_getter, .unwrap()
) { .variables
Err(e) => return Some(Err(e)), .declare(variable_name, MpsType::Op(variable))
{
Err(e) => return Some(Err(e.with(RuntimeOp(fake)))),
Ok(_) => {} Ok(_) => {}
} }
item item
@ -202,7 +205,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//println!("item is now: `{}`", &item.filename); //println!("item is now: `{}`", &item.filename);
match self match self
.predicate .predicate
.matches(&item, self.context.as_mut().unwrap(), &mut op_getter) .matches(&item, self.context.as_mut().unwrap())
{ {
Ok(is_match) => { Ok(is_match) => {
if is_match { if is_match {
@ -214,11 +217,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//println!("Declaring item variable"); //println!("Declaring item variable");
let old_item = match declare_or_replace_item( let old_item = match declare_or_replace_item(
single_op, single_op,
&mut op_getter,
self.context.as_mut().unwrap(), self.context.as_mut().unwrap(),
) { ) {
Ok(x) => x, 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 // invoke inner op
real_op.enter(self.context.take().unwrap()); real_op.enter(self.context.take().unwrap());
@ -236,11 +238,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//println!("Removing item variable"); //println!("Removing item variable");
match remove_or_replace_item( match remove_or_replace_item(
old_item, old_item,
&mut op_getter,
self.context.as_mut().unwrap(), self.context.as_mut().unwrap(),
) { ) {
Ok(_) => {} 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 Err(e) => return Some(Err(e)), // probably shouldn't occur
@ -261,11 +262,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//println!("Declaring item variable"); //println!("Declaring item variable");
let old_item = match declare_or_replace_item( let old_item = match declare_or_replace_item(
single_op, single_op,
&mut op_getter,
self.context.as_mut().unwrap(), self.context.as_mut().unwrap(),
) { ) {
Ok(x) => x, 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 // invoke inner operation
real_op.enter(self.context.take().unwrap()); real_op.enter(self.context.take().unwrap());
@ -283,11 +283,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//println!("Removing item variable"); //println!("Removing item variable");
match remove_or_replace_item( match remove_or_replace_item(
old_item, old_item,
&mut op_getter,
self.context.as_mut().unwrap(), self.context.as_mut().unwrap(),
) { ) {
Ok(_) => {} 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 Err(e) => return Some(Err(e)), // probably shouldn't occur
@ -303,7 +302,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
Some(Ok(item)) Some(Ok(item))
} }
} }
Err(e) => Some(Err(e)), Err(e) => Some(Err(e.with(RuntimeOp(fake.clone())))),
} }
} }
Some(Err(e)) => Some(Err(e)), Some(Err(e)) => Some(Err(e)),
@ -329,28 +328,26 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
fn declare_or_replace_item( fn declare_or_replace_item(
single: SingleItem, single: SingleItem,
op: &mut OpGetter,
ctx: &mut MpsContext, ctx: &mut MpsContext,
) -> Result<Option<MpsType>, RuntimeError> { ) -> Result<Option<MpsType>, RuntimeMsg> {
let old_item: Option<MpsType>; let old_item: Option<MpsType>;
if ctx.variables.exists(ITEM_VARIABLE_NAME) { 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 { } else {
old_item = None; old_item = None;
} }
ctx.variables ctx.variables
.declare(ITEM_VARIABLE_NAME, MpsType::Op(Box::new(single)), op)?; .declare(ITEM_VARIABLE_NAME, MpsType::Op(Box::new(single)))?;
Ok(old_item) Ok(old_item)
} }
fn remove_or_replace_item( fn remove_or_replace_item(
old_item: Option<MpsType>, old_item: Option<MpsType>,
op: &mut OpGetter,
ctx: &mut MpsContext, ctx: &mut MpsContext,
) -> Result<(), RuntimeError> { ) -> Result<(), RuntimeMsg> {
ctx.variables.remove(ITEM_VARIABLE_NAME, op)?; ctx.variables.remove(ITEM_VARIABLE_NAME)?;
if let Some(old_item) = old_item { 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(()) Ok(())
} }

View file

@ -3,9 +3,8 @@ use std::fmt::{Display, Error, Formatter};
//use super::MpsTypePrimitive; //use super::MpsTypePrimitive;
use super::utility::{assert_token, assert_type, check_is_type}; 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::general::MpsType;
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
@ -43,22 +42,17 @@ impl Lookup {
pub fn get_mut<'a, 'b: 'a>( pub fn get_mut<'a, 'b: 'a>(
&'b mut self, &'b mut self,
ctx: &'a mut MpsContext, ctx: &'a mut MpsContext,
op: &mut OpGetter, ) -> Result<&'a mut MpsType, RuntimeMsg> {
) -> Result<&'a mut MpsType, RuntimeError> {
match self { match self {
Self::Static(var) => Ok(var), 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>( pub fn get<'a, 'b: 'a>(&'b self, ctx: &'a MpsContext) -> Result<&'a MpsType, RuntimeMsg> {
&'b self,
ctx: &'a MpsContext,
op: &mut OpGetter,
) -> Result<&'a MpsType, RuntimeError> {
match self { match self {
Self::Static(var) => Ok(var), Self::Static(var) => Ok(var),
Self::Variable(name) => ctx.variables.get(name, op), Self::Variable(name) => ctx.variables.get(name),
} }
} }
} }

View file

@ -15,7 +15,7 @@ mod type_primitives;
pub(crate) mod utility; pub(crate) mod utility;
pub use dictionary::MpsLanguageDictionary; pub use dictionary::MpsLanguageDictionary;
pub use error::{MpsLanguageError, RuntimeError, SyntaxError}; pub use error::{MpsLanguageError, RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError};
pub use filter::{ pub use filter::{
MpsFilterFactory, MpsFilterPredicate, MpsFilterStatement, MpsFilterStatementFactory, MpsFilterFactory, MpsFilterPredicate, MpsFilterStatement, MpsFilterStatementFactory,
}; };

View file

@ -6,8 +6,7 @@ use std::marker::PhantomData;
use crate::lang::utility::{assert_name, assert_token_raw, check_name}; use crate::lang::utility::{assert_name, assert_token_raw, check_name};
use crate::lang::MpsLanguageDictionary; use crate::lang::MpsLanguageDictionary;
use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, PseudoOp}; use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, PseudoOp};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeError, RuntimeMsg, RuntimeOp, SyntaxError};
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
@ -18,8 +17,7 @@ pub trait MpsSorter: Clone + Debug + Display {
&mut self, &mut self,
iterator: &mut dyn MpsOp, iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>, item_buf: &mut VecDeque<MpsIteratorItem>,
op: &'a mut OpGetter, ) -> Result<(), RuntimeMsg>;
) -> Result<(), RuntimeError>;
fn reset(&mut self) {} fn reset(&mut self) {}
} }
@ -86,18 +84,13 @@ impl<S: MpsSorter + 'static> Iterator for MpsSortStatement<S> {
type Item = MpsIteratorItem; type Item = MpsIteratorItem;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let pseudo_self = PseudoOp::from_printable(self);
let real_op = match self.iterable.try_real() { let real_op = match self.iterable.try_real() {
Ok(op) => op, Ok(op) => op,
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
}; };
match self match self.orderer.sort(real_op.as_mut(), &mut self.item_cache) {
.orderer
.sort(real_op.as_mut(), &mut self.item_cache, &mut move || {
pseudo_self.clone()
}) {
Ok(_) => {} Ok(_) => {}
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))),
} }
self.item_cache.pop_front() self.item_cache.pop_front()
} }

View file

@ -3,8 +3,7 @@ use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::MpsLanguageDictionary; use crate::lang::MpsLanguageDictionary;
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -19,12 +18,7 @@ impl Display for EmptyFilter {
} }
impl MpsFilterPredicate for EmptyFilter { impl MpsFilterPredicate for EmptyFilter {
fn matches( fn matches(&mut self, _item: &MpsItem, _ctx: &mut MpsContext) -> Result<bool, RuntimeMsg> {
&mut self,
_item: &MpsItem,
_ctx: &mut MpsContext,
_op: &mut OpGetter,
) -> Result<bool, RuntimeError> {
Ok(true) Ok(true)
} }
@ -32,7 +26,7 @@ impl MpsFilterPredicate for EmptyFilter {
false false
} }
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeMsg> {
Ok(()) Ok(())
} }
} }

View file

@ -6,9 +6,8 @@ use crate::lang::utility::{assert_token, assert_type, check_is_type};
use crate::lang::MpsLanguageDictionary; use crate::lang::MpsLanguageDictionary;
use crate::lang::MpsTypePrimitive; use crate::lang::MpsTypePrimitive;
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::general::MpsType; use crate::processing::general::MpsType;
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -65,16 +64,11 @@ impl MpsFilterPredicate for FieldFilter {
&mut self, &mut self,
music_item_lut: &MpsItem, music_item_lut: &MpsItem,
ctx: &mut MpsContext, ctx: &mut MpsContext,
op: &mut OpGetter, ) -> Result<bool, RuntimeMsg> {
) -> Result<bool, RuntimeError> {
let variable = match &self.val { 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), MpsType::Primitive(t) => Ok(t),
_ => Err(RuntimeError { _ => Err(RuntimeMsg(format!("Variable {} is not comparable", name))),
line: 0,
op: op(),
msg: format!("Variable {} is not comparable", name),
}),
}, },
VariableOrValue::Value(val) => Ok(val), VariableOrValue::Value(val) => Ok(val),
}?; }?;
@ -82,11 +76,7 @@ impl MpsFilterPredicate for FieldFilter {
let compare_res = field.compare(variable); let compare_res = field.compare(variable);
if let Err(e) = compare_res { if let Err(e) = compare_res {
match self.comparison_errors { match self.comparison_errors {
FieldFilterErrorHandling::Error => Err(RuntimeError { FieldFilterErrorHandling::Error => Err(RuntimeMsg(e)),
line: 0,
op: op(),
msg: e,
}),
FieldFilterErrorHandling::Ignore => Ok(false), FieldFilterErrorHandling::Ignore => Ok(false),
FieldFilterErrorHandling::Include => Ok(true), FieldFilterErrorHandling::Include => Ok(true),
} }
@ -103,11 +93,10 @@ impl MpsFilterPredicate for FieldFilter {
} }
} else { } else {
match self.field_errors { match self.field_errors {
FieldFilterErrorHandling::Error => Err(RuntimeError { FieldFilterErrorHandling::Error => Err(RuntimeMsg(format!(
line: 0, "Field {} does not exist",
op: op(), &self.field_name
msg: format!("Field {} does not exist", &self.field_name), ))),
}),
FieldFilterErrorHandling::Ignore => Ok(false), FieldFilterErrorHandling::Ignore => Ok(false),
FieldFilterErrorHandling::Include => Ok(true), FieldFilterErrorHandling::Include => Ok(true),
} }
@ -118,7 +107,7 @@ impl MpsFilterPredicate for FieldFilter {
false false
} }
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeMsg> {
Ok(()) Ok(())
} }
} }

View file

@ -6,9 +6,8 @@ use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_na
use crate::lang::MpsLanguageDictionary; use crate::lang::MpsLanguageDictionary;
use crate::lang::MpsTypePrimitive; use crate::lang::MpsTypePrimitive;
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::general::MpsType; use crate::processing::general::MpsType;
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -34,35 +33,25 @@ impl MpsFilterPredicate for FieldLikeFilter {
&mut self, &mut self,
music_item_lut: &MpsItem, music_item_lut: &MpsItem,
ctx: &mut MpsContext, ctx: &mut MpsContext,
op: &mut OpGetter, ) -> Result<bool, RuntimeMsg> {
) -> Result<bool, RuntimeError> {
let variable = match &self.val { 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), MpsType::Primitive(MpsTypePrimitive::String(s)) => Ok(s),
_ => Err(RuntimeError { _ => Err(RuntimeMsg(format!("Variable {} is not comparable", name))),
line: 0,
op: op(),
msg: format!("Variable {} is not comparable", name),
}),
}, },
VariableOrValue::Value(MpsTypePrimitive::String(s)) => Ok(s), VariableOrValue::Value(MpsTypePrimitive::String(s)) => Ok(s),
// non-string values will be stopped at parse-time, so this should never occur // non-string values will be stopped at parse-time, so this should never occur
_ => Err(RuntimeError { _ => Err(RuntimeMsg("Value is not type String".to_string())),
line: 0,
op: op(),
msg: "Value is not type String".to_string(),
}),
}?; }?;
if let Some(field) = music_item_lut.field(&self.field_name) { if let Some(field) = music_item_lut.field(&self.field_name) {
let field_str = field.as_str().to_lowercase(); let field_str = field.as_str().to_lowercase();
Ok(field_str.contains(&variable.to_lowercase())) Ok(field_str.contains(&variable.to_lowercase()))
} else { } else {
match self.field_errors { match self.field_errors {
FieldFilterErrorHandling::Error => Err(RuntimeError { FieldFilterErrorHandling::Error => Err(RuntimeMsg(format!(
line: 0, "Field {} does not exist",
op: op(), &self.field_name
msg: format!("Field {} does not exist", &self.field_name), ))),
}),
FieldFilterErrorHandling::Ignore => Ok(false), FieldFilterErrorHandling::Ignore => Ok(false),
FieldFilterErrorHandling::Include => Ok(true), FieldFilterErrorHandling::Include => Ok(true),
} }
@ -73,7 +62,7 @@ impl MpsFilterPredicate for FieldLikeFilter {
false false
} }
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeMsg> {
Ok(()) Ok(())
} }
} }

View file

@ -4,8 +4,8 @@ use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::{utility::assert_token_raw, Lookup}; use crate::lang::{utility::assert_token_raw, Lookup};
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive}; use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::{general::MpsType, OpGetter}; use crate::processing::general::MpsType;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -26,32 +26,15 @@ impl Display for IndexFilter {
} }
impl MpsFilterPredicate for IndexFilter { impl MpsFilterPredicate for IndexFilter {
fn matches( fn matches(&mut self, _item: &MpsItem, ctx: &mut MpsContext) -> Result<bool, RuntimeMsg> {
&mut self, let index: u64 = match self.index.get(ctx)? {
_item: &MpsItem,
ctx: &mut MpsContext,
op: &mut OpGetter,
) -> Result<bool, RuntimeError> {
let index: u64 = match self.index.get(ctx, op)? {
MpsType::Primitive(val) => match val { MpsType::Primitive(val) => match val {
MpsTypePrimitive::Int(i) => *i as u64, MpsTypePrimitive::Int(i) => *i as u64,
MpsTypePrimitive::UInt(u) => *u, MpsTypePrimitive::UInt(u) => *u,
MpsTypePrimitive::Float(f) => *f as u64, MpsTypePrimitive::Float(f) => *f as u64,
val => { val => return Err(RuntimeMsg(format!("Cannot use {} as index", val))),
return Err(RuntimeError {
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
}
}, },
val => { val => return Err(RuntimeMsg(format!("Cannot use {} as index", val))),
return Err(RuntimeError {
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
}
}; };
if self.current == index && !self.is_opposite { if self.current == index && !self.is_opposite {
self.current += 1; self.current += 1;
@ -70,7 +53,7 @@ impl MpsFilterPredicate for IndexFilter {
self.complete self.complete
} }
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeMsg> {
self.current = 0; self.current = 0;
self.complete = false; self.complete = false;
Ok(()) Ok(())

View file

@ -5,8 +5,8 @@ use crate::lang::utility::assert_token_raw;
use crate::lang::Lookup; use crate::lang::Lookup;
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive}; use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::{general::MpsType, OpGetter}; use crate::processing::general::MpsType;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
use crate::MpsContext; use crate::MpsContext;
use crate::MpsItem; use crate::MpsItem;
@ -42,14 +42,9 @@ impl Display for RangeFilter {
} }
impl MpsFilterPredicate for RangeFilter { impl MpsFilterPredicate for RangeFilter {
fn matches( fn matches(&mut self, _item: &MpsItem, ctx: &mut MpsContext) -> Result<bool, RuntimeMsg> {
&mut self,
_item: &MpsItem,
ctx: &mut MpsContext,
op: &mut OpGetter,
) -> Result<bool, RuntimeError> {
let start_index = if let Some(start) = &self.start { let start_index = if let Some(start) = &self.start {
lookup_to_index(start.get(ctx, op)?, op)? lookup_to_index(start.get(ctx)?)?
} else { } else {
0 0
}; };
@ -57,7 +52,7 @@ impl MpsFilterPredicate for RangeFilter {
self.current += 1; self.current += 1;
if current >= start_index { if current >= start_index {
if let Some(end) = &self.end { 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 self.inclusive_end && current <= end_index {
if current == end_index { if current == end_index {
self.complete = true; self.complete = true;
@ -83,30 +78,22 @@ impl MpsFilterPredicate for RangeFilter {
self.complete self.complete
} }
fn reset(&mut self) -> Result<(), RuntimeError> { fn reset(&mut self) -> Result<(), RuntimeMsg> {
self.current = 0; self.current = 0;
self.complete = false; self.complete = false;
Ok(()) Ok(())
} }
} }
fn lookup_to_index(item: &MpsType, op: &mut OpGetter) -> Result<u64, RuntimeError> { fn lookup_to_index(item: &MpsType) -> Result<u64, RuntimeMsg> {
match item { match item {
MpsType::Primitive(val) => match val { MpsType::Primitive(val) => match val {
MpsTypePrimitive::Int(i) => Ok(*i as u64), MpsTypePrimitive::Int(i) => Ok(*i as u64),
MpsTypePrimitive::UInt(u) => Ok(*u), MpsTypePrimitive::UInt(u) => Ok(*u),
MpsTypePrimitive::Float(f) => Ok(*f as u64), MpsTypePrimitive::Float(f) => Ok(*f as u64),
val => Err(RuntimeError { val => Err(RuntimeMsg(format!("Cannot use {} as index", val))),
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
}),
}, },
val => Err(RuntimeError { val => Err(RuntimeMsg(format!("Cannot use {} as index", val))),
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
}),
} }
} }

View file

@ -10,10 +10,8 @@ use bliss_audio::Song;
use crate::lang::utility::{assert_name, check_name}; use crate::lang::utility::{assert_name, check_name};
use crate::lang::SyntaxError; use crate::lang::SyntaxError;
#[cfg(feature = "bliss-audio")] #[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}; use crate::lang::{MpsLanguageDictionary, MpsSortStatementFactory, MpsSorterFactory};
#[cfg(feature = "bliss-audio")]
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
#[cfg(feature = "bliss-audio")] #[cfg(feature = "bliss-audio")]
use crate::MpsItem; use crate::MpsItem;
@ -28,11 +26,11 @@ pub struct BlissNextSorter {
#[cfg(feature = "bliss-audio")] #[cfg(feature = "bliss-audio")]
impl BlissNextSorter { impl BlissNextSorter {
fn get_maybe(&mut self, op: &mut OpGetter) -> Option<MpsIteratorItem> { fn get_maybe(&mut self) -> Option<Result<MpsItem, RuntimeMsg>> {
if self.algorithm_done { if self.algorithm_done {
None None
} else if let Ok(Some(item)) = self.rx.as_ref().unwrap().recv() { } 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 { } else {
self.algorithm_done = true; self.algorithm_done = true;
None None
@ -157,8 +155,7 @@ impl MpsSorter for BlissNextSorter {
&mut self, &mut self,
iterator: &mut dyn MpsOp, iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>, item_buf: &mut VecDeque<MpsIteratorItem>,
op: &mut OpGetter, ) -> Result<(), RuntimeMsg> {
) -> Result<(), RuntimeError> {
if self.rx.is_none() { if self.rx.is_none() {
// first run // first run
let mut items = VecDeque::new(); let mut items = VecDeque::new();
@ -176,8 +173,8 @@ impl MpsSorter for BlissNextSorter {
std::thread::spawn(move || Self::algorithm(items, tx)); std::thread::spawn(move || Self::algorithm(items, tx));
self.rx = Some(rx); self.rx = Some(rx);
} }
if let Some(item) = self.get_maybe(op) { if let Some(item) = self.get_maybe() {
item_buf.push_back(item); item_buf.push_back(Ok(item?));
} }
Ok(()) Ok(())
} }
@ -189,12 +186,9 @@ impl MpsSorter for BlissNextSorter {
} }
#[cfg(feature = "bliss-audio")] #[cfg(feature = "bliss-audio")]
fn bliss_err<D: Display>(error: D, op: &mut OpGetter) -> RuntimeError { #[inline]
RuntimeError { fn bliss_err<D: Display>(error: D) -> RuntimeMsg {
line: 0, RuntimeMsg(format!("Bliss error: {}", error))
op: op(),
msg: format!("Bliss error: {}", error),
}
} }
#[cfg(not(feature = "bliss-audio"))] #[cfg(not(feature = "bliss-audio"))]

View file

@ -13,10 +13,8 @@ use bliss_audio::Song;
use crate::lang::utility::{assert_name, check_name}; use crate::lang::utility::{assert_name, check_name};
use crate::lang::SyntaxError; use crate::lang::SyntaxError;
#[cfg(feature = "bliss-audio")] #[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}; use crate::lang::{MpsLanguageDictionary, MpsSortStatementFactory, MpsSorterFactory};
#[cfg(feature = "bliss-audio")]
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
#[cfg(feature = "bliss-audio")] #[cfg(feature = "bliss-audio")]
@ -102,8 +100,7 @@ impl MpsSorter for BlissSorter {
&mut self, &mut self,
iterator: &mut dyn MpsOp, iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>, item_buf: &mut VecDeque<MpsIteratorItem>,
op: &mut OpGetter, ) -> Result<(), RuntimeMsg> {
) -> Result<(), RuntimeError> {
let buf_len_old = item_buf.len(); // save buffer length before modifying buffer let buf_len_old = item_buf.len(); // save buffer length before modifying buffer
if item_buf.len() < self.up_to { if item_buf.len() < self.up_to {
for item in iterator { for item in iterator {
@ -182,18 +179,15 @@ impl MpsSorter for BlissSorter {
if self.errors.is_empty() { if self.errors.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(bliss_err(self.errors.pop().unwrap(), op)) Err(bliss_err(self.errors.pop().unwrap()))
} }
} }
} }
#[cfg(feature = "bliss-audio")] #[cfg(feature = "bliss-audio")]
fn bliss_err<D: Display>(error: D, op: &mut OpGetter) -> RuntimeError { #[inline]
RuntimeError { fn bliss_err<D: Display>(error: D) -> RuntimeMsg {
line: 0, RuntimeMsg(format!("Bliss error: {}", error))
op: op(),
msg: format!("Bliss error: {}", error),
}
} }
#[cfg(not(feature = "bliss-audio"))] #[cfg(not(feature = "bliss-audio"))]

View file

@ -3,8 +3,7 @@ use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp}; use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp};
use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory}; use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -15,8 +14,7 @@ impl MpsSorter for EmptySorter {
&mut self, &mut self,
iterator: &mut dyn MpsOp, iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>, item_buf: &mut VecDeque<MpsIteratorItem>,
_op: &mut OpGetter, ) -> Result<(), RuntimeMsg> {
) -> Result<(), RuntimeError> {
if let Some(item) = iterator.next() { if let Some(item) = iterator.next() {
item_buf.push_back(item) item_buf.push_back(item)
} }

View file

@ -5,8 +5,7 @@ use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::utility::assert_token; use crate::lang::utility::assert_token;
use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp}; use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp};
use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory}; use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -21,8 +20,7 @@ impl MpsSorter for FieldSorter {
&mut self, &mut self,
iterator: &mut dyn MpsOp, iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>, item_buf: &mut VecDeque<MpsIteratorItem>,
_op: &mut OpGetter, ) -> Result<(), RuntimeMsg> {
) -> Result<(), RuntimeError> {
let buf_len_old = item_buf.len(); // save buffer length before modifying buffer let buf_len_old = item_buf.len(); // save buffer length before modifying buffer
if item_buf.len() < self.up_to { if item_buf.len() < self.up_to {
for item in iterator { for item in iterator {

View file

@ -6,8 +6,7 @@ use rand::{thread_rng, Rng};
use crate::lang::utility::{assert_name, check_name}; use crate::lang::utility::{assert_name, check_name};
use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp}; use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp};
use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory}; use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory};
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeMsg, SyntaxError};
use crate::processing::OpGetter;
use crate::tokens::MpsToken; use crate::tokens::MpsToken;
const RNG_LIMIT_BITMASK: usize = 0xffff; // bits to preserve in RNG const RNG_LIMIT_BITMASK: usize = 0xffff; // bits to preserve in RNG
@ -22,8 +21,7 @@ impl MpsSorter for ShuffleSorter {
&mut self, &mut self,
iterator: &mut dyn MpsOp, iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>, item_buf: &mut VecDeque<MpsIteratorItem>,
_op: &mut OpGetter, ) -> Result<(), RuntimeMsg> {
) -> Result<(), RuntimeError> {
// iterative shuffling algorithm // iterative shuffling algorithm
// //
// choose a random number r // choose a random number r

View file

@ -10,7 +10,7 @@ use crate::lang::MpsLanguageDictionary;
use crate::lang::{ use crate::lang::{
BoxedMpsOpFactory, MpsIteratorItem, MpsOp, MpsOpFactory, MpsTypePrimitive, PseudoOp, BoxedMpsOpFactory, MpsIteratorItem, MpsOp, MpsOpFactory, MpsTypePrimitive, PseudoOp,
}; };
use crate::lang::{RuntimeError, SyntaxError}; use crate::lang::{RuntimeError, RuntimeOp, SyntaxError};
use crate::processing::general::MpsType; use crate::processing::general::MpsType;
#[derive(Debug)] #[derive(Debug)]
@ -67,24 +67,25 @@ impl Iterator for AssignStatement {
Ok(real) => real, Ok(real) => real,
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
}; };
let pseudo_clone = self.clone();
let result; let result;
if self.is_declaration { if self.is_declaration {
result = self.context.as_mut().unwrap().variables.declare( result = self
&self.variable_name, .context
MpsType::Op(real), .as_mut()
&mut move || (Box::new(pseudo_clone.clone()) as Box<dyn MpsOp>).into(), .unwrap()
); .variables
.declare(&self.variable_name, MpsType::Op(real));
} else { } else {
result = self.context.as_mut().unwrap().variables.assign( result = self
&self.variable_name, .context
MpsType::Op(real), .as_mut()
&mut move || (Box::new(pseudo_clone.clone()) as Box<dyn MpsOp>).into(), .unwrap()
); .variables
.assign(&self.variable_name, MpsType::Op(real));
} }
match result { match result {
Ok(_) => None, Ok(_) => None,
Err(e) => Some(Err(e)), Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))),
} }
} }
} else if !self.is_simple { } else if !self.is_simple {
@ -99,24 +100,25 @@ impl Iterator for AssignStatement {
}))*/ }))*/
} else { } else {
let assign_type = self.assign_type.clone().unwrap(); let assign_type = self.assign_type.clone().unwrap();
let pseudo_clone = self.clone();
let result; let result;
if self.is_declaration { if self.is_declaration {
result = self.context.as_mut().unwrap().variables.declare( result = self
&self.variable_name, .context
MpsType::Primitive(assign_type), .as_mut()
&mut move || (Box::new(pseudo_clone.clone()) as Box<dyn MpsOp>).into(), .unwrap()
); .variables
.declare(&self.variable_name, MpsType::Primitive(assign_type));
} else { } else {
result = self.context.as_mut().unwrap().variables.assign( result = self
&self.variable_name, .context
MpsType::Primitive(assign_type), .as_mut()
&mut move || (Box::new(pseudo_clone.clone()) as Box<dyn MpsOp>).into(), .unwrap()
); .variables
.assign(&self.variable_name, MpsType::Primitive(assign_type));
} }
match result { match result {
Ok(_) => None, Ok(_) => None,
Err(e) => Some(Err(e)), Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))),
} }
} }
} }

View file

@ -4,9 +4,7 @@ use std::collections::HashMap;
use crate::lang::MpsOp; use crate::lang::MpsOp;
use crate::lang::MpsTypePrimitive; use crate::lang::MpsTypePrimitive;
use crate::lang::RuntimeError; use crate::lang::RuntimeMsg;
use super::OpGetter;
#[derive(Debug)] #[derive(Debug)]
pub enum MpsType { pub enum MpsType {
@ -24,43 +22,29 @@ impl Display for MpsType {
} }
pub trait MpsVariableStorer: Debug { 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) { match self.get_opt(name) {
Some(item) => Ok(item), Some(item) => Ok(item),
None => Err(RuntimeError { None => Err(RuntimeMsg(format!("Variable '{}' not found", name))),
line: 0,
op: op(),
msg: format!("Variable '{}' not found", name),
}),
} }
} }
fn get_opt(&self, name: &str) -> Option<&'_ MpsType>; 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) { match self.get_mut_opt(name) {
Some(item) => Ok(item), Some(item) => Ok(item),
None => Err(RuntimeError { None => Err(RuntimeMsg(format!("Variable '{}' not found", name))),
line: 0,
op: op(),
msg: format!("Variable '{}' not found", name),
}),
} }
} }
fn get_mut_opt(&mut self, name: &str) -> Option<&'_ mut MpsType>; fn get_mut_opt(&mut self, name: &str) -> Option<&'_ mut MpsType>;
fn assign(&mut self, name: &str, value: MpsType, op: &mut OpGetter) fn assign(&mut self, name: &str, value: MpsType) -> Result<(), RuntimeMsg>;
-> Result<(), RuntimeError>;
fn declare( fn declare(&mut self, name: &str, value: MpsType) -> Result<(), RuntimeMsg>;
&mut self,
name: &str,
value: MpsType,
op: &mut OpGetter,
) -> Result<(), RuntimeError>;
fn remove(&mut self, name: &str, op: &mut OpGetter) -> Result<MpsType, RuntimeError>; fn remove(&mut self, name: &str) -> Result<MpsType, RuntimeMsg>;
fn exists(&self, name: &str) -> bool { fn exists(&self, name: &str) -> bool {
self.get_opt(name).is_some() self.get_opt(name).is_some()
@ -81,41 +65,38 @@ impl MpsVariableStorer for MpsOpStorage {
self.storage.get_mut(key) 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) { if !self.storage.contains_key(key) {
Err(RuntimeError { Err(RuntimeMsg(format!(
line: 0, "Cannot assign to non-existent variable '{}'",
op: op(), key
msg: format!("Cannot assign to non-existent variable '{}'", key), )))
})
} else { } else {
self.storage.insert(key.to_string(), item); self.storage.insert(key.to_string(), item);
Ok(()) 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) { if self.storage.contains_key(key) {
Err(RuntimeError { Err(RuntimeMsg(format!(
line: 0, "Cannot overwrite existing variable '{}'",
op: op(), key
msg: format!("Cannot overwrite existing variable '{}'", key), )))
})
} else { } else {
self.storage.insert(key.to_string(), item); self.storage.insert(key.to_string(), item);
Ok(()) Ok(())
} }
} }
fn remove(&mut self, key: &str, op: &mut OpGetter) -> Result<MpsType, RuntimeError> { fn remove(&mut self, key: &str) -> Result<MpsType, RuntimeMsg> {
if self.storage.contains_key(key) { if self.storage.contains_key(key) {
Ok(self.storage.remove(key).unwrap()) Ok(self.storage.remove(key).unwrap())
} else { } else {
Err(RuntimeError { Err(RuntimeMsg(format!(
line: 0, "Cannot remove non-existing variable '{}'",
op: op(), key
msg: format!("Cannot remove non-existing variable '{}'", key), )))
})
} }
} }
} }