Refactor filter op

This commit is contained in:
NGnius (Graham) 2022-10-31 23:51:35 -04:00
parent 6897041772
commit 8910d9df18
2 changed files with 87 additions and 207 deletions

View file

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

View file

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