shex_ast/ir/
shape_expr.rs

1use super::{
2    dependency_graph::{DependencyGraph, PosNeg},
3    node_constraint::NodeConstraint,
4    shape::Shape,
5};
6use crate::{Pred, ShapeLabelIdx};
7use std::{collections::HashMap, fmt::Display};
8
9#[derive(Debug, PartialEq, Clone)]
10pub enum ShapeExpr {
11    ShapeOr {
12        exprs: Vec<ShapeExpr>,
13        display: String,
14    },
15    ShapeAnd {
16        exprs: Vec<ShapeExpr>,
17        display: String,
18    },
19    ShapeNot {
20        expr: Box<ShapeExpr>,
21        display: String,
22    },
23    NodeConstraint(NodeConstraint),
24    Shape(Shape),
25    External {},
26    Ref {
27        idx: ShapeLabelIdx,
28    },
29    Empty,
30}
31
32impl ShapeExpr {
33    pub fn mk_ref(idx: ShapeLabelIdx) -> ShapeExpr {
34        ShapeExpr::Ref { idx }
35    }
36
37    pub fn references(&self) -> HashMap<Pred, Vec<ShapeLabelIdx>> {
38        match self {
39            ShapeExpr::ShapeOr { exprs, .. } => {
40                exprs.iter().fold(HashMap::new(), |mut acc, expr| {
41                    let refs = expr.references();
42                    for (pred, idxs) in refs {
43                        acc.entry(pred).or_default().extend(idxs);
44                    }
45                    acc
46                })
47            }
48            ShapeExpr::ShapeAnd { exprs, .. } => {
49                exprs.iter().fold(HashMap::new(), |mut acc, expr| {
50                    let refs = expr.references();
51                    for (pred, idxs) in refs {
52                        acc.entry(pred).or_default().extend(idxs);
53                    }
54                    acc
55                })
56            }
57            ShapeExpr::ShapeNot { expr, .. } => expr.references(),
58            ShapeExpr::NodeConstraint(_nc) => HashMap::new(),
59            ShapeExpr::Shape(s) => s.references().clone(),
60            ShapeExpr::External {} => HashMap::new(),
61            ShapeExpr::Ref { idx } => {
62                let mut map = HashMap::new();
63                map.insert(Pred::default(), vec![*idx]);
64                map
65            }
66            ShapeExpr::Empty => HashMap::new(),
67        }
68    }
69
70    /// Adds PosNeg edges to the dependency graph.
71    pub(crate) fn add_edges(
72        &self,
73        source: ShapeLabelIdx,
74        graph: &mut DependencyGraph,
75        pos_neg: PosNeg,
76    ) {
77        match self {
78            ShapeExpr::ShapeOr { exprs, .. } => {
79                for expr in exprs {
80                    expr.add_edges(source, graph, pos_neg);
81                }
82            }
83            ShapeExpr::ShapeAnd { exprs, .. } => {
84                for expr in exprs {
85                    expr.add_edges(source, graph, pos_neg);
86                }
87            }
88            ShapeExpr::ShapeNot { expr, .. } => {
89                expr.add_edges(source, graph, pos_neg.change());
90            }
91            ShapeExpr::NodeConstraint(_) => {}
92            ShapeExpr::Shape(s) => s.add_edges(source, graph, pos_neg),
93            ShapeExpr::External {} => {}
94            ShapeExpr::Ref { idx } => {
95                graph.add_edge(source, *idx, pos_neg);
96            }
97            ShapeExpr::Empty => {}
98        }
99    }
100}
101
102impl Display for ShapeExpr {
103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104        match self {
105            ShapeExpr::ShapeOr { display, .. } => write!(f, "{display}"),
106            ShapeExpr::ShapeAnd { display, .. } => write!(f, "{display}"),
107            ShapeExpr::ShapeNot { display, .. } => write!(f, "{display}"),
108            ShapeExpr::NodeConstraint(nc) => write!(f, "{nc}"),
109            ShapeExpr::Shape(shape) => write!(f, "{shape}"),
110            ShapeExpr::External {} => write!(f, "External"),
111            ShapeExpr::Ref { idx } => write!(f, "Ref({idx})"),
112            ShapeExpr::Empty => write!(f, "<Empty>"),
113        }
114    }
115}