1mod program_scope;
20pub use program_scope::*;
21
22use leo_errors::Result;
23use leo_span::Symbol;
24
25use crate::{Module, ProgramId, Stub};
26use indexmap::IndexMap;
27use serde::{Deserialize, Serialize};
28use std::fmt;
29#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
31pub struct Program {
32 pub modules: IndexMap<Vec<Symbol>, Module>,
34 pub imports: IndexMap<Symbol, ProgramId>,
36 pub stubs: IndexMap<Symbol, Stub>,
38 pub program_scopes: IndexMap<Symbol, ProgramScope>,
40}
41
42impl fmt::Display for Program {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 for (_, stub) in self.stubs.iter() {
45 writeln!(f, "{stub}")?;
46 }
47 for (_, module) in self.modules.iter() {
48 writeln!(f, "{module}")?;
49 }
50 for (_, import_id) in self.imports.iter() {
51 writeln!(f, "import {import_id};")?;
52 }
53 for (_, program_scope) in self.program_scopes.iter() {
54 writeln!(f, "{program_scope}")?;
55 }
56 Ok(())
57 }
58}
59
60impl Default for Program {
61 fn default() -> Self {
63 Self {
64 modules: IndexMap::new(),
65 imports: IndexMap::new(),
66 stubs: IndexMap::new(),
67 program_scopes: IndexMap::new(),
68 }
69 }
70}
71
72impl Program {
73 pub fn to_json_string(&self) -> Result<String> {
75 Ok(serde_json::to_string_pretty(&self).map_err(|e| crate::errors::failed_to_convert_ast_to_json_string(&e))?)
76 }
77
78 pub fn to_json_value(&self) -> Result<serde_json::Value> {
83 Ok(serde_json::to_value(self).map_err(|e| crate::errors::failed_to_convert_ast_to_json_value(&e))?)
84 }
85
86 pub fn to_json_file(&self, mut path: std::path::PathBuf, file_name: &str) -> Result<()> {
88 path.push(file_name);
89 let file =
90 std::fs::File::create(&path).map_err(|e| crate::errors::failed_to_create_ast_json_file(&path, &e))?;
91 let writer = std::io::BufWriter::new(file);
92 Ok(serde_json::to_writer_pretty(writer, &self)
93 .map_err(|e| crate::errors::failed_to_write_ast_to_json_file(&path, &e))?)
94 }
95
96 pub fn to_json_file_without_keys(
98 &self,
99 mut path: std::path::PathBuf,
100 file_name: &str,
101 excluded_keys: &[&str],
102 ) -> Result<()> {
103 path.push(file_name);
104 let file =
105 std::fs::File::create(&path).map_err(|e| crate::errors::failed_to_create_ast_json_file(&path, &e))?;
106 let writer = std::io::BufWriter::new(file);
107
108 let mut value = self.to_json_value().unwrap();
109 for key in excluded_keys {
110 value = remove_key_from_json(value, key);
111 }
112 value = normalize_json_value(value);
113
114 Ok(serde_json::to_writer_pretty(writer, &value)
115 .map_err(|e| crate::errors::failed_to_write_ast_to_json_file(&path, &e))?)
116 }
117
118 pub fn from_json_string(json: &str) -> Result<Self> {
120 let ast: Program =
121 serde_json::from_str(json).map_err(|e| crate::errors::failed_to_read_json_string_to_ast(&e))?;
122 Ok(ast)
123 }
124
125 pub fn from_json_file(path: std::path::PathBuf) -> Result<Self> {
127 let data = std::fs::read_to_string(&path).map_err(|e| crate::errors::failed_to_read_json_file(&path, &e))?;
128 Self::from_json_string(&data)
129 }
130}
131
132pub fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
134 match value {
135 serde_json::Value::Object(map) => serde_json::Value::Object(
136 map.into_iter().filter(|(k, _)| k != key).map(|(k, v)| (k, remove_key_from_json(v, key))).collect(),
137 ),
138 serde_json::Value::Array(values) => {
139 serde_json::Value::Array(values.into_iter().map(|v| remove_key_from_json(v, key)).collect())
140 }
141 _ => value,
142 }
143}
144
145pub fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
153 match value {
154 serde_json::Value::Array(vec) => {
155 let orig_length = vec.len();
156
157 let mut new_vec: Vec<serde_json::Value> = vec
158 .into_iter()
159 .filter(|v| !matches!(v, serde_json::Value::Object(map) if map.is_empty()))
160 .map(normalize_json_value)
161 .collect();
162
163 if orig_length == 2 && new_vec.len() == 1 {
164 new_vec.pop().unwrap()
165 } else {
166 serde_json::Value::Array(new_vec)
167 }
168 }
169 serde_json::Value::Object(map) => {
170 serde_json::Value::Object(map.into_iter().map(|(k, v)| (k, normalize_json_value(v))).collect())
171 }
172 _ => value,
173 }
174}