add ternary expression module

This commit is contained in:
collin 2020-07-07 23:38:01 -07:00
parent ada42fdcf4
commit c989061ab1
4 changed files with 69 additions and 53 deletions

View File

@ -0,0 +1,2 @@
pub mod ternary;
pub use self::ternary::*;

View File

@ -0,0 +1,63 @@
//! Methods to enforce constraints on ternary expressions in a compiled Leo program.
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_types::{Expression, Span, Type};
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::select::CondSelectGadget},
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
/// Enforce ternary conditional expression
pub fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
expected_types: &Vec<Type>,
conditional: Expression,
first: Expression,
second: Expression,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let conditional_value = match self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
&vec![Type::Boolean],
conditional,
)? {
ConstrainedValue::Boolean(resolved) => resolved,
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span)),
};
let first_value = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
first,
span.clone(),
)?;
let second_value = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
second,
span.clone(),
)?;
let unique_namespace = cs.ns(|| {
format!(
"select {} or {} {}:{}",
first_value, second_value, span.line, span.start
)
});
ConstrainedValue::conditionally_select(unique_namespace, &conditional_value, &first_value, &second_value)
.map_err(|e| ExpressionError::cannot_enforce(format!("conditional select"), e, span))
}
}

View File

@ -26,7 +26,7 @@ use leo_types::{
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::select::CondSelectGadget},
gadgets::r1cs::ConstraintSystem,
};
static SELF_KEYWORD: &'static str = "self";
@ -67,58 +67,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(result_value)
}
/// Enforce ternary conditional expression
fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
expected_types: &Vec<Type>,
conditional: Expression,
first: Expression,
second: Expression,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let conditional_value = match self.enforce_expression(
cs,
file_scope.clone(),
function_scope.clone(),
&vec![Type::Boolean],
conditional,
)? {
ConstrainedValue::Boolean(resolved) => resolved,
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span)),
};
let first_value = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
first,
span.clone(),
)?;
let second_value = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
second,
span.clone(),
)?;
let unique_namespace = cs.ns(|| {
format!(
"select {} or {} {}:{}",
first_value, second_value, span.line, span.start
)
});
ConstrainedValue::conditionally_select(unique_namespace, &conditional_value, &first_value, &second_value)
.map_err(|e| ExpressionError::cannot_enforce(format!("conditional select"), e, span))
}
/// Enforce array expressions
fn enforce_array_expression<CS: ConstraintSystem<F>>(
&mut self,

View File

@ -3,6 +3,9 @@
pub mod arithmetic;
pub use self::arithmetic::*;
pub mod conditional;
pub use self::conditional::*;
pub mod expression;
pub use self::expression::*;