forked from mirrors/jj
revset: add a Result version of transform_expression_bottom_up()
I'd like to add a stage after optimization for resolving most symbols to commit IDs, and that needs to be able to fail.
This commit is contained in:
parent
998727266c
commit
1711cb61fb
1 changed files with 42 additions and 30 deletions
|
@ -1047,29 +1047,37 @@ pub fn parse(
|
||||||
parse_program(revset_str, state)
|
parse_program(revset_str, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn transform_expression_bottom_up(
|
||||||
|
expression: &Rc<RevsetExpression>,
|
||||||
|
mut f: impl FnMut(&Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>>,
|
||||||
|
) -> Option<Rc<RevsetExpression>> {
|
||||||
|
try_transform_expression_bottom_up(expression, |expression| Ok(f(expression))).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransformResult = Result<Option<Rc<RevsetExpression>>, RevsetError>;
|
||||||
/// Walks `expression` tree and applies `f` recursively from leaf nodes.
|
/// Walks `expression` tree and applies `f` recursively from leaf nodes.
|
||||||
///
|
///
|
||||||
/// If `f` returns `None`, the original expression node is reused. If no nodes
|
/// If `f` returns `None`, the original expression node is reused. If no nodes
|
||||||
/// rewritten, returns `None`. `std::iter::successors()` could be used if
|
/// rewritten, returns `None`. `std::iter::successors()` could be used if
|
||||||
/// the transformation needs to be applied repeatedly until converged.
|
/// the transformation needs to be applied repeatedly until converged.
|
||||||
fn transform_expression_bottom_up(
|
fn try_transform_expression_bottom_up(
|
||||||
expression: &Rc<RevsetExpression>,
|
expression: &Rc<RevsetExpression>,
|
||||||
mut f: impl FnMut(&Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>>,
|
mut f: impl FnMut(&Rc<RevsetExpression>) -> TransformResult,
|
||||||
) -> Option<Rc<RevsetExpression>> {
|
) -> TransformResult {
|
||||||
fn transform_child_rec(
|
fn transform_child_rec(
|
||||||
expression: &Rc<RevsetExpression>,
|
expression: &Rc<RevsetExpression>,
|
||||||
f: &mut impl FnMut(&Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>>,
|
f: &mut impl FnMut(&Rc<RevsetExpression>) -> TransformResult,
|
||||||
) -> Option<Rc<RevsetExpression>> {
|
) -> TransformResult {
|
||||||
match expression.as_ref() {
|
Ok(match expression.as_ref() {
|
||||||
RevsetExpression::None => None,
|
RevsetExpression::None => None,
|
||||||
RevsetExpression::All => None,
|
RevsetExpression::All => None,
|
||||||
RevsetExpression::Commits(_) => None,
|
RevsetExpression::Commits(_) => None,
|
||||||
RevsetExpression::Symbol(_) => None,
|
RevsetExpression::Symbol(_) => None,
|
||||||
RevsetExpression::Children(roots) => {
|
RevsetExpression::Children(roots) => {
|
||||||
transform_rec(roots, f).map(RevsetExpression::Children)
|
transform_rec(roots, f)?.map(RevsetExpression::Children)
|
||||||
}
|
}
|
||||||
RevsetExpression::Ancestors { heads, generation } => {
|
RevsetExpression::Ancestors { heads, generation } => {
|
||||||
transform_rec(heads, f).map(|heads| RevsetExpression::Ancestors {
|
transform_rec(heads, f)?.map(|heads| RevsetExpression::Ancestors {
|
||||||
heads,
|
heads,
|
||||||
generation: generation.clone(),
|
generation: generation.clone(),
|
||||||
})
|
})
|
||||||
|
@ -1078,21 +1086,21 @@ fn transform_expression_bottom_up(
|
||||||
roots,
|
roots,
|
||||||
heads,
|
heads,
|
||||||
generation,
|
generation,
|
||||||
} => transform_rec_pair((roots, heads), f).map(|(roots, heads)| {
|
} => transform_rec_pair((roots, heads), f)?.map(|(roots, heads)| {
|
||||||
RevsetExpression::Range {
|
RevsetExpression::Range {
|
||||||
roots,
|
roots,
|
||||||
heads,
|
heads,
|
||||||
generation: generation.clone(),
|
generation: generation.clone(),
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
RevsetExpression::DagRange { roots, heads } => transform_rec_pair((roots, heads), f)
|
RevsetExpression::DagRange { roots, heads } => transform_rec_pair((roots, heads), f)?
|
||||||
.map(|(roots, heads)| RevsetExpression::DagRange { roots, heads }),
|
.map(|(roots, heads)| RevsetExpression::DagRange { roots, heads }),
|
||||||
RevsetExpression::VisibleHeads => None,
|
RevsetExpression::VisibleHeads => None,
|
||||||
RevsetExpression::Heads(candidates) => {
|
RevsetExpression::Heads(candidates) => {
|
||||||
transform_rec(candidates, f).map(RevsetExpression::Heads)
|
transform_rec(candidates, f)?.map(RevsetExpression::Heads)
|
||||||
}
|
}
|
||||||
RevsetExpression::Roots(candidates) => {
|
RevsetExpression::Roots(candidates) => {
|
||||||
transform_rec(candidates, f).map(RevsetExpression::Roots)
|
transform_rec(candidates, f)?.map(RevsetExpression::Roots)
|
||||||
}
|
}
|
||||||
RevsetExpression::PublicHeads => None,
|
RevsetExpression::PublicHeads => None,
|
||||||
RevsetExpression::Branches(_) => None,
|
RevsetExpression::Branches(_) => None,
|
||||||
|
@ -1102,58 +1110,62 @@ fn transform_expression_bottom_up(
|
||||||
RevsetExpression::GitHead => None,
|
RevsetExpression::GitHead => None,
|
||||||
RevsetExpression::Filter(_) => None,
|
RevsetExpression::Filter(_) => None,
|
||||||
RevsetExpression::AsFilter(candidates) => {
|
RevsetExpression::AsFilter(candidates) => {
|
||||||
transform_rec(candidates, f).map(RevsetExpression::AsFilter)
|
transform_rec(candidates, f)?.map(RevsetExpression::AsFilter)
|
||||||
}
|
}
|
||||||
RevsetExpression::Present(candidates) => {
|
RevsetExpression::Present(candidates) => {
|
||||||
transform_rec(candidates, f).map(RevsetExpression::Present)
|
transform_rec(candidates, f)?.map(RevsetExpression::Present)
|
||||||
}
|
}
|
||||||
RevsetExpression::NotIn(complement) => {
|
RevsetExpression::NotIn(complement) => {
|
||||||
transform_rec(complement, f).map(RevsetExpression::NotIn)
|
transform_rec(complement, f)?.map(RevsetExpression::NotIn)
|
||||||
}
|
}
|
||||||
RevsetExpression::Union(expression1, expression2) => {
|
RevsetExpression::Union(expression1, expression2) => {
|
||||||
transform_rec_pair((expression1, expression2), f).map(
|
transform_rec_pair((expression1, expression2), f)?.map(
|
||||||
|(expression1, expression2)| RevsetExpression::Union(expression1, expression2),
|
|(expression1, expression2)| RevsetExpression::Union(expression1, expression2),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
RevsetExpression::Intersection(expression1, expression2) => {
|
RevsetExpression::Intersection(expression1, expression2) => {
|
||||||
transform_rec_pair((expression1, expression2), f).map(
|
transform_rec_pair((expression1, expression2), f)?.map(
|
||||||
|(expression1, expression2)| {
|
|(expression1, expression2)| {
|
||||||
RevsetExpression::Intersection(expression1, expression2)
|
RevsetExpression::Intersection(expression1, expression2)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
RevsetExpression::Difference(expression1, expression2) => {
|
RevsetExpression::Difference(expression1, expression2) => {
|
||||||
transform_rec_pair((expression1, expression2), f).map(
|
transform_rec_pair((expression1, expression2), f)?.map(
|
||||||
|(expression1, expression2)| {
|
|(expression1, expression2)| {
|
||||||
RevsetExpression::Difference(expression1, expression2)
|
RevsetExpression::Difference(expression1, expression2)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map(Rc::new)
|
.map(Rc::new))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn transform_rec_pair(
|
fn transform_rec_pair(
|
||||||
(expression1, expression2): (&Rc<RevsetExpression>, &Rc<RevsetExpression>),
|
(expression1, expression2): (&Rc<RevsetExpression>, &Rc<RevsetExpression>),
|
||||||
f: &mut impl FnMut(&Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>>,
|
f: &mut impl FnMut(&Rc<RevsetExpression>) -> TransformResult,
|
||||||
) -> Option<(Rc<RevsetExpression>, Rc<RevsetExpression>)> {
|
) -> Result<Option<(Rc<RevsetExpression>, Rc<RevsetExpression>)>, RevsetError> {
|
||||||
match (transform_rec(expression1, f), transform_rec(expression2, f)) {
|
match (
|
||||||
|
transform_rec(expression1, f)?,
|
||||||
|
transform_rec(expression2, f)?,
|
||||||
|
) {
|
||||||
(Some(new_expression1), Some(new_expression2)) => {
|
(Some(new_expression1), Some(new_expression2)) => {
|
||||||
Some((new_expression1, new_expression2))
|
Ok(Some((new_expression1, new_expression2)))
|
||||||
}
|
}
|
||||||
(Some(new_expression1), None) => Some((new_expression1, expression2.clone())),
|
(Some(new_expression1), None) => Ok(Some((new_expression1, expression2.clone()))),
|
||||||
(None, Some(new_expression2)) => Some((expression1.clone(), new_expression2)),
|
(None, Some(new_expression2)) => Ok(Some((expression1.clone(), new_expression2))),
|
||||||
(None, None) => None,
|
(None, None) => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_rec(
|
fn transform_rec(
|
||||||
expression: &Rc<RevsetExpression>,
|
expression: &Rc<RevsetExpression>,
|
||||||
f: &mut impl FnMut(&Rc<RevsetExpression>) -> Option<Rc<RevsetExpression>>,
|
f: &mut impl FnMut(&Rc<RevsetExpression>) -> TransformResult,
|
||||||
) -> Option<Rc<RevsetExpression>> {
|
) -> TransformResult {
|
||||||
if let Some(new_expression) = transform_child_rec(expression, f) {
|
if let Some(new_expression) = transform_child_rec(expression, f)? {
|
||||||
// must propagate new expression tree
|
// must propagate new expression tree
|
||||||
Some(f(&new_expression).unwrap_or(new_expression))
|
Ok(Some(f(&new_expression)?.unwrap_or(new_expression)))
|
||||||
} else {
|
} else {
|
||||||
f(expression)
|
f(expression)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue