Reduce usage of OpGetter by making RuntimeError (de)composable
This commit is contained in:
parent
46459c7da1
commit
70950e0bc7
18 changed files with 222 additions and 303 deletions
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
|
@ -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),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"))]
|
||||||
|
|
|
@ -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"))]
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue