mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-29 22:36:05 +03:00
implicit arrays and multiple definitions
This commit is contained in:
parent
d0c88a08be
commit
aa63cf1dbb
@ -1,3 +1,10 @@
|
|||||||
function main() {
|
function test(mut a: u32) {
|
||||||
let a: u32 = if true ? 1 : 5;
|
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)) => {
|
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||||
Ok(self.enforce_field_mul(cs, fe_1, 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) => {
|
(ConstrainedValue::Mutable(val_1), val_2) => {
|
||||||
self.enforce_mul_expression(cs, *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,
|
cs: &mut CS,
|
||||||
file_scope: String,
|
file_scope: String,
|
||||||
function_scope: String,
|
function_scope: String,
|
||||||
expected_types: Vec<Type<F, G>>,
|
mut 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> {
|
||||||
|
// 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![];
|
let mut result = vec![];
|
||||||
for element in array.into_iter() {
|
for element in array.into_iter() {
|
||||||
match *element {
|
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))
|
Ok(ConstrainedValue::Array(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,6 +509,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
|||||||
) -> Result<usize, ExpressionError> {
|
) -> Result<usize, ExpressionError> {
|
||||||
match self.enforce_expression(cs, file_scope, function_scope, expected_types, 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()),
|
||||||
|
ConstrainedValue::Unresolved(string) => Ok(string.parse::<usize>()?),
|
||||||
value => Err(ExpressionError::InvalidIndex(value.to_string())),
|
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
|
// Allocate each value in the current row
|
||||||
for (i, value) in arr.into_iter().enumerate() {
|
for (i, value) in arr.into_iter().enumerate() {
|
||||||
let value_name = new_scope(name.clone(), i.to_string());
|
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(
|
array_value.push(self.allocate_main_function_input(
|
||||||
cs,
|
cs,
|
||||||
@ -142,7 +142,7 @@ impl<F: Field + PrimeField, G: Group, CS: ConstraintSystem<F>> ConstrainedProgra
|
|||||||
// Allocate all row values as none
|
// Allocate all row values as none
|
||||||
for i in 0..expected_length {
|
for i in 0..expected_length {
|
||||||
let value_name = new_scope(name.clone(), i.to_string());
|
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(
|
array_value.push(
|
||||||
self.allocate_main_function_input(
|
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> {
|
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))
|
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> {
|
pub(crate) fn from_type(value: String, _type: &Type<F, G>) -> Result<Self, ValueError> {
|
||||||
Ok(match _type {
|
match _type {
|
||||||
Type::IntegerType(integer_type) => ConstrainedValue::Integer(match integer_type {
|
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(match integer_type {
|
||||||
IntegerType::U8 => Integer::U8(UInt8::constant(value.parse::<u8>()?)),
|
IntegerType::U8 => Integer::U8(UInt8::constant(value.parse::<u8>()?)),
|
||||||
IntegerType::U16 => Integer::U16(UInt16::constant(value.parse::<u16>()?)),
|
IntegerType::U16 => Integer::U16(UInt16::constant(value.parse::<u16>()?)),
|
||||||
IntegerType::U32 => Integer::U32(UInt32::constant(value.parse::<u32>()?)),
|
IntegerType::U32 => Integer::U32(UInt32::constant(value.parse::<u32>()?)),
|
||||||
IntegerType::U64 => Integer::U64(UInt64::constant(value.parse::<u64>()?)),
|
IntegerType::U64 => Integer::U64(UInt64::constant(value.parse::<u64>()?)),
|
||||||
IntegerType::U128 => Integer::U128(UInt128::constant(value.parse::<u128>()?)),
|
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(),
|
F::from_str(&value).unwrap_or_default(),
|
||||||
)),
|
))),
|
||||||
Type::GroupElement => ConstrainedValue::GroupElement({
|
Type::GroupElement => Ok(ConstrainedValue::GroupElement({
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
let scalar = G::ScalarField::from_str(&value).unwrap_or_default();
|
let scalar = G::ScalarField::from_str(&value).unwrap_or_default();
|
||||||
let point = G::default().mul(&scalar);
|
let point = G::default().mul(&scalar);
|
||||||
point
|
point
|
||||||
}),
|
})),
|
||||||
Type::Boolean => ConstrainedValue::Boolean(Boolean::Constant(value.parse::<bool>()?)),
|
Type::Boolean => Ok(ConstrainedValue::Boolean(Boolean::Constant(
|
||||||
_ => ConstrainedValue::Unresolved(value),
|
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> {
|
pub(crate) fn to_type(&self) -> Type<F, G> {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::errors::{BooleanError, FieldElementError, FunctionError, IntegerError, ValueError};
|
use crate::errors::{BooleanError, FieldElementError, FunctionError, IntegerError, ValueError};
|
||||||
|
|
||||||
use snarkos_errors::gadgets::SynthesisError;
|
use snarkos_errors::gadgets::SynthesisError;
|
||||||
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ExpressionError {
|
pub enum ExpressionError {
|
||||||
@ -21,6 +22,9 @@ pub enum ExpressionError {
|
|||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
IntegerError(IntegerError),
|
IntegerError(IntegerError),
|
||||||
|
|
||||||
|
#[error("{}", _0)]
|
||||||
|
ParseIntError(ParseIntError),
|
||||||
|
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
FieldElementError(FieldElementError),
|
FieldElementError(FieldElementError),
|
||||||
|
|
||||||
@ -46,6 +50,9 @@ pub enum ExpressionError {
|
|||||||
#[error("Index must resolve to an integer, got {}", _0)]
|
#[error("Index must resolve to an integer, got {}", _0)]
|
||||||
InvalidIndex(String),
|
InvalidIndex(String),
|
||||||
|
|
||||||
|
#[error("Expected array length {}, got {}", _0, _1)]
|
||||||
|
InvalidLength(usize, usize),
|
||||||
|
|
||||||
// Circuits
|
// Circuits
|
||||||
#[error(
|
#[error(
|
||||||
"Circuit {} must be declared before it is used in an inline expression",
|
"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 {
|
impl From<FieldElementError> for ExpressionError {
|
||||||
fn from(error: FieldElementError) -> Self {
|
fn from(error: FieldElementError) -> Self {
|
||||||
ExpressionError::FieldElementError(error)
|
ExpressionError::FieldElementError(error)
|
||||||
|
@ -156,7 +156,7 @@ pub enum Type<F: Field + PrimeField, G: Group> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field + PrimeField, G: Group> Type<F, G> {
|
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();
|
let _type = self.clone();
|
||||||
|
|
||||||
if dimensions.len() > 1 {
|
if dimensions.len() > 1 {
|
||||||
@ -168,6 +168,19 @@ impl<F: Field + PrimeField, G: Group> Type<F, G> {
|
|||||||
|
|
||||||
_type
|
_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)]
|
#[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> {
|
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
|
.from
|
||||||
.map(|from| match types::Expression::<F, G>::from(from.0) {
|
.map(|from| match types::Expression::<F, G>::from(from.0) {
|
||||||
types::Expression::Integer(number) => number,
|
types::Expression::Integer(number) => number,
|
||||||
|
types::Expression::Implicit(string) => {
|
||||||
|
types::Integer::from_implicit(string)
|
||||||
|
}
|
||||||
expression => {
|
expression => {
|
||||||
unimplemented!("Range bounds should be integers, found {}", 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
|
.to
|
||||||
.map(|to| match types::Expression::<F, G>::from(to.0) {
|
.map(|to| match types::Expression::<F, G>::from(to.0) {
|
||||||
types::Expression::Integer(number) => number,
|
types::Expression::Integer(number) => number,
|
||||||
|
types::Expression::Implicit(string) => {
|
||||||
|
types::Integer::from_implicit(string)
|
||||||
|
}
|
||||||
expression => {
|
expression => {
|
||||||
unimplemented!("Range bounds should be integers, found {}", 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> {
|
impl<'ast, F: Field + PrimeField, G: Group> types::Expression<F, G> {
|
||||||
fn get_count(count: ast::Value<'ast>) -> usize {
|
fn get_count(count: ast::Value<'ast>) -> usize {
|
||||||
match count {
|
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
|
.number
|
||||||
.value
|
.value
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
@ -590,10 +607,12 @@ impl<'ast, F: Field + PrimeField, G: Group> From<ast::ForStatement<'ast>>
|
|||||||
fn from(statement: ast::ForStatement<'ast>) -> Self {
|
fn from(statement: ast::ForStatement<'ast>) -> Self {
|
||||||
let from = match types::Expression::<F, G>::from(statement.start) {
|
let from = match types::Expression::<F, G>::from(statement.start) {
|
||||||
types::Expression::Integer(number) => number,
|
types::Expression::Integer(number) => number,
|
||||||
|
types::Expression::Implicit(string) => types::Integer::from_implicit(string),
|
||||||
expression => unimplemented!("Range bounds should be integers, found {}", expression),
|
expression => unimplemented!("Range bounds should be integers, found {}", expression),
|
||||||
};
|
};
|
||||||
let to = match types::Expression::<F, G>::from(statement.stop) {
|
let to = match types::Expression::<F, G>::from(statement.stop) {
|
||||||
types::Expression::Integer(number) => number,
|
types::Expression::Integer(number) => number,
|
||||||
|
types::Expression::Implicit(string) => types::Integer::from_implicit(string),
|
||||||
expression => unimplemented!("Range bounds should be integers, found {}", expression),
|
expression => unimplemented!("Range bounds should be integers, found {}", expression),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user