ok/jj
1
0
Fork 0
forked from mirrors/jj

revset: update doc of filter transformation, apply minor style change

The doc comment summarizes what I'm going to implement. I'm not sure if
we'll add all of them because revset evaluation isn't the key performance
bottleneck at the moment. Anyway, I don't think any of these ideas would
logically conflict with segmented changelog adaptation unless we decide to
replace the whole revset stack with Eden/Sapling's.
This commit is contained in:
Yuya Nishihara 2022-12-03 13:19:32 +09:00
parent ec6f2cf393
commit 48d426529c

View file

@ -1166,11 +1166,17 @@ fn transform_expression_bottom_up(
transform_rec(expression, &mut f) transform_rec(expression, &mut f)
} }
/// Transforms intersection of filter expressions. The resulting tree may /// Transforms filter expressions, by applying the following rules.
/// contain redundant intersections like `all() & e`. ///
fn internalize_filter_intersection( /// a. Moves as many sets to filter candidates as possible, to minimize the
expression: &Rc<RevsetExpression>, /// filter inputs.
) -> Option<Rc<RevsetExpression>> { /// b. TODO: Rewrites set operations to and/or/not of predicates, to
/// help further optimization (e.g. combine `file(_)` matchers.)
/// c. TODO: Wraps union of filter and set (e.g. `author(_) | heads()`), to
/// ensure inner filter wouldn't need to evaluate all the input sets.
///
/// The resulting tree may contain redundant intersections like `all() & e`.
fn internalize_filter(expression: &Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>> {
// Since both sides must have already been "internalize"d, we don't need to // Since both sides must have already been "internalize"d, we don't need to
// apply the whole bottom-up pass to new intersection node. Instead, just push // apply the whole bottom-up pass to new intersection node. Instead, just push
// new 'c & g(d)' down to 'g(c & d)' while either side is a filter node. // new 'c & g(d)' down to 'g(c & d)' while either side is a filter node.
@ -1209,17 +1215,16 @@ fn internalize_filter_intersection(
// so that a filter node can be found as a direct child of an intersection node. // so that a filter node can be found as a direct child of an intersection node.
// However, the rewritten intersection node 'c & e' can also be a rewrite target // However, the rewritten intersection node 'c & e' can also be a rewrite target
// if 'e' is a filter node. That's why intersect_down() is also recursive. // if 'e' is a filter node. That's why intersect_down() is also recursive.
transform_expression_bottom_up(expression, |expression| { transform_expression_bottom_up(expression, |expression| match expression.as_ref() {
if let RevsetExpression::Intersection(expression1, expression2) = expression.as_ref() { RevsetExpression::Intersection(expression1, expression2) => {
match (expression1.as_ref(), expression2.as_ref()) { match (expression1.as_ref(), expression2.as_ref()) {
(_, RevsetExpression::Filter { .. }) | (RevsetExpression::Filter { .. }, _) => { (_, RevsetExpression::Filter { .. }) | (RevsetExpression::Filter { .. }, _) => {
Some(intersect_down(expression1, expression2)) Some(intersect_down(expression1, expression2))
} }
_ => None, // don't recreate identical node _ => None, // don't recreate identical node
} }
} else {
None
} }
_ => None,
}) })
} }
@ -1262,7 +1267,7 @@ fn fold_difference(expression: &Rc<RevsetExpression>) -> Option<Rc<RevsetExpress
/// Rewrites the given `expression` tree to reduce evaluation cost. Returns new /// Rewrites the given `expression` tree to reduce evaluation cost. Returns new
/// tree. /// tree.
pub fn optimize(expression: Rc<RevsetExpression>) -> Rc<RevsetExpression> { pub fn optimize(expression: Rc<RevsetExpression>) -> Rc<RevsetExpression> {
let expression = internalize_filter_intersection(&expression).unwrap_or(expression); let expression = internalize_filter(&expression).unwrap_or(expression);
let expression = fold_redundant_expression(&expression).unwrap_or(expression); let expression = fold_redundant_expression(&expression).unwrap_or(expression);
fold_difference(&expression).unwrap_or(expression) fold_difference(&expression).unwrap_or(expression)
} }