Refactor filter op
This commit is contained in:
parent
6897041772
commit
8910d9df18
2 changed files with 87 additions and 207 deletions
|
@ -197,117 +197,19 @@ impl<P: FilterPredicate + 'static> Op for FilterStatement<P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
|
impl <P: FilterPredicate + 'static> FilterStatement<P> {
|
||||||
type Item = IteratorItem;
|
fn next_item(&mut self) -> Option<IteratorItem> {
|
||||||
|
let fake_op = PseudoOp::from_printable(self);
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if (self.predicate.is_complete() && self.other_filters.is_none()) || self.is_failing {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
//let self_clone = self.clone();
|
|
||||||
//let self_clone2 = self_clone.clone();
|
|
||||||
let fake = PseudoOp::Fake(format!("{}", self));
|
|
||||||
//let ctx = self.context.as_mut().unwrap();
|
|
||||||
match &mut self.iterable {
|
match &mut self.iterable {
|
||||||
VariableOrOp::Op(op) => match op.try_real() {
|
VariableOrOp::Op(op) => match op.try_real() {
|
||||||
Ok(real_op) => {
|
Ok(real_op) => {
|
||||||
let ctx = self.context.take().unwrap();
|
let ctx = self.context.take().unwrap();
|
||||||
real_op.enter(ctx);
|
real_op.enter(ctx);
|
||||||
let mut maybe_result = None;
|
let item = real_op.next();
|
||||||
while let Some(item) = real_op.next() {
|
|
||||||
let mut ctx = real_op.escape();
|
|
||||||
match item {
|
|
||||||
Err(e) => {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result = Some(Err(e));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(item) => {
|
|
||||||
let matches_result = self.predicate.matches(&item, &mut ctx);
|
|
||||||
let matches = match matches_result {
|
|
||||||
Err(e) => {
|
|
||||||
maybe_result = Some(Err(e.with(RuntimeOp(fake))));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(b) => b,
|
|
||||||
};
|
|
||||||
if let Some(inner) = &mut self.other_filters {
|
|
||||||
// handle other filters
|
|
||||||
// make fake inner item
|
|
||||||
let single_op = SingleItem::new_ok(item.clone());
|
|
||||||
match ctx
|
|
||||||
.variables
|
|
||||||
.declare(INNER_VARIABLE_NAME, Type::Op(Box::new(single_op)))
|
|
||||||
{
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(e) => {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result = Some(Err(e.with(RuntimeOp(fake))));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let inner_real = match inner.try_real() {
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(e) => {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
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) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => match maybe_result {
|
|
||||||
Some(Ok(_)) => {
|
|
||||||
maybe_result =
|
|
||||||
Some(Err(e.with(RuntimeOp(fake))))
|
|
||||||
}
|
|
||||||
Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error,
|
|
||||||
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) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result =
|
|
||||||
Some(Err(e.with(RuntimeOp(fake))));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if matches {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result = Some(Ok(item));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
real_op.enter(ctx);
|
|
||||||
}
|
|
||||||
if self.context.is_none() {
|
|
||||||
self.context = Some(real_op.escape());
|
self.context = Some(real_op.escape());
|
||||||
|
item
|
||||||
}
|
}
|
||||||
maybe_result
|
Err(e) => return Some(Err(e)),
|
||||||
}
|
|
||||||
Err(e) => Some(Err(e)),
|
|
||||||
},
|
},
|
||||||
VariableOrOp::Variable(variable_name) => {
|
VariableOrOp::Variable(variable_name) => {
|
||||||
let mut variable = match self
|
let mut variable = match self
|
||||||
|
@ -321,7 +223,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
return Some(Err(RuntimeError {
|
return Some(Err(RuntimeError {
|
||||||
line: 0,
|
line: 0,
|
||||||
op: fake,
|
op: fake_op,
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Expected operation/iterable type in variable {}, got {}",
|
"Expected operation/iterable type in variable {}, got {}",
|
||||||
&variable_name, x
|
&variable_name, x
|
||||||
|
@ -329,28 +231,47 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.is_failing = true; // this is unrecoverable and reproducible, so it shouldn't be tried again (to prevent error spam)
|
self.is_failing = true;
|
||||||
return Some(Err(e.with(RuntimeOp(fake))));
|
return Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self)))));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
let mut maybe_result = None;
|
|
||||||
let ctx = self.context.take().unwrap();
|
variable.enter(self.context.take().unwrap());
|
||||||
variable.enter(ctx);
|
let item = variable.next();
|
||||||
while let Some(item) = variable.next() {
|
self.context = Some(variable.escape());
|
||||||
let mut ctx = variable.escape();
|
if let Err(e) = self
|
||||||
match item {
|
.context
|
||||||
Err(e) => {
|
.as_mut()
|
||||||
maybe_result = Some(Err(e));
|
.unwrap()
|
||||||
self.context = Some(ctx);
|
.variables
|
||||||
break;
|
.declare(variable_name, Type::Op(variable))
|
||||||
|
{
|
||||||
|
return Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self)))));
|
||||||
}
|
}
|
||||||
|
item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
|
||||||
|
type Item = IteratorItem;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if (self.predicate.is_complete() && self.other_filters.is_none()) || self.is_failing {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
//let ctx = self.context.as_mut().unwrap();
|
||||||
|
while let Some(next_item) = self.next_item() {
|
||||||
|
match next_item {
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
let matches_result = self.predicate.matches(&item, &mut ctx);
|
//let ctx = self.context.as_mut().unwrap();
|
||||||
|
let matches_result = self.predicate.matches(&item, self.context.as_mut().unwrap());
|
||||||
let matches = match matches_result {
|
let matches = match matches_result {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
maybe_result = Some(Err(e.with(RuntimeOp(fake.clone()))));
|
//maybe_result = Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self)))));
|
||||||
self.context = Some(ctx);
|
//self.context = Some(ctx);
|
||||||
break;
|
return Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self)))));
|
||||||
}
|
}
|
||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
};
|
};
|
||||||
|
@ -358,85 +279,34 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
|
||||||
// handle other filters
|
// handle other filters
|
||||||
// make fake inner item
|
// make fake inner item
|
||||||
let single_op = SingleItem::new_ok(item.clone());
|
let single_op = SingleItem::new_ok(item.clone());
|
||||||
match ctx
|
let preexisting_var = self.context.as_mut().unwrap()
|
||||||
.variables
|
.variables
|
||||||
.declare(INNER_VARIABLE_NAME, Type::Op(Box::new(single_op)))
|
.swap(INNER_VARIABLE_NAME, Some(Type::Op(Box::new(single_op))));
|
||||||
{
|
|
||||||
Ok(x) => x,
|
|
||||||
Err(e) => {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result = Some(Err(e.with(RuntimeOp(fake.clone()))));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let inner_real = match inner.try_real() {
|
let inner_real = match inner.try_real() {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => {
|
Err(e) => return Some(Err(e))
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result = Some(Err(e));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
inner_real.enter(ctx);
|
inner_real.enter(self.context.take().unwrap());
|
||||||
match inner_real.next() {
|
match inner_real.next() {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
maybe_result = Some(item);
|
self.context = Some(inner_real.escape());
|
||||||
ctx = inner_real.escape();
|
self.context.as_mut().unwrap().variables.swap(INNER_VARIABLE_NAME, preexisting_var);
|
||||||
match ctx.variables.remove(INNER_VARIABLE_NAME) {
|
return Some(item);
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => match maybe_result {
|
|
||||||
Some(Ok(_)) => {
|
|
||||||
maybe_result =
|
|
||||||
Some(Err(e.with(RuntimeOp(fake.clone()))))
|
|
||||||
}
|
|
||||||
Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error,
|
|
||||||
None => {} // impossible
|
|
||||||
},
|
|
||||||
}
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
ctx = inner_real.escape(); // move ctx back to expected spot
|
self.context = Some(inner_real.escape()); // move ctx back to expected spot
|
||||||
match ctx.variables.remove(INNER_VARIABLE_NAME) {
|
self.context.as_mut().unwrap().variables.swap(INNER_VARIABLE_NAME, preexisting_var);
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
//self.context = Some(op.escape());
|
|
||||||
maybe_result =
|
|
||||||
Some(Err(e.with(RuntimeOp(fake.clone()))));
|
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matches {
|
if matches {
|
||||||
maybe_result = Some(Ok(item));
|
return Some(Ok(item));
|
||||||
self.context = Some(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
variable.enter(ctx);
|
|
||||||
}
|
|
||||||
if self.context.is_none() {
|
|
||||||
self.context = Some(variable.escape());
|
|
||||||
}
|
|
||||||
match self
|
|
||||||
.context
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.variables
|
|
||||||
.declare(variable_name, Type::Op(variable))
|
|
||||||
{
|
|
||||||
Err(e) => Some(Err(e.with(RuntimeOp(fake)))),
|
|
||||||
Ok(_) => maybe_result,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Err(e) => return Some(Err(e)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
|
|
@ -56,6 +56,8 @@ pub trait VariableStorer: Debug {
|
||||||
|
|
||||||
fn remove(&mut self, name: &str) -> Result<Type, RuntimeMsg>;
|
fn remove(&mut self, name: &str) -> Result<Type, RuntimeMsg>;
|
||||||
|
|
||||||
|
fn swap(&mut self, name: &str, value: Option<Type>) -> Option<Type>;
|
||||||
|
|
||||||
fn exists(&self, name: &str) -> bool {
|
fn exists(&self, name: &str) -> bool {
|
||||||
self.get_opt(name).is_some()
|
self.get_opt(name).is_some()
|
||||||
}
|
}
|
||||||
|
@ -99,6 +101,14 @@ impl VariableStorer for OpStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn swap(&mut self, key: &str, item: Option<Type>) -> Option<Type> {
|
||||||
|
if let Some(item) = item {
|
||||||
|
self.storage.insert(key.to_string(), item)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn remove(&mut self, key: &str) -> Result<Type, RuntimeMsg> {
|
fn remove(&mut self, key: &str) -> Result<Type, RuntimeMsg> {
|
||||||
if self.storage.contains_key(key) {
|
if self.storage.contains_key(key) {
|
||||||
Ok(self.storage.remove(key).unwrap())
|
Ok(self.storage.remove(key).unwrap())
|
||||||
|
|
Loading…
Reference in a new issue