diff --git a/benchmark/simple.leo b/benchmark/simple.leo index 3888311797..e74ec9eae1 100644 --- a/benchmark/simple.leo +++ b/benchmark/simple.leo @@ -1,4 +1,10 @@ -function main(a: private u32) -> (u32) { - b = a + 5; - return a +function main(a: private bool, b: private bool) -> (u32) { + if (a) { + res = 1; + } else if (b) { + res = 2; + } else { + res = 3; + } + return res } \ No newline at end of file diff --git a/benchmark/src/main.rs b/benchmark/src/main.rs index baea1f03d1..9830a7964e 100644 --- a/benchmark/src/main.rs +++ b/benchmark/src/main.rs @@ -1,4 +1,4 @@ -use leo_program::{self, ast}; +use leo_compiler::{self, ast}; use snarkos_algorithms::snark::{ create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, @@ -45,11 +45,11 @@ impl ConstraintSynthesizer for Benchmark { let syntax_tree = ast::File::from_pest(&mut file).expect("infallible"); // println!("{:#?}", syntax_tree); - let program = leo_program::Program::<'_, F>::from(syntax_tree); + let program = leo_compiler::Program::<'_, F>::from(syntax_tree); println!(" compiled: {:#?}", program); let program = program.name("simple".into()); - leo_program::ResolvedProgram::generate_constraints(cs, program); + leo_compiler::ResolvedProgram::generate_constraints(cs, program); Ok(()) } diff --git a/compiler/src/ast.rs b/compiler/src/ast.rs index 5aa4c030c1..f58309aaa2 100644 --- a/compiler/src/ast.rs +++ b/compiler/src/ast.rs @@ -618,7 +618,7 @@ impl<'ast> fmt::Display for Expression<'ast> { } Expression::Ternary(ref expression) => write!( f, - "if {} then {} else {} fi", + "if {} ? {} : {}", expression.first, expression.second, expression.third ), Expression::ArrayInline(ref expression) => { @@ -805,6 +805,23 @@ pub struct ReturnStatement<'ast> { pub span: Span<'ast>, } +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::conditional_nested_or_end))] +pub enum ConditionalNestedOrEnd<'ast> { + Nested(Box>), + End(Vec>), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::statement_conditional))] +pub struct ConditionalStatement<'ast> { + pub condition: Expression<'ast>, + pub statements: Vec>, + pub next: Option>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::statement_for))] pub struct ForStatement<'ast> { @@ -849,10 +866,11 @@ pub struct AssignStatement<'ast> { #[pest_ast(rule(Rule::statement))] pub enum Statement<'ast> { Return(ReturnStatement<'ast>), - Iteration(ForStatement<'ast>), - MultipleAssignment(MultipleAssignmentStatement<'ast>), Definition(DefinitionStatement<'ast>), Assign(AssignStatement<'ast>), + MultipleAssignment(MultipleAssignmentStatement<'ast>), + Conditional(ConditionalStatement<'ast>), + Iteration(ForStatement<'ast>), } impl<'ast> fmt::Display for ReturnStatement<'ast> { @@ -867,6 +885,34 @@ impl<'ast> fmt::Display for ReturnStatement<'ast> { } } +impl<'ast> fmt::Display for ConditionalNestedOrEnd<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ConditionalNestedOrEnd::Nested(ref nested) => write!(f, "else {}", nested), + ConditionalNestedOrEnd::End(ref statements) => { + write!(f, "else {{\n")?; + for statement in statements.iter() { + write!(f, "\t{}\n", statement)?; + } + write!(f, "}}") + } + } + } +} + +impl<'ast> fmt::Display for ConditionalStatement<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "if ({}) {{\n", self.condition)?; + for statement in self.statements.iter() { + write!(f, "\t{}\n", statement)?; + } + self.next + .as_ref() + .map(|n_or_e| write!(f, "}} {}", n_or_e)) + .unwrap_or(write!(f, "}}")) + } +} + impl<'ast> fmt::Display for ForStatement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( @@ -891,13 +937,13 @@ impl<'ast> fmt::Display for MultipleAssignmentStatement<'ast> { impl<'ast> fmt::Display for DefinitionStatement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} {} = {}", self.ty, self.variable, self.expression) + write!(f, "{} {} = {};", self.ty, self.variable, self.expression) } } impl<'ast> fmt::Display for AssignStatement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} = {}", self.assignee, self.expression) + write!(f, "{} = {};", self.assignee, self.expression) } } @@ -905,10 +951,11 @@ impl<'ast> fmt::Display for Statement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Statement::Return(ref statement) => write!(f, "{}", statement), - Statement::Iteration(ref statement) => write!(f, "{}", statement), - Statement::MultipleAssignment(ref statement) => write!(f, "{}", statement), - Statement::Assign(ref statement) => write!(f, "{}", statement), Statement::Definition(ref statement) => write!(f, "{}", statement), + Statement::Assign(ref statement) => write!(f, "{}", statement), + Statement::MultipleAssignment(ref statement) => write!(f, "{}", statement), + Statement::Conditional(ref statement) => write!(f, "{}", statement), + Statement::Iteration(ref statement) => write!(f, "{}", statement), } } } diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 14f95ffa5c..7e764d0c9f 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -7,11 +7,7 @@ use snarkos_models::{ }; use from_pest::FromPest; -use std::{ - fs, - marker::PhantomData, - path::PathBuf, -}; +use std::{fs, marker::PhantomData, path::PathBuf}; #[derive(Clone)] pub struct Compiler { @@ -21,7 +17,10 @@ pub struct Compiler { impl Compiler { pub fn init(main_file_path: PathBuf) -> Self { - Self { main_file_path, _engine: PhantomData } + Self { + main_file_path, + _engine: PhantomData, + } } } @@ -48,4 +47,4 @@ impl ConstraintSynthesizer for Compiler { Ok(()) } -} \ No newline at end of file +} diff --git a/compiler/src/constraints/constraints.rs b/compiler/src/constraints/constraints.rs index 62f068e108..de9f8d689d 100644 --- a/compiler/src/constraints/constraints.rs +++ b/compiler/src/constraints/constraints.rs @@ -4,7 +4,7 @@ use crate::ast; use crate::constraints::{ new_scope, new_scope_from_variable, new_variable_from_variables, ResolvedProgram, ResolvedValue, }; -use crate::{Expression, Function, Import, Program, Statement, Type}; +use crate::{Expression, Function, Import, Program, Type}; use from_pest::FromPest; use snarkos_models::curves::{Field, PrimeField}; @@ -109,54 +109,15 @@ impl> ResolvedProgram { .statements .clone() .into_iter() - .for_each(|statement| match statement { - Statement::Return(expressions) => { - return_values = self.enforce_return_statement( - cs, - scope.clone(), - function_name.clone(), - expressions, - function.returns.to_owned(), - ); - } - Statement::Assign(variable, expression) => { - self.enforce_assign_statement( - cs, - scope.clone(), - function_name.clone(), - variable, - expression, - ); - } - Statement::Definition(ty, assignee, expression) => { - self.enforce_definition_statement( - cs, - scope.clone(), - function_name.clone(), - ty, - assignee, - expression, - ); - } - Statement::MultipleDefinition(assignees, function_call) => { - self.enforce_multiple_definition_statement( - cs, - scope.clone(), - function_name.clone(), - assignees, - function_call, - ); - } - Statement::For(index, start, stop, statements) => { - self.enforce_for_statement( - cs, - scope.clone(), - function_name.clone(), - index, - start, - stop, - statements, - ); + .for_each(|statement| { + if let Some(returned) = self.enforce_statement( + cs, + scope.clone(), + function_name.clone(), + statement, + function.returns.clone(), + ) { + return_values = returned; } }); diff --git a/compiler/src/constraints/statement.rs b/compiler/src/constraints/statement.rs index d176bd8c41..4d09e8c870 100644 --- a/compiler/src/constraints/statement.rs +++ b/compiler/src/constraints/statement.rs @@ -1,10 +1,15 @@ //! Methods to enforce constraints on statements in a resolved aleo program. use crate::constraints::{new_scope_from_variable, ResolvedProgram, ResolvedValue}; -use crate::{Assignee, Expression, Integer, RangeOrExpression, Statement, Type, Variable}; +use crate::{ + Assignee, ConditionalNestedOrEnd, ConditionalStatement, Expression, Integer, RangeOrExpression, + Statement, Type, Variable, +}; use snarkos_models::curves::{Field, PrimeField}; -use snarkos_models::gadgets::{r1cs::ConstraintSystem, utilities::uint32::UInt32}; +use snarkos_models::gadgets::{ + r1cs::ConstraintSystem, utilities::boolean::Boolean, utilities::uint32::UInt32, +}; impl> ResolvedProgram { fn resolve_assignee(&mut self, scope: String, assignee: Assignee) -> String { @@ -124,7 +129,7 @@ impl> ResolvedProgram { } } - pub(crate) fn enforce_assign_statement( + fn enforce_assign_statement( &mut self, cs: &mut CS, file_scope: String, @@ -142,7 +147,7 @@ impl> ResolvedProgram { self.store_assignment(cs, file_scope, function_scope, assignee, result_value); } - pub(crate) fn enforce_definition_statement( + fn enforce_definition_statement( &mut self, cs: &mut CS, file_scope: String, @@ -165,7 +170,7 @@ impl> ResolvedProgram { } } - pub(crate) fn enforce_multiple_definition_statement( + fn enforce_multiple_definition_statement( &mut self, cs: &mut CS, file_scope: String, @@ -198,16 +203,16 @@ impl> ResolvedProgram { }); } - pub(crate) fn enforce_return_statement( + fn enforce_return_statement( &mut self, cs: &mut CS, file_scope: String, function_scope: String, - statements: Vec>, + expressions: Vec>, return_types: Vec>, ) -> ResolvedValue { ResolvedValue::Return( - statements + expressions .into_iter() .zip(return_types.into_iter()) .map(|(expression, ty)| { @@ -227,27 +232,125 @@ impl> ResolvedProgram { ) } - fn enforce_statement( + fn enforce_conditional_statement( + &mut self, + cs: &mut CS, + file_scope: String, + function_scope: String, + statement: ConditionalStatement, + ) -> Option> { + let mut res = None; + + let condition = match self.enforce_expression( + cs, + file_scope.clone(), + function_scope.clone(), + statement.condition.clone(), + ) { + ResolvedValue::Boolean(resolved) => resolved, + value => unimplemented!("if else conditional must resolve to boolean, got {}", value), + }; + + if condition.eq(&Boolean::Constant(true)) { + statement + .statements + .clone() + .into_iter() + .for_each(|statement| { + if let Some(early_return) = self.enforce_statement( + cs, + file_scope.clone(), + function_scope.clone(), + statement, + vec![], + ) { + res = Some(early_return) + } + }); + } else { + if let Some(next) = statement.next { + match next { + ConditionalNestedOrEnd::Nested(nested) => { + res = self.enforce_conditional_statement( + cs, + file_scope, + function_scope, + *nested, + ) + } + ConditionalNestedOrEnd::End(statements) => { + statements.into_iter().for_each(|statement| { + if let Some(early_return) = self.enforce_statement( + cs, + file_scope.clone(), + function_scope.clone(), + statement, + vec![], + ) { + res = Some(early_return) + } + }) + } + } + } + } + + res + } + + fn enforce_for_statement( + &mut self, + cs: &mut CS, + file_scope: String, + function_scope: String, + index: Variable, + start: Integer, + stop: Integer, + statements: Vec>, + ) -> Option> { + let mut res = None; + + for i in start.to_usize()..stop.to_usize() { + // Store index in current function scope. + // For loop scope is not implemented. + let index_name = new_scope_from_variable(function_scope.clone(), &index); + self.store(index_name, ResolvedValue::U32(UInt32::constant(i as u32))); + + // Evaluate statements (for loop statements should not have a return type) + statements.clone().into_iter().for_each(|statement| { + // TODO: handle for loop early termination here + res = self.enforce_statement( + cs, + file_scope.clone(), + function_scope.clone(), + statement, + vec![], + ); + }); + } + + res + } + + pub(crate) fn enforce_statement( &mut self, cs: &mut CS, file_scope: String, function_scope: String, statement: Statement, return_types: Vec>, - ) { + ) -> Option> { + let mut res = None; match statement { - Statement::Return(statements) => { + Statement::Return(expressions) => { // TODO: add support for early termination - let _res = self.enforce_return_statement( + res = Some(self.enforce_return_statement( cs, file_scope, function_scope, - statements, + expressions, return_types, - ); - } - Statement::Assign(variable, expression) => { - self.enforce_assign_statement(cs, file_scope, function_scope, variable, expression); + )); } Statement::Definition(ty, assignee, expression) => { self.enforce_definition_statement( @@ -259,7 +362,10 @@ impl> ResolvedProgram { expression, ); } - Statement::MultipleDefinition(assignees, function) => { + Statement::Assign(variable, expression) => { + self.enforce_assign_statement(cs, file_scope, function_scope, variable, expression); + } + Statement::MultipleAssign(assignees, function) => { self.enforce_multiple_definition_statement( cs, file_scope, @@ -268,8 +374,15 @@ impl> ResolvedProgram { function, ); } + Statement::Conditional(statement) => { + if let Some(early_return) = + self.enforce_conditional_statement(cs, file_scope, function_scope, statement) + { + res = Some(early_return) + } + } Statement::For(index, start, stop, statements) => { - self.enforce_for_statement( + if let Some(early_return) = self.enforce_for_statement( cs, file_scope, function_scope, @@ -277,37 +390,12 @@ impl> ResolvedProgram { start, stop, statements, - ); + ) { + res = Some(early_return) + } } }; - } - pub(crate) fn enforce_for_statement( - &mut self, - cs: &mut CS, - file_scope: String, - function_scope: String, - index: Variable, - start: Integer, - stop: Integer, - statements: Vec>, - ) { - for i in start.to_usize()..stop.to_usize() { - // Store index in current function scope. - // For loop scope is not implemented. - let index_name = new_scope_from_variable(function_scope.clone(), &index); - self.store(index_name, ResolvedValue::U32(UInt32::constant(i as u32))); - - // Evaluate statements (for loop statements should not have a return type) - statements.clone().into_iter().for_each(|statement| { - self.enforce_statement( - cs, - file_scope.clone(), - function_scope.clone(), - statement, - vec![], - ) - }); - } + res } } diff --git a/compiler/src/leo.pest b/compiler/src/leo.pest index 9859b30fa4..b243b9f23b 100644 --- a/compiler/src/leo.pest +++ b/compiler/src/leo.pest @@ -121,7 +121,7 @@ expression_inline_struct = { variable ~ "{" ~ NEWLINE* ~ inline_struct_member_li /// Conditionals -expression_conditional = { "if" ~ expression ~ "then" ~ expression ~ "else" ~ expression ~ "fi"} +expression_conditional = { "if" ~ expression ~ "?" ~ expression ~ ":" ~ expression} /// Expressions @@ -142,15 +142,18 @@ expression = { expression_term ~ (operation_binary ~ expression_term)* } expression_tuple = _{ (expression ~ ("," ~ expression)*)? } /// Statements - +// statement_one_or_more = { (statement ~ NEWLINE*)* } statement_return = { "return" ~ expression_tuple } -statement_for = { "for" ~ variable ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} -statement_multiple_assignment = { optionally_typed_variable_tuple ~ "=" ~ variable ~ "(" ~ expression_tuple ~ ")" } statement_definition = { ty ~ variable ~ "=" ~ expression } statement_assign = { assignee ~ "=" ~ expression } +statement_multiple_assignment = { optionally_typed_variable_tuple ~ "=" ~ variable ~ "(" ~ expression_tuple ~ ")" } +statement_conditional = {"if" ~ "(" ~ expression ~ ")" ~ "{" ~ NEWLINE* ~ statement+ ~ "}" ~ ("else" ~ conditional_nested_or_end)?} +conditional_nested_or_end = { statement_conditional | "{" ~ NEWLINE* ~ statement+ ~ "}"} +statement_for = { "for" ~ variable ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} statement = { (statement_return + | statement_conditional | (statement_for | statement_multiple_assignment | statement_definition diff --git a/compiler/src/types.rs b/compiler/src/types.rs index 479f01a057..53095f72bc 100644 --- a/compiler/src/types.rs +++ b/compiler/src/types.rs @@ -107,14 +107,28 @@ pub enum Type { Struct(Variable), } +#[derive(Clone)] +pub enum ConditionalNestedOrEnd { + Nested(Box>), + End(Vec>), +} + +#[derive(Clone)] +pub struct ConditionalStatement { + pub condition: Expression, + pub statements: Vec>, + pub next: Option>, +} + /// Program statement that defines some action (or expression) to be carried out. #[derive(Clone)] pub enum Statement { // Declaration(Variable), Return(Vec>), - Assign(Assignee, Expression), Definition(Type, Assignee, Expression), - MultipleDefinition(Vec>, Expression), + Assign(Assignee, Expression), + MultipleAssign(Vec>, Expression), + Conditional(ConditionalStatement), For(Variable, Integer, Integer, Vec>), } diff --git a/compiler/src/types_display.rs b/compiler/src/types_display.rs index b179c508ff..e35cbfb2e7 100644 --- a/compiler/src/types_display.rs +++ b/compiler/src/types_display.rs @@ -1,8 +1,9 @@ //! Format display functions for zokrates_program types. use crate::{ - Assignee, Expression, Function, FunctionName, Integer, Parameter, RangeOrExpression, - SpreadOrExpression, Statement, Struct, StructField, Type, Variable, + Assignee, ConditionalNestedOrEnd, ConditionalStatement, Expression, Function, FunctionName, + Integer, Parameter, RangeOrExpression, SpreadOrExpression, Statement, Struct, StructField, + Type, Variable, }; use snarkos_models::curves::{Field, PrimeField}; @@ -138,6 +139,34 @@ impl fmt::Display for Assignee { } } +impl fmt::Display for ConditionalNestedOrEnd { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ConditionalNestedOrEnd::Nested(ref nested) => write!(f, "else {}", nested), + ConditionalNestedOrEnd::End(ref statements) => { + write!(f, "else {{\n")?; + for statement in statements.iter() { + write!(f, "\t\t{}\n", statement)?; + } + write!(f, "\t}}") + } + } + } +} + +impl fmt::Display for ConditionalStatement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "if ({}) {{\n", self.condition)?; + for statement in self.statements.iter() { + write!(f, "\t\t{}\n", statement)?; + } + match self.next.clone() { + Some(n_or_e) => write!(f, "\t}} {}", n_or_e), + None => write!(f, "\t}}"), + } + } +} + impl fmt::Display for Statement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -151,13 +180,13 @@ impl fmt::Display for Statement { } write!(f, "\n") } - Statement::Assign(ref variable, ref statement) => { - write!(f, "{} = {};", variable, statement) - } Statement::Definition(ref ty, ref assignee, ref statement) => { write!(f, "{} {} = {};", ty, assignee, statement) } - Statement::MultipleDefinition(ref assignees, ref function) => { + Statement::Assign(ref variable, ref statement) => { + write!(f, "{} = {};", variable, statement) + } + Statement::MultipleAssign(ref assignees, ref function) => { for (i, id) in assignees.iter().enumerate() { write!(f, "{}", id)?; if i < assignees.len() - 1 { @@ -166,6 +195,7 @@ impl fmt::Display for Statement { } write!(f, " = {};", function) } + Statement::Conditional(ref statement) => write!(f, "{}", statement), Statement::For(ref var, ref start, ref stop, ref list) => { write!(f, "for {} in {}..{} do\n", var, start, stop)?; for l in list { @@ -190,25 +220,26 @@ impl fmt::Debug for Statement { } write!(f, "\n") } - Statement::Assign(ref variable, ref statement) => { - write!(f, "{} = {};", variable, statement) - } Statement::Definition(ref ty, ref assignee, ref statement) => { write!(f, "{} {} = {};", ty, assignee, statement) } - Statement::MultipleDefinition(ref assignees, ref function) => { + Statement::Assign(ref variable, ref statement) => { + write!(f, "{} = {};", variable, statement) + } + Statement::MultipleAssign(ref assignees, ref function) => { for (i, id) in assignees.iter().enumerate() { write!(f, "{}", id)?; if i < assignees.len() - 1 { write!(f, ", ")?; } } - write!(f, " = {}();", function) + write!(f, " = {};", function) } + Statement::Conditional(ref statement) => write!(f, "{}", statement), Statement::For(ref var, ref start, ref stop, ref list) => { - write!(f, "for {:?} in {:?}..{:?} do\n", var, start, stop)?; + write!(f, "for {} in {}..{} do\n", var, start, stop)?; for l in list { - write!(f, "\t\t{:?}\n", l)?; + write!(f, "\t\t{}\n", l)?; } write!(f, "\tendfor;") } diff --git a/compiler/src/types_from.rs b/compiler/src/types_from.rs index 3be11ba471..7813960a66 100644 --- a/compiler/src/types_from.rs +++ b/compiler/src/types_from.rs @@ -346,6 +346,86 @@ impl<'ast, F: Field + PrimeField> From> for types::St } } +impl<'ast, F: Field + PrimeField> From> for types::Statement { + fn from(statement: ast::DefinitionStatement<'ast>) -> Self { + types::Statement::Definition( + types::Type::from(statement.ty), + types::Assignee::from(statement.variable), + types::Expression::from(statement.expression), + ) + } +} + +impl<'ast, F: Field + PrimeField> From> for types::Statement { + fn from(statement: ast::AssignStatement<'ast>) -> Self { + types::Statement::Assign( + types::Assignee::from(statement.assignee), + types::Expression::from(statement.expression), + ) + } +} + +impl<'ast, F: Field + PrimeField> From> + for types::Statement +{ + fn from(statement: ast::MultipleAssignmentStatement<'ast>) -> Self { + let assignees = statement + .assignees + .into_iter() + .map(|i| types::Assignee::Variable(types::Variable::from(i.id))) + .collect(); + + types::Statement::MultipleAssign( + assignees, + types::Expression::FunctionCall( + types::Variable::from(statement.function_name), + statement + .arguments + .into_iter() + .map(|e| types::Expression::from(e)) + .collect(), + ), + ) + } +} + +impl<'ast, F: Field + PrimeField> From> + for types::ConditionalNestedOrEnd +{ + fn from(statement: ast::ConditionalNestedOrEnd<'ast>) -> Self { + match statement { + ast::ConditionalNestedOrEnd::Nested(nested) => types::ConditionalNestedOrEnd::Nested( + Box::new(types::ConditionalStatement::from(*nested)), + ), + ast::ConditionalNestedOrEnd::End(statements) => types::ConditionalNestedOrEnd::End( + statements + .into_iter() + .map(|statement| types::Statement::from(statement)) + .collect(), + ), + } + } +} + +impl<'ast, F: Field + PrimeField> From> + for types::ConditionalStatement +{ + fn from(statement: ast::ConditionalStatement<'ast>) -> Self { + types::ConditionalStatement { + condition: types::Expression::from(statement.condition), + statements: statement + .statements + .into_iter() + .map(|statement| types::Statement::from(statement)) + .collect(), + next: statement + .next + .map(|n_or_e| Some(types::ConditionalNestedOrEnd::from(n_or_e))) + .unwrap_or(None), + } + } +} + impl<'ast, F: Field + PrimeField> From> for types::Statement { fn from(statement: ast::ForStatement<'ast>) -> Self { let from = match types::Expression::::from(statement.start) { @@ -370,57 +450,17 @@ impl<'ast, F: Field + PrimeField> From> for types::State } } -impl<'ast, F: Field + PrimeField> From> - for types::Statement -{ - fn from(statement: ast::MultipleAssignmentStatement<'ast>) -> Self { - let assignees = statement - .assignees - .into_iter() - .map(|i| types::Assignee::Variable(types::Variable::from(i.id))) - .collect(); - - types::Statement::MultipleDefinition( - assignees, - types::Expression::FunctionCall( - types::Variable::from(statement.function_name), - statement - .arguments - .into_iter() - .map(|e| types::Expression::from(e)) - .collect(), - ), - ) - } -} - -impl<'ast, F: Field + PrimeField> From> for types::Statement { - fn from(statement: ast::AssignStatement<'ast>) -> Self { - types::Statement::Assign( - types::Assignee::from(statement.assignee), - types::Expression::from(statement.expression), - ) - } -} - -impl<'ast, F: Field + PrimeField> From> for types::Statement { - fn from(statement: ast::DefinitionStatement<'ast>) -> Self { - types::Statement::Definition( - types::Type::from(statement.ty), - types::Assignee::from(statement.variable), - types::Expression::from(statement.expression), - ) - } -} - impl<'ast, F: Field + PrimeField> From> for types::Statement { fn from(statement: ast::Statement<'ast>) -> Self { match statement { ast::Statement::Return(statement) => types::Statement::from(statement), - ast::Statement::Iteration(statement) => types::Statement::from(statement), - ast::Statement::MultipleAssignment(statement) => types::Statement::from(statement), - ast::Statement::Assign(statement) => types::Statement::from(statement), ast::Statement::Definition(statement) => types::Statement::from(statement), + ast::Statement::Assign(statement) => types::Statement::from(statement), + ast::Statement::MultipleAssignment(statement) => types::Statement::from(statement), + ast::Statement::Conditional(statement) => { + types::Statement::Conditional(types::ConditionalStatement::from(statement)) + } + ast::Statement::Iteration(statement) => types::Statement::from(statement), } } } diff --git a/leo/cli.rs b/leo/cli.rs index 5ba8367697..cd12663ba3 100644 --- a/leo/cli.rs +++ b/leo/cli.rs @@ -18,10 +18,7 @@ pub trait CLI { fn new<'a, 'b>() -> App<'a, 'b> { let arguments = &Self::ARGUMENTS .iter() - .map(|a| Arg::with_name(a.0) - .help(a.1) - .required(a.2) - .index(a.3)) + .map(|a| Arg::with_name(a.0).help(a.1).required(a.2).index(a.3)) .collect::>>(); let flags = &Self::FLAGS .iter() @@ -34,7 +31,9 @@ pub trait CLI { .conflicts_with_all(a.1) .possible_values(a.2) .requires_all(a.3), - false => Arg::from_usage(a.0).conflicts_with_all(a.1).requires_all(a.3), + false => Arg::from_usage(a.0) + .conflicts_with_all(a.1) + .requires_all(a.3), }) .collect::>>(); let subcommands = Self::SUBCOMMANDS @@ -49,7 +48,9 @@ pub trait CLI { .conflicts_with_all(a.1) .possible_values(a.2) .requires_all(a.3), - false => Arg::from_usage(a.0).conflicts_with_all(a.1).requires_all(a.3), + false => Arg::from_usage(a.0) + .conflicts_with_all(a.1) + .requires_all(a.3), }) .collect::>>(), ) diff --git a/leo/cli_types.rs b/leo/cli_types.rs index ef33d69cb9..8ca662ed14 100644 --- a/leo/cli_types.rs +++ b/leo/cli_types.rs @@ -21,4 +21,9 @@ pub type OptionType = ( &'static [&'static str], ); -pub type SubCommandType = (NameType, AboutType, &'static [OptionType], &'static [AppSettings]); +pub type SubCommandType = ( + NameType, + AboutType, + &'static [OptionType], + &'static [AppSettings], +); diff --git a/leo/commands/build.rs b/leo/commands/build.rs index 873ab5833b..16a9e46862 100644 --- a/leo/commands/build.rs +++ b/leo/commands/build.rs @@ -1,8 +1,8 @@ -use crate::{cli::*, cli_types::*}; -use crate::directories::{OutputsDirectory, source::SOURCE_DIRECTORY_NAME}; -use crate::errors::{CLIError, BuildError}; +use crate::directories::{source::SOURCE_DIRECTORY_NAME, OutputsDirectory}; +use crate::errors::{BuildError, CLIError}; use crate::files::{MainFile, MAIN_FILE_NAME}; use crate::manifest::Manifest; +use crate::{cli::*, cli_types::*}; use leo_compiler::compiler::Compiler; use snarkos_curves::bls12_377::Fr; @@ -43,7 +43,9 @@ impl CLI for BuildCommand { // Verify the main file exists if !MainFile::exists_at(&package_path) { - return Err(BuildError::MainFileDoesNotExist(package_path.as_os_str().to_owned()).into()); + return Err( + BuildError::MainFileDoesNotExist(package_path.as_os_str().to_owned()).into(), + ); } // Create the outputs directory diff --git a/leo/commands/init.rs b/leo/commands/init.rs index 5ccfc1bb0e..ba5ad01071 100644 --- a/leo/commands/init.rs +++ b/leo/commands/init.rs @@ -1,8 +1,8 @@ -use crate::{cli::*, cli_types::*}; use crate::directories::{InputsDirectory, SourceDirectory}; use crate::errors::{CLIError, InitError}; use crate::files::MainFile; use crate::manifest::Manifest; +use crate::{cli::*, cli_types::*}; use clap::ArgMatches; use std::env::current_dir; diff --git a/leo/commands/new.rs b/leo/commands/new.rs index 7878c7c735..1100eb6e6c 100644 --- a/leo/commands/new.rs +++ b/leo/commands/new.rs @@ -1,8 +1,8 @@ -use crate::{cli::*, cli_types::*}; use crate::directories::{InputsDirectory, SourceDirectory}; use crate::errors::{CLIError, NewError}; use crate::files::MainFile; use crate::manifest::Manifest; +use crate::{cli::*, cli_types::*}; use clap::ArgMatches; use std::env::current_dir; @@ -19,7 +19,12 @@ impl CLI for NewCommand { const ABOUT: AboutType = "Creates a new Leo package"; const ARGUMENTS: &'static [ArgumentType] = &[ // (name, description, required, index) - ("NAME", "Sets the resulting package name, defaults to the directory name", true, 1u64) + ( + "NAME", + "Sets the resulting package name, defaults to the directory name", + true, + 1u64, + ), ]; const FLAGS: &'static [FlagType] = &[]; const OPTIONS: &'static [OptionType] = &[]; @@ -29,7 +34,7 @@ impl CLI for NewCommand { fn parse(arguments: &ArgMatches) -> Result { match arguments.value_of("NAME") { Some(name) => Ok(Some(name.to_string())), - None => Ok(None) + None => Ok(None), } } @@ -56,9 +61,8 @@ impl CLI for NewCommand { } // Create the package directory - fs::create_dir_all(&path).map_err(|error| { - NewError::CreatingRootDirectory(path.as_os_str().to_owned(), error) - })?; + fs::create_dir_all(&path) + .map_err(|error| NewError::CreatingRootDirectory(path.as_os_str().to_owned(), error))?; // Create the manifest file Manifest::new(&package_name).write_to(&path)?; diff --git a/leo/commands/run.rs b/leo/commands/run.rs index 840a2b4ffb..7b03e0ad39 100644 --- a/leo/commands/run.rs +++ b/leo/commands/run.rs @@ -1,6 +1,6 @@ -use crate::{cli::*, cli_types::*}; use crate::commands::SetupCommand; use crate::errors::CLIError; +use crate::{cli::*, cli_types::*}; use snarkos_algorithms::snark::{create_random_proof, verify_proof}; diff --git a/leo/commands/setup.rs b/leo/commands/setup.rs index 36f2ca2367..abaf79ca93 100644 --- a/leo/commands/setup.rs +++ b/leo/commands/setup.rs @@ -1,9 +1,11 @@ -use crate::{cli::*, cli_types::*}; use crate::commands::BuildCommand; use crate::errors::CLIError; +use crate::{cli::*, cli_types::*}; use leo_compiler::compiler::Compiler; -use snarkos_algorithms::snark::{generate_random_parameters, prepare_verifying_key, Parameters, PreparedVerifyingKey}; +use snarkos_algorithms::snark::{ + generate_random_parameters, prepare_verifying_key, Parameters, PreparedVerifyingKey, +}; use snarkos_curves::bls12_377::{Bls12_377, Fr}; use clap::ArgMatches; @@ -15,7 +17,11 @@ pub struct SetupCommand; impl CLI for SetupCommand { type Options = (); - type Output = (Compiler, Parameters, PreparedVerifyingKey); + type Output = ( + Compiler, + Parameters, + PreparedVerifyingKey, + ); const NAME: NameType = "setup"; const ABOUT: AboutType = "Run a program setup"; @@ -36,7 +42,8 @@ impl CLI for SetupCommand { let start = Instant::now(); let rng = &mut thread_rng(); - let parameters = generate_random_parameters::(circuit.clone(), rng).unwrap(); + let parameters = + generate_random_parameters::(circuit.clone(), rng).unwrap(); let prepared_verifying_key = prepare_verifying_key::(¶meters.vk); let finish = start.elapsed(); diff --git a/leo/directories/inputs.rs b/leo/directories/inputs.rs index 0982527c76..5a891db265 100644 --- a/leo/directories/inputs.rs +++ b/leo/directories/inputs.rs @@ -32,9 +32,9 @@ impl InputsDirectory { let file_path = file_entry.path(); // Verify that the entry is structured as a valid file - let file_type = file_entry - .file_type() - .map_err(|error| InputsDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?; + let file_type = file_entry.file_type().map_err(|error| { + InputsDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error) + })?; if !file_type.is_file() { return Err(InputsDirectoryError::InvalidFileType( file_path.as_os_str().to_owned(), @@ -43,9 +43,9 @@ impl InputsDirectory { } // Verify that the file has the default file extension - let file_extension = file_path - .extension() - .ok_or_else(|| InputsDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()))?; + let file_extension = file_path.extension().ok_or_else(|| { + InputsDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()) + })?; if file_extension != INPUTS_FILE_EXTENSION { return Err(InputsDirectoryError::InvalidFileExtension( file_path.as_os_str().to_owned(), diff --git a/leo/directories/source.rs b/leo/directories/source.rs index eb9bb78c37..9132ccca16 100644 --- a/leo/directories/source.rs +++ b/leo/directories/source.rs @@ -32,9 +32,9 @@ impl SourceDirectory { let file_path = file_entry.path(); // Verify that the entry is structured as a valid file - let file_type = file_entry - .file_type() - .map_err(|error| SourceDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error))?; + let file_type = file_entry.file_type().map_err(|error| { + SourceDirectoryError::GettingFileType(file_path.as_os_str().to_owned(), error) + })?; if !file_type.is_file() { return Err(SourceDirectoryError::InvalidFileType( file_path.as_os_str().to_owned(), @@ -43,9 +43,9 @@ impl SourceDirectory { } // Verify that the file has the default file extension - let file_extension = file_path - .extension() - .ok_or_else(|| SourceDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()))?; + let file_extension = file_path.extension().ok_or_else(|| { + SourceDirectoryError::GettingFileExtension(file_path.as_os_str().to_owned()) + })?; if file_extension != SOURCE_FILE_EXTENSION { return Err(SourceDirectoryError::InvalidFileExtension( file_path.as_os_str().to_owned(), diff --git a/leo/errors/cli.rs b/leo/errors/cli.rs index f8a31d7cd6..6f91e5b3f8 100644 --- a/leo/errors/cli.rs +++ b/leo/errors/cli.rs @@ -2,7 +2,6 @@ use crate::errors::*; #[derive(Debug, Fail)] pub enum CLIError { - #[fail(display = "{}", _0)] BuildError(BuildError), @@ -32,7 +31,6 @@ pub enum CLIError { #[fail(display = "{}", _0)] SourceDirectoryError(SourceDirectoryError), - } impl From for CLIError { diff --git a/leo/errors/commands/build.rs b/leo/errors/commands/build.rs index f74f995c33..dc302e2010 100644 --- a/leo/errors/commands/build.rs +++ b/leo/errors/commands/build.rs @@ -4,13 +4,11 @@ use std::ffi::OsString; #[derive(Debug, Fail)] pub enum BuildError { - #[fail(display = "main file {:?} does not exist", _0)] MainFileDoesNotExist(OsString), #[fail(display = "{}", _0)] ManifestError(ManifestError), - } impl From for BuildError { diff --git a/leo/errors/commands/init.rs b/leo/errors/commands/init.rs index d721c5a80f..5d8c9c118e 100644 --- a/leo/errors/commands/init.rs +++ b/leo/errors/commands/init.rs @@ -5,7 +5,6 @@ use std::io; #[derive(Debug, Fail)] pub enum InitError { - #[fail(display = "root directory {:?} creating: {}", _0, _1)] CreatingRootDirectory(OsString, io::Error), @@ -20,7 +19,6 @@ pub enum InitError { #[fail(display = "package name is missing - {:?}", _0)] ProjectNameInvalid(OsString), - } impl From for InitError { diff --git a/leo/errors/commands/new.rs b/leo/errors/commands/new.rs index f06d18de4e..e420d648ca 100644 --- a/leo/errors/commands/new.rs +++ b/leo/errors/commands/new.rs @@ -5,7 +5,6 @@ use std::io; #[derive(Debug, Fail)] pub enum NewError { - #[fail(display = "root directory {:?} creating: {}", _0, _1)] CreatingRootDirectory(OsString, io::Error), @@ -20,7 +19,6 @@ pub enum NewError { #[fail(display = "package name is missing - {:?}", _0)] ProjectNameInvalid(OsString), - } impl From for NewError { diff --git a/leo/errors/commands/run.rs b/leo/errors/commands/run.rs index 5c16d35933..ab23f3be90 100644 --- a/leo/errors/commands/run.rs +++ b/leo/errors/commands/run.rs @@ -4,13 +4,11 @@ use std::ffi::OsString; #[derive(Debug, Fail)] pub enum RunError { - #[fail(display = "main file {:?} does not exist", _0)] MainFileDoesNotExist(OsString), #[fail(display = "{}", _0)] ManifestError(ManifestError), - } impl From for RunError { diff --git a/leo/errors/directory/inputs.rs b/leo/errors/directory/inputs.rs index e13479e456..38e92b335f 100644 --- a/leo/errors/directory/inputs.rs +++ b/leo/errors/directory/inputs.rs @@ -2,7 +2,6 @@ use std::{ffi::OsString, fs::FileType, io}; #[derive(Debug, Fail)] pub enum InputsDirectoryError { - #[fail(display = "creating: {}", _0)] Creating(io::Error), @@ -23,5 +22,4 @@ pub enum InputsDirectoryError { #[fail(display = "reading: {}", _0)] Reading(io::Error), - } diff --git a/leo/errors/directory/outputs.rs b/leo/errors/directory/outputs.rs index 87c61db1f0..156dd866af 100644 --- a/leo/errors/directory/outputs.rs +++ b/leo/errors/directory/outputs.rs @@ -2,7 +2,6 @@ use std::{ffi::OsString, fs::FileType, io}; #[derive(Debug, Fail)] pub enum OutputsDirectoryError { - #[fail(display = "creating: {}", _0)] Creating(io::Error), @@ -26,5 +25,4 @@ pub enum OutputsDirectoryError { #[fail(display = "removing: {}", _0)] Removing(io::Error), - } diff --git a/leo/errors/directory/source.rs b/leo/errors/directory/source.rs index 2ac823ad3b..bbfc7394f3 100644 --- a/leo/errors/directory/source.rs +++ b/leo/errors/directory/source.rs @@ -2,7 +2,6 @@ use std::{ffi::OsString, fs::FileType, io}; #[derive(Debug, Fail)] pub enum SourceDirectoryError { - #[fail(display = "creating: {}", _0)] Creating(io::Error), @@ -23,5 +22,4 @@ pub enum SourceDirectoryError { #[fail(display = "reading: {}", _0)] Reading(io::Error), - } diff --git a/leo/errors/files/main.rs b/leo/errors/files/main.rs index e7c5a48de3..4a10c35bcd 100644 --- a/leo/errors/files/main.rs +++ b/leo/errors/files/main.rs @@ -2,7 +2,6 @@ use std::io; #[derive(Debug, Fail)] pub enum MainFileError { - #[fail(display = "{}: {}", _0, _1)] Crate(&'static str, String), @@ -11,7 +10,6 @@ pub enum MainFileError { #[fail(display = "writing: {}", _0)] Writing(io::Error), - } impl From for MainFileError { diff --git a/leo/errors/manifest.rs b/leo/errors/manifest.rs index b62184b4c1..7520d70005 100644 --- a/leo/errors/manifest.rs +++ b/leo/errors/manifest.rs @@ -2,7 +2,6 @@ use std::io; #[derive(Debug, Fail)] pub enum ManifestError { - #[fail(display = "`{}` creating: {}", _0, _1)] Creating(&'static str, io::Error), @@ -20,5 +19,4 @@ pub enum ManifestError { #[fail(display = "`{}` writing: {}", _0, _1)] Writing(&'static str, io::Error), - } diff --git a/leo/files/main.rs b/leo/files/main.rs index 8862d66b51..bfa79ff964 100644 --- a/leo/files/main.rs +++ b/leo/files/main.rs @@ -17,7 +17,9 @@ pub struct MainFile { impl MainFile { pub fn new(package_name: &str) -> Self { - Self { package_name: package_name.to_string() } + Self { + package_name: package_name.to_string(), + } } pub fn exists_at(path: &PathBuf) -> bool { @@ -55,4 +57,4 @@ function main() -> (u32) {{ self.package_name ) } -} \ No newline at end of file +} diff --git a/leo/main.rs b/leo/main.rs index 1f322217e7..47ac498d52 100644 --- a/leo/main.rs +++ b/leo/main.rs @@ -1,5 +1,5 @@ -use leo::{cli::*, commands::*, logger}; use leo::errors::CLIError; +use leo::{cli::*, commands::*, logger}; use clap::{App, AppSettings}; @@ -34,11 +34,11 @@ fn main() -> Result<(), CLIError> { ("build", Some(arguments)) => { BuildCommand::output(BuildCommand::parse(arguments)?)?; Ok(()) - }, + } ("setup", Some(arguments)) => { SetupCommand::output(SetupCommand::parse(arguments)?)?; Ok(()) - }, + } ("run", Some(arguments)) => RunCommand::output(RunCommand::parse(arguments)?), _ => unreachable!(), } diff --git a/leo/manifest.rs b/leo/manifest.rs index 61e885d853..f6c2a84ec6 100644 --- a/leo/manifest.rs +++ b/leo/manifest.rs @@ -44,8 +44,8 @@ impl Manifest { path.push(PathBuf::from(FILE_NAME_DEFAULT)); } - let mut file = - File::create(&path).map_err(|error| ManifestError::Creating(FILE_NAME_DEFAULT, error))?; + let mut file = File::create(&path) + .map_err(|error| ManifestError::Creating(FILE_NAME_DEFAULT, error))?; file.write_all(self.template().as_bytes()) .map_err(|error| ManifestError::Writing(FILE_NAME_DEFAULT, error)) } @@ -81,6 +81,7 @@ impl TryFrom<&PathBuf> for Manifest { file.read_to_string(&mut buffer) .map_err(|error| ManifestError::Reading(FILE_NAME_DEFAULT, error))?; - Ok(toml::from_str(&buffer).map_err(|error| ManifestError::Parsing(FILE_NAME_DEFAULT, error))?) + Ok(toml::from_str(&buffer) + .map_err(|error| ManifestError::Parsing(FILE_NAME_DEFAULT, error))?) } }