fn to_datalog()

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),
        };
    }