cargo fmt

This commit is contained in:
NGnius (Graham) 2022-01-24 16:12:29 -05:00
parent 8dc571521f
commit 0a6dae930f
33 changed files with 531 additions and 323 deletions

View file

@ -3,12 +3,12 @@ use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator;
use std::marker::PhantomData;
use crate::lang::utility::{assert_token, assert_token_raw, check_name, assert_name};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{BoxedMpsOpFactory, MpsOp, PseudoOp, MpsIteratorItem};
use crate::lang::{RuntimeError, SyntaxError};
use crate::lang::SingleItem;
use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_name};
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::processing::general::MpsType;
use crate::processing::OpGetter;
use crate::tokens::MpsToken;
@ -77,7 +77,11 @@ impl<P: MpsFilterPredicate + 'static> std::clone::Clone for MpsFilterStatement<P
impl<P: MpsFilterPredicate + 'static> Display for MpsFilterStatement<P> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
if let Some(other_filters) = &self.other_filters {
write!(f, "{}.({} || (like) {})", self.iterable, self.predicate, other_filters)
write!(
f,
"{}.({} || (like) {})",
self.iterable, self.predicate, other_filters
)
} else {
write!(f, "{}.({})", self.iterable, self.predicate)
}
@ -103,15 +107,19 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
} else {
false
}
} else {true} // ASSUMPTION
} else {
true
} // ASSUMPTION
}
VariableOrOp::Op(PseudoOp::Real(op)) => op.is_resetable(),
VariableOrOp::Op(PseudoOp::Fake(_)) => false,
};
let is_other_filter_resetable = if let Some(PseudoOp::Real(other_filter)) = &self.other_filters {
other_filter.is_resetable()
} else {true};
let is_other_filter_resetable =
if let Some(PseudoOp::Real(other_filter)) = &self.other_filters {
other_filter.is_resetable()
} else {
true
};
is_iterable_resetable && is_other_filter_resetable
}
@ -122,7 +130,12 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
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)?;
let mut var = self
.context
.as_mut()
.unwrap()
.variables
.remove(s, fake_getter)?;
let result = if let MpsType::Op(var) = &mut var {
var.enter(self.context.take().unwrap());
let result = var.reset();
@ -135,16 +148,22 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
msg: "Cannot reset non-iterable filter variable".to_string(),
})
};
self.context.as_mut().unwrap().variables.declare(s, var, fake_getter)?;
self.context
.as_mut()
.unwrap()
.variables
.declare(s, var, fake_getter)?;
result
} else {Ok(())}
},
} else {
Ok(())
}
}
VariableOrOp::Op(PseudoOp::Real(op)) => {
op.enter(self.context.take().unwrap());
let result = op.reset();
self.context = Some(op.escape());
result
},
}
VariableOrOp::Op(PseudoOp::Fake(_)) => Err(RuntimeError {
line: 0,
op: fake,
@ -156,7 +175,9 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
let result = other_filter.reset();
self.context = Some(other_filter.escape());
result
} else {Ok(())}
} else {
Ok(())
}
}
}
@ -185,7 +206,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
maybe_result = Some(Err(e));
self.context = Some(ctx);
break;
},
}
Ok(item) => {
let matches_result =
self.predicate.matches(&item, &mut ctx, &mut op_getter);
@ -201,14 +222,18 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
// handle other filters
// make fake inner item
let single_op = SingleItem::new_ok(item.clone());
match ctx.variables.declare(INNER_VARIABLE_NAME, MpsType::Op(Box::new(single_op)), &mut op_getter) {
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));
self.context = Some(ctx);
break;
},
}
};
let inner_real = match inner.try_real() {
Ok(x) => x,
@ -217,28 +242,34 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
maybe_result = Some(Err(e));
self.context = Some(ctx);
break;
},
}
};
inner_real.enter(ctx);
match inner_real.next() {
Some(item) => {
maybe_result = Some(item);
ctx = inner_real.escape();
match ctx.variables.remove(INNER_VARIABLE_NAME, &mut op_getter) {
Ok(_) => {},
match ctx
.variables
.remove(INNER_VARIABLE_NAME, &mut op_getter)
{
Ok(_) => {}
Err(e) => match maybe_result {
Some(Ok(_)) => maybe_result = Some(Err(e)),
Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error,
None => {}, // impossible
}
None => {} // impossible
},
}
self.context = Some(ctx);
break;
},
}
None => {
ctx = inner_real.escape(); // move ctx back to expected spot
match ctx.variables.remove(INNER_VARIABLE_NAME, &mut op_getter) {
Ok(_) => {},
match ctx
.variables
.remove(INNER_VARIABLE_NAME, &mut op_getter)
{
Ok(_) => {}
Err(e) => {
//self.context = Some(op.escape());
maybe_result = Some(Err(e));
@ -377,7 +408,9 @@ impl<P: MpsFilterPredicate + 'static, F: MpsFilterFactory<P> + 'static> BoxedMps
if tokens2.len() != 0 && check_name("if", &tokens2[0]) {
// replacement filter
if let Some(colon_location) = first_colon2(&tokens2) {
let tokens3 = VecDeque::from_iter(tokens.range(start_of_predicate+1..start_of_predicate+colon_location));
let tokens3 = VecDeque::from_iter(tokens.range(
start_of_predicate + 1..start_of_predicate + colon_location,
));
self.filter_factory.is_filter(&tokens3)
} else {
false
@ -386,9 +419,7 @@ impl<P: MpsFilterPredicate + 'static, F: MpsFilterFactory<P> + 'static> BoxedMps
// regular filter
self.filter_factory.is_filter(&tokens2)
}
}
}
} else {
false
@ -442,7 +473,7 @@ impl<P: MpsFilterPredicate + 'static, F: MpsFilterFactory<P> + 'static> BoxedMps
tokens.extend(end_tokens);
assert_name("else", tokens)?;
let end_tokens = tokens.split_off(tokens.len() - 1); // up to ending close bracket
// build replacement system
// build replacement system
else_op = Some(dict.try_build_statement(tokens)?.into());
tokens.extend(end_tokens);
} else {
@ -458,7 +489,7 @@ impl<P: MpsFilterPredicate + 'static, F: MpsFilterFactory<P> + 'static> BoxedMps
context: None,
op_if: if_op,
op_else: else_op,
item_cache: super::filter_replace::item_cache_deque()
item_cache: super::filter_replace::item_cache_deque(),
}))
} else {
Err(SyntaxError {
@ -467,13 +498,13 @@ impl<P: MpsFilterPredicate + 'static, F: MpsFilterFactory<P> + 'static> BoxedMps
got: None,
})
}
}
};
} else {
let mut another_filter = None;
let (has_or, end_tokens) = if let Some(pipe_location) = first_double_pipe(tokens, 0) {
(true, tokens.split_off(pipe_location)) // parse up to OR operator
} else {
(false, tokens.split_off(tokens.len()-1)) // don't parse closing bracket in filter
(false, tokens.split_off(tokens.len() - 1)) // don't parse closing bracket in filter
};
let filter = self.filter_factory.build_filter(tokens, dict)?;
tokens.extend(end_tokens);
@ -496,7 +527,6 @@ impl<P: MpsFilterPredicate + 'static, F: MpsFilterFactory<P> + 'static> BoxedMps
other_filters: another_filter,
}))
}
}
}
@ -552,7 +582,7 @@ fn first_double_pipe(tokens: &VecDeque<MpsToken>, in_brackets: usize) -> Option<
for i in 0..tokens.len() {
if tokens[i].is_pipe() && inside_brackets == in_brackets {
if pipe_found {
return Some(i-1);
return Some(i - 1);
} else {
pipe_found = true;
}

View file

@ -2,10 +2,10 @@ use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator;
use crate::lang::{MpsOp, PseudoOp, MpsIteratorItem};
use crate::lang::RuntimeError;
use crate::lang::{MpsFilterPredicate, filter::VariableOrOp};
use crate::lang::SingleItem;
use crate::lang::{filter::VariableOrOp, MpsFilterPredicate};
use crate::lang::{MpsIteratorItem, MpsOp, PseudoOp};
use crate::processing::general::MpsType;
use crate::processing::OpGetter;
use crate::MpsContext;
@ -45,9 +45,17 @@ impl<P: MpsFilterPredicate + 'static> std::clone::Clone for MpsFilterReplaceStat
impl<P: MpsFilterPredicate + 'static> Display for MpsFilterReplaceStatement<P> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
if let Some(op_else) = &self.op_else {
write!(f, "{}.(if {}: {} else {})", self.iterable, self.predicate, self.op_if, op_else)
write!(
f,
"{}.(if {}: {} else {})",
self.iterable, self.predicate, self.op_if, op_else
)
} else {
write!(f, "{}.(if {}: {})", self.iterable, self.predicate, self.op_if)
write!(
f,
"{}.(if {}: {})",
self.iterable, self.predicate, self.op_if
)
}
}
}
@ -71,8 +79,9 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
} else {
false
}
} else {true} // ASSUMPTION
} else {
true
} // ASSUMPTION
}
VariableOrOp::Op(PseudoOp::Real(op)) => op.is_resetable(),
VariableOrOp::Op(PseudoOp::Fake(_)) => false,
@ -87,7 +96,12 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
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)?;
let mut var = self
.context
.as_mut()
.unwrap()
.variables
.remove(s, fake_getter)?;
let result = if let MpsType::Op(var) = &mut var {
var.enter(self.context.take().unwrap());
let result = var.reset();
@ -100,16 +114,22 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
msg: "Cannot reset non-iterable filter variable".to_string(),
})
};
self.context.as_mut().unwrap().variables.declare(s, var, fake_getter)?;
self.context
.as_mut()
.unwrap()
.variables
.declare(s, var, fake_getter)?;
result
} else {Ok(())}
},
} else {
Ok(())
}
}
VariableOrOp::Op(PseudoOp::Real(op)) => {
op.enter(self.context.take().unwrap());
let result = op.reset();
self.context = Some(op.escape());
result
},
}
VariableOrOp::Op(PseudoOp::Fake(_)) => Err(RuntimeError {
line: 0,
op: fake,
@ -171,7 +191,7 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
&mut op_getter,
) {
Err(e) => return Some(Err(e)),
Ok(_) => {},
Ok(_) => {}
}
item
}
@ -180,8 +200,11 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
match next_item {
Some(Ok(item)) => {
//println!("item is now: `{}`", &item.filename);
match self.predicate.matches(&item, self.context.as_mut().unwrap(), &mut op_getter) {
Ok(is_match) =>
match self
.predicate
.matches(&item, self.context.as_mut().unwrap(), &mut op_getter)
{
Ok(is_match) => {
if is_match {
// unwrap inner operation
match self.op_if.try_real() {
@ -189,7 +212,11 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
// build item variable
let single_op = SingleItem::new_ok(item);
//println!("Declaring item variable");
let old_item = match declare_or_replace_item(single_op, &mut op_getter, self.context.as_mut().unwrap()) {
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
};
@ -207,9 +234,13 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
self.context = Some(real_op.escape());
// destroy item variable
//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))
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)), // probably shouldn't occur
@ -228,7 +259,11 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
// build item variable
let single_op = SingleItem::new_ok(item);
//println!("Declaring item variable");
let old_item = match declare_or_replace_item(single_op, &mut op_getter, self.context.as_mut().unwrap()) {
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
};
@ -244,11 +279,15 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
self.item_cache.push_back(item);
}
self.context = Some(real_op.escape());
// destroy item variable
// destroy item variable
//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))
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)), // probably shouldn't occur
@ -262,28 +301,38 @@ impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P>
}
} else {
Some(Ok(item))
},
Err(e) => return Some(Err(e))
}
}
Err(e) => return Some(Err(e)),
}
},
}
Some(Err(e)) => Some(Err(e)),
None => None,
}
}
}
fn declare_or_replace_item(single: SingleItem, op: &mut OpGetter, ctx: &mut MpsContext) -> Result<Option<MpsType>, RuntimeError> {
fn declare_or_replace_item(
single: SingleItem,
op: &mut OpGetter,
ctx: &mut MpsContext,
) -> Result<Option<MpsType>, RuntimeError> {
let old_item: Option<MpsType>;
if ctx.variables.exists(ITEM_VARIABLE_NAME) {
old_item = Some(ctx.variables.remove(ITEM_VARIABLE_NAME, op)?);
} else {
old_item = None;
}
ctx.variables.declare(ITEM_VARIABLE_NAME, MpsType::Op(Box::new(single)), op)?;
ctx.variables
.declare(ITEM_VARIABLE_NAME, MpsType::Op(Box::new(single)), op)?;
Ok(old_item)
}
fn remove_or_replace_item(old_item: Option<MpsType>, op: &mut OpGetter, ctx: &mut MpsContext) -> Result<(), RuntimeError> {
fn remove_or_replace_item(
old_item: Option<MpsType>,
op: &mut OpGetter,
ctx: &mut MpsContext,
) -> Result<(), RuntimeError> {
ctx.variables.remove(ITEM_VARIABLE_NAME, op)?;
if let Some(old_item) = old_item {
ctx.variables.declare(ITEM_VARIABLE_NAME, old_item, op)?;

View file

@ -2,17 +2,17 @@ use std::collections::VecDeque;
use std::fmt::{Display, Error, Formatter};
//use super::MpsTypePrimitive;
use crate::processing::general::MpsType;
use super::utility::{assert_token, assert_type, check_is_type};
use crate::lang::{RuntimeError, SyntaxError};
use super::utility::{assert_type, assert_token, check_is_type};
use crate::processing::general::MpsType;
use crate::processing::OpGetter;
use crate::tokens::MpsToken;
use crate::MpsContext;
use crate::processing::OpGetter;
#[derive(Debug)]
pub enum Lookup {
Static(MpsType),
Variable(String)
Variable(String),
}
impl Lookup {
@ -29,24 +29,36 @@ impl Lookup {
} else if check_is_type(&tokens[0]) {
Ok(Self::Static(MpsType::Primitive(assert_type(tokens)?)))
} else {
Ok(Self::Variable(assert_token(|t| match t {
MpsToken::Name(s) => Some(s),
_ => None,
}, MpsToken::Name("variable_name".into()), tokens)?))
Ok(Self::Variable(assert_token(
|t| match t {
MpsToken::Name(s) => Some(s),
_ => None,
},
MpsToken::Name("variable_name".into()),
tokens,
)?))
}
}
pub fn get_mut<'a, 'b: 'a>(&'b mut self, ctx: &'a mut MpsContext, op: &mut OpGetter) -> Result<&'a mut MpsType, RuntimeError> {
pub fn get_mut<'a, 'b: 'a>(
&'b mut self,
ctx: &'a mut MpsContext,
op: &mut OpGetter,
) -> Result<&'a mut MpsType, RuntimeError> {
match self {
Self::Static(var) => Ok(var),
Self::Variable(name) => ctx.variables.get_mut(name, op)
Self::Variable(name) => ctx.variables.get_mut(name, op),
}
}
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,
op: &mut OpGetter,
) -> Result<&'a MpsType, RuntimeError> {
match self {
Self::Static(var) => Ok(var),
Self::Variable(name) => ctx.variables.get(name, op)
Self::Variable(name) => ctx.variables.get(name, op),
}
}
}
@ -57,7 +69,6 @@ impl Display for Lookup {
Self::Static(var) => write!(f, "{}", var),
Self::Variable(name) => write!(f, "{}", name),
}
}
}
@ -66,7 +77,7 @@ impl std::clone::Clone for Lookup {
match self {
Self::Static(var) => match var {
MpsType::Primitive(p) => Self::Static(MpsType::Primitive(p.clone())),
_ => panic!("Can't clone static operator (invalid state)")
_ => panic!("Can't clone static operator (invalid state)"),
},
Self::Variable(name) => Self::Variable(name.clone()),
}

View file

@ -22,11 +22,11 @@ pub use filter::{
pub use filter_replace::MpsFilterReplaceStatement;
pub use function::{MpsFunctionFactory, MpsFunctionStatementFactory};
pub use lookup::Lookup;
pub use operation::{BoxedMpsOpFactory, MpsOp, MpsOpFactory, SimpleMpsOpFactory, MpsIteratorItem};
pub use operation::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, MpsOpFactory, SimpleMpsOpFactory};
pub use pseudo_op::PseudoOp;
pub use repeated_meme::{repeated_tokens, RepeatedTokens};
pub use single_op::SingleItem;
pub use sorter::{MpsSorterFactory, MpsSorter, MpsSortStatement, MpsSortStatementFactory};
pub use sorter::{MpsSortStatement, MpsSortStatementFactory, MpsSorter, MpsSorterFactory};
//pub(crate) use statement::MpsStatement;
pub use type_primitives::MpsTypePrimitive;

View file

@ -1,7 +1,7 @@
use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator;
use crate::lang::{MpsOp, RuntimeError, MpsIteratorItem};
use crate::lang::{MpsIteratorItem, MpsOp, RuntimeError};
use crate::MpsContext;
use crate::MpsItem;
@ -34,7 +34,7 @@ impl Display for SingleItem {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match &self.item {
Ok(item) => write!(f, "*single item*[Ok({})]", item),
Err(e) => write!(f, "*single-item*[Err({})]", e)
Err(e) => write!(f, "*single-item*[Err({})]", e),
}
}
}

