mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
implicit arrays and multiple definitions
This commit is contained in:
parent
d0c88a08be
commit
aa63cf1dbb
@ -1,3 +1,10 @@
|
||||
function main() {
|
||||
let a: u32 = if true ? 1 : 5;
|
||||
function test(mut a: u32) {
|
||||
a = 0;
|
||||
}
|
||||
|
||||
function main() -> u32 {
|
||||
let a = 1;
|
||||
test(a);
|
||||
|
||||
return a // <- returns 1
|
||||
}
|
@ -142,6 +142,9 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(self.enforce_field_mul(cs, fe_1, fe_2)?)
|
||||
}
|
||||
// (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)
|
||||
}
|
||||
@ -439,9 +442,20 @@ 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>>,
|
||||
mut 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 expected_dimensions = vec![];
|
||||
if !expected_types.is_empty() {
|
||||
match expected_types[0] {
|
||||
Type::Array(ref _type, ref dimensions) => {
|
||||
expected_types = vec![expected_types[0].inner_dimension(dimensions)];
|
||||
}
|
||||
ref _type => return Err(ExpressionError::IncompatibleTypes(_type.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
let mut result = vec![];
|
||||
for element in array.into_iter() {
|
||||
match *element {
|
||||
@ -471,6 +485,17 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check expected_dimensions if given
|
||||
if !expected_dimensions.is_empty() {
|
||||
if expected_dimensions[expected_dimensions.len() - 1] != result.len() {
|
||||
return Err(ExpressionError::InvalidLength(
|
||||
expected_dimensions[expected_dimensions.len() - 1],
|
||||
result.len(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ConstrainedValue::Array(result))
|
||||
}
|
||||
|
||||
@ -484,6 +509,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
) -> Result<usize, ExpressionError> {
|
||||
match self.enforce_expression(cs, file_scope, function_scope, expected_types, index)? {
|
||||
ConstrainedValue::Integer(number) => Ok(number.to_usize()),
|
||||
ConstrainedValue::Unresolved(string) => Ok(string.parse::<usize>()?),
|
||||
value => Err(ExpressionError::InvalidIndex(value.to_string())),
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// Allocate each value in the current row
|
||||
for (i, value) in arr.into_iter().enumerate() {
|
||||
let value_name = new_scope(name.clone(), i.to_string());
|
||||
let value_type = array_type.next_dimension(&array_dimensions);
|
||||
let value_type = array_type.outer_dimension(&array_dimensions);
|
||||
|
||||
array_value.push(self.allocate_main_function_input(
|
||||
cs,
|
||||
@ -142,7 +142,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
// Allocate all row values as none
|
||||
for i in 0..expected_length {
|
||||
let value_name = new_scope(name.clone(), i.to_string());
|
||||
let value_type = array_type.next_dimension(&array_dimensions);
|
||||
let value_type = array_type.outer_dimension(&array_dimensions);
|
||||
|
||||
array_value.push(
|
||||
self.allocate_main_function_input(
|
||||
|
@ -17,4 +17,8 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
||||
pub fn evaluate_group_sub(group_element_1: G, group_element_2: G) -> ConstrainedValue<F, G> {
|
||||
ConstrainedValue::GroupElement(group_element_1.sub(&group_element_2))
|
||||
}
|
||||
//
|
||||
// pub fn evaluate_group_mul(group_element: G, scalar_field: G::ScalarField) -> ConstrainedValue<F, G> {
|
||||
// ConstrainedValue::GroupElement(group_element.mul(&scalar_field))
|
||||
// }
|
||||
}
|
||||
|
@ -51,27 +51,30 @@ impl<F: Field + PrimeField, G: Group> ConstrainedValue<F, G> {
|
||||
}
|
||||
|
||||
pub(crate) fn from_type(value: String, _type: &Type<F, G>) -> Result<Self, ValueError> {
|
||||
Ok(match _type {
|
||||
Type::IntegerType(integer_type) => ConstrainedValue::Integer(match integer_type {
|
||||
match _type {
|
||||
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(match integer_type {
|
||||
IntegerType::U8 => Integer::U8(UInt8::constant(value.parse::<u8>()?)),
|
||||
IntegerType::U16 => Integer::U16(UInt16::constant(value.parse::<u16>()?)),
|
||||
IntegerType::U32 => Integer::U32(UInt32::constant(value.parse::<u32>()?)),
|
||||
IntegerType::U64 => Integer::U64(UInt64::constant(value.parse::<u64>()?)),
|
||||
IntegerType::U128 => Integer::U128(UInt128::constant(value.parse::<u128>()?)),
|
||||
}),
|
||||
Type::FieldElement => ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
})),
|
||||
Type::FieldElement => Ok(ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
F::from_str(&value).unwrap_or_default(),
|
||||
)),
|
||||
Type::GroupElement => ConstrainedValue::GroupElement({
|
||||
))),
|
||||
Type::GroupElement => Ok(ConstrainedValue::GroupElement({
|
||||
use std::str::FromStr;
|
||||
|
||||
let scalar = G::ScalarField::from_str(&value).unwrap_or_default();
|
||||
let point = G::default().mul(&scalar);
|
||||
point
|
||||
}),
|
||||
Type::Boolean => ConstrainedValue::Boolean(Boolean::Constant(value.parse::<bool>()?)),
|
||||
_ => ConstrainedValue::Unresolved(value),
|
||||
})
|
||||
})),
|
||||
Type::Boolean => Ok(ConstrainedValue::Boolean(Boolean::Constant(
|
||||
value.parse::<bool>()?,
|
||||
))),
|
||||
Type::Array(ref _type, _dimensions) => ConstrainedValue::from_type(value, _type),
|
||||
_ => Ok(ConstrainedValue::Unresolved(value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_type(&self) -> Type<F, G> {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::errors::{BooleanError, FieldElementError, FunctionError, IntegerError, ValueError};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use std::num::ParseIntError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExpressionError {
|
||||
@ -21,6 +22,9 @@ pub enum ExpressionError {
|
||||
#[error("{}", _0)]
|
||||
IntegerError(IntegerError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParseIntError(ParseIntError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
FieldElementError(FieldElementError),
|
||||
|
||||
@ -46,6 +50,9 @@ pub enum ExpressionError {
|
||||
#[error("Index must resolve to an integer, got {}", _0)]
|
||||
InvalidIndex(String),
|
||||
|
||||
#[error("Expected array length {}, got {}", _0, _1)]
|
||||
InvalidLength(usize, usize),
|
||||
|
||||
// Circuits
|
||||
#[error(
|
||||
"Circuit {} must be declared before it is used in an inline expression",
|
||||
@ -110,6 +117,12 @@ impl From<IntegerError> for ExpressionError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ExpressionError {
|
||||
fn from(error: ParseIntError) -> Self {
|
||||
ExpressionError::ParseIntError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FieldElementError> for ExpressionError {
|
||||
fn from(error: FieldElementError) -> Self {
|
||||
ExpressionError::FieldElementError(error)
|
||||
|
@ -156,7 +156,7 @@ pub enum Type<F: Field + PrimeField, G: Group> {
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField, G: Group> Type<F, G> {
|
||||
pub fn next_dimension(&self, dimensions: &Vec<usize>) -> Self {
|
||||
pub fn outer_dimension(&self, dimensions: &Vec<usize>) -> Self {
|
||||
let _type = self.clone();
|
||||
|
||||
if dimensions.len() > 1 {
|
||||
@ -168,6 +168,19 @@ impl<F: Field + PrimeField, G: Group> Type<F, G> {
|
||||
|
||||
_type
|
||||
}
|
||||
|
||||
pub fn inner_dimension(&self, dimensions: &Vec<usize>) -> Self {
|
||||
let _type = self.clone();
|
||||
|
||||
if dimensions.len() > 1 {
|
||||
let mut next = vec![];
|
||||
next.extend_from_slice(&dimensions[..dimensions.len() - 1]);
|
||||
|
||||
return Type::Array(Box::new(_type), next);
|
||||
}
|
||||
|
||||
_type
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
|
@ -61,6 +61,12 @@ impl<'ast> types::Integer {
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_implicit(number: String) -> Self {
|
||||
types::Integer::U128(UInt128::constant(
|
||||
number.parse::<u128>().expect("unable to parse u128"),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField, G: Group> From<ast::Integer<'ast>> for types::Expression<F, G> {
|
||||
@ -79,6 +85,9 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::RangeOrExpression<'ast>>
|
||||
.from
|
||||
.map(|from| match types::Expression::<F, G>::from(from.0) {
|
||||
types::Expression::Integer(number) => number,
|
||||
types::Expression::Implicit(string) => {
|
||||
types::Integer::from_implicit(string)
|
||||
}
|
||||
expression => {
|
||||
unimplemented!("Range bounds should be integers, found {}", expression)
|
||||
}
|
||||
@ -87,6 +96,9 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::RangeOrExpression<'ast>>
|
||||
.to
|
||||
.map(|to| match types::Expression::<F, G>::from(to.0) {
|
||||
types::Expression::Integer(number) => number,
|
||||
types::Expression::Implicit(string) => {
|
||||
types::Integer::from_implicit(string)
|
||||
}
|
||||
expression => {
|
||||
unimplemented!("Range bounds should be integers, found {}", expression)
|
||||
}
|
||||
@ -375,7 +387,12 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::Expression<'ast>>
|
||||
impl<'ast, F: Field + PrimeField, G: Group> types::Expression<F, G> {
|
||||
fn get_count(count: ast::Value<'ast>) -> usize {
|
||||
match count {
|
||||
ast::Value::Integer(f) => f
|
||||
ast::Value::Integer(integer) => integer
|
||||
.number
|
||||
.value
|
||||
.parse::<usize>()
|
||||
.expect("Unable to read array size"),
|
||||
ast::Value::Implicit(number) => number
|
||||
.number
|
||||
.value
|
||||
.parse::<usize>()
|
||||
@ -590,10 +607,12 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::ForStatement<'ast>>
|
||||
fn from(statement: ast::ForStatement<'ast>) -> Self {
|
||||
let from = match types::Expression::<F, G>::from(statement.start) {
|
||||
types::Expression::Integer(number) => number,
|
||||
types::Expression::Implicit(string) => types::Integer::from_implicit(string),
|
||||
expression => unimplemented!("Range bounds should be integers, found {}", expression),
|
||||
};
|
||||
let to = match types::Expression::<F, G>::from(statement.stop) {
|
||||
types::Expression::Integer(number) => number,
|
||||
types::Expression::Implicit(string) => types::Integer::from_implicit(string),
|
||||
expression => unimplemented!("Range bounds should be integers, found {}", expression),
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user