impl if else conditional statements

This commit is contained in:
collin 2020-04-27 14:36:05 -07:00
parent efbf4f54e9
commit f69032c833
32 changed files with 437 additions and 246 deletions

View File

@ -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
}

View File

@ -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<F: Field + PrimeField> ConstraintSynthesizer<F> for Benchmark<F> {
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(())
}

View File

@ -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<ConditionalStatement<'ast>>),
End(Vec<Statement<'ast>>),
}
#[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_conditional))]
pub struct ConditionalStatement<'ast> {
pub condition: Expression<'ast>,
pub statements: Vec<Statement<'ast>>,
pub next: Option<ConditionalNestedOrEnd<'ast>>,
#[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),
}
}
}

View File

@ -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<F: Field + PrimeField> {
@ -21,7 +17,10 @@ pub struct Compiler<F: Field + PrimeField> {
impl<F: Field + PrimeField> Compiler<F> {
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<F: Field + PrimeField> ConstraintSynthesizer<F> for Compiler<F> {
Ok(())
}
}
}

View File

@ -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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
.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;
}
});

View File

@ -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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
fn resolve_assignee(&mut self, scope: String, assignee: Assignee<F>) -> String {
@ -124,7 +129,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
}
}
pub(crate) fn enforce_assign_statement(
fn enforce_assign_statement(
&mut self,
cs: &mut CS,
file_scope: String,
@ -142,7 +147,7 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
}
}
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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
});
}
pub(crate) fn enforce_return_statement(
fn enforce_return_statement(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
statements: Vec<Expression<F>>,
expressions: Vec<Expression<F>>,
return_types: Vec<Type<F>>,
) -> ResolvedValue<F> {
ResolvedValue::Return(
statements
expressions
.into_iter()
.zip(return_types.into_iter())
.map(|(expression, ty)| {
@ -227,27 +232,125 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
)
}
fn enforce_statement(
fn enforce_conditional_statement(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
statement: ConditionalStatement<F>,
) -> Option<ResolvedValue<F>> {
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<F>,
start: Integer,
stop: Integer,
statements: Vec<Statement<F>>,
) -> Option<ResolvedValue<F>> {
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<F>,
return_types: Vec<Type<F>>,
) {
) -> Option<ResolvedValue<F>> {
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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
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<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
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<F>,
start: Integer,
stop: Integer,
statements: Vec<Statement<F>>,
) {
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
}
}

View File

@ -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

View File

@ -107,14 +107,28 @@ pub enum Type<F: Field + PrimeField> {
Struct(Variable<F>),
}
#[derive(Clone)]
pub enum ConditionalNestedOrEnd<F: Field + PrimeField> {
Nested(Box<ConditionalStatement<F>>),
End(Vec<Statement<F>>),
}
#[derive(Clone)]
pub struct ConditionalStatement<F: Field + PrimeField> {
pub condition: Expression<F>,
pub statements: Vec<Statement<F>>,
pub next: Option<ConditionalNestedOrEnd<F>>,
}
/// Program statement that defines some action (or expression) to be carried out.
#[derive(Clone)]
pub enum Statement<F: Field + PrimeField> {
// Declaration(Variable),
Return(Vec<Expression<F>>),
Assign(Assignee<F>, Expression<F>),
Definition(Type<F>, Assignee<F>, Expression<F>),
MultipleDefinition(Vec<Assignee<F>>, Expression<F>),
Assign(Assignee<F>, Expression<F>),
MultipleAssign(Vec<Assignee<F>>, Expression<F>),
Conditional(ConditionalStatement<F>),
For(Variable<F>, Integer, Integer, Vec<Statement<F>>),
}

View File

@ -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<F: Field + PrimeField> fmt::Display for Assignee<F> {
}
}
impl<F: Field + PrimeField> fmt::Display for ConditionalNestedOrEnd<F> {
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<F: Field + PrimeField> fmt::Display for ConditionalStatement<F> {
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<F: Field + PrimeField> fmt::Display for Statement<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -151,13 +180,13 @@ impl<F: Field + PrimeField> fmt::Display for Statement<F> {
}
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<F: Field + PrimeField> fmt::Display for Statement<F> {
}
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<F: Field + PrimeField> fmt::Debug for Statement<F> {
}
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;")
}

View File

@ -346,6 +346,86 @@ impl<'ast, F: Field + PrimeField> From<ast::ReturnStatement<'ast>> for types::St
}
}
impl<'ast, F: Field + PrimeField> From<ast::DefinitionStatement<'ast>> for types::Statement<F> {
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<ast::AssignStatement<'ast>> for types::Statement<F> {
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<ast::MultipleAssignmentStatement<'ast>>
for types::Statement<F>
{
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<ast::ConditionalNestedOrEnd<'ast>>
for types::ConditionalNestedOrEnd<F>
{
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<ast::ConditionalStatement<'ast>>
for types::ConditionalStatement<F>
{
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<ast::ForStatement<'ast>> for types::Statement<F> {
fn from(statement: ast::ForStatement<'ast>) -> Self {
let from = match types::Expression::<F>::from(statement.start) {
@ -370,57 +450,17 @@ impl<'ast, F: Field + PrimeField> From<ast::ForStatement<'ast>> for types::State
}
}
impl<'ast, F: Field + PrimeField> From<ast::MultipleAssignmentStatement<'ast>>
for types::Statement<F>
{
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<ast::AssignStatement<'ast>> for types::Statement<F> {
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<ast::DefinitionStatement<'ast>> for types::Statement<F> {
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<ast::Statement<'ast>> for types::Statement<F> {
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),
}
}
}

View File

@ -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::<Vec<Arg<'static, 'static>>>();
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::<Vec<Arg<'static, 'static>>>();
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::<Vec<Arg<'static, 'static>>>(),
)

View File

@ -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],
);

View File

@ -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

View File

@ -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;

View File

@ -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<Self::Options, CLIError> {
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)?;

View File

@ -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};

View File

@ -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<Fr>, Parameters<Bls12_377>, PreparedVerifyingKey<Bls12_377>);
type Output = (
Compiler<Fr>,
Parameters<Bls12_377>,
PreparedVerifyingKey<Bls12_377>,
);
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::<Bls12_377, _, _>(circuit.clone(), rng).unwrap();
let parameters =
generate_random_parameters::<Bls12_377, _, _>(circuit.clone(), rng).unwrap();
let prepared_verifying_key = prepare_verifying_key::<Bls12_377>(&parameters.vk);
let finish = start.elapsed();

View File

@ -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(),

View File

@ -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(),

View File

@ -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<BuildError> for CLIError {

View File

@ -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<ManifestError> for BuildError {

View File

@ -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<ManifestError> for InitError {

View File

@ -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<ManifestError> for NewError {

View File

@ -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<ManifestError> for RunError {

View File

@ -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),
}

View File

@ -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),
}

View File

@ -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),
}

View File

@ -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<std::io::Error> for MainFileError {

View File

@ -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),
}

View File

@ -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
)
}
}
}

View File

@ -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!(),
}

View File

@ -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))?)
}
}