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]
//b = 2 + 2
bool[2] a = [true, false]
bool[2] b = [true; 2]
field[4] c = [1, 2, 3, 4]
field[3] d = [1; 3]
return a

View File

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

View File

@ -90,8 +90,6 @@ pub enum Expression {
/// Program statement that defines some action (or expression) to be carried out.
#[derive(Clone)]
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),
Definition(Variable, Expression),
Return(Vec<Expression>),

View File

@ -5,8 +5,8 @@
//! @date 2020
use crate::aleo_program::{
BooleanExpression, Expression, FieldExpression, FieldSpread, FieldSpreadOrExpression,
Statement, Struct, StructField, Type, Variable,
BooleanExpression, BooleanSpread, BooleanSpreadOrExpression, Expression, FieldExpression,
FieldSpread, FieldSpreadOrExpression, Statement, Struct, StructField, Type, Variable,
};
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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -77,7 +94,16 @@ impl<'ast> fmt::Display for BooleanExpression {
BooleanExpression::IfElse(ref a, ref b, ref 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::Binary(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")
}
ast::Expression::ArrayInitializer(_expression) => {
unimplemented!("unknown type for array initializer expression")
}
_ => unimplemented!(),
}
}
@ -313,12 +316,13 @@ impl<'ast> From<ast::Spread<'ast>> for types::BooleanSpread {
}
}
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::BooleanSpreadOrExpression {
fn from(expression: ast::Expression<'ast>) -> Self {
match types::Expression::from(expression) {
types::Expression::Boolean(expression) => {
types::BooleanSpreadOrExpression::BooleanExpression(expression)
}
_ => 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))
}
ast::SpreadOrExpression::Expression(expression) => {
let boolean_expression = types::Expression::from(expression);
match boolean_expression {
match types::Expression::from(expression) {
types::Expression::Boolean(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 {
fn from(s_or_e: ast::SpreadOrExpression<'ast>) -> Self {
match s_or_e {
@ -349,20 +373,14 @@ impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::FieldSpreadOrExpressio
types::FieldSpreadOrExpression::Spread(types::FieldSpread::from(spread))
}
ast::SpreadOrExpression::Expression(expression) => {
let field_expression = types::Expression::from(expression);
match field_expression {
types::Expression::FieldElement(expression) => {
types::FieldSpreadOrExpression::FieldExpression(expression)
}
_ => unimplemented!("cannot create field expression from boolean type"),
}
types::FieldSpreadOrExpression::from(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");
}
@ -375,8 +393,17 @@ impl<'ast> types::Expression {
.into_iter()
.map(|s_or_e| Box::new(types::BooleanSpreadOrExpression::from(s_or_e)))
.collect(),
ast::Expression::ArrayInitializer(expression) => {
unimplemented!("no array init yet")
ast::Expression::ArrayInitializer(array) => {
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"),
};
@ -389,8 +416,17 @@ impl<'ast> types::Expression {
.into_iter()
.map(|s_or_e| Box::new(types::FieldSpreadOrExpression::from(s_or_e)))
.collect(),
ast::Expression::ArrayInitializer(expression) => {
unimplemented!("array init not yet")
ast::Expression::ArrayInitializer(array) => {
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"),
};
@ -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");
}