Add iterable manipulations to blocks

This commit is contained in:
NGnius (Graham) 2022-02-20 12:04:56 -05:00
parent 3a2c2629ca
commit a915cbd029
22 changed files with 188 additions and 12 deletions

View file

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

View file

@ -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> {

View file

@ -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> {

View file

@ -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 {

View file

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

View file

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

View file

@ -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> {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 {

View file

@ -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 {

View file

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

View file

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

View file

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