constraints for loops

This commit is contained in:
collin 2020-04-16 11:36:23 -07:00
parent 0a8cda3d7f
commit 455c0b631a
7 changed files with 100 additions and 61 deletions

View File

@ -1,9 +1,6 @@
struct Foo {
bool x
}
def main() -> (field): def main() -> (field):
field[3] a = [1, 2, 3] // initialize the array a = 1
field[4] b = [42; 4] for i in 0..4 do
c = a[1..3] // helloo??? a = a + 1
bool[3] d = [true, false, true] endfor
return a[0] return a

View File

@ -639,21 +639,50 @@ impl ResolvedProgram {
) )
} }
// fn enforce_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>( fn enforce_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
// &mut self, &mut self,
// cs: &mut CS, cs: &mut CS,
// statement: Statement, statement: Statement,
// ) { ) {
// match statement { match statement {
// Statement::Definition(variable, expression) => { Statement::Definition(variable, expression) => {
// self.enforce_definition_statement(cs, variable, expression); self.enforce_definition_statement(cs, variable, expression);
// } }
// Statement::Return(statements) => { Statement::For(index, start, stop, statements) => {
// let res = self.enforce_return_statement(cs, 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<F: Field + PrimeField, CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
index: Variable,
start: FieldExpression,
stop: FieldExpression,
statements: Vec<Statement>,
) {
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<F: Field + PrimeField, CS: ConstraintSystem<F>>( fn enforce_function<F: Field + PrimeField, CS: ConstraintSystem<F>>(
&mut self, &mut self,
@ -715,7 +744,10 @@ impl ResolvedProgram {
.into_iter() .into_iter()
.for_each(|statement| match statement { .for_each(|statement| match statement {
Statement::Definition(variable, expression) => { 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) => { Statement::Return(expressions) => {
return_values = self.enforce_return_statement(cs, expressions) return_values = self.enforce_return_statement(cs, expressions)

View File

@ -103,6 +103,7 @@ pub enum Expression {
pub enum Statement { pub enum Statement {
// Declaration(Variable), // Declaration(Variable),
Definition(Variable, Expression), Definition(Variable, Expression),
For(Variable, FieldExpression, FieldExpression, Vec<Statement>),
Return(Vec<Expression>), Return(Vec<Expression>),
} }
@ -120,12 +121,6 @@ pub struct StructMember {
pub expression: Expression, pub expression: Expression,
} }
// #[derive(Clone, Debug)]
// pub struct StructExpression {
// pub variable: Variable,
// pub members: Vec<StructMember>
// }
#[derive(Clone)] #[derive(Clone)]
pub struct StructField { pub struct StructField {
pub variable: Variable, pub variable: Variable,

View File

@ -6,8 +6,8 @@
use crate::aleo_program::{ use crate::aleo_program::{
BooleanExpression, BooleanSpread, BooleanSpreadOrExpression, Expression, FieldExpression, BooleanExpression, BooleanSpread, BooleanSpreadOrExpression, Expression, FieldExpression,
FieldRangeOrExpression, FieldSpread, FieldSpreadOrExpression, Function, FunctionName, Parameter, Statement, FieldRangeOrExpression, FieldSpread, FieldSpreadOrExpression, Function, FunctionName,
Struct, StructField, Type, Variable, Parameter, Statement, Struct, StructField, Type, Variable,
}; };
use std::fmt; use std::fmt;
@ -166,15 +166,22 @@ impl<'ast> fmt::Display for Expression {
impl fmt::Display for Statement { impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { 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) => { Statement::Return(ref statements) => {
statements.iter().for_each(|statement| { statements.iter().for_each(|statement| {
write!(f, "return {}", statement).unwrap(); write!(f, "return {}", statement).unwrap();
}); });
write!(f, "\n") 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 { impl fmt::Debug for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { 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) => { Statement::Return(ref statements) => {
statements.iter().for_each(|statement| { statements.iter().for_each(|statement| {
write!(f, "return {}", statement).unwrap(); write!(f, "return {}", statement).unwrap();
}); });
write!(f, "\n") write!(f, "\n")
} }
Statement::Definition(ref variable, ref statement) => {
write!(f, "{} = {}", variable, statement)
}
} }
} }
} }

View File

@ -561,10 +561,18 @@ impl<'ast> From<ast::ReturnStatement<'ast>> for types::Statement {
} }
} }
impl<'ast> From<ast::IterationStatement<'ast>> for types::Statement { impl<'ast> From<ast::ForStatement<'ast>> for types::Statement {
fn from(statement: ast::IterationStatement<'ast>) -> Self { fn from(statement: ast::ForStatement<'ast>) -> Self {
println!("{:#?}", statement); types::Statement::For(
unimplemented!() 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<ast::Function<'ast>> for types::Function {
impl<'ast> From<ast::File<'ast>> for types::Program { impl<'ast> From<ast::File<'ast>> for types::Program {
fn from(file: ast::File<'ast>) -> Self { 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 structs = HashMap::new();
let mut functions = HashMap::new(); let mut functions = HashMap::new();
@ -721,17 +730,10 @@ impl<'ast> From<ast::File<'ast>> for types::Program {
); );
}); });
// let statements: Vec<types::Statement> = file
// .statements
// .into_iter()
// .map(|statement| types::Statement::from(statement))
// .collect();
types::Program { types::Program {
id: "main".into(), id: "main".into(),
structs, structs,
functions, functions,
// statements,
arguments: vec![], arguments: vec![],
returns: vec![], returns: vec![],
} }

View File

@ -701,12 +701,11 @@ pub struct DefinitionStatement<'ast> {
} }
#[derive(Clone, Debug, FromPest, PartialEq)] #[derive(Clone, Debug, FromPest, PartialEq)]
#[pest_ast(rule(Rule::statement_iteration))] #[pest_ast(rule(Rule::statement_for))]
pub struct IterationStatement<'ast> { pub struct ForStatement<'ast> {
pub ty: Type<'ast>,
pub index: Variable<'ast>, pub index: Variable<'ast>,
pub from: Expression<'ast>, pub start: Expression<'ast>,
pub to: Expression<'ast>, pub stop: Expression<'ast>,
pub statements: Vec<Statement<'ast>>, pub statements: Vec<Statement<'ast>>,
#[pest_ast(outer())] #[pest_ast(outer())]
pub span: Span<'ast>, pub span: Span<'ast>,
@ -725,7 +724,7 @@ pub struct ReturnStatement<'ast> {
pub enum Statement<'ast> { pub enum Statement<'ast> {
Assign(AssignStatement<'ast>), Assign(AssignStatement<'ast>),
Definition(DefinitionStatement<'ast>), Definition(DefinitionStatement<'ast>),
Iteration(IterationStatement<'ast>), Iteration(ForStatement<'ast>),
Return(ReturnStatement<'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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
"for {} {} in {}..{} do {:#?} endfor", "for {} in {}..{} do {:#?} endfor",
self.ty, self.index, self.from, self.to, self.statements self.index, self.start, self.stop, self.statements
) )
} }
} }

View File

@ -135,11 +135,11 @@ expression_tuple = _{ (expression ~ ("," ~ expression)*)? }
statement_assign = { variable ~ "=" ~ expression } statement_assign = { variable ~ "=" ~ expression }
statement_definition = { ty ~ variable ~ "=" ~ expression } statement_definition = { ty ~ variable ~ "=" ~ expression }
statement_return = { "return" ~ expression_tuple } 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 = {
(statement_return (statement_return
| (statement_iteration | (statement_for
| statement_definition | statement_definition
| statement_assign | statement_assign
) ~ NEWLINE ) ~ NEWLINE