diff --git a/mps-interpreter/src/interpretor.rs b/mps-interpreter/src/interpretor.rs index ab9815d..2276298 100644 --- a/mps-interpreter/src/interpretor.rs +++ b/mps-interpreter/src/interpretor.rs @@ -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) diff --git a/mps-interpreter/src/lang/filter.rs b/mps-interpreter/src/lang/filter.rs index 66b49ea..a92d34e 100644 --- a/mps-interpreter/src/lang/filter.rs +++ b/mps-interpreter/src/lang/filter.rs @@ -176,6 +176,18 @@ impl MpsOp for MpsFilterStatement

{ Ok(()) } } + + fn dup(&self) -> Box { + 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 Iterator for MpsFilterStatement

{ diff --git a/mps-interpreter/src/lang/filter_replace.rs b/mps-interpreter/src/lang/filter_replace.rs index 6a2f6b7..5c09300 100644 --- a/mps-interpreter/src/lang/filter_replace.rs +++ b/mps-interpreter/src/lang/filter_replace.rs @@ -139,6 +139,20 @@ impl MpsOp for MpsFilterReplaceStatement

{ }), } } + + fn dup(&self) -> Box { + 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 Iterator for MpsFilterReplaceStatement

{ diff --git a/mps-interpreter/src/lang/iter_block.rs b/mps-interpreter/src/lang/iter_block.rs index 3f8c2e4..7f16185 100644 --- a/mps-interpreter/src/lang/iter_block.rs +++ b/mps-interpreter/src/lang/iter_block.rs @@ -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 + 'static, Y: Deref + MpsIte #[derive(Debug)] pub struct MpsItemBlockStatement { - statements: Vec>, + statements: Vec>>, iterable: PseudoOp, // state last_item: Option, @@ -104,6 +105,19 @@ impl MpsOp for MpsItemBlockStatement { fn reset(&mut self) -> Result<(), RuntimeError> { self.iterable.try_real()?.reset() } + + fn dup(&self) -> Box { + /*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 { diff --git a/mps-interpreter/src/lang/operation.rs b/mps-interpreter/src/lang/operation.rs index 5b9cfc8..658bfb5 100644 --- a/mps-interpreter/src/lang/operation.rs +++ b/mps-interpreter/src/lang/operation.rs @@ -83,4 +83,7 @@ pub trait MpsOp: Iterator + 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; } diff --git a/mps-interpreter/src/lang/single_op.rs b/mps-interpreter/src/lang/single_op.rs index b686cd6..e9c8c4b 100644 --- a/mps-interpreter/src/lang/single_op.rs +++ b/mps-interpreter/src/lang/single_op.rs @@ -79,4 +79,12 @@ impl MpsOp for SingleItem { self.is_complete = false; Ok(()) } + + fn dup(&self) -> Box { + Box::new(Self { + context: None, + item: self.item.clone(), + is_complete: false, + }) + } } diff --git a/mps-interpreter/src/lang/sorter.rs b/mps-interpreter/src/lang/sorter.rs index 87deb72..2d3e0bf 100644 --- a/mps-interpreter/src/lang/sorter.rs +++ b/mps-interpreter/src/lang/sorter.rs @@ -78,6 +78,14 @@ impl MpsOp for MpsSortStatement { self.orderer.reset(); self.iterable.try_real()?.reset() } + + fn dup(&self) -> Box { + Box::new(Self { + orderer: self.orderer.clone(), + iterable: PseudoOp::from(self.iterable.try_real_ref().unwrap().dup()), + item_cache: VecDeque::new(), + }) + } } impl Iterator for MpsSortStatement { diff --git a/mps-interpreter/src/lang/vocabulary/comment.rs b/mps-interpreter/src/lang/vocabulary/comment.rs index 02984b9..fc21321 100644 --- a/mps-interpreter/src/lang/vocabulary/comment.rs +++ b/mps-interpreter/src/lang/vocabulary/comment.rs @@ -63,6 +63,10 @@ impl MpsOp for CommentStatement { fn escape(&mut self) -> MpsContext { self.context.take().unwrap() } + + fn dup(&self) -> Box { + Box::new(self.clone()) + } } pub struct CommentStatementFactory; diff --git a/mps-interpreter/src/lang/vocabulary/empty.rs b/mps-interpreter/src/lang/vocabulary/empty.rs index e278db7..5d02ff2 100644 --- a/mps-interpreter/src/lang/vocabulary/empty.rs +++ b/mps-interpreter/src/lang/vocabulary/empty.rs @@ -56,6 +56,10 @@ impl MpsOp for EmptyStatement { fn reset(&mut self) -> Result<(), RuntimeError> { Ok(()) } + + fn dup(&self) -> Box { + Box::new(self.clone()) + } } pub struct EmptyFunctionFactory; diff --git a/mps-interpreter/src/lang/vocabulary/files.rs b/mps-interpreter/src/lang/vocabulary/files.rs index dd0b82f..29664ac 100644 --- a/mps-interpreter/src/lang/vocabulary/files.rs +++ b/mps-interpreter/src/lang/vocabulary/files.rs @@ -120,6 +120,12 @@ impl MpsOp for FilesStatement { self.file_iter = None; Ok(()) } + + fn dup(&self) -> Box { + let mut clone = self.clone(); + clone.reset().unwrap(); + Box::new(clone) + } } pub struct FilesFunctionFactory; diff --git a/mps-interpreter/src/lang/vocabulary/intersection.rs b/mps-interpreter/src/lang/vocabulary/intersection.rs index 25b39bd..bc59acb 100644 --- a/mps-interpreter/src/lang/vocabulary/intersection.rs +++ b/mps-interpreter/src/lang/vocabulary/intersection.rs @@ -123,6 +123,20 @@ impl MpsOp for IntersectionStatement { } Ok(()) } + + fn dup(&self) -> Box { + 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; diff --git a/mps-interpreter/src/lang/vocabulary/item_ops/iter_op.rs b/mps-interpreter/src/lang/vocabulary/item_ops/iter_op.rs index 56c44d3..d337c63 100644 --- a/mps-interpreter/src/lang/vocabulary/item_ops/iter_op.rs +++ b/mps-interpreter/src/lang/vocabulary/item_ops/iter_op.rs @@ -30,7 +30,7 @@ impl Display for IterItemOp { impl MpsItemOp for IterItemOp { fn execute(&self, _context: &mut MpsContext) -> Result { - Ok(MpsType::Op(self.inner.duplicate().into())) + Ok(MpsType::Op(self.inner.dup().into())) } } diff --git a/mps-interpreter/src/lang/vocabulary/item_ops/mod.rs b/mps-interpreter/src/lang/vocabulary/item_ops/mod.rs index b9ba94f..4490909 100644 --- a/mps-interpreter/src/lang/vocabulary/item_ops/mod.rs +++ b/mps-interpreter/src/lang/vocabulary/item_ops/mod.rs @@ -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}; diff --git a/mps-interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs b/mps-interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs index 878e0da..a8a73c8 100644 --- a/mps-interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs +++ b/mps-interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs @@ -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())) } diff --git a/mps-interpreter/src/lang/vocabulary/repeat.rs b/mps-interpreter/src/lang/vocabulary/repeat.rs index 5c19e05..d9d2062 100644 --- a/mps-interpreter/src/lang/vocabulary/repeat.rs +++ b/mps-interpreter/src/lang/vocabulary/repeat.rs @@ -203,6 +203,21 @@ impl MpsOp for RepeatStatement { } Ok(()) } + + fn dup(&self) -> Box { + 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; diff --git a/mps-interpreter/src/lang/vocabulary/reset.rs b/mps-interpreter/src/lang/vocabulary/reset.rs index 0904a64..615c176 100644 --- a/mps-interpreter/src/lang/vocabulary/reset.rs +++ b/mps-interpreter/src/lang/vocabulary/reset.rs @@ -74,6 +74,14 @@ impl MpsOp for ResetStatement { self.has_tried = false; Ok(()) } + + fn dup(&self) -> Box { + Box::new(Self { + context: None, + inner: PseudoOp::from(self.inner.try_real_ref().unwrap().dup()), + has_tried: false, + }) + } } pub struct ResetFunctionFactory; diff --git a/mps-interpreter/src/lang/vocabulary/sql_init.rs b/mps-interpreter/src/lang/vocabulary/sql_init.rs index 9e7723b..b658631 100644 --- a/mps-interpreter/src/lang/vocabulary/sql_init.rs +++ b/mps-interpreter/src/lang/vocabulary/sql_init.rs @@ -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, params: HashMap, + 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 { + 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 { + Box::new(Self { + context: None, + params: self.params.clone(), + has_tried: false, + }) + } } pub struct SqlInitFunctionFactory; @@ -110,6 +132,7 @@ impl MpsFunctionFactory for SqlInitFunctionFactory { Ok(SqlInitStatement { context: None, params: HashMap::from_iter(params), + has_tried: false, }) } } diff --git a/mps-interpreter/src/lang/vocabulary/sql_query.rs b/mps-interpreter/src/lang/vocabulary/sql_query.rs index 70d6ffb..d021836 100644 --- a/mps-interpreter/src/lang/vocabulary/sql_query.rs +++ b/mps-interpreter/src/lang/vocabulary/sql_query.rs @@ -68,6 +68,15 @@ impl MpsOp for SqlStatement { self.current = 0; Ok(()) } + + fn dup(&self) -> Box { + Box::new(Self { + query: self.query.clone(), + context: None, + rows: None, + current: 0, + }) + } } impl std::clone::Clone for SqlStatement { diff --git a/mps-interpreter/src/lang/vocabulary/sql_simple_query.rs b/mps-interpreter/src/lang/vocabulary/sql_simple_query.rs index 2c0cbb4..93a6871 100644 --- a/mps-interpreter/src/lang/vocabulary/sql_simple_query.rs +++ b/mps-interpreter/src/lang/vocabulary/sql_simple_query.rs @@ -117,6 +117,16 @@ impl MpsOp for SimpleSqlStatement { self.current = 0; Ok(()) } + + fn dup(&self) -> Box { + Box::new(Self { + query: self.query.clone(), + mode: self.mode.clone(), + context: None, + rows: None, + current: 0, + }) + } } impl std::clone::Clone for SimpleSqlStatement { diff --git a/mps-interpreter/src/lang/vocabulary/union.rs b/mps-interpreter/src/lang/vocabulary/union.rs index 6e4266c..a2656c1 100644 --- a/mps-interpreter/src/lang/vocabulary/union.rs +++ b/mps-interpreter/src/lang/vocabulary/union.rs @@ -133,6 +133,19 @@ impl MpsOp for UnionStatement { } Ok(()) } + + fn dup(&self) -> Box { + 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; diff --git a/mps-interpreter/src/lang/vocabulary/variable_assign.rs b/mps-interpreter/src/lang/vocabulary/variable_assign.rs index f2d5cb5..b3f1875 100644 --- a/mps-interpreter/src/lang/vocabulary/variable_assign.rs +++ b/mps-interpreter/src/lang/vocabulary/variable_assign.rs @@ -136,6 +136,17 @@ impl MpsOp for AssignStatement { fn escape(&mut self) -> MpsContext { self.context.take().unwrap() } + + fn dup(&self) -> Box { + 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; diff --git a/mps-interpreter/tests/single_line.rs b/mps-interpreter/tests/single_line.rs index 6a64cf9..cce064e 100644 --- a/mps-interpreter/tests/single_line.rs +++ b/mps-interpreter/tests/single_line.rs @@ -709,13 +709,13 @@ fn execute_constructitemop_line() -> Result<(), Box> { ) } -/*#[test] +#[test] fn execute_iteritemop_line() -> Result<(), Box> { execute_single_line( "files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).{ item = iter empty() }", - false, + true, true, ) -}*/ +}