refactor compiler methods

This commit is contained in:
collin 2020-10-27 00:31:36 -07:00
parent 52810588ff
commit 46f585e2ff
5 changed files with 100 additions and 64 deletions

View File

@ -59,6 +59,9 @@ pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
}
impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
///
/// 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<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
}
}
///
/// 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<Self, CompilerError> {
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<Self, CompilerError> {
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<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
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<Self, CompilerError> {
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<Self, CompilerError> {
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<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
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<Components>,
@ -195,6 +253,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(result)
}
///
/// Returns a Sha256 checksum of the program file.
///
pub fn checksum(&self) -> Result<String, CompilerError> {
// Read in the main file as string
let unparsed_file = fs::read_to_string(&self.main_file_path)
@ -208,7 +269,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
Ok(hex::encode(hash))
}
///
/// Synthesizes the circuit without program input to verify correctness.
///
pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
let path = self.main_file_path;
@ -245,26 +308,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
},
)
}
pub fn to_bytes(&self) -> Result<Vec<u8>, CompilerError> {
Ok(bincode::serialize(&self.program)?)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CompilerError> {
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<F: Field + PrimeField, G: GroupType<F>> ConstraintSynthesizer<F> for Compiler<F, G> {

View File

@ -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::<Fq>::new();
// let _output = program.generate_constraints_helper(&mut cs).unwrap();
//
// assert!(!cs.is_satisfied());
// }
pub(crate) fn generate_main_input(input: Vec<(&str, Option<InputValue>)>) -> MainInput {
let mut main_input = MainInput::new();

View File

@ -4,7 +4,7 @@ version = "1.0.3"
authors = [ "The Aleo Team <hello@aleo.org>" ]
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",

View File

@ -4,7 +4,7 @@ version = "1.0.3"
authors = [ "The Aleo Team <hello@aleo.org>"]
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",

View File

@ -4,7 +4,7 @@ version = "1.0.3"
authors = [ "The Aleo Team <hello@aleo.org>" ]
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",