git_branchless_revset/
ast.rs

1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::fmt::Display;
4
5/// A node in the parsed AST.
6#[allow(missing_docs)]
7#[derive(Clone, Debug)]
8pub enum Expr<'input> {
9    Name(Cow<'input, str>),
10    FunctionCall(Cow<'input, str>, Vec<Expr<'input>>),
11}
12
13impl Display for Expr<'_> {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        match self {
16            Expr::Name(name) => write!(f, "{name}"),
17            Expr::FunctionCall(name, args) => {
18                write!(f, "{name}(")?;
19                for (i, arg) in args.iter().enumerate() {
20                    if i > 0 {
21                        write!(f, ", ")?;
22                    }
23                    write!(f, "{arg}")?;
24                }
25                write!(f, ")")
26            }
27        }
28    }
29}
30
31impl<'input> Expr<'input> {
32    /// Replace names in this expression with arbitrary expressions.
33    ///
34    /// Given a HashMap of names to Expr's, build a new Expr by crawling this
35    /// one and replacing any names contained in the map with the corresponding
36    /// Expr.
37    pub fn replace_names(&self, map: &HashMap<String, Expr<'input>>) -> Expr<'input> {
38        match self {
39            Expr::Name(name) => match map.get(&name.to_string()) {
40                Some(expr) => expr.clone(),
41                None => self.clone(),
42            },
43            Expr::FunctionCall(name, args) => {
44                let args = args.iter().map(|arg| arg.replace_names(map)).collect();
45                Expr::FunctionCall(name.clone(), args)
46            }
47        }
48    }
49}