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,
}
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,
}
}
}

View file

@ -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<bool, RuntimeError>;
fn matches(&mut self, item: &MpsItem, ctx: &mut MpsContext) -> Result<bool, RuntimeMsg>;
fn is_complete(&self) -> bool;
fn reset(&mut self) -> Result<(), RuntimeError>;
fn reset(&mut self) -> Result<(), RuntimeMsg>;
}
pub trait MpsFilterFactory<P: MpsFilterPredicate + 'static> {
@ -125,17 +119,19 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
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<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
} 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<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
.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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
}
let self_clone = self.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();
match &mut self.iterable {
VariableOrOp::Op(op) => match op.try_real() {
@ -208,11 +205,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
}
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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
.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<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 ctx = self.context.take().unwrap();
@ -330,11 +325,10 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
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,
}
}

View file

@ -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<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
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<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
} 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<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
.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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
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<dyn MpsOp>).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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
.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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
//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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
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<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
fn declare_or_replace_item(
single: SingleItem,
op: &mut OpGetter,
ctx: &mut MpsContext,
) -> Result<Option<MpsType>, RuntimeError> {
) -> Result<Option<MpsType>, RuntimeMsg> {
let old_item: Option<MpsType>;
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<MpsType>,
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(())
}

View file

@ -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),
}
}
}

View file

@ -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,
};

View file

@ -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<MpsIteratorItem>,
op: &'a mut OpGetter,
) -> Result<(), RuntimeError>;
) -> Result<(), RuntimeMsg>;
fn reset(&mut self) {}
}
@ -86,18 +84,13 @@ impl<S: MpsSorter + 'static> Iterator for MpsSortStatement<S> {
type Item = MpsIteratorItem;
fn next(&mut self) -> Option<Self::Item> {
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()
}

View file

@ -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<bool, RuntimeError> {
fn matches(&mut self, _item: &MpsItem, _ctx: &mut MpsContext) -> Result<bool, RuntimeMsg> {
Ok(true)
}
@ -32,7 +26,7 @@ impl MpsFilterPredicate for EmptyFilter {
false
}
fn reset(&mut self) -> Result<(), RuntimeError> {
fn reset(&mut self) -> Result<(), RuntimeMsg> {
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::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<bool, RuntimeError> {
) -> Result<bool, RuntimeMsg> {
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(())
}
}

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::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<bool, RuntimeError> {
) -> Result<bool, RuntimeMsg> {
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(())
}
}

View file

@ -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<bool, RuntimeError> {
let index: u64 = match self.index.get(ctx, op)? {
fn matches(&mut self, _item: &MpsItem, ctx: &mut MpsContext) -> Result<bool, RuntimeMsg> {
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(())

View file

@ -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<bool, RuntimeError> {
fn matches(&mut self, _item: &MpsItem, ctx: &mut MpsContext) -> Result<bool, RuntimeMsg> {
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<u64, RuntimeError> {
fn lookup_to_index(item: &MpsType) -> Result<u64, RuntimeMsg> {
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))),
}
}

View file

@ -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<MpsIteratorItem> {
fn get_maybe(&mut self) -> Option<Result<MpsItem, RuntimeMsg>> {
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<MpsIteratorItem>,
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<D: Display>(error: D, op: &mut OpGetter) -> RuntimeError {
RuntimeError {
line: 0,
op: op(),
msg: format!("Bliss error: {}", error),
}
#[inline]
fn bliss_err<D: Display>(error: D) -> RuntimeMsg {
RuntimeMsg(format!("Bliss error: {}", error))
}
#[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::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<MpsIteratorItem>,
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<D: Display>(error: D, op: &mut OpGetter) -> RuntimeError {
RuntimeError {
line: 0,
op: op(),
msg: format!("Bliss error: {}", error),
}
#[inline]
fn bliss_err<D: Display>(error: D) -> RuntimeMsg {
RuntimeMsg(format!("Bliss error: {}", error))
}
#[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::{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<MpsIteratorItem>,
_op: &mut OpGetter,
) -> Result<(), RuntimeError> {
) -> Result<(), RuntimeMsg> {
if let Some(item) = iterator.next() {
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::{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<MpsIteratorItem>,
_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 {

View file

@ -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<MpsIteratorItem>,
_op: &mut OpGetter,
) -> Result<(), RuntimeError> {
) -> Result<(), RuntimeMsg> {
// iterative shuffling algorithm
//
// choose a random number r

View file

@ -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<dyn MpsOp>).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<dyn MpsOp>).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<dyn MpsOp>).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<dyn MpsOp>).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))))),
}
}
}

View file

@ -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<MpsType, RuntimeError>;
fn remove(&mut self, name: &str) -> Result<MpsType, RuntimeMsg>;
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<MpsType, RuntimeError> {
fn remove(&mut self, key: &str) -> Result<MpsType, RuntimeMsg> {
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
)))
}
}
}