shex_ast/ir/
shape_expr.rs1use 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 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}