mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 02:01:54 +03:00
constraints array initializer
This commit is contained in:
parent
83763a6817
commit
3f83786871
@ -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
|
@ -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()
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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>),
|
||||
|
@ -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, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user