From 455c0b631a624891bf9aa641b84628ef54245203 Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 16 Apr 2020 11:36:23 -0700 Subject: [PATCH] constraints for loops --- simple.program | 13 +++---- src/aleo_program/constraints.rs | 64 +++++++++++++++++++++++-------- src/aleo_program/types.rs | 7 +--- src/aleo_program/types_display.rs | 30 +++++++++++---- src/aleo_program/types_from.rs | 26 +++++++------ src/ast.rs | 17 ++++---- src/language.pest | 4 +- 7 files changed, 100 insertions(+), 61 deletions(-) diff --git a/simple.program b/simple.program index 39835d769f..ab2b0dfdbd 100644 --- a/simple.program +++ b/simple.program @@ -1,9 +1,6 @@ -struct Foo { - bool x -} def main() -> (field): - field[3] a = [1, 2, 3] // initialize the array - field[4] b = [42; 4] - c = a[1..3] // helloo??? - bool[3] d = [true, false, true] - return a[0] + a = 1 + for i in 0..4 do + a = a + 1 + endfor + return a \ No newline at end of file diff --git a/src/aleo_program/constraints.rs b/src/aleo_program/constraints.rs index f2304c8488..932415cca4 100644 --- a/src/aleo_program/constraints.rs +++ b/src/aleo_program/constraints.rs @@ -639,21 +639,50 @@ impl ResolvedProgram { ) } - // fn enforce_statement>( - // &mut self, - // cs: &mut CS, - // statement: Statement, - // ) { - // match statement { - // Statement::Definition(variable, expression) => { - // self.enforce_definition_statement(cs, variable, expression); - // } - // Statement::Return(statements) => { - // let res = self.enforce_return_statement(cs, statements); - // - // } - // }; - // } + fn enforce_statement>( + &mut self, + cs: &mut CS, + statement: Statement, + ) { + match statement { + Statement::Definition(variable, expression) => { + self.enforce_definition_statement(cs, variable, expression); + } + Statement::For(index, start, stop, statements) => { + self.enforce_for_statement(cs, index, start, stop, statements); + } + Statement::Return(statements) => { + // TODO: add support for early termination + let _res = self.enforce_return_statement(cs, statements); + } + }; + } + + fn enforce_for_statement>( + &mut self, + cs: &mut CS, + index: Variable, + start: FieldExpression, + stop: FieldExpression, + statements: Vec, + ) { + let start_index = self.enforce_index(cs, start); + let stop_index = self.enforce_index(cs, stop); + + for i in start_index..stop_index { + // Store index + self.resolved_variables.insert( + index.clone(), + ResolvedValue::FieldElement(UInt32::constant(i as u32)), + ); + + // Evaluate statements + statements + .clone() + .into_iter() + .for_each(|statement| self.enforce_statement(cs, statement)); + } + } fn enforce_function>( &mut self, @@ -715,7 +744,10 @@ impl ResolvedProgram { .into_iter() .for_each(|statement| match statement { Statement::Definition(variable, expression) => { - self.enforce_definition_statement(cs, variable, expression) + self.enforce_definition_statement(cs, variable, expression); + } + Statement::For(index, start, stop, statements) => { + self.enforce_for_statement(cs, index, start, stop, statements); } Statement::Return(expressions) => { return_values = self.enforce_return_statement(cs, expressions) diff --git a/src/aleo_program/types.rs b/src/aleo_program/types.rs index 6b099c102e..bf53e71904 100644 --- a/src/aleo_program/types.rs +++ b/src/aleo_program/types.rs @@ -103,6 +103,7 @@ pub enum Expression { pub enum Statement { // Declaration(Variable), Definition(Variable, Expression), + For(Variable, FieldExpression, FieldExpression, Vec), Return(Vec), } @@ -120,12 +121,6 @@ pub struct StructMember { pub expression: Expression, } -// #[derive(Clone, Debug)] -// pub struct StructExpression { -// pub variable: Variable, -// pub members: Vec -// } - #[derive(Clone)] pub struct StructField { pub variable: Variable, diff --git a/src/aleo_program/types_display.rs b/src/aleo_program/types_display.rs index f27dcc86ce..64991746ae 100644 --- a/src/aleo_program/types_display.rs +++ b/src/aleo_program/types_display.rs @@ -6,8 +6,8 @@ use crate::aleo_program::{ BooleanExpression, BooleanSpread, BooleanSpreadOrExpression, Expression, FieldExpression, - FieldRangeOrExpression, FieldSpread, FieldSpreadOrExpression, Function, FunctionName, Parameter, Statement, - Struct, StructField, Type, Variable, + FieldRangeOrExpression, FieldSpread, FieldSpreadOrExpression, Function, FunctionName, + Parameter, Statement, Struct, StructField, Type, Variable, }; use std::fmt; @@ -166,15 +166,22 @@ impl<'ast> fmt::Display for Expression { impl fmt::Display for Statement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { + Statement::Definition(ref variable, ref statement) => { + write!(f, "{} = {}", variable, statement) + } + Statement::For(ref var, ref start, ref stop, ref list) => { + write!(f, "for {} in {}..{} do\n", var, start, stop)?; + for l in list { + write!(f, "\t\t{}\n", l)?; + } + write!(f, "\tendfor") + } Statement::Return(ref statements) => { statements.iter().for_each(|statement| { write!(f, "return {}", statement).unwrap(); }); write!(f, "\n") } - Statement::Definition(ref variable, ref statement) => { - write!(f, "{} = {}", variable, statement) - } } } } @@ -182,15 +189,22 @@ impl fmt::Display for Statement { impl fmt::Debug for Statement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { + Statement::Definition(ref variable, ref statement) => { + write!(f, "{} = {}", variable, statement) + } + Statement::For(ref var, ref start, ref stop, ref list) => { + write!(f, "for {:?} in {:?}..{:?} do\n", var, start, stop)?; + for l in list { + write!(f, "\t\t{:?}\n", l)?; + } + write!(f, "\tendfor") + } Statement::Return(ref statements) => { statements.iter().for_each(|statement| { write!(f, "return {}", statement).unwrap(); }); write!(f, "\n") } - Statement::Definition(ref variable, ref statement) => { - write!(f, "{} = {}", variable, statement) - } } } } diff --git a/src/aleo_program/types_from.rs b/src/aleo_program/types_from.rs index 0db8ffe941..17a9d4f259 100644 --- a/src/aleo_program/types_from.rs +++ b/src/aleo_program/types_from.rs @@ -561,10 +561,18 @@ impl<'ast> From> for types::Statement { } } -impl<'ast> From> for types::Statement { - fn from(statement: ast::IterationStatement<'ast>) -> Self { - println!("{:#?}", statement); - unimplemented!() +impl<'ast> From> for types::Statement { + fn from(statement: ast::ForStatement<'ast>) -> Self { + types::Statement::For( + types::Variable::from(statement.index), + types::FieldExpression::from(statement.start), + types::FieldExpression::from(statement.stop), + statement + .statements + .into_iter() + .map(|statement| types::Statement::from(statement)) + .collect(), + ) } } @@ -704,7 +712,8 @@ impl<'ast> From> for types::Function { impl<'ast> From> for types::Program { fn from(file: ast::File<'ast>) -> Self { - // 1. compile ast -> aleo program representation + // Compiled ast -> aleo program representation + let mut structs = HashMap::new(); let mut functions = HashMap::new(); @@ -721,17 +730,10 @@ impl<'ast> From> for types::Program { ); }); - // let statements: Vec = file - // .statements - // .into_iter() - // .map(|statement| types::Statement::from(statement)) - // .collect(); - types::Program { id: "main".into(), structs, functions, - // statements, arguments: vec![], returns: vec![], } diff --git a/src/ast.rs b/src/ast.rs index 4539e63b9d..79b070fa6a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -701,12 +701,11 @@ pub struct DefinitionStatement<'ast> { } #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::statement_iteration))] -pub struct IterationStatement<'ast> { - pub ty: Type<'ast>, +#[pest_ast(rule(Rule::statement_for))] +pub struct ForStatement<'ast> { pub index: Variable<'ast>, - pub from: Expression<'ast>, - pub to: Expression<'ast>, + pub start: Expression<'ast>, + pub stop: Expression<'ast>, pub statements: Vec>, #[pest_ast(outer())] pub span: Span<'ast>, @@ -725,7 +724,7 @@ pub struct ReturnStatement<'ast> { pub enum Statement<'ast> { Assign(AssignStatement<'ast>), Definition(DefinitionStatement<'ast>), - Iteration(IterationStatement<'ast>), + Iteration(ForStatement<'ast>), Return(ReturnStatement<'ast>), } @@ -741,12 +740,12 @@ impl<'ast> fmt::Display for DefinitionStatement<'ast> { } } -impl<'ast> fmt::Display for IterationStatement<'ast> { +impl<'ast> fmt::Display for ForStatement<'ast> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "for {} {} in {}..{} do {:#?} endfor", - self.ty, self.index, self.from, self.to, self.statements + "for {} in {}..{} do {:#?} endfor", + self.index, self.start, self.stop, self.statements ) } } diff --git a/src/language.pest b/src/language.pest index dd2691ac6f..83ec815dc8 100644 --- a/src/language.pest +++ b/src/language.pest @@ -135,11 +135,11 @@ expression_tuple = _{ (expression ~ ("," ~ expression)*)? } statement_assign = { variable ~ "=" ~ expression } statement_definition = { ty ~ variable ~ "=" ~ expression } statement_return = { "return" ~ expression_tuple } -statement_iteration = { "for" ~ ty ~ variable ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} +statement_for = { "for" ~ variable ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} statement = { (statement_return - | (statement_iteration + | (statement_for | statement_definition | statement_assign ) ~ NEWLINE