need to handle input differently than we used to

This commit is contained in:
gluax 2022-04-25 16:09:49 -07:00
parent ae5fbef58a
commit bd356e1f31
8 changed files with 54 additions and 15 deletions

3
Cargo.lock generated
View File

@ -1229,6 +1229,9 @@ dependencies = [
"leo-parser", "leo-parser",
"leo-passes", "leo-passes",
"leo-span", "leo-span",
"leo-test-framework",
"serde",
"serde_yaml",
"sha2", "sha2",
] ]

View File

@ -14,8 +14,10 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{normalize_json_value, remove_key_from_json};
use super::*; use super::*;
use leo_errors::AstError; use leo_errors::{AstError, Result};
/// Input data which includes [`ProgramInput`] and [`ProgramState`]. /// Input data which includes [`ProgramInput`] and [`ProgramState`].
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
@ -31,6 +33,34 @@ pub struct ParsedInputFile {
pub sections: Vec<Section>, pub sections: Vec<Section>,
} }
impl ParsedInputFile {
/// Serializes the `ParsedInputFile` into a JSON Value.
pub fn to_json_value(&self) -> Result<serde_json::Value> {
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 { impl Input {
/// Serializes the ast into a JSON string. /// Serializes the ast into a JSON string.
pub fn to_json_string(&self) -> Result<String> { pub fn to_json_string(&self) -> Result<String> {

View File

@ -144,7 +144,7 @@ impl AsRef<Program> for Ast {
} }
/// Helper function to recursively filter keys from AST JSON /// 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 { match value {
serde_json::Value::Object(map) => serde_json::Value::Object( serde_json::Value::Object(map) => serde_json::Value::Object(
map.into_iter() 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 /// 1. Remove empty object mappings from JSON arrays
/// 2. If there are two elements in a JSON array and one is an empty object /// 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 /// 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 { match value {
serde_json::Value::Array(vec) => { serde_json::Value::Array(vec) => {
let orig_length = vec.len(); let orig_length = vec.len();

View File

@ -76,7 +76,7 @@ impl<'a> Compiler<'a> {
/// ///
/// Runs the compiler stages. /// Runs the compiler stages.
/// ///
fn compiler_stages(&self) -> Result<leo_ast::Ast> { fn compiler_stages(&self, program_string: &str) -> Result<leo_ast::Ast> {
//load the input file if it exists. //load the input file if it exists.
if let Some(input_file_path) = self.input_file_path.as_ref() { if let Some(input_file_path) = self.input_file_path.as_ref() {
let _input_ast = if input_file_path.exists() { 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). // Use the parser to construct the abstract syntax tree (ast).
let ast: leo_ast::Ast = leo_parser::parse_ast( let ast: leo_ast::Ast = leo_parser::parse_ast(
self.handler, self.handler,
@ -116,10 +112,21 @@ impl<'a> Compiler<'a> {
Ok(ast) 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<Ast> {
// 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. /// Returns a compiled Leo program.
/// ///
pub fn compile(&self) -> Result<leo_ast::Ast> { pub fn compile(&self) -> Result<leo_ast::Ast> {
create_session_if_not_set_then(|_| self.compiler_stages()) create_session_if_not_set_then(|_| self.parse_program())
} }
} }

View File

@ -77,8 +77,7 @@ impl Namespace for CompileNamespace {
let handler = Handler::new(Box::new(err_buf.clone())); let handler = Handler::new(Box::new(err_buf.clone()));
create_session_if_not_set_then(|_| { create_session_if_not_set_then(|_| {
// run_test(test, &handler, &err_buf).map_err(|()| err_buf.0.take().to_string()) run_test(test, &handler, &err_buf).map_err(|()| err_buf.0.take().to_string())
Err("todo".to_string())
}) })
} }
} }
@ -220,7 +219,7 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Va
} }
let initial_ast = hash_file("/tmp/output/initial_ast.json"); let initial_ast = hash_file("/tmp/output/initial_ast.json");
let input_ast = hash_file("/tmp/output/input_ast.json"); let initial_input = hash_file("/tmp/output/input_ast.json");
if fs::read_dir("/tmp/output").is_ok() { if fs::read_dir("/tmp/output").is_ok() {
fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir."); fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir.");

View File

@ -22,7 +22,7 @@ use indexmap::IndexMap;
use crate::VariableSymbol; use crate::VariableSymbol;
#[derive(Default)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SymbolTable<'a> { pub struct SymbolTable<'a> {
functions: IndexMap<Symbol, &'a Function>, functions: IndexMap<Symbol, &'a Function>,
variables: VariableSymbol<'a>, variables: VariableSymbol<'a>,

View File

@ -19,7 +19,7 @@ use leo_ast::{DefinitionStatement, FunctionInput, FunctionInputVariable};
use leo_errors::{AstError, Result}; use leo_errors::{AstError, Result};
use leo_span::Symbol; use leo_span::Symbol;
#[derive(Debug, Default)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct VariableSymbol<'a> { pub struct VariableSymbol<'a> {
parent: Option<Box<VariableSymbol<'a>>>, parent: Option<Box<VariableSymbol<'a>>>,
inputs: IndexMap<Symbol, &'a FunctionInputVariable>, inputs: IndexMap<Symbol, &'a FunctionInputVariable>,

View File

@ -180,7 +180,7 @@ impl Command for Build {
// Initialize error handler // Initialize error handler
let handler = leo_errors::emitter::Handler::default(); 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 // Compute the current program checksum
let program_checksum = program.checksum()?; let program_checksum = program.checksum()?;