circom_lsp_program_structure/program_library/
program_merger.rs1use 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}