circomspect_program_structure/program_library/
program_merger.rs

1use super::ast::Definition;
2use super::report_code::ReportCode;
3use super::report::Report;
4use super::file_definition::FileID;
5use super::function_data::{FunctionData, FunctionInfo};
6use super::template_data::{TemplateData, TemplateInfo};
7
8#[derive(Default)]
9pub struct Merger {
10    fresh_id: usize,
11    function_info: FunctionInfo,
12    template_info: TemplateInfo,
13}
14
15impl Merger {
16    pub fn new() -> Merger {
17        Merger::default()
18    }
19
20    pub fn add_definitions(
21        &mut self,
22        file_id: FileID,
23        definitions: &Vec<Definition>,
24    ) -> Result<(), Vec<Report>> {
25        let mut reports = vec![];
26        for definition in definitions {
27            let (name, meta) = match definition {
28                Definition::Template {
29                    name,
30                    args,
31                    arg_location,
32                    body,
33                    meta,
34                    parallel,
35                    is_custom_gate,
36                } => {
37                    if self.contains_function(name) || self.contains_template(name) {
38                        (Option::Some(name), meta)
39                    } else {
40                        let new_data = TemplateData::new(
41                            name.clone(),
42                            file_id,
43                            body.clone(),
44                            args.len(),
45                            args.clone(),
46                            arg_location.clone(),
47                            &mut self.fresh_id,
48                            *parallel,
49                            *is_custom_gate,
50                        );
51                        self.get_mut_template_info().insert(name.clone(), new_data);
52                        (Option::None, meta)
53                    }
54                }
55                Definition::Function { name, body, args, arg_location, meta } => {
56                    if self.contains_function(name) || self.contains_template(name) {
57                        (Option::Some(name), meta)
58                    } else {
59                        let new_data = FunctionData::new(
60                            name.clone(),
61                            file_id,
62                            body.clone(),
63                            args.len(),
64                            args.clone(),
65                            arg_location.clone(),
66                            &mut self.fresh_id,
67                        );
68                        self.get_mut_function_info().insert(name.clone(), new_data);
69                        (Option::None, meta)
70                    }
71                }
72            };
73            if let Option::Some(definition_name) = name {
74                let mut report = Report::error(
75                    String::from("Duplicated function or template."),
76                    ReportCode::SameSymbolDeclaredTwice,
77                );
78                report.add_primary(
79                    meta.file_location(),
80                    file_id,
81                    format!("The name `{definition_name}` is already used."),
82                );
83                reports.push(report);
84            }
85        }
86        if reports.is_empty() {
87            Ok(())
88        } else {
89            Err(reports)
90        }
91    }
92    pub fn contains_function(&self, function_name: &str) -> bool {
93        self.get_function_info().contains_key(function_name)
94    }
95    fn get_function_info(&self) -> &FunctionInfo {
96        &self.function_info
97    }
98    fn get_mut_function_info(&mut self) -> &mut FunctionInfo {
99        &mut self.function_info
100    }
101
102    pub fn contains_template(&self, template_name: &str) -> bool {
103        self.get_template_info().contains_key(template_name)
104    }
105    fn get_template_info(&self) -> &TemplateInfo {
106        &self.template_info
107    }
108    fn get_mut_template_info(&mut self) -> &mut TemplateInfo {
109        &mut self.template_info
110    }
111
112    pub fn decompose(self) -> (usize, FunctionInfo, TemplateInfo) {
113        (self.fresh_id, self.function_info, self.template_info)
114    }
115}