mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
implict ternary expression
This commit is contained in:
parent
2b48224689
commit
d0c88a08be
@ -1,11 +1,3 @@
|
||||
circuit Foo {
|
||||
x: u32
|
||||
|
||||
static function new() -> Self {
|
||||
return Self { x: 5 }
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
let a = Foo::new();
|
||||
let a: u32 = if true ? 1 : 5;
|
||||
}
|
@ -10,12 +10,15 @@ use crate::{
|
||||
CircuitFieldDefinition, CircuitMember, Expression, Identifier, RangeOrExpression,
|
||||
SpreadOrExpression,
|
||||
},
|
||||
Type,
|
||||
Integer, Type,
|
||||
};
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, Group, PrimeField},
|
||||
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
|
||||
gadgets::{
|
||||
r1cs::ConstraintSystem,
|
||||
utilities::{boolean::Boolean, select::CondSelectGadget},
|
||||
},
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgram<F, G, CS> {
|
||||
@ -382,6 +385,54 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce ternary conditional expression
|
||||
fn enforce_conditional_expression(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
expected_types: Vec<Type<F, G>>,
|
||||
first: Expression<F, G>,
|
||||
second: Expression<F, G>,
|
||||
third: Expression<F, G>,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let resolved_first = match self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
vec![Type::Boolean],
|
||||
first,
|
||||
)? {
|
||||
ConstrainedValue::Boolean(resolved) => resolved,
|
||||
value => return Err(ExpressionError::IfElseConditional(value.to_string())),
|
||||
};
|
||||
|
||||
let resolved_second = self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
second,
|
||||
)?;
|
||||
let resolved_third =
|
||||
self.enforce_expression(cs, file_scope, function_scope, expected_types, third)?;
|
||||
|
||||
match (resolved_second, resolved_third) {
|
||||
(ConstrainedValue::Boolean(bool_2), ConstrainedValue::Boolean(bool_3)) => {
|
||||
let result = Boolean::conditionally_select(cs, &resolved_first, &bool_2, &bool_3)?;
|
||||
Ok(ConstrainedValue::Boolean(result))
|
||||
}
|
||||
(ConstrainedValue::Integer(integer_2), ConstrainedValue::Integer(integer_3)) => {
|
||||
let result =
|
||||
Integer::conditionally_select(cs, &resolved_first, &integer_2, &integer_3)?;
|
||||
Ok(ConstrainedValue::Integer(result))
|
||||
}
|
||||
(_, _) => {
|
||||
unimplemented!("conditional select gadget not implemented between given types")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce array expressions
|
||||
fn enforce_array_expression(
|
||||
&mut self,
|
||||
@ -976,24 +1027,15 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
}
|
||||
|
||||
// Conditionals
|
||||
Expression::IfElse(first, second, third) => {
|
||||
let resolved_first = match self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expected_types.clone(),
|
||||
*first,
|
||||
)? {
|
||||
ConstrainedValue::Boolean(resolved) => resolved,
|
||||
value => return Err(ExpressionError::IfElseConditional(value.to_string())),
|
||||
};
|
||||
|
||||
if resolved_first.eq(&Boolean::Constant(true)) {
|
||||
self.enforce_expression(cs, file_scope, function_scope, expected_types, *second)
|
||||
} else {
|
||||
self.enforce_expression(cs, file_scope, function_scope, expected_types, *third)
|
||||
}
|
||||
}
|
||||
Expression::IfElse(first, second, third) => self.enforce_conditional_expression(
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
expected_types,
|
||||
*first,
|
||||
*second,
|
||||
*third,
|
||||
),
|
||||
|
||||
// Arrays
|
||||
Expression::Array(array) => {
|
||||
|
@ -7,11 +7,72 @@ use crate::{
|
||||
IntegerType,
|
||||
};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, Group, PrimeField},
|
||||
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
|
||||
gadgets::{
|
||||
r1cs::ConstraintSystem,
|
||||
utilities::{
|
||||
boolean::Boolean, select::CondSelectGadget, uint128::UInt128, uint16::UInt16,
|
||||
uint32::UInt32, uint64::UInt64, uint8::UInt8,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
impl Integer {
|
||||
pub fn to_usize(&self) -> usize {
|
||||
match self {
|
||||
Integer::U8(u8) => u8.value.unwrap() as usize,
|
||||
Integer::U16(u16) => u16.value.unwrap() as usize,
|
||||
Integer::U32(u32) => u32.value.unwrap() as usize,
|
||||
Integer::U64(u64) => u64.value.unwrap() as usize,
|
||||
Integer::U128(u128) => u128.value.unwrap() as usize,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_type(&self) -> IntegerType {
|
||||
match self {
|
||||
Integer::U8(_u8) => IntegerType::U8,
|
||||
Integer::U16(_u16) => IntegerType::U16,
|
||||
Integer::U32(_u32) => IntegerType::U32,
|
||||
Integer::U64(_u64) => IntegerType::U64,
|
||||
Integer::U128(_u128) => IntegerType::U128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> CondSelectGadget<F> for Integer {
|
||||
fn conditionally_select<CS: ConstraintSystem<F>>(
|
||||
cs: CS,
|
||||
cond: &Boolean,
|
||||
first: &Self,
|
||||
second: &Self,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
match (first, second) {
|
||||
(Integer::U8(u8_first), Integer::U8(u8_second)) => Ok(Integer::U8(
|
||||
UInt8::conditionally_select(cs, cond, u8_first, u8_second)?,
|
||||
)),
|
||||
(Integer::U16(u16_first), Integer::U16(u18_second)) => Ok(Integer::U16(
|
||||
UInt16::conditionally_select(cs, cond, u16_first, u18_second)?,
|
||||
)),
|
||||
(Integer::U32(u32_first), Integer::U32(u32_second)) => Ok(Integer::U32(
|
||||
UInt32::conditionally_select(cs, cond, u32_first, u32_second)?,
|
||||
)),
|
||||
(Integer::U64(u64_first), Integer::U64(u64_second)) => Ok(Integer::U64(
|
||||
UInt64::conditionally_select(cs, cond, u64_first, u64_second)?,
|
||||
)),
|
||||
(Integer::U128(u128_first), Integer::U128(u128_second)) => Ok(Integer::U128(
|
||||
UInt128::conditionally_select(cs, cond, u128_first, u128_second)?,
|
||||
)),
|
||||
(_, _) => Err(SynthesisError::Unsatisfiable), // types do not match
|
||||
}
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
unimplemented!("Cannot calculate cost.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgram<F, G, CS> {
|
||||
pub(crate) fn get_integer_constant(integer: Integer) -> ConstrainedValue<F, G> {
|
||||
ConstrainedValue::Integer(integer)
|
||||
|
@ -1,5 +1,7 @@
|
||||
use crate::errors::{BooleanError, FieldElementError, FunctionError, IntegerError, ValueError};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExpressionError {
|
||||
// Identifiers
|
||||
@ -85,6 +87,15 @@ pub enum ExpressionError {
|
||||
// Conditionals
|
||||
#[error("If, else conditional must resolve to a boolean, got {}", _0)]
|
||||
IfElseConditional(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
SynthesisError(SynthesisError),
|
||||
}
|
||||
|
||||
impl From<SynthesisError> for ExpressionError {
|
||||
fn from(error: SynthesisError) -> Self {
|
||||
ExpressionError::SynthesisError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValueError> for ExpressionError {
|
||||
|
@ -54,28 +54,6 @@ pub enum Integer {
|
||||
U128(UInt128),
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
pub fn to_usize(&self) -> usize {
|
||||
match self {
|
||||
Integer::U8(u8) => u8.value.unwrap() as usize,
|
||||
Integer::U16(u16) => u16.value.unwrap() as usize,
|
||||
Integer::U32(u32) => u32.value.unwrap() as usize,
|
||||
Integer::U64(u64) => u64.value.unwrap() as usize,
|
||||
Integer::U128(u128) => u128.value.unwrap() as usize,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_type(&self) -> IntegerType {
|
||||
match self {
|
||||
Integer::U8(_u8) => IntegerType::U8,
|
||||
Integer::U16(_u16) => IntegerType::U16,
|
||||
Integer::U32(_u32) => IntegerType::U32,
|
||||
Integer::U64(_u64) => IntegerType::U64,
|
||||
Integer::U128(_u128) => IntegerType::U128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A constant or allocated element in the field
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum FieldElement<F: Field + PrimeField> {
|
||||
|
Loading…
Reference in New Issue
Block a user