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