Skip to content

Commit

Permalink
Merge pull request #597 from AleoHQ/asg-compiler
Browse files Browse the repository at this point in the history
[Feature] Abstract Semantic Graph (ASG) - Compiler Integration
  • Loading branch information
howardwu authored Feb 2, 2021
2 parents 49bb4ab + e028255 commit 2657c44
Show file tree
Hide file tree
Showing 221 changed files with 1,365 additions and 9,311 deletions.
49 changes: 3 additions & 46 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ path = "leo/main.rs"
members = [
"ast",
"compiler",
"core",
"gadgets",
"grammar",
"imports",
Expand All @@ -37,8 +36,6 @@ members = [
"package",
"state",
"asg",
"symbol-table",
"type-inference"
]

[dependencies.leo-ast]
Expand Down
4 changes: 0 additions & 4 deletions ast/src/common/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ impl Identifier {
pub fn is_self(&self) -> bool {
self.is_self_type() || self.name == "self"
}

pub fn is_core(&self) -> bool {
self.name.starts_with('#')
}
}

impl<'ast> From<GrammarIdentifier<'ast>> for Identifier {
Expand Down
16 changes: 6 additions & 10 deletions compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ edition = "2018"
path = "../ast"
version = "1.0.8"

[dependencies.leo-core]
path = "../core"
version = "1.0.8"

[dependencies.leo-gadgets]
path = "../gadgets"
version = "1.0.8"
Expand All @@ -49,12 +45,8 @@ version = "1.0.8"
path = "../state"
version = "1.0.8"

[dependencies.leo-symbol-table]
path = "../symbol-table"
version = "1.0.8"

[dependencies.leo-type-inference]
path = "../type-inference"
[dependencies.leo-asg]
path = "../asg"
version = "1.0.8"

[dependencies.snarkvm-curves]
Expand Down Expand Up @@ -116,6 +108,10 @@ version = "1.0"
[dependencies.tracing]
version = "0.1"

[dependencies.uuid]
version = "0.8"
features = ["v4", "serde"]

[dev-dependencies.num-bigint]
version = "0.3"

Expand Down
76 changes: 21 additions & 55 deletions compiler/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ use crate::{
};
use leo_ast::{Ast, Input, MainInput, Program};
use leo_grammar::Grammar;
use leo_imports::ImportParser;
use leo_input::LeoInputParser;
use leo_package::inputs::InputPairs;
use leo_state::verify_local_data_commitment;
use leo_symbol_table::SymbolTable;
use leo_type_inference::TypeInference;

use leo_asg::Program as AsgProgram;
use snarkvm_dpc::{base_dpc::instantiated::Components, SystemParameters};
use snarkvm_errors::gadgets::SynthesisError;
use snarkvm_models::{
Expand All @@ -54,7 +52,7 @@ pub struct Compiler<F: Field + PrimeField, G: GroupType<F>> {
output_directory: PathBuf,
program: Program,
program_input: Input,
imported_programs: ImportParser,
asg: Option<AsgProgram>,
_engine: PhantomData<F>,
_group: PhantomData<G>,
}
Expand All @@ -70,7 +68,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
output_directory,
program: Program::new(package_name),
program_input: Input::new(),
imported_programs: ImportParser::default(),
asg: None,
_engine: PhantomData,
_group: PhantomData,
}
Expand Down Expand Up @@ -162,9 +160,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
/// Runs program parser and type inference checker consecutively.
///
pub(crate) fn parse_and_check_program(&mut self) -> Result<(), CompilerError> {
self.parse_program()?;

self.check_program()
self.parse_program()
}

///
Expand All @@ -189,38 +185,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
// Store the main program file.
self.program = core_ast.into_repr();

// Parse and store all programs imported by the main program file.
self.imported_programs = ImportParser::parse(&self.program)?;

tracing::debug!("Program parsing complete\n{:#?}", self.program);

self.program_asg_generate()?;

Ok(())
}

///
/// Runs a type check on the program, imports, and input.
///
/// First, a symbol table of all user defined types is created.
/// Second, a type inference check is run on the program - inferring a data type for all implicit types and
/// catching type mismatch errors.
///
pub(crate) fn check_program(&self) -> Result<(), CompilerError> {
pub(crate) fn program_asg_generate(&mut self) -> Result<(), CompilerError> {
// Create a new symbol table from the program, imported_programs, and program_input.
let symbol_table =
SymbolTable::new(&self.program, &self.imported_programs, &self.program_input).map_err(|mut e| {
e.set_path(&self.main_file_path);
let asg = leo_asg::InnerProgram::new(&self.program, &mut leo_imports::ImportParser::default())?;

e
})?;
tracing::debug!("ASG generation complete");

// Run type inference check on program.
TypeInference::new(&self.program, symbol_table).map_err(|mut e| {
e.set_path(&self.main_file_path);

e
})?;

tracing::debug!("Program checks complete");
self.asg = Some(asg);

Ok(())
}
Expand All @@ -246,17 +224,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
// Store the main program file.
self.program = core_ast.into_repr();

// Parse and store all programs imported by the main program file.
self.imported_programs = ImportParser::parse(&self.program)?;

// Create a new symbol table from the program, imported programs, and program input.
let symbol_table = SymbolTable::new(&self.program, &self.imported_programs, &self.program_input)?;

// Run type inference check on program.
TypeInference::new(&self.program, symbol_table)?;

tracing::debug!("Program parsing complete\n{:#?}", self.program);

self.program_asg_generate()?;

Ok(())
}

Expand Down Expand Up @@ -303,23 +274,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
pub fn compile_constraints<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<OutputBytes, CompilerError> {
let path = self.main_file_path;

generate_constraints::<F, G, CS>(cs, &self.program, &self.program_input, &self.imported_programs).map_err(
|mut error| {
error.set_path(&path);
generate_constraints::<F, G, CS>(cs, self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
error.set_path(&path);

error
},
)
error
})
}

