constraints bool and field spreads

This commit is contained in:
collin 2020-04-16 22:46:51 -07:00
parent e1db8ed483
commit 1743c7a1f1
3 changed files with 85 additions and 51 deletions

View File

@ -1,10 +1,4 @@
struct Point { def main() -> (bool[4]):
field x bool[2] a = [true, true]
field y bool[4] x = [...a, ...a]
} return x
def main() -> ():
Point p = Point { x: 1, y: 1 }
p.x = 2
p.y = 2
return p

View File

@ -167,7 +167,7 @@ impl ResolvedProgram {
// TODO: return synthesis error: "assignment missing" here // TODO: return synthesis error: "assignment missing" here
match self.get(&variable_name).unwrap() { match self.get(&variable_name).unwrap() {
ResolvedValue::FieldElement(field) => field.clone(), ResolvedValue::FieldElement(field) => field.clone(),
_ => panic!("expected a field, got boolean"), value => panic!("expected a field, got {}", value),
} }
} else { } else {
let argument = std::env::args() let argument = std::env::args()
@ -326,23 +326,44 @@ impl ResolvedProgram {
self.enforce_boolean_expression(cs, scope, *third) self.enforce_boolean_expression(cs, scope, *third)
} }
} }
BooleanExpression::Array(array) => ResolvedValue::BooleanArray( BooleanExpression::Array(array) => {
array let mut result = vec![];
.into_iter() array.into_iter().for_each(|element| match *element {
.map(|element| match *element { BooleanSpreadOrExpression::Spread(spread) => match spread.0 {
BooleanSpreadOrExpression::Spread(_spread) => { BooleanExpression::Variable(variable) => {
unimplemented!("spreads not enforced yet") let array_name = new_scope_from_variable(scope.clone(), &variable);
} match self.get(&array_name) {
BooleanSpreadOrExpression::BooleanExpression(expression) => { Some(value) => match value {
match self.enforce_boolean_expression(cs, scope.clone(), expression) { ResolvedValue::BooleanArray(array) => {
ResolvedValue::Boolean(value) => value, result.extend(array.clone())
_ => unimplemented!("cannot resolve boolean"), }
value => unimplemented!(
"spreads only implemented for arrays, got {}",
value
),
},
None => unimplemented!(
"cannot copy elements from array that does not exist {}",
variable.0
),
} }
} }
}) value => {
.collect::<Vec<Boolean>>(), unimplemented!("spreads only implemented for arrays, got {}", value)
), }
_ => unimplemented!(), },
BooleanSpreadOrExpression::BooleanExpression(expression) => {
match self.enforce_boolean_expression(cs, scope.clone(), expression) {
ResolvedValue::Boolean(value) => result.push(value),
value => {
unimplemented!("expected boolean for boolean array, got {}", value)
}
}
}
});
ResolvedValue::BooleanArray(result)
}
expression => unimplemented!("boolean expression {}", expression),
} }
} }
@ -481,22 +502,41 @@ impl ResolvedProgram {
self.enforce_field_expression(cs, scope, *third) self.enforce_field_expression(cs, scope, *third)
} }
} }
FieldExpression::Array(array) => ResolvedValue::FieldElementArray( FieldExpression::Array(array) => {
array let mut result = vec![];
.into_iter() array.into_iter().for_each(|element| match *element {
.map(|element| match *element { FieldSpreadOrExpression::Spread(spread) => match spread.0 {
FieldSpreadOrExpression::Spread(_spread) => { FieldExpression::Variable(variable) => {
unimplemented!("spreads not enforced yet") let array_name = new_scope_from_variable(scope.clone(), &variable);
} match self.get(&array_name) {
FieldSpreadOrExpression::FieldExpression(expression) => { Some(value) => match value {
match self.enforce_field_expression(cs, scope.clone(), expression) { ResolvedValue::FieldElementArray(array) => {
ResolvedValue::FieldElement(value) => value, result.extend(array.clone())
_ => unimplemented!("cannot resolve field"), }
value => unimplemented!(
"spreads only implemented for arrays, got {}",
value
),
},
None => unimplemented!(
"cannot copy elements from array that does not exist {}",
variable.0
),
} }
} }
}) value => {
.collect::<Vec<UInt32>>(), unimplemented!("spreads only implemented for arrays, got {}", value)
), }
},
FieldSpreadOrExpression::FieldExpression(expression) => {
match self.enforce_field_expression(cs, scope.clone(), expression) {
ResolvedValue::FieldElement(value) => result.push(value),
_ => unimplemented!("cannot resolve field"),
}
}
});
ResolvedValue::FieldElementArray(result)
}
} }
} }
@ -704,14 +744,6 @@ impl ResolvedProgram {
} }
} }
// fn modify_array<F: Field + PrimeField, CS: ConstraintSystem<F>>(
// &mut self,
// cs: &mut CS,
// scope: String,
// assignee: Assignee,
// expression: Expression,
// )
fn enforce_definition_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>( fn enforce_definition_statement<F: Field + PrimeField, CS: ConstraintSystem<F>>(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,

View File

@ -405,6 +405,9 @@ impl<'ast> From<ast::Spread<'ast>> for types::BooleanSpread {
let boolean_expression = types::Expression::from(spread.expression); let boolean_expression = types::Expression::from(spread.expression);
match boolean_expression { match boolean_expression {
types::Expression::Boolean(expression) => types::BooleanSpread(expression), types::Expression::Boolean(expression) => types::BooleanSpread(expression),
types::Expression::Variable(variable) => {
types::BooleanSpread(types::BooleanExpression::Variable(variable))
}
_ => unimplemented!("cannot create boolean spread from field type"), _ => unimplemented!("cannot create boolean spread from field type"),
} }
} }
@ -441,10 +444,15 @@ impl<'ast> From<ast::SpreadOrExpression<'ast>> for types::BooleanSpreadOrExpress
impl<'ast> From<ast::Spread<'ast>> for types::FieldSpread { impl<'ast> From<ast::Spread<'ast>> for types::FieldSpread {
fn from(spread: ast::Spread<'ast>) -> Self { fn from(spread: ast::Spread<'ast>) -> Self {
let field_expression = types::Expression::from(spread.expression); match types::Expression::from(spread.expression) {
match field_expression {
types::Expression::FieldElement(expression) => types::FieldSpread(expression), types::Expression::FieldElement(expression) => types::FieldSpread(expression),
_ => unimplemented!("cannot create field spread from boolean type"), types::Expression::Variable(variable) => {
types::FieldSpread(types::FieldExpression::Variable(variable))
}
expression => unimplemented!(
"cannot create field spread from boolean type {}",
expression
),
} }
} }
} }