constraints array initializer

This commit is contained in:
collin 2020-04-14 17:50:26 -07:00
parent 83763a6817
commit 3f83786871
5 changed files with 163 additions and 68 deletions

View File

@ -1,3 +1,7 @@
field[3] a = [1, 2, 3] bool[2] a = [true, false]
//b = 2 + 2 bool[2] b = [true; 2]
field[4] c = [1, 2, 3, 4]
field[3] d = [1; 3]
return a return a

View File

@ -25,6 +25,17 @@ pub enum ResolvedValue {
impl fmt::Display for ResolvedValue { impl fmt::Display for ResolvedValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
ResolvedValue::Boolean(ref value) => write!(f, "{}", value.get_value().unwrap()),
ResolvedValue::BooleanArray(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e.get_value().unwrap())?;
if i < array.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "]")
}
ResolvedValue::FieldElement(ref value) => write!(f, "{}", value.value.unwrap()), ResolvedValue::FieldElement(ref value) => write!(f, "{}", value.value.unwrap()),
ResolvedValue::FieldElementArray(ref array) => { ResolvedValue::FieldElementArray(ref array) => {
write!(f, "[")?; write!(f, "[")?;
@ -112,7 +123,10 @@ impl ResolvedProgram {
match expression { match expression {
BooleanExpression::Variable(variable) => self.bool_from_variable(cs, variable), BooleanExpression::Variable(variable) => self.bool_from_variable(cs, variable),
BooleanExpression::Value(value) => Boolean::Constant(value), BooleanExpression::Value(value) => Boolean::Constant(value),
expression => self.enforce_boolean_expression(cs, expression), expression => match self.enforce_boolean_expression(cs, expression) {
ResolvedValue::Boolean(value) => value,
_ => unimplemented!("boolean expression did not resolve to boolean"),
},
} }
} }
@ -126,7 +140,7 @@ impl ResolvedProgram {
FieldExpression::Number(number) => UInt32::constant(number), FieldExpression::Number(number) => UInt32::constant(number),
field => match self.enforce_field_expression(cs, field) { field => match self.enforce_field_expression(cs, field) {
ResolvedValue::FieldElement(value) => value, ResolvedValue::FieldElement(value) => value,
_ => unimplemented!("value not resolved"), _ => unimplemented!("field expression did not resolve to field"),
}, },
} }
} }
@ -203,27 +217,54 @@ impl ResolvedProgram {
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
expression: BooleanExpression, expression: BooleanExpression,
) -> Boolean { ) -> ResolvedValue {
match expression { match expression {
BooleanExpression::Variable(variable) => self.bool_from_variable(cs, variable), BooleanExpression::Variable(variable) => {
BooleanExpression::Value(value) => Boolean::Constant(value), ResolvedValue::Boolean(self.bool_from_variable(cs, variable))
BooleanExpression::Not(expression) => self.enforce_not(cs, *expression), }
BooleanExpression::Or(left, right) => self.enforce_or(cs, *left, *right), BooleanExpression::Value(value) => ResolvedValue::Boolean(Boolean::Constant(value)),
BooleanExpression::And(left, right) => self.enforce_and(cs, *left, *right), BooleanExpression::Not(expression) => {
BooleanExpression::BoolEq(left, right) => self.enforce_bool_equality(cs, *left, *right), ResolvedValue::Boolean(self.enforce_not(cs, *expression))
}
BooleanExpression::Or(left, right) => {
ResolvedValue::Boolean(self.enforce_or(cs, *left, *right))
}
BooleanExpression::And(left, right) => {
ResolvedValue::Boolean(self.enforce_and(cs, *left, *right))
}
BooleanExpression::BoolEq(left, right) => {
ResolvedValue::Boolean(self.enforce_bool_equality(cs, *left, *right))
}
BooleanExpression::FieldEq(left, right) => { BooleanExpression::FieldEq(left, right) => {
self.enforce_field_equality(cs, *left, *right) ResolvedValue::Boolean(self.enforce_field_equality(cs, *left, *right))
} }
BooleanExpression::IfElse(first, second, third) => { BooleanExpression::IfElse(first, second, third) => {
if self let resolved_first = match self.enforce_boolean_expression(cs, *first) {
.enforce_boolean_expression(cs, *first) ResolvedValue::Boolean(resolved) => resolved,
.eq(&Boolean::Constant(true)) _ => unimplemented!("if else conditional must resolve to boolean"),
{ };
if resolved_first.eq(&Boolean::Constant(true)) {
self.enforce_boolean_expression(cs, *second) self.enforce_boolean_expression(cs, *second)
} else { } else {
self.enforce_boolean_expression(cs, *third) self.enforce_boolean_expression(cs, *third)
} }
} }
BooleanExpression::Array(array) => ResolvedValue::BooleanArray(
array
.into_iter()
.map(|element| match *element {
BooleanSpreadOrExpression::Spread(_spread) => {
unimplemented!("spreads not enforced yet")
}
BooleanSpreadOrExpression::BooleanExpression(expression) => {
match self.enforce_boolean_expression(cs, expression) {
ResolvedValue::Boolean(value) => value,
_ => unimplemented!("cannot resolve boolean"),
}
}
})
.collect::<Vec<Boolean>>(),
),
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -345,10 +386,12 @@ impl ResolvedProgram {
ResolvedValue::FieldElement(self.enforce_pow(cs, *left, *right)) ResolvedValue::FieldElement(self.enforce_pow(cs, *left, *right))
} }
FieldExpression::IfElse(first, second, third) => { FieldExpression::IfElse(first, second, third) => {
if self let resolved_first = match self.enforce_boolean_expression(cs, *first) {
.enforce_boolean_expression(cs, *first) ResolvedValue::Boolean(resolved) => resolved,
.eq(&Boolean::Constant(true)) _ => unimplemented!("if else conditional must resolve to boolean"),
{ };
if resolved_first.eq(&Boolean::Constant(true)) {
self.enforce_field_expression(cs, *second) self.enforce_field_expression(cs, *second)
} else { } else {
self.enforce_field_expression(cs, *third) self.enforce_field_expression(cs, *third)
@ -358,12 +401,11 @@ impl ResolvedProgram {
array array
.into_iter() .into_iter()
.map(|element| match *element { .map(|element| match *element {
FieldSpreadOrExpression::Spread(spread) => { FieldSpreadOrExpression::Spread(_spread) => {
unimplemented!("spreads not enforced yet") unimplemented!("spreads not enforced yet")
} }
FieldSpreadOrExpression::FieldExpression(expression) => { FieldSpreadOrExpression::FieldExpression(expression) => {
let resolved = self.enforce_field_expression(cs, expression); match self.enforce_field_expression(cs, expression) {
match resolved {
ResolvedValue::FieldElement(value) => value, ResolvedValue::FieldElement(value) => value,
_ => unimplemented!("cannot resolve field"), _ => unimplemented!("cannot resolve field"),
} }
@ -383,12 +425,8 @@ impl ResolvedProgram {
Statement::Definition(variable, expression) => match expression { Statement::Definition(variable, expression) => match expression {
Expression::Boolean(boolean_expression) => { Expression::Boolean(boolean_expression) => {
let res = self.enforce_boolean_expression(cs, boolean_expression); let res = self.enforce_boolean_expression(cs, boolean_expression);
println!( println!(" variable boolean result: {} = {}", variable.0, res);
" variable boolean result: {} = {}", self.insert(variable, res);
variable.0,
res.get_value().unwrap()
);
self.insert(variable, ResolvedValue::Boolean(res));
} }
Expression::FieldElement(field_expression) => { Expression::FieldElement(field_expression) => {
let res = self.enforce_field_expression(cs, field_expression); let res = self.enforce_field_expression(cs, field_expression);
@ -441,24 +479,17 @@ impl ResolvedProgram {
.for_each(|expression| match expression { .for_each(|expression| match expression {
Expression::Boolean(boolean_expression) => { Expression::Boolean(boolean_expression) => {
let res = self.enforce_boolean_expression(cs, boolean_expression); let res = self.enforce_boolean_expression(cs, boolean_expression);
println!("\n Boolean result = {}", res.get_value().unwrap()); println!("\n Boolean result = {}", res);
} }
Expression::FieldElement(field_expression) => { Expression::FieldElement(field_expression) => {
let res = self.enforce_field_expression(cs, field_expression); let res = self.enforce_field_expression(cs, field_expression);
println!("\n Field result = {}", res); println!("\n Field result = {}", res);
} }
Expression::Variable(variable) => { Expression::Variable(variable) => {
match self.resolved_variables.get_mut(&variable).unwrap().clone() { println!(
ResolvedValue::Boolean(boolean) => println!( "\n Return = {}",
"\n Variable result = {}", self.resolved_variables.get_mut(&variable).unwrap().clone()
boolean.get_value().unwrap() );
),
ResolvedValue::FieldElement(field_element) => println!(
"\n Variable field result = {}",
field_element.value.unwrap()
),
_ => {}
}
} }
}); });
} }

View File

@ -90,8 +90,6 @@ pub enum Expression {
/// Program statement that defines some action (or expression) to be carried out. /// Program statement that defines some action (or expression) to be carried out.
#[derive(Clone)] #[derive(Clone)]
pub enum Statement { pub enum Statement {
/// A statement that could be directly translated to a R1CS constraint a * b = c to be enforced
// Constraint(QuadraticCombination, LinearCombination),
// Declaration(Variable), // Declaration(Variable),
Definition(Variable, Expression), Definition(Variable, Expression),
Return(Vec<Expression>), Return(Vec<Expression>),

View File

@ -5,8 +5,8 @@
//! @date 2020 //! @date 2020
use crate::aleo_program::{ use crate::aleo_program::{
BooleanExpression, Expression, FieldExpression, FieldSpread, FieldSpreadOrExpression, BooleanExpression, BooleanSpread, BooleanSpreadOrExpression, Expression, FieldExpression,
Statement, Struct, StructField, Type, Variable, FieldSpread, FieldSpreadOrExpression, Statement, Struct, StructField, Type, Variable,
}; };
use std::fmt; use std::fmt;
@ -59,6 +59,23 @@ impl<'ast> fmt::Display for FieldExpression {
} }
} }
impl fmt::Display for BooleanSpread {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "...{}", self.0)
}
}
impl fmt::Display for BooleanSpreadOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
BooleanSpreadOrExpression::Spread(ref spread) => write!(f, "{}", spread),
BooleanSpreadOrExpression::BooleanExpression(ref expression) => {
write!(f, "{}", expression)
}
}
}
}
impl<'ast> fmt::Display for BooleanExpression { impl<'ast> fmt::Display for BooleanExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
@ -77,7 +94,16 @@ impl<'ast> fmt::Display for BooleanExpression {
BooleanExpression::IfElse(ref a, ref b, ref c) => { BooleanExpression::IfElse(ref a, ref b, ref c) => {
write!(f, "if {} then {} else {} fi", a, b, c) write!(f, "if {} then {} else {} fi", a, b, c)
} }
_ => unimplemented!(), BooleanExpression::Array(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?;
if i < array.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "]")
}
} }
} }
} }

View File

@ -286,9 +286,12 @@ impl<'ast> From<ast::Expression<'ast>> for types::Expression {
ast::Expression::Not(expression) => types::Expression::from(expression), ast::Expression::Not(expression) => types::Expression::from(expression),
ast::Expression::Binary(expression) => types::Expression::from(expression), ast::Expression::Binary(expression) => types::Expression::from(expression),
ast::Expression::Ternary(expression) => types::Expression::from(expression), ast::Expression::Ternary(expression) => types::Expression::from(expression),
ast::Expression::ArrayInline(expression) => { ast::Expression::ArrayInline(_expression) => {
unimplemented!("unknown type for inline array expression") unimplemented!("unknown type for inline array expression")
} }
ast::Expression::ArrayInitializer(_expression) => {
unimplemented!("unknown type for array initializer expression")
}
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -313,12 +316,13 @@ impl<'ast> From<ast::Spread<'ast>> for types::BooleanSpread {
} }
} }
impl<'ast> From<ast::Spread<'ast>> for types::FieldSpread { impl<'ast> From<ast::Expression<'ast>> for types::BooleanSpreadOrExpression {
fn from(spread: ast::Spread<'ast>) -> Self { fn from(expression: ast::Expression<'ast>) -> Self {
let field_expression = types::Expression::from(spread.expression); match types::Expression::from(expression) {
match field_expression { types::Expression::Boolean(expression) => {
types::Expression::FieldElement(expression) => types::FieldSpread(expression), types::BooleanSpreadOrExpression::BooleanExpression(expression)
_ => unimplemented!("cannot create field spread from boolean type"), }
_ => unimplemented!("cannot create boolean expression from field type"),
} }
} }
} }
@ -330,8 +334,7 @@ impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::BooleanSpreadOrExpress
types::BooleanSpreadOrExpression::Spread(types::BooleanSpread::from(spread)) types::BooleanSpreadOrExpression::Spread(types::BooleanSpread::from(spread))
} }
ast::SpreadOrExpression::Expression(expression) => { ast::SpreadOrExpression::Expression(expression) => {
let boolean_expression = types::Expression::from(expression); match types::Expression::from(expression) {
match boolean_expression {
types::Expression::Boolean(expression) => { types::Expression::Boolean(expression) => {
types::BooleanSpreadOrExpression::BooleanExpression(expression) types::BooleanSpreadOrExpression::BooleanExpression(expression)
} }
@ -342,6 +345,27 @@ impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::BooleanSpreadOrExpress
} }
} }
impl<'ast> From<ast::Spread<'ast>> for types::FieldSpread {
fn from(spread: ast::Spread<'ast>) -> Self {
let field_expression = types::Expression::from(spread.expression);
match field_expression {
types::Expression::FieldElement(expression) => types::FieldSpread(expression),
_ => unimplemented!("cannot create field spread from boolean type"),
}
}
}
impl<'ast> From<ast::Expression<'ast>> for types::FieldSpreadOrExpression {
fn from(expression: ast::Expression<'ast>) -> Self {
match types::Expression::from(expression) {
types::Expression::FieldElement(expression) => {
types::FieldSpreadOrExpression::FieldExpression(expression)
}
_ => unimplemented!("cannot create field expression from boolean type"),
}
}
}
impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::FieldSpreadOrExpression { impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::FieldSpreadOrExpression {
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self { fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
match s_or_e { match s_or_e {
@ -349,20 +373,14 @@ impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::FieldSpreadOrExpressio
types::FieldSpreadOrExpression::Spread(types::FieldSpread::from(spread)) types::FieldSpreadOrExpression::Spread(types::FieldSpread::from(spread))
} }
ast::SpreadOrExpression::Expression(expression) => { ast::SpreadOrExpression::Expression(expression) => {
let field_expression = types::Expression::from(expression); types::FieldSpreadOrExpression::from(expression)
match field_expression {
types::Expression::FieldElement(expression) => {
types::FieldSpreadOrExpression::FieldExpression(expression)
}
_ => unimplemented!("cannot create field expression from boolean type"),
}
} }
} }
} }
} }
impl<'ast> types::Expression { impl<'ast> types::Expression {
fn from_basic(ty: ast::BasicType<'ast>, expression: ast::Expression<'ast>) -> Self { fn from_basic(_ty: ast::BasicType<'ast>, _expression: ast::Expression<'ast>) -> Self {
unimplemented!("from basic not impl"); unimplemented!("from basic not impl");
} }
@ -375,8 +393,17 @@ impl<'ast> types::Expression {
.into_iter() .into_iter()
.map(|s_or_e| Box::new(types::BooleanSpreadOrExpression::from(s_or_e))) .map(|s_or_e| Box::new(types::BooleanSpreadOrExpression::from(s_or_e)))
.collect(), .collect(),
ast::Expression::ArrayInitializer(expression) => { ast::Expression::ArrayInitializer(array) => {
unimplemented!("no array init yet") let count = match array.count {
ast::Value::Field(f) => {
f.value.parse::<usize>().expect("Unable to read array size")
}
_ => unimplemented!("Array size should be an integer"),
};
let expression =
Box::new(types::BooleanSpreadOrExpression::from(*array.expression));
vec![expression; count]
} }
_ => unimplemented!("expected array after array type"), _ => unimplemented!("expected array after array type"),
}; };
@ -389,8 +416,17 @@ impl<'ast> types::Expression {
.into_iter() .into_iter()
.map(|s_or_e| Box::new(types::FieldSpreadOrExpression::from(s_or_e))) .map(|s_or_e| Box::new(types::FieldSpreadOrExpression::from(s_or_e)))
.collect(), .collect(),
ast::Expression::ArrayInitializer(expression) => { ast::Expression::ArrayInitializer(array) => {
unimplemented!("array init not yet") let count = match array.count {
ast::Value::Field(f) => {
f.value.parse::<usize>().expect("Unable to read array size")
}
_ => unimplemented!("Array size should be an integer"),
};
let expression =
Box::new(types::FieldSpreadOrExpression::from(*array.expression));
vec![expression; count]
} }
_ => unimplemented!("expected array after array type"), _ => unimplemented!("expected array after array type"),
}; };
@ -399,7 +435,7 @@ impl<'ast> types::Expression {
} }
} }
fn from_struct(ty: ast::StructType<'ast>, expression: ast::Expression<'ast>) -> Self { fn from_struct(_ty: ast::StructType<'ast>, _expression: ast::Expression<'ast>) -> Self {
unimplemented!("from struct not impl"); unimplemented!("from struct not impl");
} }