View file

@ -3,9 +3,9 @@ use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator;
use std::marker::PhantomData;
use crate::lang::utility::{assert_token_raw, check_name, assert_name};
use crate::lang::utility::{assert_name, assert_token_raw, check_name};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{BoxedMpsOpFactory, MpsOp, PseudoOp, MpsIteratorItem};
use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, PseudoOp};
use crate::lang::{RuntimeError, SyntaxError};
use crate::tokens::MpsToken;
use crate::MpsContext;
@ -13,7 +13,11 @@ use crate::MpsContext;
const SORTER_ITEM_CACHE_SIZE: usize = 8;
pub trait MpsSorter: Clone + Debug + Display {
fn sort(&mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque<MpsIteratorItem>) -> Result<(), RuntimeError>;
fn sort(
&mut self,
iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>,
) -> Result<(), RuntimeError>;
}
pub trait MpsSorterFactory<S: MpsSorter + 'static> {
@ -62,7 +66,9 @@ impl<S: MpsSorter + 'static> MpsOp for MpsSortStatement<S> {
fn is_resetable(&self) -> bool {
if let Ok(iter) = self.iterable.try_real_ref() {
iter.is_resetable()
} else {false}
} else {
false
}
}
fn reset(&mut self) -> Result<(), RuntimeError> {
@ -80,7 +86,7 @@ impl<S: MpsSorter + 'static> Iterator for MpsSortStatement<S> {
Err(e) => return Some(Err(e)),
};
match self.orderer.sort(real_op.as_mut(), &mut self.item_cache) {
Ok(_) => {},
Ok(_) => {}
Err(e) => return Some(Err(e)),
}
self.item_cache.pop_front()
@ -92,9 +98,7 @@ pub struct MpsSortStatementFactory<S: MpsSorter + 'static, F: MpsSorterFactory<S
idc: PhantomData<S>,
}
impl<S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static>
MpsSortStatementFactory<S, F>
{
impl<S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static> MpsSortStatementFactory<S, F> {
pub fn new(factory: F) -> Self {
Self {
sort_factory: factory,
@ -103,7 +107,7 @@ impl<S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static>
}
}
impl <S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static> BoxedMpsOpFactory
impl<S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static> BoxedMpsOpFactory
for MpsSortStatementFactory<S, F>
{
fn is_op_boxed(&self, tokens: &VecDeque<MpsToken>) -> bool {
@ -112,18 +116,20 @@ impl <S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static> BoxedMpsOpFactor
// iterable~(sorter)
if tokens_len > tilde_location + 2 {
let tokens2: VecDeque<&MpsToken> =
VecDeque::from_iter(tokens.range(tilde_location+2..tokens_len-1));
tokens[tokens_len-1].is_close_bracket()
&& self.sort_factory.is_sorter(&tokens2)
} else {false}
VecDeque::from_iter(tokens.range(tilde_location + 2..tokens_len - 1));
tokens[tokens_len - 1].is_close_bracket() && self.sort_factory.is_sorter(&tokens2)
} else {
false
}
} else if let Some(dot_location) = last_dot_sort(tokens, 1) {
// iterable.sort(sorter)
if tokens_len > dot_location + 3 {
let tokens2: VecDeque<&MpsToken> =
VecDeque::from_iter(tokens.range(dot_location+3..tokens_len-1));
tokens[tokens_len-1].is_close_bracket()
&& self.sort_factory.is_sorter(&tokens2)
} else {false}
VecDeque::from_iter(tokens.range(dot_location + 3..tokens_len - 1));
tokens[tokens_len - 1].is_close_bracket() && self.sort_factory.is_sorter(&tokens2)
} else {
false
}
} else {
false
}
@ -150,21 +156,19 @@ impl <S: MpsSorter + 'static, F: MpsSorterFactory<S> + 'static> BoxedMpsOpFactor
return Err(SyntaxError {
line: 0,
token: MpsToken::Name(".|~".into()),
got: tokens.pop_front()
})
got: tokens.pop_front(),
});
}
assert_token_raw(MpsToken::OpenBracket, tokens)?;
let end_tokens = tokens.split_off(tokens.len()-1);
let end_tokens = tokens.split_off(tokens.len() - 1);
let sorter = self.sort_factory.build_sorter(tokens, dict)?;
tokens.extend(end_tokens);
assert_token_raw(MpsToken::CloseBracket, tokens)?;
Ok(Box::new(
MpsSortStatement {
orderer: sorter,
iterable: inner_op.into(),
item_cache: VecDeque::with_capacity(SORTER_ITEM_CACHE_SIZE),
}
))
Ok(Box::new(MpsSortStatement {
orderer: sorter,
iterable: inner_op.into(),
item_cache: VecDeque::with_capacity(SORTER_ITEM_CACHE_SIZE),
}))
}
}
@ -177,7 +181,7 @@ fn last_tilde(tokens: &VecDeque<MpsToken>, target_depth: usize) -> Option<usize>
} else if current_token.is_open_bracket() && bracket_depth != 0 {
bracket_depth -= 1;
} else if current_token.is_tilde() && bracket_depth == target_depth {
return Some(i)
return Some(i);
}
}
None
@ -196,7 +200,7 @@ fn last_dot_sort(tokens: &VecDeque<MpsToken>, target_depth: usize) -> Option<usi
} else {
None
}
}
};
} else if bracket_found {
if check_name("sort", current_token) {
sort_found = true;

View file

@ -1,7 +1,7 @@
//! Basic types for MPS
use std::cmp::{Ord, Ordering};
use std::fmt::{Debug, Display, Error, Formatter};
use std::cmp::{Ordering, Ord};
#[derive(Debug, Clone, PartialEq)]
pub enum MpsTypePrimitive {
@ -38,7 +38,7 @@ impl MpsTypePrimitive {
Self::UInt(x) => format!("{}", x),
Self::Int(x) => format!("{}", x),
Self::Float(x) => format!("{}", x),
Self::Bool(x) => format!("{}", x)
Self::Bool(x) => format!("{}", x),
}
}
@ -61,7 +61,7 @@ impl MpsTypePrimitive {
}
pub fn parse(s: String) -> Self {
if let Ok(i) = s.parse::<i64>() {
if let Ok(i) = s.parse::<i64>() {
Self::Int(i)
} else if let Ok(u) = s.parse::<u64>() {
Self::UInt(u)
@ -117,9 +117,7 @@ impl PartialOrd for MpsTypePrimitive {
_ => None,
},
Self::Float(f1) => match other {
Self::Float(f2) => Some(
f1.partial_cmp(f2).unwrap_or(std::cmp::Ordering::Less),
),
Self::Float(f2) => Some(f1.partial_cmp(f2).unwrap_or(std::cmp::Ordering::Less)),
Self::Int(f2) => Some(
f1.partial_cmp(&(*f2 as f64))
.unwrap_or(std::cmp::Ordering::Less),

View file

@ -143,7 +143,7 @@ pub fn assert_type(tokens: &mut VecDeque<MpsToken>) -> Result<MpsTypePrimitive,
match token {
MpsToken::Literal(s) => Ok(MpsTypePrimitive::String(s)),
MpsToken::Name(s) => {
if let Ok(i) = s.parse::<i64>() {
if let Ok(i) = s.parse::<i64>() {
Ok(MpsTypePrimitive::Int(i))
} else if let Ok(u) = s.parse::<u64>() {
Ok(MpsTypePrimitive::UInt(u))

View file

@ -7,8 +7,8 @@ use crate::MpsContext;
use crate::lang::utility::assert_token;
use crate::lang::MpsLanguageDictionary;
use crate::lang::{BoxedMpsOpFactory, MpsOp, MpsOpFactory, SimpleMpsOpFactory, MpsIteratorItem};
use crate::lang::SyntaxError;
use crate::lang::{BoxedMpsOpFactory, MpsIteratorItem, MpsOp, MpsOpFactory, SimpleMpsOpFactory};
#[derive(Debug)]
pub struct CommentStatement {

View file

@ -8,7 +8,7 @@ use crate::MpsContext;
use crate::lang::repeated_tokens;
use crate::lang::utility::{assert_token, assert_token_raw};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsOp, MpsIteratorItem};
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsOp};
use crate::lang::{RuntimeError, SyntaxError};
use crate::processing::general::FileIter;

View file

@ -30,8 +30,8 @@ pub struct FieldFilter {
#[derive(Debug, Clone)]
pub enum FieldFilterErrorHandling {
Error, // return error
Ignore, // return Ok(false) when error encountered
Error, // return error
Ignore, // return Ok(false) when error encountered
Include, // return Ok(true) when error encountered
}
@ -44,7 +44,7 @@ fn comparison_op(c: &[i8; 2]) -> &str {
[0, -1] => "<=",
[0, 1] => ">=",
[-1, 1] => "!=",
_ => "??"
_ => "??",
}
}
@ -52,7 +52,9 @@ impl Display for FieldFilter {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
let comp_op = comparison_op(&self.comparison);
match &self.val {
VariableOrValue::Variable(name) => write!(f, "{} {} {}", self.field_name, comp_op, name),
VariableOrValue::Variable(name) => {
write!(f, "{} {} {}", self.field_name, comp_op, name)
}
VariableOrValue::Value(t) => write!(f, "{} {} {}", self.field_name, comp_op, t),
}
}

View file

@ -1,11 +1,11 @@
use std::collections::VecDeque;
use super::utility::assert_comparison_operator;
use super::{FieldFilter, FieldFilterErrorHandling, field_filter::VariableOrValue};
use crate::lang::utility::{assert_token, assert_type, check_is_type, assert_token_raw};
use super::{field_filter::VariableOrValue, FieldFilter, FieldFilterErrorHandling};
use crate::lang::utility::{assert_token, assert_token_raw, assert_type, check_is_type};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{MpsFilterFactory, MpsFilterStatementFactory};
use crate::lang::SyntaxError;
use crate::lang::{MpsFilterFactory, MpsFilterStatementFactory};
use crate::tokens::MpsToken;
pub struct FieldFilterMaybeFactory;
@ -80,7 +80,8 @@ impl MpsFilterFactory<FieldFilter> for FieldFilterMaybeFactory {
}
}
pub type FieldFilterMaybeStatementFactory = MpsFilterStatementFactory<FieldFilter, FieldFilterMaybeFactory>;
pub type FieldFilterMaybeStatementFactory =
MpsFilterStatementFactory<FieldFilter, FieldFilterMaybeFactory>;
#[inline(always)]
pub fn field_filter_maybe() -> FieldFilterMaybeStatementFactory {

View file

@ -1,8 +1,8 @@
use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter};
use super::field_filter::{VariableOrValue, FieldFilterErrorHandling};
use crate::lang::utility::{assert_token, check_name, assert_name, assert_token_raw};
use super::field_filter::{FieldFilterErrorHandling, VariableOrValue};
use crate::lang::utility::{assert_name, assert_token, assert_token_raw, check_name};
use crate::lang::MpsLanguageDictionary;
use crate::lang::MpsTypePrimitive;
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
@ -51,7 +51,7 @@ impl MpsFilterPredicate for FieldLikeFilter {
line: 0,
op: op(),
msg: format!("Value is not type String"),
})
}),
}?;
if let Some(field) = music_item_lut.field(&self.field_name) {
let field_str = field.as_str().to_lowercase();
@ -150,7 +150,8 @@ impl MpsFilterFactory<FieldLikeFilter> for FieldLikeFilterFactory {
}
}
pub type FieldLikeFilterStatementFactory = MpsFilterStatementFactory<FieldLikeFilter, FieldLikeFilterFactory>;
pub type FieldLikeFilterStatementFactory =
MpsFilterStatementFactory<FieldLikeFilter, FieldLikeFilterFactory>;
#[inline(always)]
pub fn field_like_filter() -> FieldLikeFilterStatementFactory {

View file

@ -1,11 +1,11 @@
use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive};
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::lang::{Lookup, utility::assert_token_raw};
use crate::processing::{OpGetter, general::MpsType};
use crate::processing::{general::MpsType, OpGetter};
use crate::tokens::MpsToken;
use crate::MpsContext;
use crate::MpsItem;
@ -37,17 +37,21 @@ impl MpsFilterPredicate for IndexFilter {
MpsTypePrimitive::Int(i) => *i as u64,
MpsTypePrimitive::UInt(u) => *u,
MpsTypePrimitive::Float(f) => *f as u64,
val => return Err(RuntimeError {
val => {
return Err(RuntimeError {
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
}
},
val => {
return Err(RuntimeError {
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
},
val => return Err(RuntimeError {
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
}
};
if self.current == index && !self.is_opposite {
self.current += 1;
@ -77,14 +81,8 @@ pub struct IndexFilterFactory;
impl MpsFilterFactory<IndexFilter> for IndexFilterFactory {
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
(
tokens.len() == 1
&& Lookup::check_is(&tokens[0])
) || (
tokens.len() == 2
&& tokens[0].is_exclamation()
&& Lookup::check_is(&tokens[1])
)
(tokens.len() == 1 && Lookup::check_is(&tokens[0]))
|| (tokens.len() == 2 && tokens[0].is_exclamation() && Lookup::check_is(&tokens[1]))
}
fn build_filter(
@ -95,7 +93,9 @@ impl MpsFilterFactory<IndexFilter> for IndexFilterFactory {
let is_inverted = if tokens[0].is_exclamation() {
assert_token_raw(MpsToken::Exclamation, tokens)?;
true
} else {false};
} else {
false
};
let lookup = Lookup::parse(tokens)?;
Ok(IndexFilter {
index: lookup,

View file

@ -10,9 +10,18 @@ pub use empty_filter::{
empty_filter, EmptyFilter, EmptyFilterFactory, EmptyFilterStatementFactory,
};
pub use field_filter::{
field_filter, FieldFilter, FieldFilterFactory, FieldFilterStatementFactory, FieldFilterErrorHandling,
field_filter, FieldFilter, FieldFilterErrorHandling, FieldFilterFactory,
FieldFilterStatementFactory,
};
pub use field_filter_maybe::{
field_filter_maybe, FieldFilterMaybeFactory, FieldFilterMaybeStatementFactory,
};
pub use field_like_filter::{
field_like_filter, FieldLikeFilterFactory, FieldLikeFilterStatementFactory,
};
pub use index_filter::{
index_filter, IndexFilter, IndexFilterFactory, IndexFilterStatementFactory,
};
pub use range_filter::{
range_filter, RangeFilter, RangeFilterFactory, RangeFilterStatementFactory,
};
pub use field_filter_maybe::{field_filter_maybe, FieldFilterMaybeFactory, FieldFilterMaybeStatementFactory};
pub use field_like_filter::{field_like_filter, FieldLikeFilterFactory, FieldLikeFilterStatementFactory};
pub use index_filter::{index_filter, IndexFilter, IndexFilterFactory, IndexFilterStatementFactory};
pub use range_filter::{range_filter, RangeFilter, RangeFilterFactory, RangeFilterStatementFactory};

View file

@ -1,12 +1,12 @@
use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive};
use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory};
use crate::lang::{RuntimeError, SyntaxError};
use crate::lang::Lookup;
use crate::lang::utility::assert_token_raw;
use crate::processing::{OpGetter, general::MpsType};
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::tokens::MpsToken;
use crate::MpsContext;
use crate::MpsItem;
@ -23,10 +23,21 @@ pub struct RangeFilter {
impl Display for RangeFilter {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}{}{}",
if let Some(start) = &self.start {format!("{}", start)} else {"".into()},
if self.inclusive_end {"="} else {""},
if let Some(end) = &self.end {format!("{}", end)} else {"".into()},)
write!(
f,
"{}{}{}",
if let Some(start) = &self.start {
format!("{}", start)
} else {
"".into()
},
if self.inclusive_end { "=" } else { "" },
if let Some(end) = &self.end {
format!("{}", end)
} else {
"".into()
},
)
}
}
@ -39,7 +50,9 @@ impl MpsFilterPredicate for RangeFilter {
) -> Result<bool, RuntimeError> {
let start_index = if let Some(start) = &self.start {
lookup_to_index(start.get(ctx, op)?, op)?
} else {0};
} else {
0
};
let current = self.current;
self.current += 1;
if current >= start_index {
@ -87,13 +100,13 @@ fn lookup_to_index(item: &MpsType, op: &mut OpGetter) -> Result<u64, RuntimeErro
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
}),
},
val => Err(RuntimeError {
line: 0,
op: op(),
msg: format!("Cannot use {} as index", val),
})
}),
}
}
@ -103,44 +116,38 @@ impl MpsFilterFactory<RangeFilter> for RangeFilterFactory {
fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool {
(
// ..
tokens.len() == 2
&& tokens[0].is_dot()
&& tokens[1].is_dot()
) || (
tokens.len() == 3
tokens.len() == 2 && tokens[0].is_dot() && tokens[1].is_dot()
) || (tokens.len() == 3
&& ((
// ..number
tokens[0].is_dot()
&& tokens[1].is_dot()
&& Lookup::check_is(&tokens[2])
tokens[0].is_dot() && tokens[1].is_dot() && Lookup::check_is(&tokens[2])
) || (
// number..
Lookup::check_is(&tokens[0])
&& tokens[1].is_dot()
&& tokens[2].is_dot()
))
) || (
tokens.len() == 4
&& (( // number..number
Lookup::check_is(&tokens[0])
&& tokens[1].is_dot()
&& tokens[2].is_dot()
&& Lookup::check_is(&tokens[3])
) || ( // ..=number
tokens[0].is_dot()
&& tokens[1].is_dot()
&& tokens[2].is_equals()
&& Lookup::check_is(&tokens[3])
))
) || (
// number..=number
tokens.len() == 5
&& Lookup::check_is(&tokens[0])
&& tokens[1].is_dot()
&& tokens[2].is_dot()
&& tokens[3].is_equals()
&& Lookup::check_is(&tokens[4])
)
Lookup::check_is(&tokens[0]) && tokens[1].is_dot() && tokens[2].is_dot()
)))
|| (tokens.len() == 4
&& ((
// number..number
Lookup::check_is(&tokens[0])
&& tokens[1].is_dot()
&& tokens[2].is_dot()
&& Lookup::check_is(&tokens[3])
) || (
// ..=number
tokens[0].is_dot()
&& tokens[1].is_dot()
&& tokens[2].is_equals()
&& Lookup::check_is(&tokens[3])
)))
|| (
// number..=number
tokens.len() == 5
&& Lookup::check_is(&tokens[0])
&& tokens[1].is_dot()
&& tokens[2].is_dot()
&& tokens[3].is_equals()
&& Lookup::check_is(&tokens[4])
)
}
fn build_filter(
@ -151,7 +158,9 @@ impl MpsFilterFactory<RangeFilter> for RangeFilterFactory {
// start index
let start = if Lookup::check_is(&tokens[0]) {
Some(Lookup::parse(tokens)?)
} else {None};
} else {
None
};
// ..
assert_token_raw(MpsToken::Dot, tokens)?;
assert_token_raw(MpsToken::Dot, tokens)?;
@ -166,7 +175,9 @@ impl MpsFilterFactory<RangeFilter> for RangeFilterFactory {
// end index
let end = if !tokens.is_empty() {
Some(Lookup::parse(tokens)?)
} else {None};
} else {
None
};
Ok(RangeFilter {
start: start,

View file

@ -8,7 +8,9 @@ use crate::MpsItem;
use crate::lang::utility::{assert_token, assert_token_raw};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsOp, PseudoOp, MpsIteratorItem};
use crate::lang::{
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsOp, PseudoOp,
};
use crate::lang::{RuntimeError, SyntaxError};
#[derive(Debug)]
@ -28,7 +30,11 @@ impl Display for RepeatStatement {
if self.loop_forever {
write!(f, "repeat({})", self.inner_statement)
} else {
write!(f, "repeat({}, {})", self.inner_statement, self.original_repetitions)
write!(
f,
"repeat({}, {})",
self.inner_statement, self.original_repetitions
)
}
}
}

View file

@ -1,8 +1,8 @@
use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter};
use crate::lang::{MpsSorter, MpsSorterFactory, MpsSortStatementFactory};
use crate::lang::{MpsLanguageDictionary, MpsIteratorItem, MpsOp};
use crate::lang::{MpsIteratorItem, MpsLanguageDictionary, MpsOp};
use crate::lang::{MpsSortStatementFactory, MpsSorter, MpsSorterFactory};
use crate::lang::{RuntimeError, SyntaxError};
use crate::tokens::MpsToken;
@ -10,7 +10,11 @@ use crate::tokens::MpsToken;
pub struct EmptySorter;
impl MpsSorter for EmptySorter {
fn sort(&mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque<MpsIteratorItem>) -> Result<(), RuntimeError> {
fn sort(
&mut self,
iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>,
) -> Result<(), RuntimeError> {
if let Some(item) = iterator.next() {
item_buf.push_back(item)
}

View file

@ -1,11 +1,11 @@
use std::cmp::Ordering;
use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter};
use std::cmp::Ordering;
use crate::lang::{MpsSorter, MpsSorterFactory, MpsSortStatementFactory};
use crate::lang::{MpsLanguageDictionary, MpsIteratorItem, MpsOp};
use crate::lang::{RuntimeError, SyntaxError};
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::tokens::MpsToken;
#[derive(Debug, Clone)]
@ -16,7 +16,11 @@ pub struct FieldSorter {
}
impl MpsSorter for FieldSorter {
fn sort(&mut self, iterator: &mut dyn MpsOp, item_buf: &mut VecDeque<MpsIteratorItem>) -> Result<(), RuntimeError> {
fn sort(
&mut self,
iterator: &mut dyn MpsOp,
item_buf: &mut VecDeque<MpsIteratorItem>,
) -> Result<(), RuntimeError> {
let buf_len_old = item_buf.len(); // save buffer length before modifying buffer
if item_buf.len() < self.up_to {
for item in iterator {
@ -29,20 +33,18 @@ impl MpsSorter for FieldSorter {
if buf_len_old != item_buf.len() {
// when buf_len_old == item_buf.len(), iterator was already complete
// no need to sort in that case, since buffer was sorted in last call to sort or buffer never had any items to sort
item_buf.make_contiguous().sort_by(
|a, b| {
if let Ok(a) = a {
if let Some(a_field) = a.field(&self.field_name) {
if let Ok(b) = b {
if let Some(b_field) = b.field(&self.field_name) {
return a_field.partial_cmp(b_field).unwrap_or(self.default_order);
}
item_buf.make_contiguous().sort_by(|a, b| {
if let Ok(a) = a {
if let Some(a_field) = a.field(&self.field_name) {
if let Ok(b) = b {
if let Some(b_field) = b.field(&self.field_name) {
return a_field.partial_cmp(b_field).unwrap_or(self.default_order);
}
}
}
self.default_order
}
);
self.default_order
});
println!("Field-sorted item_buf: {:?}", item_buf);
}
Ok(())
@ -67,14 +69,18 @@ impl MpsSorterFactory<FieldSorter> for FieldSorterFactory {
tokens: &mut VecDeque<MpsToken>,
_dict: &MpsLanguageDictionary,
) -> Result<FieldSorter, SyntaxError> {
let name = assert_token(|t| match t {
MpsToken::Name(s) => Some(s),
_ => None
}, MpsToken::Name("field_name".into()), tokens)?;
let name = assert_token(
|t| match t {
MpsToken::Name(s) => Some(s),
_ => None,
},
MpsToken::Name("field_name".into()),
tokens,
)?;
Ok(FieldSorter {
field_name: name,
up_to: usize::MAX,
default_order: Ordering::Equal
default_order: Ordering::Equal,
})
}
}

View file

@ -9,8 +9,8 @@ use crate::MpsContext;
use crate::lang::repeated_tokens;
use crate::lang::utility::{assert_token, assert_token_raw};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsOp, MpsIteratorItem};
use crate::lang::SyntaxError;
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsOp};
#[derive(Debug)]
pub struct SqlInitStatement {

View file

@ -3,7 +3,9 @@ use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator;
use crate::lang::utility::assert_token;
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsLanguageDictionary, MpsOp, MpsIteratorItem};
use crate::lang::{
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsLanguageDictionary, MpsOp,
};
use crate::lang::{RuntimeError, SyntaxError};
use crate::tokens::MpsToken;
use crate::MpsContext;

View file

@ -3,7 +3,9 @@ use std::fmt::{Debug, Display, Error, Formatter};
use std::iter::Iterator;
use crate::lang::utility::assert_token;
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsLanguageDictionary, MpsOp, MpsIteratorItem};
use crate::lang::{
MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsLanguageDictionary, MpsOp,
};
use crate::lang::{RuntimeError, SyntaxError};
use crate::tokens::MpsToken;
use crate::MpsContext;

View file

@ -7,7 +7,9 @@ use crate::MpsContext;
use crate::lang::utility::{assert_token, assert_token_raw, assert_type, check_is_type};
use crate::lang::MpsLanguageDictionary;
use crate::lang::{BoxedMpsOpFactory, MpsOp, MpsOpFactory, MpsTypePrimitive, PseudoOp, MpsIteratorItem};
use crate::lang::{
BoxedMpsOpFactory, MpsIteratorItem, MpsOp, MpsOpFactory, MpsTypePrimitive, PseudoOp,
};
use crate::lang::{RuntimeError, SyntaxError};
use crate::processing::general::MpsType;

View file

@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
use regex::Regex;
use super::OpGetter;
use crate::lang::{RuntimeError, MpsTypePrimitive};
use crate::lang::{MpsTypePrimitive, RuntimeError};
use crate::MpsItem;
const DEFAULT_REGEX: &str = r"/(?P<artist>[^/]+)/(?P<album>[^/]+)/(?:(?:(?P<disc>\d+)\s+)?(?P<track>\d+)\.?\s+)?(?P<title>[^/]+)\.(?P<format>(?:mp3)|(?:wav)|(?:ogg)|(?:flac)|(?:mp4)|(?:aac))$";
@ -100,11 +100,12 @@ impl FileIter {
} else {
Vec::with_capacity(DEFAULT_VEC_CACHE_SIZE)
};
let pattern_re = Regex::new(pattern.unwrap_or(DEFAULT_REGEX)).map_err(|e| RuntimeError {
line: 0,
op: op(),
msg: format!("Regex compile error: {}", e),
})?;
let pattern_re =
Regex::new(pattern.unwrap_or(DEFAULT_REGEX)).map_err(|e| RuntimeError {
line: 0,
op: op(),
msg: format!("Regex compile error: {}", e),
})?;
Ok(Self {
root: root_path,
pattern: pattern_re,
@ -182,12 +183,12 @@ impl FileIter {
}
}
Some(item)
},
}
Err(_) => {
let mut item = MpsItem::new();
self.populate_item_impl_simple(&mut item, path_str, captures, capture_names);
Some(item)
},
}
}
}
@ -214,7 +215,10 @@ impl FileIter {
// populates fields from named capture groups
while let Some(name_maybe) = capture_names.next() {
if let Some(name) = name_maybe {
if let Some(value) = captures.name(name).and_then(|m| Some(m.as_str().to_string())) {
if let Some(value) = captures
.name(name)
.and_then(|m| Some(m.as_str().to_string()))
{
item.set_field(name, MpsTypePrimitive::parse(value));
}
}

View file

@ -259,10 +259,7 @@ impl std::convert::TryInto<rusqlite::Connection> for SqliteSettings {
}
#[inline(always)]
fn build_mps_item(
conn: &mut rusqlite::Connection,
item: DbMusicItem,
) -> rusqlite::Result<MpsItem> {
fn build_mps_item(conn: &mut rusqlite::Connection, item: DbMusicItem) -> rusqlite::Result<MpsItem> {
// query artist
let mut stmt = conn.prepare_cached("SELECT * from artists WHERE artist_id = ?")?;
let artist = stmt.query_row([item.artist], DbArtistItem::map_row)?;
@ -331,7 +328,6 @@ fn rows_to_item(
meta: DbMetaItem,
genre: DbGenreItem,
) -> MpsItem {
let mut item = MpsItem::new();
item
// music row

View file

@ -45,7 +45,9 @@ impl MpsToken {
_ => {
// name validation
let mut ok = true;
for invalid_c in ["-", "+", ",", " ", "/", "\n", "\r", "!", "?", "=", ".", "&", "|"] {
for invalid_c in [
"-", "+", ",", " ", "/", "\n", "\r", "!", "?", "=", ".", "&", "|",
] {
if s.contains(invalid_c) {
ok = false;
break;

View file

@ -258,10 +258,12 @@ impl ReaderStateMachine {
'#' => Self::Octothorpe { out: input },
'`' => Self::StartTickLiteral {},
'"' => Self::StartQuoteLiteral {},
'\n'| '\r' | '\t' | ' ' => Self::EndToken {},
'\n' | '\r' | '\t' | ' ' => Self::EndToken {},
';' => Self::EndStatement {},
'\0' => Self::EndOfFile {},
'(' | ')' | ',' | '=' | '<' | '>' | '.' | '!' | '?' | '|' | ':' => Self::SingleCharToken { out: input },
'(' | ')' | ',' | '=' | '<' | '>' | '.' | '!' | '?' | '|' | ':' => {
Self::SingleCharToken { out: input }
}
_ => Self::Regular { out: input },
},
Self::Escaped { inside } => match inside {

View file

@ -62,9 +62,18 @@ fn execute_single_line(
break;
}
} // no need to spam the rest of the songs
println!("Got song `{}` (file: `{}`)",
item.field("title").expect("Expected field `title` to exist").clone().to_str().expect("Expected field `title` to be String"),
item.field("filename").expect("Expected field `filename` to exist").clone().to_str().expect("Expected field `filename` to be String")
println!(
"Got song `{}` (file: `{}`)",
item.field("title")
.expect("Expected field `title` to exist")
.clone()
.to_str()
.expect("Expected field `title` to be String"),
item.field("filename")
.expect("Expected field `filename` to exist")
.clone()
.to_str()
.expect("Expected field `filename` to be String")
);
} else {
println!("!!! Got error while iterating (executing) !!!");
@ -109,9 +118,21 @@ fn execute_comment_line() -> Result<(), Box<dyn MpsLanguageError>> {
#[test]
fn execute_repeat_line() -> Result<(), Box<dyn MpsLanguageError>> {
execute_single_line("repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`))", false, false)?;
execute_single_line("repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`), 4)", false, true)?;
execute_single_line("repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`), 0)", true, true)
execute_single_line(
"repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`))",
false,
false,
)?;
execute_single_line(
"repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`), 4)",
false,
true,
)?;
execute_single_line(
"repeat(files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`), 0)",
true,
true,
)
}
#[test]
@ -135,7 +156,11 @@ fn execute_assign_line() -> Result<(), Box<dyn MpsLanguageError>> {
#[test]
fn execute_emptyfilter_line() -> Result<(), Box<dyn MpsLanguageError>> {
execute_single_line("files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).().().()", false, true)
execute_single_line(
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).().().()",
false,
true,
)
}
#[test]

View file

@ -26,8 +26,14 @@ impl MpsController {
let (playback_tx, playback_rx) = channel();
let mut sys_ctrl = SystemControlWrapper::new(control_tx.clone());
sys_ctrl.init(playback_rx);
let handle =
MpsPlayerServer::spawn(player_gen, control_tx.clone(), control_rx, event_tx, playback_tx, false);
let handle = MpsPlayerServer::spawn(
player_gen,
control_tx.clone(),
control_rx,
event_tx,
playback_tx,
false,
);
Self {
control: control_tx,
event: event_rx,
@ -44,8 +50,14 @@ impl MpsController {
let (playback_tx, playback_rx) = channel();
let mut sys_ctrl = SystemControlWrapper::new(control_tx.clone());
sys_ctrl.init(playback_rx);
let handle =
MpsPlayerServer::spawn(player_gen, control_tx.clone(), control_rx, event_tx, playback_tx, true);
let handle = MpsPlayerServer::spawn(
player_gen,
control_tx.clone(),
control_rx,
event_tx,
playback_tx,
true,
);
Self {
control: control_tx,
event: event_rx,

View file

@ -1,10 +1,10 @@
#[allow(unused_imports)]
use std::sync::mpsc::{channel, Sender, Receiver};
use std::sync::mpsc::{channel, Receiver, Sender};
#[cfg(all(target_os = "linux", feature = "os-controls"))]
use std::thread::JoinHandle;
#[cfg(all(target_os = "linux", feature = "os-controls"))]
use mpris_player::{MprisPlayer, PlaybackStatus, Metadata};
use mpris_player::{Metadata, MprisPlayer, PlaybackStatus};
#[cfg(all(target_os = "linux", feature = "os-controls"))]
use mps_interpreter::MpsItem;
@ -21,7 +21,6 @@ pub struct SystemControlWrapper {
dbus_ctrl: Option<Sender<DbusControl>>,
playback_event_handler: Option<JoinHandle<()>>,
playback_event_handler_killer: Option<Sender<()>>,
}
/// OS-specific APIs for media controls.
@ -135,27 +134,25 @@ impl SystemControlWrapper {
loop {
dbus_conn.poll(5);
match dbus_ctrl.try_recv() {
Err(_) => {},
Err(_) => {}
Ok(DbusControl::Die) => break,
Ok(DbusControl::SetMetadata(meta)) => {
dbus_conn.set_metadata(meta);
},
}
}
}
}));
let (tx, rx) = channel();
self.playback_event_handler_killer = Some(tx);
self.playback_event_handler = Some(std::thread::spawn(move || {
loop {
if let Ok(_) = rx.try_recv() {
break;
}
match playback.recv() {
Err(_) => break,
Ok(PlaybackAction::Exit) => break,
Ok(PlaybackAction::Enqueued(item)) => Self::enqueued(item, &dbus_ctrl_tx_clone),
Ok(PlaybackAction::Empty) => Self::empty(&dbus_ctrl_tx_clone),
}
self.playback_event_handler = Some(std::thread::spawn(move || loop {
if let Ok(_) = rx.try_recv() {
break;
}
match playback.recv() {
Err(_) => break,
Ok(PlaybackAction::Exit) => break,
Ok(PlaybackAction::Enqueued(item)) => Self::enqueued(item, &dbus_ctrl_tx_clone),
Ok(PlaybackAction::Empty) => Self::empty(&dbus_ctrl_tx_clone),
}
}));
}
@ -179,35 +176,48 @@ impl SystemControlWrapper {
fn enqueued(item: MpsItem, dbus_ctrl: &Sender<DbusControl>) {
//println!("Got enqueued item {}", &item.title);
dbus_ctrl.send(DbusControl::SetMetadata(Metadata {
length: None,
art_url: None,
album: item.field("album").and_then(|x| x.to_owned().to_str()),
album_artist: None, // TODO maybe?
artist: item.field("artist").and_then(|x| x.to_owned().to_str()).map(|x| vec![x]),
composer: None,
disc_number: None,
genre: item.field("genre").and_then(|x| x.to_owned().to_str()).map(|genre| vec![genre]),
title: item.field("title").and_then(|x| x.to_owned().to_str()),
track_number: item.field("track").and_then(|x| x.to_owned().to_i64()).map(|track| track as i32),
url: item.field("filename").and_then(|x| x.to_owned().to_str()),
})).unwrap_or(());
dbus_ctrl
.send(DbusControl::SetMetadata(Metadata {
length: None,
art_url: None,
album: item.field("album").and_then(|x| x.to_owned().to_str()),
album_artist: None, // TODO maybe?
artist: item
.field("artist")
.and_then(|x| x.to_owned().to_str())
.map(|x| vec![x]),
composer: None,
disc_number: None,
genre: item
.field("genre")
.and_then(|x| x.to_owned().to_str())
.map(|genre| vec![genre]),
title: item.field("title").and_then(|x| x.to_owned().to_str()),
track_number: item
.field("track")
.and_then(|x| x.to_owned().to_i64())
.map(|track| track as i32),
url: item.field("filename").and_then(|x| x.to_owned().to_str()),
}))
.unwrap_or(());
}
fn empty(dbus_ctrl: &Sender<DbusControl>) {
dbus_ctrl.send(DbusControl::SetMetadata(Metadata {
length: None,
art_url: None,
album: None,
album_artist: None, // TODO maybe?
artist: None,
composer: None,
disc_number: None,
genre: None,
title: None,
track_number: None,
url: None,
})).unwrap_or(());
dbus_ctrl
.send(DbusControl::SetMetadata(Metadata {
length: None,
art_url: None,
album: None,
album_artist: None, // TODO maybe?
artist: None,
composer: None,
disc_number: None,
genre: None,
title: None,
track_number: None,
url: None,
}))
.unwrap_or(());
}
}
@ -216,7 +226,7 @@ impl SystemControlWrapper {
pub fn new(control: Sender<ControlAction>) -> Self {
Self {
control: control,
playback_receiver: None
playback_receiver: None,
}
}

View file

@ -5,7 +5,7 @@ use rodio::{decoder::Decoder, OutputStream, OutputStreamHandle, Sink};
use m3u8_rs::{MediaPlaylist, MediaSegment};
use mps_interpreter::{tokens::MpsTokenReader, MpsRunner, MpsItem};
use mps_interpreter::{tokens::MpsTokenReader, MpsItem, MpsRunner};
use super::PlaybackError;
@ -36,14 +36,18 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
self.sink.sleep_until_end();
match item {
Ok(music) => {
if let Some(filename) = music.field("filename").and_then(|x| x.to_owned().to_str()) {
if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str())
{
let file = fs::File::open(filename).map_err(PlaybackError::from_err)?;
let stream = io::BufReader::new(file);
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?;
self.sink.append(source);
Ok(())
} else {
Err(PlaybackError::from_err("Field `filename` does not exist on item"))
Err(PlaybackError::from_err(
"Field `filename` does not exist on item",
))
}
}
Err(e) => Err(PlaybackError::from_err(e)),
@ -59,14 +63,18 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
match item {
Ok(music) => {
enqueued.push(music.clone());
if let Some(filename) = music.field("filename").and_then(|x| x.to_owned().to_str()) {
if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str())
{
let file = fs::File::open(filename).map_err(PlaybackError::from_err)?;
let stream = io::BufReader::new(file);
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?;
self.sink.append(source);
Ok(())
} else {
Err(PlaybackError::from_err("Field `filename` does not exist on item"))
Err(PlaybackError::from_err(
"Field `filename` does not exist on item",
))
}
}
Err(e) => Err(PlaybackError::from_err(e)),
@ -85,14 +93,18 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
match item {
Ok(music) => {
enqueued.push(music.clone());
if let Some(filename) = music.field("filename").and_then(|x| x.to_owned().to_str()) {
if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str())
{
let file = fs::File::open(filename).map_err(PlaybackError::from_err)?;
let stream = io::BufReader::new(file);
let source = Decoder::new(stream).map_err(PlaybackError::from_err)?;
self.sink.append(source);
Ok(())
} else {
Err(PlaybackError::from_err("Field `filename` does not exist on item"))
Err(PlaybackError::from_err(
"Field `filename` does not exist on item",
))
}
}
Err(e) => Err(PlaybackError::from_err(e)),
@ -139,7 +151,9 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
for item in &mut self.runner {
match item {
Ok(music) => {
if let Some(filename) = music.field("filename").and_then(|x| x.to_owned().to_str()) {
if let Some(filename) =
music.field("filename").and_then(|x| x.to_owned().to_str())
{
playlist.segments.push(MediaSegment {
uri: filename,
title: music.field("title").and_then(|x| x.to_owned().to_str()),
@ -147,7 +161,9 @@ impl<T: MpsTokenReader> MpsPlayer<T> {
});
Ok(())
} else {
Err(PlaybackError::from_err("Field `filename` does not exist on item"))
Err(PlaybackError::from_err(
"Field `filename` does not exist on item",
))
}
}
Err(e) => Err(PlaybackError::from_err(e)),

View file

@ -40,9 +40,12 @@ impl<T: MpsTokenReader> MpsPlayerServer<T> {
//println!("Enqueuing up to {} items", count);
match self.player.enqueue(count) {
Err(e) => self.event.send(PlayerAction::Exception(e)).unwrap(),
Ok(items) => for item in items { // notify of new items that have been enqueued
self.playback.send(PlaybackAction::Enqueued(item)).unwrap();
},
Ok(items) => {
for item in items {
// notify of new items that have been enqueued
self.playback.send(PlaybackAction::Enqueued(item)).unwrap();
}
}
}
}

View file

@ -56,7 +56,7 @@ pub fn repl(args: CliArgs) {
while let Err(e) = player.save_m3u8(&mut playlist_writer) {
eprintln!("{}", e.message());
}
},
}
}
playlist_writer
.flush()
@ -111,7 +111,7 @@ fn read_loop<F: FnMut()>(args: &CliArgs, state: &mut ReplState, mut execute: F)
} else {
state.in_literal = Some(read_buf[0] as char);
}
},
}
'(' => state.bracket_depth += 1,
')' => state.bracket_depth -= 1,
';' => {
@ -123,7 +123,7 @@ fn read_loop<F: FnMut()>(args: &CliArgs, state: &mut ReplState, mut execute: F)
execute();
state.statement_buf.clear();
}
},
}
'\n' => {
let statement_result = std::str::from_utf8(state.statement_buf.as_slice());
if statement_result.is_ok() && statement_result.unwrap().trim().starts_with("?") {
@ -140,8 +140,8 @@ fn read_loop<F: FnMut()>(args: &CliArgs, state: &mut ReplState, mut execute: F)
state.statement_buf.clear();
}
prompt(&mut state.line_number, args);
},
_ => {},
}
_ => {}
}
}
}