initial support for implicit value types

This commit is contained in:
collin 2020-05-15 17:35:12 -07:00
parent fd51ee28e2
commit a31ee8b884
5 changed files with 96 additions and 39 deletions

View File

@ -1,5 +1,3 @@
function main() { function main() {
let g: group = 123456789; let g: group = 123456789;
} }

View File

@ -1,16 +1,11 @@
//! Methods to enforce constraints on expressions in a resolved Leo program. //! Methods to enforce constraints on expressions in a resolved Leo program.
use crate::{ use crate::{constraints::{
constraints::{ new_scope_from_variable, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue,
new_scope_from_variable, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue, }, errors::ExpressionError, new_scope, types::{
}, CircuitFieldDefinition, CircuitMember, Expression, Identifier, RangeOrExpression,
errors::ExpressionError, SpreadOrExpression,
new_scope, }, Type};
types::{
CircuitFieldDefinition, CircuitMember, Expression, Identifier, RangeOrExpression,
SpreadOrExpression,
},
};
use snarkos_models::{ use snarkos_models::{
curves::{Field, Group, PrimeField}, curves::{Field, Group, PrimeField},
@ -312,6 +307,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
array: Vec<Box<SpreadOrExpression<F, G>>>, array: Vec<Box<SpreadOrExpression<F, G>>>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let mut result = vec![]; let mut result = vec![];
@ -337,6 +333,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
expression, expression,
)?); )?);
} }
@ -350,9 +347,10 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
index: Expression<F, G>, index: Expression<F, G>,
) -> Result<usize, ExpressionError> { ) -> Result<usize, ExpressionError> {
match self.enforce_expression(cs, file_scope, function_scope, index)? { match self.enforce_expression(cs, file_scope, function_scope, expected_types, index)? {
ConstrainedValue::Integer(number) => Ok(number.to_usize()), ConstrainedValue::Integer(number) => Ok(number.to_usize()),
value => Err(ExpressionError::InvalidIndex(value.to_string())), value => Err(ExpressionError::InvalidIndex(value.to_string())),
} }
@ -363,6 +361,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
array: Box<Expression<F, G>>, array: Box<Expression<F, G>>,
index: RangeOrExpression<F, G>, index: RangeOrExpression<F, G>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
@ -370,6 +369,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
*array, *array,
)? { )? {
ConstrainedValue::Array(array) => array, ConstrainedValue::Array(array) => array,
@ -395,7 +395,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
)) ))
} }
RangeOrExpression::Expression(index) => { RangeOrExpression::Expression(index) => {
let index_resolved = self.enforce_index(cs, file_scope, function_scope, index)?; let index_resolved = self.enforce_index(cs, file_scope, function_scope, expected_types, index)?;
Ok(array[index_resolved].to_owned()) Ok(array[index_resolved].to_owned())
} }
} }
@ -406,6 +406,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
identifier: Identifier<F, G>, identifier: Identifier<F, G>,
members: Vec<CircuitFieldDefinition<F, G>>, members: Vec<CircuitFieldDefinition<F, G>>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
@ -434,6 +435,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
field.expression, field.expression,
)?; )?;
@ -482,6 +484,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
circuit_identifier: Box<Expression<F, G>>, circuit_identifier: Box<Expression<F, G>>,
circuit_member: Identifier<F, G>, circuit_member: Identifier<F, G>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
@ -489,6 +492,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
*circuit_identifier.clone(), *circuit_identifier.clone(),
)? { )? {
ConstrainedValue::CircuitExpression(name, members) => (name, members), ConstrainedValue::CircuitExpression(name, members) => (name, members),
@ -541,6 +545,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
circuit_identifier: Box<Expression<F, G>>, circuit_identifier: Box<Expression<F, G>>,
circuit_member: Identifier<F, G>, circuit_member: Identifier<F, G>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
@ -549,6 +554,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
*circuit_identifier.clone(), *circuit_identifier.clone(),
)? { )? {
ConstrainedValue::CircuitDefinition(circuit_definition) => circuit_definition, ConstrainedValue::CircuitDefinition(circuit_definition) => circuit_definition,
@ -591,6 +597,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F, G>>,
function: Box<Expression<F, G>>, function: Box<Expression<F, G>>,
arguments: Vec<Expression<F, G>>, arguments: Vec<Expression<F, G>>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
@ -598,6 +605,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
*function.clone(), *function.clone(),
)?; )?;
@ -627,11 +635,25 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
} }
pub(crate) fn enforce_number_implicit(
expected_types: Vec<Type<F, G>>,
value: String,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
if expected_types.len() != 1 {
return Err(ExpressionError::SingleType(value))
}
Ok(ConstrainedValue::from_type(value, &expected_types[0])?)
}
pub(crate) fn enforce_expression( pub(crate) fn enforce_expression(
&mut self, &mut self,
cs: &mut CS, cs: &mut CS,
file_scope: String, file_scope: String,
function_scope: String, function_scope: String,
expected_types: Vec<Type<F,G>>,
expression: Expression<F, G>, expression: Expression<F, G>,
) -> Result<ConstrainedValue<F, G>, ExpressionError> { ) -> Result<ConstrainedValue<F, G>, ExpressionError> {
match expression { match expression {
@ -645,16 +667,17 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
Expression::FieldElement(fe) => Ok(Self::get_field_element_constant(fe)), Expression::FieldElement(fe) => Ok(Self::get_field_element_constant(fe)),
Expression::GroupElement(gr) => Ok(ConstrainedValue::GroupElement(gr)), Expression::GroupElement(gr) => Ok(ConstrainedValue::GroupElement(gr)),
Expression::Boolean(bool) => Ok(Self::get_boolean_constant(bool)), Expression::Boolean(bool) => Ok(Self::get_boolean_constant(bool)),
Expression::Implicit(string) => unimplemented!(), Expression::Implicit(value) => Self::enforce_number_implicit(expected_types, value),
// Binary operations // Binary operations
Expression::Add(left, right) => { Expression::Add(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -662,11 +685,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Sub(left, right) => { Expression::Sub(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -674,11 +698,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Mul(left, right) => { Expression::Mul(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -686,11 +711,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Div(left, right) => { Expression::Div(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -698,11 +724,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Pow(left, right) => { Expression::Pow(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -714,15 +741,17 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope, file_scope,
function_scope, function_scope,
expected_types,
*expression, *expression,
)?)?), )?)?),
Expression::Or(left, right) => { Expression::Or(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -730,11 +759,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::And(left, right) => { Expression::And(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -742,11 +772,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Eq(left, right) => { Expression::Eq(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -754,11 +785,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Geq(left, right) => { Expression::Geq(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -766,11 +798,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Gt(left, right) => { Expression::Gt(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -778,11 +811,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Leq(left, right) => { Expression::Leq(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -790,11 +824,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Expression::Lt(left, right) => { Expression::Lt(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types.clone(), *left)?;
let resolved_right = self.enforce_expression( let resolved_right = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
*right, *right,
)?; )?;
@ -807,6 +842,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types.clone(),
*first, *first,
)? { )? {
ConstrainedValue::Boolean(resolved) => resolved, ConstrainedValue::Boolean(resolved) => resolved,
@ -814,18 +850,18 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
}; };
if resolved_first.eq(&Boolean::Constant(true)) { if resolved_first.eq(&Boolean::Constant(true)) {
self.enforce_expression(cs, file_scope, function_scope, *second) self.enforce_expression(cs, file_scope, function_scope, expected_types, *second)
} else { } else {
self.enforce_expression(cs, file_scope, function_scope, *third) self.enforce_expression(cs, file_scope, function_scope, expected_types, *third)
} }
} }
// Arrays // Arrays
Expression::Array(array) => { Expression::Array(array) => {
self.enforce_array_expression(cs, file_scope, function_scope, array) self.enforce_array_expression(cs, file_scope, function_scope, expected_types, array)
} }
Expression::ArrayAccess(array, index) => { Expression::ArrayAccess(array, index) => {
self.enforce_array_access_expression(cs, file_scope, function_scope, array, *index) self.enforce_array_access_expression(cs, file_scope, function_scope, expected_types, array, *index)
} }
// Circuits // Circuits
@ -833,6 +869,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope, file_scope,
function_scope, function_scope,
expected_types,
circuit_name, circuit_name,
members, members,
), ),
@ -841,6 +878,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope, file_scope,
function_scope, function_scope,
expected_types,
circuit_variable, circuit_variable,
circuit_member, circuit_member,
), ),
@ -849,6 +887,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope, file_scope,
function_scope, function_scope,
expected_types,
circuit_identifier, circuit_identifier,
circuit_member, circuit_member,
), ),
@ -858,6 +897,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
cs, cs,
file_scope, file_scope,
function_scope, function_scope,
expected_types,
function, function,
arguments, arguments,
), ),

View File

@ -34,7 +34,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
Ok(self.evaluate_identifier(caller_scope, function_name, identifier)?) Ok(self.evaluate_identifier(caller_scope, function_name, identifier)?)
} }
expression => Ok(self.enforce_expression(cs, scope, function_name, expression)?), expression => Ok(self.enforce_expression(cs, scope, function_name, vec![], expression)?),
} }
} }

View File

@ -54,7 +54,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
match range_or_expression { match range_or_expression {
RangeOrExpression::Expression(index) => { RangeOrExpression::Expression(index) => {
let index = let index =
self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index)?; self.enforce_index(cs, file_scope.clone(), function_scope.clone(), vec![], index)?;
// Modify the single value of the array in place // Modify the single value of the array in place
match self.get_mutable_assignee(name)? { match self.get_mutable_assignee(name)? {
@ -137,7 +137,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
// Evaluate new value // Evaluate new value
let new_value = let new_value =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expression)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), vec![], expression)?;
// Mutate the old value into the new value // Mutate the old value into the new value
match assignee { match assignee {
@ -193,8 +193,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
variable: Variable<F, G>, variable: Variable<F, G>,
expression: Expression<F, G>, expression: Expression<F, G>,
) -> Result<(), StatementError> { ) -> Result<(), StatementError> {
let mut expected_types = vec![];
if let Some(ref _type) = variable._type {
expected_types.push(_type.clone());
}
let value = let value =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expression)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), expected_types, expression)?;
self.store_definition(function_scope, variable, value) self.store_definition(function_scope, variable, value)
} }
@ -207,11 +211,19 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
variables: Vec<Variable<F, G>>, variables: Vec<Variable<F, G>>,
function: Expression<F, G>, function: Expression<F, G>,
) -> Result<(), StatementError> { ) -> Result<(), StatementError> {
let mut expected_types = vec![];
for variable in variables.iter() {
if let Some(ref _type) = variable._type {
expected_types.push(_type.clone());
}
}
// Expect return values from function // Expect return values from function
let return_values = match self.enforce_expression( let return_values = match self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
function, function,
)? { )? {
ConstrainedValue::Return(values) => values, ConstrainedValue::Return(values) => values,
@ -252,10 +264,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
let mut returns = vec![]; let mut returns = vec![];
for (expression, ty) in expressions.into_iter().zip(return_types.into_iter()) { for (expression, ty) in expressions.into_iter().zip(return_types.into_iter()) {
let expected_types = vec![ty.clone()];
let result = self.enforce_expression( let result = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
expression, expression,
)?; )?;
result.expect_type(&ty)?; result.expect_type(&ty)?;
@ -300,10 +314,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
statement: ConditionalStatement<F, G>, statement: ConditionalStatement<F, G>,
return_types: Vec<Type<F, G>>, return_types: Vec<Type<F, G>>,
) -> Result<Option<ConstrainedValue<F, G>>, StatementError> { ) -> Result<Option<ConstrainedValue<F, G>>, StatementError> {
let expected_types = vec![Type::Boolean];
let condition = match self.enforce_expression( let condition = match self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
expected_types,
statement.condition.clone(), statement.condition.clone(),
)? { )? {
ConstrainedValue::Boolean(resolved) => resolved, ConstrainedValue::Boolean(resolved) => resolved,
@ -488,14 +504,14 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
} }
Statement::AssertEq(left, right) => { Statement::AssertEq(left, right) => {
let resolved_left = let resolved_left =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), left)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), vec![], left)?;
let resolved_right = let resolved_right =
self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), right)?; self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), vec![], right)?;
self.enforce_assert_eq_statement(cs, resolved_left, resolved_right)?; self.enforce_assert_eq_statement(cs, resolved_left, resolved_right)?;
} }
Statement::Expression(expression) => { Statement::Expression(expression) => {
match self.enforce_expression(cs, file_scope, function_scope, expression.clone())? { match self.enforce_expression(cs, file_scope, function_scope, vec![], expression.clone())? {
ConstrainedValue::Return(values) => { ConstrainedValue::Return(values) => {
if !values.is_empty() { if !values.is_empty() {
return Err(StatementError::Unassigned(expression.to_string())); return Err(StatementError::Unassigned(expression.to_string()));

View File

@ -7,6 +7,9 @@ pub enum ExpressionError {
UndefinedIdentifier(String), UndefinedIdentifier(String),
// Types // Types
#[error("Expected single type for implicit number {}", _0)]
SingleType(String),
#[error("{}", _0)] #[error("{}", _0)]
IncompatibleTypes(String), IncompatibleTypes(String),