use super::{
annotation::Annotation,
dependency_graph::{DependencyGraph, PosNeg},
sem_act::SemAct,
};
use crate::{Expr, Pred, ShapeLabelIdx, ir::schema_ir::SchemaIR};
use itertools::Itertools;
use std::{collections::HashMap, fmt::Display};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Shape {
closed: bool,
extra: Vec<Pred>,
expr: Expr,
sem_acts: Vec<SemAct>,
annotations: Vec<Annotation>,
preds: Vec<Pred>,
extends: Vec<ShapeLabelIdx>,
}
impl Shape {
#[allow(clippy::too_many_arguments)]
pub fn new(
closed: bool,
extra: Vec<Pred>,
expr: Expr,
sem_acts: Vec<SemAct>,
annotations: Vec<Annotation>,
preds: Vec<Pred>,
extends: Vec<ShapeLabelIdx>,
) -> Self {
Shape {
closed,
extra,
expr,
sem_acts,
annotations,
preds,
extends,
}
}
pub fn extends(&self) -> &Vec<ShapeLabelIdx> {
&self.extends
}
pub fn preds(&self) -> Vec<Pred> {
self.preds.clone()
}
pub fn extra(&self) -> &Vec<Pred> {
&self.extra
}
pub fn references(&self, schema: &SchemaIR) -> HashMap<Pred, Vec<ShapeLabelIdx>> {
let mut result = self.get_value_expr_references();
for e in &self.extends {
let info = schema.find_shape_idx(e).unwrap();
let refs = info.expr().references(schema);
for (p, v) in refs {
result.entry(p).or_default().extend(v);
}
}
result
}
pub fn triple_expr(&self) -> &Expr {
&self.expr
}
pub fn is_closed(&self) -> bool {
self.closed
}
pub fn add_edges(&self, source: ShapeLabelIdx, graph: &mut DependencyGraph, pos_neg: PosNeg) {
for (_component, _pred, cond) in self.expr.components() {
match cond {
rbe::MatchCond::Single(_single_cond) => {},
rbe::MatchCond::And(_match_conds) => {},
rbe::MatchCond::Ref(r) => graph.add_edge(source, r, pos_neg),
}
}
}
fn get_value_expr_references(&self) -> HashMap<Pred, Vec<ShapeLabelIdx>> {
let mut result: HashMap<Pred, Vec<ShapeLabelIdx>> = HashMap::new();
for (_component, pred, cond) in self.expr.components() {
match cond {
rbe::MatchCond::Single(_single_cond) => {},
rbe::MatchCond::And(_match_conds) => {},
rbe::MatchCond::Ref(r) => {
result.entry(pred.clone()).or_default().push(r);
},
}
}
result
}
}
impl Display for Shape {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let extends = if self.extends.is_empty() {
"".to_string()
} else {
format!("EXTENDS [{}]", self.extends.iter().map(|e| e.to_string()).join(" "))
};
let closed = if self.closed { "CLOSED" } else { "" };
let extra = if self.extra.is_empty() {
"".to_string()
} else {
format!("EXTRA [{}]", self.extra.iter().join(" "))
};
let preds = if self.preds.is_empty() {
"".to_string()
} else {
self.preds.iter().join(",")
};
write!(f, "Shape {extends}{closed}{extra} ")?;
write!(f, "Preds: {preds}")?;
write!(f, ", TripleExpr: {}", self.expr)?;
Ok(())
}
}