ast generation now in the compiler and has options

This commit is contained in:
gluax 2021-06-30 23:47:20 -07:00
parent d4aaac6577
commit 026708d64d
8 changed files with 146 additions and 10 deletions

40
ast/src/errors/ast.rs Normal file
View File

@ -0,0 +1,40 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{FormattedError, LeoError, ReducerError, Span};
#[derive(Debug, Error)]
pub enum AstError {
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
IOError(#[from] std::io::Error),
#[error("{}", _0)]
ReducerError(#[from] ReducerError),
#[error("{}", _0)]
SerdeJsonError(#[from] ::serde_json::Error),
}
impl LeoError for AstError {}
impl AstError {
fn _new_from_span(message: String, span: &Span) -> Self {
AstError::Error(FormattedError::new_from_span(message, span))
}
}

View File

@ -14,6 +14,9 @@
// 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/>.
pub mod ast;
pub use ast::*;
pub mod canonicalization;
pub use canonicalization::*;

View File

@ -86,7 +86,7 @@ impl Ast {
}
/// Mutates the program ast by preforming canonicalization on it.
pub fn canonicalize(&mut self) -> Result<(), ReducerError> {
pub fn canonicalize(&mut self) -> Result<(), AstError> {
self.ast = ReconstructingDirector::new(Canonicalizer::default()).reduce_program(self.as_repr())?;
Ok(())
}
@ -101,12 +101,20 @@ impl Ast {
}
/// Serializes the ast into a JSON string.
pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
serde_json::to_string_pretty(&self.ast)
pub fn to_json_string(&self) -> Result<String, AstError> {
Ok(serde_json::to_string_pretty(&self.ast)?)
}
pub fn to_json_file(&self, mut path: std::path::PathBuf, file_name: &str) -> Result<(), AstError> {
path.push(file_name);
let file = std::fs::File::create(path)?;
let writer = std::io::BufWriter::new(file);
serde_json::to_writer_pretty(writer, &self.ast)?;
Ok(())
}
/// Deserializes the JSON string into a ast.
pub fn from_json_string(json: &str) -> Result<Self, serde_json::Error> {
pub fn from_json_string(json: &str) -> Result<Self, AstError> {
let ast: Program = serde_json::from_str(json)?;
Ok(Self { ast })
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! Compiles a Leo program from a file path.
use crate::{
constraints::{generate_constraints, generate_test_constraints},
errors::CompilerError,
@ -23,6 +22,8 @@ use crate::{
GroupType,
Output,
OutputFile,
ProofOptions,
TypeInferencePhase,
};
pub use leo_asg::{new_context, AsgContext as Context, AsgContext};
use leo_asg::{Asg, AsgPass, FormattedError, Program as AsgProgram};
@ -66,6 +67,7 @@ pub struct Compiler<'a, F: PrimeField, G: GroupType<F>> {
context: AsgContext<'a>,
asg: Option<AsgProgram<'a>>,
options: CompilerOptions,
proof_options: ProofOptions,
_engine: PhantomData<F>,
_group: PhantomData<G>,
}
@ -80,6 +82,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
output_directory: PathBuf,
context: AsgContext<'a>,
options: Option<CompilerOptions>,
proof_options: Option<ProofOptions>,
) -> Self {
Self {
program_name: package_name.clone(),
@ -90,6 +93,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
asg: None,
context,
options: options.unwrap_or_default(),
proof_options: proof_options.unwrap_or_default(),
_engine: PhantomData,
_group: PhantomData,
}
@ -108,8 +112,16 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
output_directory: PathBuf,
context: AsgContext<'a>,
options: Option<CompilerOptions>,
proof_options: Option<ProofOptions>,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory, context, options);
let mut compiler = Self::new(
package_name,
main_file_path,
output_directory,
context,
options,
proof_options,
);
compiler.parse_program()?;
@ -139,8 +151,16 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
state_path: &Path,
context: AsgContext<'a>,
options: Option<CompilerOptions>,
proof_options: Option<ProofOptions>,
) -> Result<Self, CompilerError> {
let mut compiler = Self::new(package_name, main_file_path, output_directory, context, options);
let mut compiler = Self::new(
package_name,
main_file_path,
output_directory,
context,
options,
proof_options,
);
compiler.parse_input(input_string, input_path, state_string, state_path)?;
@ -218,11 +238,19 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<(), CompilerError> {
// Use the parser to construct the abstract syntax tree (ast).
let mut ast = parse_ast(self.main_file_path.to_str().unwrap_or_default(), program_string)?;
let mut ast: leo_ast::Ast = parse_ast(self.main_file_path.to_str().unwrap_or_default(), program_string)?;
if self.proof_options.initial {
ast.to_json_file(self.output_directory.clone(), "inital_ast.json")?;
}
// Preform compiler optimization via canonicalizing AST if its enabled.
if self.options.canonicalization_enabled {
ast.canonicalize()?;
if self.proof_options.canonicalized {
ast.to_json_file(self.output_directory.clone(), "canonicalization_ast.json")?;
}
}
// Store the main program file.
@ -238,6 +266,13 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
&mut leo_imports::ImportParser::new(self.main_file_path.clone()),
)?;
if self.proof_options.type_inferenced {
let new_ast = TypeInferencePhase::default()
.phase_ast(&self.program, &asg.clone().into_repr())
.expect("Failed to produce type inference ast.");
new_ast.to_json_file(self.output_directory.clone(), "type_inferenced_ast.json")?;
}
tracing::debug!("ASG generation complete");
// Store the ASG.

View File

@ -16,7 +16,7 @@
use crate::errors::{ExpressionError, FunctionError, ImportError, StatementError};
use leo_asg::{AsgConvertError, FormattedError};
use leo_ast::{LeoError, ReducerError};
use leo_ast::{AstError, LeoError};
use leo_input::InputParserError;
use leo_parser::SyntaxError;
use leo_state::LocalDataVerificationError;
@ -62,7 +62,7 @@ pub enum CompilerError {
AsgConvertError(#[from] AsgConvertError),
#[error("{}", _0)]
ReducerError(#[from] ReducerError),
AstError(#[from] AstError),
#[error("{}", _0)]
StatementError(#[from] StatementError),

View File

@ -36,3 +36,20 @@ impl Default for CompilerOptions {
}
}
}
#[derive(Clone)]
pub struct ProofOptions {
pub initial: bool,
pub canonicalized: bool,
pub type_inferenced: bool,
}
impl Default for ProofOptions {
fn default() -> Self {
Self {
initial: false,
canonicalized: false,
type_inferenced: false,
}
}
}

View File

@ -19,6 +19,7 @@ use leo_compiler::{
compiler::{thread_leaked_context, Compiler},
group::targets::edwards_bls12::EdwardsGroupType,
CompilerOptions,
ProofOptions,
};
use leo_package::{
inputs::*,
@ -43,6 +44,14 @@ pub struct BuildOptions {
pub disable_code_elimination: bool,
#[structopt(long, help = "Disable all compiler optimizations")]
pub disable_all_optimizations: bool,
#[structopt(long, help = "Enables all json ast proof generations.")]
pub enable_all_proofs: bool,
#[structopt(long, help = "Enables the initial parsed json ast proof generation.")]
pub enable_initial_proof: bool,
#[structopt(long, help = "Enables the post canonicalization json ast proof generation.")]
pub enable_canonicalized_proof: bool,
#[structopt(long, help = "Enables the post canonicalization json ast proof generation.")]
pub enable_type_inferenced_proof: bool,
}
impl Default for BuildOptions {
@ -51,6 +60,10 @@ impl Default for BuildOptions {
disable_constant_folding: true,
disable_code_elimination: true,
disable_all_optimizations: true,
enable_all_proofs: false,
enable_initial_proof: false,
enable_canonicalized_proof: false,
enable_type_inferenced_proof: false,
}
}
}
@ -73,6 +86,24 @@ impl From<BuildOptions> for CompilerOptions {
}
}
impl From<BuildOptions> for ProofOptions {
fn from(options: BuildOptions) -> Self {
if options.enable_all_proofs {
ProofOptions {
initial: true,
canonicalized: true,
type_inferenced: true,
}
} else {
ProofOptions {
initial: options.enable_initial_proof,
canonicalized: options.enable_canonicalized_proof,
type_inferenced: options.enable_type_inferenced_proof,
}
}
}
}
/// Compile and build program command.
#[derive(StructOpt, Debug)]
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
@ -141,6 +172,7 @@ impl Command for Build {
&state_string,
&state_path,
thread_leaked_context(),
Some(self.compiler_options.clone().into()),
Some(self.compiler_options.into()),
)?;

View File

@ -112,6 +112,7 @@ impl Command for Test {
output_directory.clone(),
thread_leaked_context(),
Some(self.compiler_options.clone().into()),
Some(self.compiler_options.clone().into()),
)?;
let temporary_program = program;