mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-29 22:36:05 +03:00
initial support for implicit value types
This commit is contained in:
parent
fd51ee28e2
commit
a31ee8b884
@ -1,5 +1,3 @@
|
|||||||
function main() {
|
function main() {
|
||||||
let g: group = 123456789;
|
let g: group = 123456789;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -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,
|
||||||
),
|
),
|
||||||
|
@ -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)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()));
|
||||||
|
@ -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),
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user