Add iterable manipulations to blocks
This commit is contained in:
parent
3a2c2629ca
commit
a915cbd029
22 changed files with 188 additions and 12 deletions
|
@ -172,7 +172,7 @@ pub(crate) fn standard_vocab(vocabulary: &mut MpsLanguageDictionary) {
|
|||
.add(crate::lang::vocabulary::item_ops::VariableDeclareItemOpFactory)
|
||||
.add(crate::lang::vocabulary::item_ops::InterpolateStringItemOpFactory)
|
||||
.add(crate::lang::vocabulary::item_ops::BranchItemOpFactory)
|
||||
//.add(crate::lang::vocabulary::item_ops::IterItemOpFactory)
|
||||
.add(crate::lang::vocabulary::item_ops::IterItemOpFactory)
|
||||
.add(crate::lang::vocabulary::item_ops::ConstructorItemOpFactory)
|
||||
.add(crate::lang::vocabulary::item_ops::EmptyItemOpFactory)
|
||||
.add(crate::lang::vocabulary::item_ops::RemoveItemOpFactory)
|
||||
|
|
|
@ -176,6 +176,18 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterStatement<P> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
predicate: self.predicate.clone(),
|
||||
iterable: match &self.iterable {
|
||||
VariableOrOp::Variable(s) => VariableOrOp::Variable(s.clone()),
|
||||
VariableOrOp::Op(op) => VariableOrOp::Op(op.try_real_ref().unwrap().dup().into())
|
||||
},
|
||||
context: None,
|
||||
other_filters: self.other_filters.as_ref().map(|x| PseudoOp::from(x.try_real_ref().unwrap().dup())),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterStatement<P> {
|
||||
|
|
|
@ -139,6 +139,20 @@ impl<P: MpsFilterPredicate + 'static> MpsOp for MpsFilterReplaceStatement<P> {
|
|||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
predicate: self.predicate.clone(),
|
||||
iterable: match &self.iterable {
|
||||
VariableOrOp::Variable(s) => VariableOrOp::Variable(s.clone()),
|
||||
VariableOrOp::Op(op) => VariableOrOp::Op(op.try_real_ref().unwrap().dup().into())
|
||||
},
|
||||
context: None,
|
||||
op_if: PseudoOp::from(self.op_if.try_real_ref().unwrap().dup()),
|
||||
op_else: self.op_else.as_ref().map(|x| PseudoOp::from(x.try_real_ref().unwrap().dup())),
|
||||
item_cache: VecDeque::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MpsFilterPredicate + 'static> Iterator for MpsFilterReplaceStatement<P> {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::{Debug, Display, Error, Formatter};
|
||||
use std::iter::Iterator;
|
||||
|
@ -54,7 +55,7 @@ impl<X: MpsItemOpFactory<Y> + 'static, Y: Deref<Target = dyn MpsItemOp> + MpsIte
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct MpsItemBlockStatement {
|
||||
statements: Vec<Box<dyn MpsItemOp>>,
|
||||
statements: Vec<Arc<Box<dyn MpsItemOp>>>,
|
||||
iterable: PseudoOp,
|
||||
// state
|
||||
last_item: Option<PseudoOp>,
|
||||
|
@ -104,6 +105,19 @@ impl MpsOp for MpsItemBlockStatement {
|
|||
fn reset(&mut self) -> Result<(), RuntimeError> {
|
||||
self.iterable.try_real()?.reset()
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
/*let mut statements_clone = Vec::with_capacity(self.statements.len());
|
||||
for stmt in &self.statements {
|
||||
statements_clone.push(stmt.dup());
|
||||
}*/
|
||||
Box::new(Self {
|
||||
statements: self.statements.clone(),
|
||||
iterable: PseudoOp::from(self.iterable.try_real_ref().unwrap().dup()),
|
||||
// state
|
||||
last_item: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for MpsItemBlockStatement {
|
||||
|
@ -263,11 +277,11 @@ impl BoxedMpsOpFactory for MpsItemBlockFactory {
|
|||
while !tokens.is_empty() {
|
||||
if let Some(next_comma) = find_next_comma(tokens) {
|
||||
let end_tokens = tokens.split_off(next_comma);
|
||||
item_ops.push(self.try_build_item_statement(tokens, dict)?);
|
||||
item_ops.push(Arc::new(self.try_build_item_statement(tokens, dict)?));
|
||||
tokens.extend(end_tokens);
|
||||
assert_token_raw(MpsToken::Comma, tokens)?;
|
||||
} else {
|
||||
item_ops.push(self.try_build_item_statement(tokens, dict)?);
|
||||
item_ops.push(Arc::new(self.try_build_item_statement(tokens, dict)?));
|
||||
}
|
||||
}
|
||||
Ok(Box::new(MpsItemBlockStatement {
|
||||
|
|
|
@ -83,4 +83,7 @@ pub trait MpsOp: Iterator<Item = MpsIteratorItem> + Debug + Display {
|
|||
msg: "Op does not support reset()".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
// create an already-reset boxed clone of the op (without context)
|
||||
fn dup(&self) -> Box<dyn MpsOp>;
|
||||
}
|
||||
|
|
|
@ -79,4 +79,12 @@ impl MpsOp for SingleItem {
|
|||
self.is_complete = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
context: None,
|
||||
item: self.item.clone(),
|
||||
is_complete: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,14 @@ impl<S: MpsSorter + 'static> MpsOp for MpsSortStatement<S> {
|
|||
self.orderer.reset();
|
||||
self.iterable.try_real()?.reset()
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
orderer: self.orderer.clone(),
|
||||
iterable: PseudoOp::from(self.iterable.try_real_ref().unwrap().dup()),
|
||||
item_cache: VecDeque::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: MpsSorter + 'static> Iterator for MpsSortStatement<S> {
|
||||
|
|
|
@ -63,6 +63,10 @@ impl MpsOp for CommentStatement {
|
|||
fn escape(&mut self) -> MpsContext {
|
||||
self.context.take().unwrap()
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommentStatementFactory;
|
||||
|
|
|
@ -56,6 +56,10 @@ impl MpsOp for EmptyStatement {
|
|||
fn reset(&mut self) -> Result<(), RuntimeError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EmptyFunctionFactory;
|
||||
|
|
|
@ -120,6 +120,12 @@ impl MpsOp for FilesStatement {
|
|||
self.file_iter = None;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
let mut clone = self.clone();
|
||||
clone.reset().unwrap();
|
||||
Box::new(clone)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilesFunctionFactory;
|
||||
|
|
|
@ -123,6 +123,20 @@ impl MpsOp for IntersectionStatement {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
let mut clone = Self {
|
||||
context: None,
|
||||
ops: Vec::with_capacity(self.ops.len()),
|
||||
items: None,
|
||||
original_order: None,
|
||||
init_needed: true,
|
||||
};
|
||||
for op in self.ops.iter() {
|
||||
clone.ops.push(PseudoOp::from(op.try_real_ref().unwrap().dup()));
|
||||
}
|
||||
Box::new(clone)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntersectionFunctionFactory;
|
||||
|
|
|
@ -30,7 +30,7 @@ impl Display for IterItemOp {
|
|||
|
||||
impl MpsItemOp for IterItemOp {
|
||||
fn execute(&self, _context: &mut MpsContext) -> Result<MpsType, RuntimeMsg> {
|
||||
Ok(MpsType::Op(self.inner.duplicate().into()))
|
||||
Ok(MpsType::Op(self.inner.dup().into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ mod constant;
|
|||
mod constructor;
|
||||
mod empty;
|
||||
mod field_assign;
|
||||
//mod iter_op;
|
||||
mod iter_op;
|
||||
mod logical_and;
|
||||
mod logical_or;
|
||||
mod negate;
|
||||
|
@ -26,7 +26,7 @@ pub use compare::{CompareItemOpFactory, CompareItemOp};
|
|||
pub use constructor::{ConstructorItemOpFactory, ConstructorItemOp};
|
||||
pub use empty::{EmptyItemOpFactory, EmptyItemOp};
|
||||
pub use field_assign::{FieldAssignItemOpFactory, FieldAssignItemOp};
|
||||
//pub use iter_op::{IterItemOpFactory, IterItemOp};
|
||||
pub use iter_op::{IterItemOpFactory, IterItemOp};
|
||||
pub use logical_and::{AndItemOpFactory, AndItemOp};
|
||||
pub use logical_or::{OrItemOpFactory, OrItemOp};
|
||||
pub use negate::{NegateItemOpFactory, NegateItemOp};
|
||||
|
|
|
@ -48,7 +48,7 @@ impl MpsItemOp for VariableRetrieveItemOp {
|
|||
}
|
||||
} else {
|
||||
match var {
|
||||
MpsType::Op(op) => Err(RuntimeMsg(format!("Cannot clone op-type `{}` variable `{}`", op, self.variable_name))),
|
||||
MpsType::Op(op) => Ok(MpsType::Op(op.dup())),
|
||||
MpsType::Primitive(x) => Ok(MpsType::Primitive(x.clone())),
|
||||
MpsType::Item(item) => Ok(MpsType::Item(item.clone()))
|
||||
}
|
||||
|
|
|
@ -203,6 +203,21 @@ impl MpsOp for RepeatStatement {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
let clone = Self {
|
||||
inner_statement: PseudoOp::from(self.inner_statement.try_real_ref().unwrap().dup()),
|
||||
inner_done: self.original_repetitions == 0,
|
||||
context: None,
|
||||
cache: Vec::new(),
|
||||
cache_position: 0,
|
||||
repetitions: if self.original_repetitions != 0 {self.original_repetitions-1} else {0},
|
||||
loop_forever: self.loop_forever,
|
||||
original_repetitions: self.original_repetitions,
|
||||
};
|
||||
//clone.reset().unwrap();
|
||||
Box::new(clone)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RepeatFunctionFactory;
|
||||
|
|
|
@ -74,6 +74,14 @@ impl MpsOp for ResetStatement {
|
|||
self.has_tried = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
context: None,
|
||||
inner: PseudoOp::from(self.inner.try_real_ref().unwrap().dup()),
|
||||
has_tried: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResetFunctionFactory;
|
||||
|
|
|
@ -10,12 +10,13 @@ use crate::lang::repeated_tokens;
|
|||
use crate::lang::utility::{assert_token, assert_token_raw};
|
||||
use crate::lang::MpsLanguageDictionary;
|
||||
use crate::lang::{MpsFunctionFactory, MpsFunctionStatementFactory, MpsIteratorItem, MpsOp};
|
||||
use crate::lang::{PseudoOp, RuntimeOp, SyntaxError};
|
||||
use crate::lang::{PseudoOp, RuntimeOp, SyntaxError, RuntimeError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SqlInitStatement {
|
||||
context: Option<MpsContext>,
|
||||
params: HashMap<String, String>,
|
||||
has_tried: bool,
|
||||
}
|
||||
|
||||
impl Display for SqlInitStatement {
|
||||
|
@ -33,6 +34,7 @@ impl std::clone::Clone for SqlInitStatement {
|
|||
Self {
|
||||
context: None,
|
||||
params: HashMap::new(),
|
||||
has_tried: self.has_tried,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +43,9 @@ impl Iterator for SqlInitStatement {
|
|||
type Item = MpsIteratorItem;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.has_tried {
|
||||
return None;
|
||||
}
|
||||
// execute
|
||||
match self
|
||||
.context
|
||||
|
@ -67,6 +72,23 @@ impl MpsOp for SqlInitStatement {
|
|||
fn escape(&mut self) -> MpsContext {
|
||||
self.context.take().unwrap()
|
||||
}
|
||||
|
||||
fn is_resetable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> Result<(), RuntimeError> {
|
||||
self.has_tried = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
context: None,
|
||||
params: self.params.clone(),
|
||||
has_tried: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SqlInitFunctionFactory;
|
||||
|
@ -110,6 +132,7 @@ impl MpsFunctionFactory<SqlInitStatement> for SqlInitFunctionFactory {
|
|||
Ok(SqlInitStatement {
|
||||
context: None,
|
||||
params: HashMap::from_iter(params),
|
||||
has_tried: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,15 @@ impl MpsOp for SqlStatement {
|
|||
self.current = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
query: self.query.clone(),
|
||||
context: None,
|
||||
rows: None,
|
||||
current: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::clone::Clone for SqlStatement {
|
||||
|
|
|
@ -117,6 +117,16 @@ impl MpsOp for SimpleSqlStatement {
|
|||
self.current = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
query: self.query.clone(),
|
||||
mode: self.mode.clone(),
|
||||
context: None,
|
||||
rows: None,
|
||||
current: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::clone::Clone for SimpleSqlStatement {
|
||||
|
|
|
@ -133,6 +133,19 @@ impl MpsOp for UnionStatement {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
let mut ops_clone = Vec::with_capacity(self.ops.len());
|
||||
for op in self.ops.iter() {
|
||||
ops_clone.push(PseudoOp::from(op.try_real_ref().unwrap().dup()))
|
||||
}
|
||||
Box::new(Self {
|
||||
context: None,
|
||||
ops: ops_clone,
|
||||
strategy: self.strategy,
|
||||
index: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnionFunctionFactory;
|
||||
|
|
|
@ -136,6 +136,17 @@ impl MpsOp for AssignStatement {
|
|||
fn escape(&mut self) -> MpsContext {
|
||||
self.context.take().unwrap()
|
||||
}
|
||||
|
||||
fn dup(&self) -> Box<dyn MpsOp> {
|
||||
Box::new(Self {
|
||||
variable_name: self.variable_name.clone(),
|
||||
inner_statement: self.inner_statement.as_ref().map(|x| PseudoOp::from(x.try_real_ref().unwrap().dup())),
|
||||
assign_type: self.assign_type.clone(),
|
||||
context: None,
|
||||
is_declaration: self.is_declaration,
|
||||
is_simple: self.is_simple,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AssignStatementFactory;
|
||||
|
|
|
@ -709,13 +709,13 @@ fn execute_constructitemop_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
|||
)
|
||||
}
|
||||
|
||||
/*#[test]
|
||||
#[test]
|
||||
fn execute_iteritemop_line() -> Result<(), Box<dyn MpsLanguageError>> {
|
||||
execute_single_line(
|
||||
"files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).{
|
||||
item = iter empty()
|
||||
}",
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}*/
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue