diff --git a/Cargo.lock b/Cargo.lock
index 13cd67d69f..9c88ebb2f9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1229,6 +1229,9 @@ dependencies = [
"leo-parser",
"leo-passes",
"leo-span",
+ "leo-test-framework",
+ "serde",
+ "serde_yaml",
"sha2",
]
diff --git a/compiler/ast/src/input/input_ast.rs b/compiler/ast/src/input/input_ast.rs
index f5c6d9658f..be83f33f52 100644
--- a/compiler/ast/src/input/input_ast.rs
+++ b/compiler/ast/src/input/input_ast.rs
@@ -14,8 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
+use crate::{normalize_json_value, remove_key_from_json};
+
use super::*;
-use leo_errors::AstError;
+use leo_errors::{AstError, Result};
/// Input data which includes [`ProgramInput`] and [`ProgramState`].
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
@@ -31,6 +33,34 @@ pub struct ParsedInputFile {
pub sections: Vec,
}
+impl ParsedInputFile {
+ /// Serializes the `ParsedInputFile` into a JSON Value.
+ pub fn to_json_value(&self) -> Result {
+ Ok(serde_json::to_value(&self).map_err(|e| AstError::failed_to_convert_ast_to_json_value(&e))?)
+ }
+
+ /// Serializes the `ParsedInputFile` into a JSON value and removes keys from object mappings before writing to a file.
+ pub fn to_json_file_without_keys(
+ &self,
+ mut path: std::path::PathBuf,
+ file_name: &str,
+ excluded_keys: &[&str],
+ ) -> Result<()> {
+ path.push(file_name);
+ let file = std::fs::File::create(&path).map_err(|e| AstError::failed_to_create_ast_json_file(&path, &e))?;
+ let writer = std::io::BufWriter::new(file);
+
+ let mut value = self.to_json_value().unwrap();
+ for key in excluded_keys {
+ value = remove_key_from_json(value, key);
+ }
+ value = normalize_json_value(value);
+
+ Ok(serde_json::to_writer_pretty(writer, &value)
+ .map_err(|e| AstError::failed_to_write_ast_to_json_file(&path, &e))?)
+ }
+}
+
impl Input {
/// Serializes the ast into a JSON string.
pub fn to_json_string(&self) -> Result {
diff --git a/compiler/ast/src/lib.rs b/compiler/ast/src/lib.rs
index 2b2b82cd16..64adaed260 100644
--- a/compiler/ast/src/lib.rs
+++ b/compiler/ast/src/lib.rs
@@ -144,7 +144,7 @@ impl AsRef for Ast {
}
/// Helper function to recursively filter keys from AST JSON
-fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
+pub(crate) fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
match value {
serde_json::Value::Object(map) => serde_json::Value::Object(
map.into_iter()
@@ -165,7 +165,7 @@ fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Valu
/// 1. Remove empty object mappings from JSON arrays
/// 2. If there are two elements in a JSON array and one is an empty object
/// mapping and the other is not, then lift up the one that isn't
-fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
+pub(crate) fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
match value {
serde_json::Value::Array(vec) => {
let orig_length = vec.len();
diff --git a/compiler/compiler/src/lib.rs b/compiler/compiler/src/lib.rs
index 0de90b387d..4974481db1 100644
--- a/compiler/compiler/src/lib.rs
+++ b/compiler/compiler/src/lib.rs
@@ -76,7 +76,7 @@ impl<'a> Compiler<'a> {
///
/// Runs the compiler stages.
///
- fn compiler_stages(&self) -> Result {
+ fn compiler_stages(&self, program_string: &str) -> Result {
//load the input file if it exists.
if let Some(input_file_path) = self.input_file_path.as_ref() {
let _input_ast = if input_file_path.exists() {
@@ -93,10 +93,6 @@ impl<'a> Compiler<'a> {
};
}
- // Load the program file.
- let program_string = fs::read_to_string(&self.main_file_path)
- .map_err(|e| CompilerError::file_read_error(self.main_file_path.clone(), e))?;
-
// Use the parser to construct the abstract syntax tree (ast).
let ast: leo_ast::Ast = leo_parser::parse_ast(
self.handler,
@@ -116,10 +112,21 @@ impl<'a> Compiler<'a> {
Ok(ast)
}
+ /// Parses and stores the main program file, constructs a syntax tree, and generates a program.
+ ///
+ /// Parses and stores all programs imported by the main program file.
+ pub fn parse_program(&self) -> Result {
+ // Load the program file.
+ let program_string = fs::read_to_string(&self.main_file_path)
+ .map_err(|e| CompilerError::file_read_error(self.main_file_path.clone(), e))?;
+
+ self.compiler_stages(&program_string)
+ }
+
///
/// Returns a compiled Leo program.
///
pub fn compile(&self) -> Result {
- create_session_if_not_set_then(|_| self.compiler_stages())
+ create_session_if_not_set_then(|_| self.parse_program())
}
}
diff --git a/compiler/compiler/src/test.rs b/compiler/compiler/src/test.rs
index a0515dc80c..ef871fd127 100644
--- a/compiler/compiler/src/test.rs
+++ b/compiler/compiler/src/test.rs
@@ -77,8 +77,7 @@ impl Namespace for CompileNamespace {
let handler = Handler::new(Box::new(err_buf.clone()));
create_session_if_not_set_then(|_| {
- // run_test(test, &handler, &err_buf).map_err(|()| err_buf.0.take().to_string())
- Err("todo".to_string())
+ run_test(test, &handler, &err_buf).map_err(|()| err_buf.0.take().to_string())
})
}
}
@@ -220,7 +219,7 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result {
functions: IndexMap,
variables: VariableSymbol<'a>,
diff --git a/compiler/passes/src/symbol_table/variable_symbol.rs b/compiler/passes/src/symbol_table/variable_symbol.rs
index 9f453b84d1..8f172656b6 100644
--- a/compiler/passes/src/symbol_table/variable_symbol.rs
+++ b/compiler/passes/src/symbol_table/variable_symbol.rs
@@ -19,7 +19,7 @@ use leo_ast::{DefinitionStatement, FunctionInput, FunctionInputVariable};
use leo_errors::{AstError, Result};
use leo_span::Symbol;
-#[derive(Debug, Default)]
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct VariableSymbol<'a> {
parent: Option>>,
inputs: IndexMap,
diff --git a/leo/commands/build.rs b/leo/commands/build.rs
index 3996c17dcf..176243e074 100644
--- a/leo/commands/build.rs
+++ b/leo/commands/build.rs
@@ -180,7 +180,7 @@ impl Command for Build {
// Initialize error handler
let handler = leo_errors::emitter::Handler::default();
- let program = Compiler::new(&handler, main_file_path, output_directory, input_path.to_path_buf());
+ let program = Compiler::new(&handler, main_file_path, output_directory);
// Compute the current program checksum
let program_checksum = program.checksum()?;