From 46f585e2ffc0bf21bcd02b54698dea543d67c363 Mon Sep 17 00:00:00 2001 From: collin Date: Tue, 27 Oct 2020 00:31:36 -0700 Subject: [PATCH] refactor compiler methods --- compiler/src/compiler.rs | 151 +++++++++++++++++++++++++-------------- compiler/tests/mod.rs | 7 -- dynamic-check/Cargo.toml | 2 +- imports/Cargo.toml | 2 +- static-check/Cargo.toml | 2 +- 5 files changed, 100 insertions(+), 64 deletions(-) diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index a87443fdb1..7515d6c359 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -59,6 +59,9 @@ pub struct Compiler> { } impl> Compiler { + /// + /// Returns a new Leo program compiler. + /// pub fn new(package_name: String, main_file_path: PathBuf, output_directory: PathBuf) -> Self { Self { package_name: package_name.clone(), @@ -72,8 +75,51 @@ impl> Compiler { } } + /// + /// Parses program files. + /// + /// Returns a compiler struct that stores the typed program abstract syntax trees (ast). + /// + pub fn parse_program_without_input( + package_name: String, + main_file_path: PathBuf, + output_directory: PathBuf, + ) -> Result { + let mut compiler = Self::new(package_name, main_file_path, output_directory); + + compiler.parse_and_check_program()?; + + Ok(compiler) + } + + /// + /// Parses input, state, and program files. + /// + /// Returns a compiler struct that stores the typed input and typed program abstract syntax trees (ast). + /// + pub fn parse_program_with_input( + package_name: String, + main_file_path: PathBuf, + output_directory: PathBuf, + input_string: &str, + input_path: &Path, + state_string: &str, + state_path: &Path, + ) -> Result { + let mut compiler = Self::new(package_name, main_file_path, output_directory); + + compiler.parse_input(input_string, input_path, state_string, state_path)?; + + compiler.parse_and_check_program()?; + + Ok(compiler) + } + + /// /// Parse the input and state files. + /// /// Stores a typed ast of all input variables to the program. + /// pub fn parse_input( &mut self, input_string: &str, @@ -106,51 +152,59 @@ impl> Compiler { Ok(()) } - /// Parses program files. - /// Returns a compiler struct that stores the typed program abstract syntax trees (ast). - pub fn parse_program_without_input( - package_name: String, - main_file_path: PathBuf, - output_directory: PathBuf, - ) -> Result { - let mut compiler = Self::new(package_name, main_file_path, output_directory); + /// + /// Runs program parser and program checker consecutively. + /// + pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> { + self.parse_program()?; - compiler.parse_program()?; - - Ok(compiler) - } - - /// Parses input, state, and program files. - /// Returns a compiler struct that stores the typed input and typed program abstract syntax trees (ast). - pub fn parse_program_with_input( - package_name: String, - main_file_path: PathBuf, - output_directory: PathBuf, - input_string: &str, - input_path: &Path, - state_string: &str, - state_path: &Path, - ) -> Result { - let mut compiler = Self::new(package_name, main_file_path, output_directory); - - compiler.parse_input(input_string, input_path, state_string, state_path)?; - - compiler.parse_program()?; - - Ok(compiler) + self.check_program() } + /// /// Parses the Leo program file, constructs a syntax tree, and generates a program. - #[allow(deprecated)] + /// pub(crate) fn parse_program(&mut self) -> Result<(), CompilerError> { - // Use the parser to construct the abstract syntax tree. + // Load the program file. let program_string = LeoAst::load_file(&self.main_file_path)?; - self.parse_program_from_string(&program_string) + // Use the parser to construct the abstract syntax tree. + let ast = LeoAst::new(&self.main_file_path, &program_string).map_err(|mut e| { + e.set_path(&self.main_file_path); + + e + })?; + + // Use the typed parser to construct the typed syntax tree. + let typed_tree = LeoTypedAst::new(&self.package_name, &ast); + + self.program = typed_tree.into_repr(); + self.imported_programs = ImportParser::parse(&self.program)?; + + tracing::debug!("Program parsing complete\n{:#?}", self.program); + + Ok(()) } + /// + /// Runs static and dynamic type checks on the program, imports, and input. + /// + pub(crate) fn check_program(&self) -> Result<(), CompilerError> { + // Run static check on program. + let symbol_table = StaticCheck::new(&self.program, &self.imported_programs, &self.program_input)?; + + // Run dynamic check on program. + DynamicCheck::new(&self.program, symbol_table)?; + + tracing::debug!("Program checks complete"); + + Ok(()) + } + + /// /// Parses the Leo program string, constructs a syntax tree, and generates a program. /// Used for testing only. + /// #[deprecated(note = "Please use the 'parse_program' method instead.")] pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> { // Use the given bytes to construct the abstract syntax tree. @@ -180,12 +234,16 @@ impl> Compiler { Ok(()) } + /// /// Manually sets main function input + /// pub fn set_main_input(&mut self, input: MainInput) { self.program_input.set_main_input(input); } + /// /// Verifies the input to the program + /// pub fn verify_local_data_commitment( &self, system_parameters: &SystemParameters, @@ -195,6 +253,9 @@ impl> Compiler { Ok(result) } + /// + /// Returns a Sha256 checksum of the program file. + /// pub fn checksum(&self) -> Result { // Read in the main file as string let unparsed_file = fs::read_to_string(&self.main_file_path) @@ -208,7 +269,9 @@ impl> Compiler { Ok(hex::encode(hash)) } + /// /// Synthesizes the circuit without program input to verify correctness. + /// pub fn compile_constraints>(self, cs: &mut CS) -> Result { let path = self.main_file_path; @@ -245,26 +308,6 @@ impl> Compiler { }, ) } - - pub fn to_bytes(&self) -> Result, CompilerError> { - Ok(bincode::serialize(&self.program)?) - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - let program: Program = bincode::deserialize(bytes)?; - let program_input = Input::new(); - - Ok(Self { - package_name: program.name.clone(), - main_file_path: PathBuf::new(), - output_directory: PathBuf::new(), - program, - program_input, - imported_programs: ImportParser::new(), - _engine: PhantomData, - _group: PhantomData, - }) - } } impl> ConstraintSynthesizer for Compiler { diff --git a/compiler/tests/mod.rs b/compiler/tests/mod.rs index e4fce62e92..bd3e196c32 100644 --- a/compiler/tests/mod.rs +++ b/compiler/tests/mod.rs @@ -199,13 +199,6 @@ pub(crate) fn expect_static_check_error(error: CompilerError) { assert!(is_static_check) } -// pub(crate) fn expect_synthesis_error(program: EdwardsTestCompiler) { -// let mut cs = TestConstraintSystem::::new(); -// let _output = program.generate_constraints_helper(&mut cs).unwrap(); -// -// assert!(!cs.is_satisfied()); -// } - pub(crate) fn generate_main_input(input: Vec<(&str, Option)>) -> MainInput { let mut main_input = MainInput::new(); diff --git a/dynamic-check/Cargo.toml b/dynamic-check/Cargo.toml index c10ea4bc98..76855ac894 100644 --- a/dynamic-check/Cargo.toml +++ b/dynamic-check/Cargo.toml @@ -4,7 +4,7 @@ version = "1.0.3" authors = [ "The Aleo Team " ] description = "Checks that a program is correct using type inference" homepage = "https://aleo.org" -respository = "https://github.com/AleoHQ/leo" +repository = "https://github.com/AleoHQ/leo" keywords = [ "aleo", "cryptography", diff --git a/imports/Cargo.toml b/imports/Cargo.toml index 51bca2a856..6ef01f1426 100644 --- a/imports/Cargo.toml +++ b/imports/Cargo.toml @@ -4,7 +4,7 @@ version = "1.0.3" authors = [ "The Aleo Team "] description = "Import parser for Leo program package dependencies" homepage = "https://aleo.org" -respository = "https://github.com/AleoHQ/leo" +repository = "https://github.com/AleoHQ/leo" keywords = [ "aleo", "cryptography", diff --git a/static-check/Cargo.toml b/static-check/Cargo.toml index c79a458702..0e605147d9 100644 --- a/static-check/Cargo.toml +++ b/static-check/Cargo.toml @@ -4,7 +4,7 @@ version = "1.0.3" authors = [ "The Aleo Team " ] description = "Stores user-defined variables during type resolution" homepage = "https://aleo.org" -respository = "https://github.com/AleoHQ/leo" +repository = "https://github.com/AleoHQ/leo" keywords = [ "aleo", "cryptography",