circom_lsp_program_structure/program_library/
program_merger.rs

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