1mod program_scope;
20pub use program_scope::*;
21
22use leo_errors::{AstError, 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| AstError::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| AstError::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 = std::fs::File::create(&path).map_err(|e| AstError::failed_to_create_ast_json_file(&path, &e))?;
90 let writer = std::io::BufWriter::new(file);
91 Ok(serde_json::to_writer_pretty(writer, &self)
92 .map_err(|e| AstError::failed_to_write_ast_to_json_file(&path, &e))?)
93 }
94
95 pub fn to_json_file_without_keys(
97 &self,
98 mut path: std::path::PathBuf,
99 file_name: &str,
100 excluded_keys: &[&str],
101 ) -> Result<()> {
102 path.push(file_name);
103 let file = std::fs::File::create(&path).map_err(|e| AstError::failed_to_create_ast_json_file(&path, &e))?;
104 let writer = std::io::BufWriter::new(file);
105
106 let mut value = self.to_json_value().unwrap();
107 for key in excluded_keys {
108 value = remove_key_from_json(value, key);
109 }
110 value = normalize_json_value(value);
111
112 Ok(serde_json::to_writer_pretty(writer, &value)
113 .map_err(|e| AstError::failed_to_write_ast_to_json_file(&path, &e))?)
114 }
115
116 pub fn from_json_string(json: &str) -> Result<Self> {
118 let ast: Program = serde_json::from_str(json).map_err(|e| AstError::failed_to_read_json_string_to_ast(&e))?;
119 Ok(ast)
120 }
121
122 pub fn from_json_file(path: std::path::PathBuf) -> Result<Self> {
124 let data = std::fs::read_to_string(&path).map_err(|e| AstError::failed_to_read_json_file(&path, &e))?;
125 Self::from_json_string(&data)
126 }
127}
128
129pub fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
131 match value {
132 serde_json::Value::Object(map) => serde_json::Value::Object(
133 map.into_iter().filter(|(k, _)| k != key).map(|(k, v)| (k, remove_key_from_json(v, key))).collect(),
134 ),
135 serde_json::Value::Array(values) => {
136 serde_json::Value::Array(values.into_iter().map(|v| remove_key_from_json(v, key)).collect())
137 }
138 _ => value,
139 }
140}
141
142pub fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
150 match value {
151 serde_json::Value::Array(vec) => {
152 let orig_length = vec.len();
153
154 let mut new_vec: Vec<serde_json::Value> = vec
155 .into_iter()
156 .filter(|v| !matches!(v, serde_json::Value::Object(map) if map.is_empty()))
157 .map(normalize_json_value)
158 .collect();
159
160 if orig_length == 2 && new_vec.len() == 1 {
161 new_vec.pop().unwrap()
162 } else {
163 serde_json::Value::Array(new_vec)
164 }
165 }
166 serde_json::Value::Object(map) => {
167 serde_json::Value::Object(map.into_iter().map(|(k, v)| (k, normalize_json_value(v))).collect())
168 }
169 _ => value,
170 }
171}