in checker/src/call_graph.rs [903:990]
fn to_datalog(
&self,
backend: DatalogBackend,
ddlog_path: &Path,
type_map_path: &Path,
type_relations_path: Option<&Path>,
) {
let mut ctr: u32 = 0;
let mut used_types = HashSet::<TypeId>::new();
let mut output = DatalogOutput::new();
// Output dominance relations
self.graph.map(
|node_id1, node| {
if let Some(nodes) = self.dominance.get(&node.defid) {
for defid2 in nodes.iter() {
if let Some(node_id2) = self.get_node_by_defid(*defid2) {
output.add_relation(DatalogRelation::new_dom(
node_id1.index() as u32,
node_id2.index() as u32,
))
}
}
}
},
|_, _| (),
);
// Output edge and edge type relations
self.graph.map(
|_, _| (),
|edge_id, edge| {
if let Some((start_id, end_id)) = self.graph.edge_endpoints(edge_id) {
output.add_relation(DatalogRelation::new_edge(
ctr,
start_id.index() as u32,
end_id.index() as u32,
));
output.add_relation(DatalogRelation::new_edge_type(ctr, edge.type_id));
used_types.insert(edge.type_id);
ctr += 1;
}
},
);
// Output type relations
let mut index_to_type = HashMap::<TypeId, Box<str>>::new();
for (_, edge_type) in self.edge_types.iter() {
if used_types.contains(&edge_type.id) {
index_to_type.insert(edge_type.id, edge_type.name.to_owned());
}
}
let type_relations = self.gather_type_relations(&mut index_to_type, type_relations_path);
let mut type_to_index = HashMap::<Box<str>, TypeId>::new();
for (type_id, type_str) in index_to_type.iter() {
type_to_index.insert(type_str.to_owned(), *type_id);
}
for type_relation in type_relations.iter() {
if let Some(type_id1) = type_to_index.get(type_relation.type1.as_ref()) {
if let Some(type_id2) = type_to_index.get(type_relation.type2.as_ref()) {
match type_relation.kind {
TypeRelationKind::Eq => {
output.add_relation(DatalogRelation::new_eq_type(*type_id1, *type_id2))
}
TypeRelationKind::Member => {
output.add_relation(DatalogRelation::new_member(*type_id1, *type_id2))
}
}
}
}
}
// Output the Datalog operations in the format of the configured
// Datalog backend
let output_result = match backend {
DatalogBackend::DifferentialDatalog => output.to_differential_datalog(ddlog_path),
DatalogBackend::Souffle => output.to_souffle(ddlog_path),
};
match output_result {
Ok(_) => (),
Err(e) => panic!("Failed to write ddlog output: {:?}", e),
}
// Output the type map
match serde_json::to_string_pretty(&TypeMapOutput { map: index_to_type })
.map_err(|e| e.to_string())
.and_then(|type_map_output| {
fs::write(type_map_path, type_map_output).map_err(|e| e.to_string())
}) {
Ok(_) => (),
Err(e) => panic!("Failed to write type map output: {:?}", e),
};
}