///
/// Synthesizes the circuit for test functions with program input.
///
pub fn compile_test_constraints(self, input_pairs: InputPairs) -> Result<(u32, u32), CompilerError> {
generate_test_constraints::<F, G>(
self.program,
self.asg.as_ref().unwrap(),
input_pairs,
&self.imported_programs,
&self.main_file_path,
&self.output_directory,
)
Expand All @@ -333,12 +301,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
cs: &mut CS,
) -> Result<OutputBytes, CompilerError> {
let path = &self.main_file_path;
generate_constraints::<_, G, _>(cs, &self.program, &self.program_input, &self.imported_programs).map_err(
|mut error| {
error.set_path(&path);
error
},
)
generate_constraints::<_, G, _>(cs, self.asg.as_ref().unwrap(), &self.program_input).map_err(|mut error| {
error.set_path(&path);
error
})
}
}

Expand Down
16 changes: 6 additions & 10 deletions compiler/src/console/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ use crate::{
value::ConstrainedValue,
GroupType,
};
use leo_ast::{Expression, Span, Type};
use leo_asg::{Expression, Span};
use std::sync::Arc;

use snarkvm_models::{
curves::{Field, PrimeField},
Expand All @@ -34,17 +35,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn evaluate_console_assert<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: &str,
function_scope: &str,
indicator: &Boolean,
expression: Expression,
expression: &Arc<Expression>,
span: &Span,
) -> Result<(), ConsoleError> {
let expected_type = Some(Type::Boolean);
let expression_string = expression.to_string();

// Evaluate assert expression
let assert_expression = self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?;
let assert_expression = self.enforce_expression(cs, expression)?;

// If the indicator bit is false, do not evaluate the assertion
// This is okay since we are not enforcing any constraints
Expand All @@ -57,15 +53,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
ConstrainedValue::Boolean(boolean) => boolean.get_value(),
_ => {
return Err(ConsoleError::assertion_must_be_boolean(
expression_string,
span.text.clone(),
span.to_owned(),
));
}
};
let result_bool = result_option.ok_or_else(|| ConsoleError::assertion_depends_on_input(span.to_owned()))?;

if !result_bool {
return Err(ConsoleError::assertion_failed(expression_string, span.to_owned()));
return Err(ConsoleError::assertion_failed(span.text.clone(), span.to_owned()));
}

Ok(())
Expand Down
16 changes: 7 additions & 9 deletions compiler/src/console/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! Evaluates a macro in a compiled Leo program.

use crate::{errors::ConsoleError, program::ConstrainedProgram, statement::get_indicator_value, GroupType};
use leo_ast::{ConsoleFunction, ConsoleStatement};
use leo_asg::{ConsoleFunction, ConsoleStatement};

use snarkvm_models::{
curves::{Field, PrimeField},
Expand All @@ -28,31 +28,29 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn evaluate_console_function_call<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: &str,
function_scope: &str,
indicator: &Boolean,
console: ConsoleStatement,
console: &ConsoleStatement,
) -> Result<(), ConsoleError> {
match console.function {
match &console.function {
ConsoleFunction::Assert(expression) => {
self.evaluate_console_assert(cs, file_scope, function_scope, indicator, expression, &console.span)?;
self.evaluate_console_assert(cs, indicator, expression, &console.span.clone().unwrap_or_default())?;
}
ConsoleFunction::Debug(string) => {
let string = self.format(cs, file_scope, function_scope, string)?;
let string = self.format(cs, string)?;

if get_indicator_value(indicator) {
tracing::debug!("{}", string);
}
}
ConsoleFunction::Error(string) => {
let string = self.format(cs, file_scope, function_scope, string)?;
let string = self.format(cs, string)?;

if get_indicator_value(indicator) {
tracing::error!("{}", string);
}
}
ConsoleFunction::Log(string) => {
let string = self.format(cs, file_scope, function_scope, string)?;
let string = self.format(cs, string)?;

if get_indicator_value(indicator) {
tracing::info!("{}", string);
Expand Down
Loading

0 comments on commit 2657c44

Please sign in to comment.