mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
impl mutability tests. simplify mut expression evaluation
This commit is contained in:
parent
9309f95a89
commit
a9a8cb95c6
@ -4,7 +4,7 @@ use crate::{
|
||||
ast,
|
||||
constraints::{generate_constraints, ConstrainedValue},
|
||||
errors::CompilerError,
|
||||
InputValue, Program
|
||||
InputValue, Program,
|
||||
};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
@ -44,6 +44,10 @@ impl<F: Field + PrimeField, G: Group> Compiler<F, G> {
|
||||
Ok(program)
|
||||
}
|
||||
|
||||
pub fn set_inputs(&mut self, program_inputs: Vec<Option<InputValue<F, G>>>) {
|
||||
self.program_inputs = program_inputs;
|
||||
}
|
||||
|
||||
pub fn checksum(&self) -> Result<String, CompilerError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path)
|
||||
@ -60,12 +64,8 @@ impl<F: Field + PrimeField, G: Group> Compiler<F, G> {
|
||||
pub fn compile_constraints<CS: ConstraintSystem<F>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<ConstrainedValue<F, G>, SynthesisError> {
|
||||
let result = generate_constraints(cs, self.program, self.program_inputs).unwrap();
|
||||
|
||||
// Write results to file or something
|
||||
|
||||
Ok(result)
|
||||
) -> Result<ConstrainedValue<F, G>, CompilerError> {
|
||||
generate_constraints(cs, self.program, self.program_inputs)
|
||||
}
|
||||
|
||||
// pub fn compile(&self) -> Result<ast::File, CompilerError> {
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
CircuitFieldDefinition, CircuitMember, Expression, Identifier, RangeOrExpression,
|
||||
SpreadOrExpression,
|
||||
},
|
||||
Integer, Type,
|
||||
Integer, IntegerType, Type,
|
||||
};
|
||||
|
||||
use snarkos_models::{
|
||||
@ -27,14 +27,14 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
&mut self,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
unresolved_identifier: Identifier<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
// Evaluate the identifier name in the current function scope
|
||||
let variable_name = new_scope(function_scope, unresolved_identifier.to_string());
|
||||
let identifier_name = new_scope(file_scope, unresolved_identifier.to_string());
|
||||
|
||||
let result_value = if let Some(value) = self.get(&variable_name) {
|
||||
let mut result_value = if let Some(value) = self.get(&variable_name) {
|
||||
// Reassigning variable to another variable
|
||||
value.clone()
|
||||
} else if let Some(value) = self.get(&identifier_name) {
|
||||
@ -46,12 +46,9 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
));
|
||||
};
|
||||
|
||||
match result_value {
|
||||
ConstrainedValue::Unresolved(string) => {
|
||||
Self::enforce_number_implicit(expected_types, string)
|
||||
}
|
||||
value => Ok(value),
|
||||
}
|
||||
result_value.resolve_type(expected_types)?;
|
||||
|
||||
Ok(result_value)
|
||||
}
|
||||
|
||||
/// Enforce numerical operations
|
||||
@ -71,12 +68,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
(ConstrainedValue::GroupElement(ge_1), ConstrainedValue::GroupElement(ge_2)) => {
|
||||
Ok(Self::evaluate_group_add(ge_1, ge_2))
|
||||
}
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.enforce_add_expression(cs, *val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.enforce_add_expression(cs, val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_add_expression(cs, val_1, val_2)
|
||||
@ -108,12 +99,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
(ConstrainedValue::GroupElement(ge_1), ConstrainedValue::GroupElement(ge_2)) => {
|
||||
Ok(Self::evaluate_group_sub(ge_1, ge_2))
|
||||
}
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.enforce_sub_expression(cs, *val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.enforce_sub_expression(cs, val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_sub_expression(cs, val_1, val_2)
|
||||
@ -145,12 +130,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// (ConstrainedValue::GroupElement(group), ConstrainedValue::FieldElement(scalar)) => {
|
||||
// Ok(Self::evaluate_group_mul(group, scalar))
|
||||
// }
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.enforce_mul_expression(cs, *val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.enforce_mul_expression(cs, val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_mul_expression(cs, val_1, val_2)
|
||||
@ -181,12 +160,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(self.enforce_field_div(cs, fe_1, fe_2)?)
|
||||
}
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.enforce_div_expression(cs, *val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.enforce_div_expression(cs, val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_div_expression(cs, val_1, val_2)
|
||||
@ -216,12 +189,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(self.enforce_field_pow(cs, fe_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.enforce_pow_expression(cs, *val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.enforce_pow_expression(cs, val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_pow_expression(cs, val_1, val_2)
|
||||
@ -259,8 +226,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
(ConstrainedValue::GroupElement(ge_1), ConstrainedValue::GroupElement(ge_2)) => {
|
||||
Ok(Self::evaluate_group_eq(ge_1, ge_2))
|
||||
}
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => self.evaluate_eq_expression(*val_1, val_2),
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => self.evaluate_eq_expression(val_1, *val_2),
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_eq_expression(val_1, val_2)
|
||||
@ -285,12 +250,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// (ResolvedValue::FieldElement(fe_1), ResolvedValue::FieldElement(fe_2)) => {
|
||||
// Self::field_geq(fe_1, fe_2)
|
||||
// }
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.evaluate_geq_expression(*val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.evaluate_geq_expression(val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_geq_expression(val_1, val_2)
|
||||
@ -315,8 +274,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// (ResolvedValue::FieldElement(fe_1), ResolvedValue::FieldElement(fe_2)) => {
|
||||
// Self::field_gt(fe_1, fe_2)
|
||||
// }
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => self.evaluate_gt_expression(*val_1, val_2),
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => self.evaluate_gt_expression(val_1, *val_2),
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_gt_expression(val_1, val_2)
|
||||
@ -341,12 +298,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// (ResolvedValue::FieldElement(fe_1), ResolvedValue::FieldElement(fe_2)) => {
|
||||
// Self::field_leq(fe_1, fe_2)
|
||||
// }
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||
self.evaluate_leq_expression(*val_1, val_2)
|
||||
}
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => {
|
||||
self.evaluate_leq_expression(val_1, *val_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_leq_expression(val_1, val_2)
|
||||
@ -371,8 +322,6 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// (ResolvedValue::FieldElement(fe_1), ResolvedValue::FieldElement(fe_2)) => {
|
||||
// Self::field_lt(fe_1, fe_2)
|
||||
// }
|
||||
(ConstrainedValue::Mutable(val_1), val_2) => self.evaluate_lt_expression(*val_1, val_2),
|
||||
(val_1, ConstrainedValue::Mutable(val_2)) => self.evaluate_lt_expression(val_1, *val_2),
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.evaluate_lt_expression(val_1, val_2)
|
||||
@ -394,7 +343,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
first: Expression<F, G>,
|
||||
second: Expression<F, G>,
|
||||
third: Expression<F, G>,
|
||||
@ -403,22 +352,22 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![Type::Boolean],
|
||||
&vec![Type::Boolean],
|
||||
first,
|
||||
)? {
|
||||
ConstrainedValue::Boolean(resolved) => resolved,
|
||||
value => return Err(ExpressionError::IfElseConditional(value.to_string())),
|
||||
};
|
||||
|
||||
let resolved_second = self.enforce_expression(
|
||||
let resolved_second = self.enforce_branch(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
expected_types,
|
||||
second,
|
||||
)?;
|
||||
let resolved_third =
|
||||
self.enforce_expression(cs, file_scope, function_scope, expected_types, third)?;
|
||||
self.enforce_branch(cs, file_scope, function_scope, expected_types, third)?;
|
||||
|
||||
match (resolved_second, resolved_third) {
|
||||
(ConstrainedValue::Boolean(bool_2), ConstrainedValue::Boolean(bool_3)) => {
|
||||
@ -442,11 +391,13 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
mut expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
array: Vec<Box<SpreadOrExpression<F, G>>>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
// Check explicit array type dimension if given
|
||||
let mut expected_types = expected_types.clone();
|
||||
let expected_dimensions = vec![];
|
||||
|
||||
if !expected_types.is_empty() {
|
||||
match expected_types[0] {
|
||||
Type::Array(ref _type, ref dimensions) => {
|
||||
@ -479,7 +430,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
&expected_types,
|
||||
expression,
|
||||
)?);
|
||||
}
|
||||
@ -504,12 +455,17 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
index: Expression<F, G>,
|
||||
) -> Result<usize, ExpressionError> {
|
||||
match self.enforce_expression(cs, file_scope, function_scope, expected_types, index)? {
|
||||
let expected_types = vec![Type::IntegerType(IntegerType::U32)];
|
||||
match self.enforce_branch(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
&expected_types,
|
||||
index,
|
||||
)? {
|
||||
ConstrainedValue::Integer(number) => Ok(number.to_usize()),
|
||||
ConstrainedValue::Unresolved(string) => Ok(string.parse::<usize>()?),
|
||||
value => Err(ExpressionError::InvalidIndex(value.to_string())),
|
||||
}
|
||||
}
|
||||
@ -519,7 +475,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
array: Box<Expression<F, G>>,
|
||||
index: RangeOrExpression<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
@ -527,14 +483,10 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
expected_types,
|
||||
*array,
|
||||
)? {
|
||||
ConstrainedValue::Array(array) => array,
|
||||
ConstrainedValue::Mutable(value) => match *value {
|
||||
ConstrainedValue::Array(array) => array,
|
||||
value => return Err(ExpressionError::InvalidArrayAccess(value.to_string())),
|
||||
},
|
||||
value => return Err(ExpressionError::InvalidArrayAccess(value.to_string())),
|
||||
};
|
||||
|
||||
@ -553,8 +505,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
))
|
||||
}
|
||||
RangeOrExpression::Expression(index) => {
|
||||
let index_resolved =
|
||||
self.enforce_index(cs, file_scope, function_scope, expected_types, index)?;
|
||||
let index_resolved = self.enforce_index(cs, file_scope, function_scope, index)?;
|
||||
Ok(array[index_resolved].to_owned())
|
||||
}
|
||||
}
|
||||
@ -593,7 +544,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![_type.clone()],
|
||||
&vec![_type.clone()],
|
||||
field.expression,
|
||||
)?;
|
||||
|
||||
@ -639,22 +590,18 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
circuit_identifier: Box<Expression<F, G>>,
|
||||
circuit_member: Identifier<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let (circuit_name, members) = match self.enforce_expression(
|
||||
let (circuit_name, members) = match self.enforce_branch(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
expected_types,
|
||||
*circuit_identifier.clone(),
|
||||
)? {
|
||||
ConstrainedValue::CircuitExpression(name, members) => (name, members),
|
||||
ConstrainedValue::Mutable(value) => match *value {
|
||||
ConstrainedValue::CircuitExpression(name, members) => (name, members),
|
||||
value => return Err(ExpressionError::InvalidCircuitAccess(value.to_string())),
|
||||
},
|
||||
value => return Err(ExpressionError::InvalidCircuitAccess(value.to_string())),
|
||||
};
|
||||
|
||||
@ -700,7 +647,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
circuit_identifier: Box<Expression<F, G>>,
|
||||
circuit_member: Identifier<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
@ -709,7 +656,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
expected_types,
|
||||
*circuit_identifier.clone(),
|
||||
)? {
|
||||
ConstrainedValue::CircuitDefinition(circuit_definition) => circuit_definition,
|
||||
@ -752,7 +699,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
function: Box<Expression<F, G>>,
|
||||
arguments: Vec<Expression<F, G>>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
@ -760,7 +707,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
expected_types,
|
||||
*function.clone(),
|
||||
)?;
|
||||
|
||||
@ -791,7 +738,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_number_implicit(
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
value: String,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
if expected_types.len() == 1 {
|
||||
@ -801,12 +748,59 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
Ok(ConstrainedValue::Unresolved(value))
|
||||
}
|
||||
|
||||
/// Enforce a branch of a binary expression.
|
||||
/// We don't care about mutability because we are not changing any variables.
|
||||
/// We try to resolve unresolved types here if the type is given explicitly.
|
||||
pub(crate) fn enforce_branch(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
expression: Expression<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut branch =
|
||||
self.enforce_expression(cs, file_scope, function_scope, expected_types, expression)?;
|
||||
|
||||
branch.get_inner_mut();
|
||||
branch.resolve_type(expected_types)?;
|
||||
|
||||
Ok(branch)
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_binary_expression(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
left: Expression<F, G>,
|
||||
right: Expression<F, G>,
|
||||
) -> Result<(ConstrainedValue<F, G>, ConstrainedValue<F, G>), ExpressionError> {
|
||||
let resolved_left = self.enforce_branch(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_branch(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
right,
|
||||
)?;
|
||||
|
||||
Ok((resolved_left, resolved_right))
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_expression(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
expected_types: &Vec<Type<F, G>>,
|
||||
expression: Expression<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
match expression {
|
||||
@ -827,90 +821,60 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
|
||||
// Binary operations
|
||||
Expression::Add(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_add_expression(cs, resolved_left, resolved_right)
|
||||
}
|
||||
Expression::Sub(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_sub_expression(cs, resolved_left, resolved_right)
|
||||
}
|
||||
Expression::Mul(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_mul_expression(cs, resolved_left, resolved_right)
|
||||
}
|
||||
Expression::Div(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
self.enforce_div_expression(cs, resolved_left, resolved_right)
|
||||
}
|
||||
Expression::Pow(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
@ -926,126 +890,84 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
*expression,
|
||||
)?)?),
|
||||
Expression::Or(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.enforce_or(cs, resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::And(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.enforce_and(cs, resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::Eq(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_eq_expression(resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::Geq(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_geq_expression(resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::Gt(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_gt_expression(resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::Leq(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
Ok(self.evaluate_leq_expression(resolved_left, resolved_right)?)
|
||||
}
|
||||
Expression::Lt(left, right) => {
|
||||
let resolved_left = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
let (resolved_left, resolved_right) = self.enforce_binary_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
*left,
|
||||
*right,
|
||||
)?;
|
||||
|
||||
|
@ -37,12 +37,16 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
Expression::Identifier(identifier) => Ok(self.evaluate_identifier(
|
||||
caller_scope,
|
||||
function_name,
|
||||
expected_types,
|
||||
&expected_types,
|
||||
identifier,
|
||||
)?),
|
||||
expression => {
|
||||
Ok(self.enforce_expression(cs, scope, function_name, expected_types, expression)?)
|
||||
}
|
||||
expression => Ok(self.enforce_expression(
|
||||
cs,
|
||||
scope,
|
||||
function_name,
|
||||
&expected_types,
|
||||
expression,
|
||||
)?),
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,7 +206,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
function.inputs.clone().into_iter().zip(inputs.into_iter())
|
||||
{
|
||||
let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone());
|
||||
let mut input_value = self.allocate_main_function_input(
|
||||
let input_value = self.allocate_main_function_input(
|
||||
cs,
|
||||
input_model._type,
|
||||
input_name.clone(),
|
||||
@ -210,14 +214,12 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
input_option,
|
||||
)?;
|
||||
|
||||
if input_model.mutable {
|
||||
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
||||
}
|
||||
|
||||
// Store a new variable for every allocated main function input
|
||||
self.store(input_name.clone(), input_value);
|
||||
|
||||
input_variables.push(Expression::Identifier(Identifier::new(input_name)));
|
||||
input_variables.push(Expression::Identifier(Identifier::new(
|
||||
input_model.identifier.name.clone(),
|
||||
)));
|
||||
}
|
||||
|
||||
self.enforce_function(cs, scope, function_name, function, input_variables)
|
||||
|
@ -55,6 +55,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
}
|
||||
|
||||
pub(crate) fn store(&mut self, name: String, value: ConstrainedValue<F, G>) {
|
||||
println!("storing {}", name);
|
||||
self.identifiers.insert(name, value);
|
||||
}
|
||||
|
||||
|
@ -53,13 +53,8 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// Resolve index so we know if we are assigning to a single value or a range of values
|
||||
match range_or_expression {
|
||||
RangeOrExpression::Expression(index) => {
|
||||
let index = self.enforce_index(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![],
|
||||
index,
|
||||
)?;
|
||||
let index =
|
||||
self.enforce_index(cs, file_scope.clone(), function_scope.clone(), index)?;
|
||||
|
||||
// Modify the single value of the array in place
|
||||
match self.get_mutable_assignee(name)? {
|
||||
@ -145,7 +140,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![],
|
||||
&vec![],
|
||||
expression,
|
||||
)?;
|
||||
|
||||
@ -206,7 +201,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
&expected_types,
|
||||
expression,
|
||||
)?;
|
||||
|
||||
@ -233,7 +228,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
&expected_types,
|
||||
function,
|
||||
)? {
|
||||
ConstrainedValue::Return(values) => values,
|
||||
@ -275,11 +270,11 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
let mut returns = vec![];
|
||||
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_branch(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
&expected_types,
|
||||
expression,
|
||||
)?;
|
||||
|
||||
@ -328,7 +323,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types,
|
||||
&expected_types,
|
||||
statement.condition.clone(),
|
||||
)? {
|
||||
ConstrainedValue::Boolean(resolved) => resolved,
|
||||
@ -516,14 +511,14 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![],
|
||||
&vec![],
|
||||
left,
|
||||
)?;
|
||||
let resolved_right = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![],
|
||||
&vec![],
|
||||
right,
|
||||
)?;
|
||||
|
||||
@ -534,7 +529,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
vec![],
|
||||
&vec![],
|
||||
expression.clone(),
|
||||
)? {
|
||||
ConstrainedValue::Return(values) => {
|
||||
|
@ -86,6 +86,22 @@ impl<F: Field + PrimeField, G: Group> ConstrainedValue<F, G> {
|
||||
_ => unimplemented!("to type only implemented for primitives"),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_type(&mut self, types: &Vec<Type<F, G>>) -> Result<(), ValueError> {
|
||||
if let ConstrainedValue::Unresolved(ref string) = self {
|
||||
if !types.is_empty() {
|
||||
*self = ConstrainedValue::from_type(string.clone(), &types[0])?
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn get_inner_mut(&mut self) {
|
||||
if let ConstrainedValue::Mutable(inner) = self {
|
||||
*self = *inner.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField, G: Group> fmt::Display for ConstrainedValue<F, G> {
|
||||
|
@ -785,6 +785,7 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::InputModel<'ast>>
|
||||
for types::InputModel<F, G>
|
||||
{
|
||||
fn from(parameter: ast::InputModel<'ast>) -> Self {
|
||||
println!("{}", parameter.mutable.is_some());
|
||||
types::InputModel {
|
||||
identifier: types::Identifier::from(parameter.identifier),
|
||||
mutable: parameter.mutable.is_some(),
|
||||
|
@ -1 +1,31 @@
|
||||
pub mod mutability;
|
||||
pub mod u32;
|
||||
|
||||
use leo_compiler::{compiler::Compiler, errors::CompilerError};
|
||||
|
||||
use snarkos_curves::{bls12_377::Fr, edwards_bls12::EdwardsProjective};
|
||||
|
||||
use std::env::current_dir;
|
||||
|
||||
pub(crate) fn compile_program(
|
||||
directory_name: &str,
|
||||
file_name: &str,
|
||||
) -> Result<Compiler<Fr, EdwardsProjective>, CompilerError> {
|
||||
let path = current_dir().map_err(|error| CompilerError::DirectoryError(error))?;
|
||||
|
||||
// Sanitize the package path to the test directory
|
||||
let mut package_path = path.clone();
|
||||
if package_path.is_file() {
|
||||
package_path.pop();
|
||||
}
|
||||
|
||||
// Construct the path to the test file in the test directory
|
||||
let mut main_file_path = package_path.clone();
|
||||
main_file_path.push(directory_name);
|
||||
main_file_path.push(file_name);
|
||||
|
||||
println!("Compiling file - {:?}", main_file_path);
|
||||
|
||||
// Compile from the main file path
|
||||
Compiler::<Fr, EdwardsProjective>::init(file_name.to_string(), main_file_path)
|
||||
}
|
||||
|
4
compiler/tests/mutability/function_input.leo
Normal file
4
compiler/tests/mutability/function_input.leo
Normal file
@ -0,0 +1,4 @@
|
||||
// Function inputs are immutable by default.
|
||||
function main(a: u32) {
|
||||
a = 0;
|
||||
}
|
6
compiler/tests/mutability/function_input_mut.leo
Normal file
6
compiler/tests/mutability/function_input_mut.leo
Normal file
@ -0,0 +1,6 @@
|
||||
// Adding the `mut` keyword makes a function variable mutable.
|
||||
function main(mut a: u32) -> u32 {
|
||||
a = 0;
|
||||
|
||||
return a
|
||||
}
|
5
compiler/tests/mutability/let.leo
Normal file
5
compiler/tests/mutability/let.leo
Normal file
@ -0,0 +1,5 @@
|
||||
// Variables are immutable by default.
|
||||
function main() {
|
||||
let a = 1u32;
|
||||
a = 0;
|
||||
}
|
7
compiler/tests/mutability/let_mut.leo
Normal file
7
compiler/tests/mutability/let_mut.leo
Normal file
@ -0,0 +1,7 @@
|
||||
// Adding the `mut` keyword makes a variable mutable.
|
||||
function main() -> u32 {
|
||||
let mut a = 1u32;
|
||||
a = 0;
|
||||
|
||||
return a
|
||||
}
|
59
compiler/tests/mutability/mod.rs
Normal file
59
compiler/tests/mutability/mod.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use crate::compile_program;
|
||||
|
||||
use leo_compiler::{types::Integer, ConstrainedValue, InputValue};
|
||||
|
||||
use snarkos_curves::{bls12_377::Fr, edwards_bls12::EdwardsProjective};
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::utilities::uint32::UInt32;
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/mutability/";
|
||||
|
||||
#[test]
|
||||
fn test_let() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let program = compile_program(DIRECTORY_NAME, "let.leo").unwrap();
|
||||
let output = program.compile_constraints(&mut cs).is_err();
|
||||
assert!(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_let_mut() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let program = compile_program(DIRECTORY_NAME, "let_mut.leo").unwrap();
|
||||
let output = program.compile_constraints(&mut cs).unwrap();
|
||||
println!("{}", output);
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(
|
||||
Integer::U32(UInt32::constant(0))
|
||||
)]),
|
||||
output
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_input() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut program = compile_program(DIRECTORY_NAME, "function_input.leo").unwrap();
|
||||
program.set_inputs(vec![Some(InputValue::Integer(1))]);
|
||||
let output = program.compile_constraints(&mut cs).is_err();
|
||||
assert!(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_input_mut() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let mut program = compile_program(DIRECTORY_NAME, "function_input_mut.leo").unwrap();
|
||||
program.set_inputs(vec![Some(InputValue::Integer(1))]);
|
||||
let output = program.compile_constraints(&mut cs).unwrap();
|
||||
println!("{}", output);
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(
|
||||
Integer::U32(UInt32::constant(0))
|
||||
)]),
|
||||
output
|
||||
);
|
||||
}
|
@ -1,36 +1,13 @@
|
||||
use leo_compiler::{compiler::Compiler, errors::CompilerError, types::Integer, ConstrainedValue};
|
||||
use crate::compile_program;
|
||||
|
||||
use snarkos_curves::{
|
||||
bls12_377::{Bls12_377, Fr},
|
||||
edwards_bls12::EdwardsProjective
|
||||
};
|
||||
use snarkos_models::gadgets::r1cs::{ConstraintSynthesizer, TestConstraintSystem};
|
||||
use leo_compiler::{types::Integer, ConstrainedValue};
|
||||
|
||||
use snarkos_curves::{bls12_377::Fr, edwards_bls12::EdwardsProjective};
|
||||
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
|
||||
use snarkos_models::gadgets::utilities::uint32::UInt32;
|
||||
|
||||
use std::env::current_dir;
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/u32/";
|
||||
|
||||
fn compile_program(directory_name: &str, file_name: &str) -> Result<Compiler<Fr, EdwardsProjective>, CompilerError> {
|
||||
let path = current_dir().map_err(|error| CompilerError::DirectoryError(error))?;
|
||||
|
||||
// Sanitize the package path to the test directory
|
||||
let mut package_path = path.clone();
|
||||
if package_path.is_file() {
|
||||
package_path.pop();
|
||||
}
|
||||
|
||||
// Construct the path to the test file in the test directory
|
||||
let mut main_file_path = package_path.clone();
|
||||
main_file_path.push(directory_name);
|
||||
main_file_path.push(file_name);
|
||||
|
||||
println!("Compiling file - {:?}", main_file_path);
|
||||
|
||||
// Compile from the main file path
|
||||
Compiler::<Fr, EdwardsProjective>::init(file_name.to_string(), main_file_path)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero() {
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
@ -40,7 +17,9 @@ fn test_zero() {
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0)))]),
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(
|
||||
Integer::U32(UInt32::constant(0))
|
||||
)]),
|
||||
output
|
||||
);
|
||||
}
|
||||
@ -54,7 +33,9 @@ fn test_one() {
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(1)))]),
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(
|
||||
Integer::U32(UInt32::constant(1))
|
||||
)]),
|
||||
output
|
||||
);
|
||||
}
|
||||
@ -68,7 +49,9 @@ fn test_1_plus_1() {
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(2)))]),
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(
|
||||
Integer::U32(UInt32::constant(2))
|
||||
)]),
|
||||
output
|
||||
);
|
||||
}
|
||||
@ -82,17 +65,19 @@ fn test_1_minus_1() {
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(Integer::U32(UInt32::constant(0)))]),
|
||||
ConstrainedValue::<Fr, EdwardsProjective>::Return(vec![ConstrainedValue::Integer(
|
||||
Integer::U32(UInt32::constant(0))
|
||||
)]),
|
||||
output
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_minus_2_should_fail() {
|
||||
// TODO (howardwu): Catch panic from subtraction overflow
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
let program = compile_program(DIRECTORY_NAME, "1-2.leo").unwrap();
|
||||
let output = program.compile_constraints(&mut cs);
|
||||
assert!(output.is_err());
|
||||
}
|
||||
// #[test]
|
||||
// fn test_1_minus_2_should_fail() {
|
||||
// // TODO (howardwu): Catch panic from subtraction overflow
|
||||
//
|
||||
// let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
// let program = compile_program(DIRECTORY_NAME, "1-2.leo").unwrap();
|
||||
// let output = program.compile_constraints(&mut cs);
|
||||
// assert!(output.is_err());
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user