mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-23 17:43:06 +03:00
array dimensions check added, const tuples added
This commit is contained in:
parent
258255102a
commit
2508ec7ef1
@ -118,6 +118,15 @@ impl FunctionError {
|
|||||||
Self::new_from_span(message, span)
|
Self::new_from_span(message, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tuple_size_mismatch(expected: usize, actual: usize, span: &Span) -> Self {
|
||||||
|
let message = format!(
|
||||||
|
"Input tuple size mismatch expected {}, found tuple with length {}",
|
||||||
|
expected, actual
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invalid_tuple(actual: String, span: &Span) -> Self {
|
pub fn invalid_tuple(actual: String, span: &Span) -> Self {
|
||||||
let message = format!("Expected function input tuple, found `{}`", actual);
|
let message = format!("Expected function input tuple, found `{}`", actual);
|
||||||
|
|
||||||
@ -141,4 +150,10 @@ impl FunctionError {
|
|||||||
|
|
||||||
Self::new_from_span(message, span)
|
Self::new_from_span(message, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn double_input_declaration(input_name: String, span: &Span) -> Self {
|
||||||
|
let message = format!("Input variable {} declared twice", input_name);
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,18 +60,18 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
)?)),
|
)?)),
|
||||||
Type::Array(type_, len) => self.allocate_array(cs, name, &*type_, *len, input_option, span),
|
Type::Array(type_, len) => self.allocate_array(cs, name, &*type_, *len, input_option, span),
|
||||||
Type::Tuple(types) => self.allocate_tuple(cs, &name, types, input_option, span),
|
Type::Tuple(types) => self.allocate_tuple(cs, &name, types, input_option, span),
|
||||||
_ => unimplemented!("main function input not implemented for type"),
|
_ => unimplemented!("main function input not implemented for type {}", type_),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process constant inputs and return ConstrainedValue with constant value in it.
|
/// Process constant inputs and return ConstrainedValue with constant value in it.
|
||||||
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||||
pub fn parse_constant_main_function_input<CS: ConstraintSystem<F>>(
|
pub fn constant_main_function_input<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
// TODO: remove unnecessary arguments
|
// TODO: remove unnecessary arguments
|
||||||
_cs: &mut CS,
|
_cs: &mut CS,
|
||||||
_type_: &Type,
|
type_: &Type,
|
||||||
name: &str,
|
name: &str,
|
||||||
input_option: Option<InputValue>,
|
input_option: Option<InputValue>,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
@ -101,18 +101,48 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
|
|
||||||
ConstrainedValue::Integer(Integer::new(&const_int))
|
ConstrainedValue::Integer(Integer::new(&const_int))
|
||||||
}
|
}
|
||||||
InputValue::Array(values) => ConstrainedValue::Array(
|
InputValue::Array(values) => {
|
||||||
values
|
// Get ASG type and array length to compare with provided inputs.
|
||||||
.iter()
|
let (type_, arr_len) = if let Type::Array(type_, len) = type_ {
|
||||||
.map(|x| self.parse_constant_main_function_input(_cs, _type_, name, Some(x.clone()), span))
|
(type_, *len)
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
} else {
|
||||||
),
|
return Err(FunctionError::input_not_found("expected".to_string(), &span));
|
||||||
InputValue::Tuple(values) => ConstrainedValue::Tuple(
|
};
|
||||||
values
|
|
||||||
.iter()
|
if arr_len != values.len() {
|
||||||
.map(|x| self.parse_constant_main_function_input(_cs, _type_, name, Some(x.clone()), span))
|
return Err(FunctionError::invalid_input_array_dimensions(
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
arr_len,
|
||||||
),
|
values.len(),
|
||||||
|
span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstrainedValue::Array(
|
||||||
|
values
|
||||||
|
.iter()
|
||||||
|
.map(|x| self.constant_main_function_input(_cs, type_, name, Some(x.clone()), span))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
InputValue::Tuple(values) => {
|
||||||
|
// Get ASG tuple size and compare it to input tuple size.
|
||||||
|
let tuple_len = if let Type::Tuple(types) = type_ {
|
||||||
|
types.len()
|
||||||
|
} else {
|
||||||
|
return Err(FunctionError::tuple_size_mismatch(0, values.len(), span));
|
||||||
|
};
|
||||||
|
|
||||||
|
if values.len() != tuple_len {
|
||||||
|
return Err(FunctionError::tuple_size_mismatch(tuple_len, values.len(), span));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstrainedValue::Tuple(
|
||||||
|
values
|
||||||
|
.iter()
|
||||||
|
.map(|x| self.constant_main_function_input(_cs, type_, name, Some(x.clone()), span))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,15 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
let name = input_variable.name.name.clone();
|
let name = input_variable.name.name.clone();
|
||||||
|
|
||||||
let input_value = match (input.get(&name), input.get_constant(&name)) {
|
let input_value = match (input.get(&name), input.get_constant(&name)) {
|
||||||
|
// If variable is in both [main] and [constants] sections - error.
|
||||||
|
(Some(_), Some(_)) => {
|
||||||
|
return Err(FunctionError::double_input_declaration(
|
||||||
|
name.clone(),
|
||||||
|
&function.span.clone().unwrap_or_default(),
|
||||||
|
));
|
||||||
|
}
|
||||||
// If input option is found in [main] section.
|
// If input option is found in [main] section.
|
||||||
(Some(input_option), _) => self.parse_constant_main_function_input(
|
(Some(input_option), _) => self.allocate_main_function_input(
|
||||||
cs,
|
cs,
|
||||||
&input_variable.type_.clone(),
|
&input_variable.type_.clone(),
|
||||||
&name,
|
&name,
|
||||||
@ -72,7 +79,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
&function.span.clone().unwrap_or_default(),
|
&function.span.clone().unwrap_or_default(),
|
||||||
)?,
|
)?,
|
||||||
// If input option is found in [constants] section.
|
// If input option is found in [constants] section.
|
||||||
(_, Some(input_option)) => self.allocate_main_function_input(
|
(_, Some(input_option)) => self.constant_main_function_input(
|
||||||
cs,
|
cs,
|
||||||
&input_variable.type_.clone(),
|
&input_variable.type_.clone(),
|
||||||
&name,
|
&name,
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
[main]
|
||||||
|
a: bool = true;
|
||||||
|
|
||||||
|
[constants]
|
||||||
|
a: bool = false;
|
@ -0,0 +1,2 @@
|
|||||||
|
[constants]
|
||||||
|
x: (u8, bool) = (10, true); // wrong size here; main expects (u8, bool, u8)
|
@ -0,0 +1,3 @@
|
|||||||
|
function main(x: (u8, bool, u8)) {
|
||||||
|
console.log("x: {}", x);
|
||||||
|
}
|
@ -94,6 +94,26 @@ fn test_input_array_dimensions_mismatch() {
|
|||||||
expect_fail(program);
|
expect_fail(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_input_double_declaration() {
|
||||||
|
let program_string = include_str!("main.leo");
|
||||||
|
let input_string = include_str!("input/main_double_declaration_fail.in");
|
||||||
|
|
||||||
|
let program = parse_program_with_input(program_string, input_string).unwrap();
|
||||||
|
|
||||||
|
expect_fail(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tuple_size_mismatch() {
|
||||||
|
let program_string = include_str!("main_tuple_fail.leo");
|
||||||
|
let input_string = include_str!("input/main_tuple_fail.in");
|
||||||
|
|
||||||
|
let program = parse_program_with_input(program_string, input_string).unwrap();
|
||||||
|
|
||||||
|
expect_fail(program);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_field_input() {
|
fn test_field_input() {
|
||||||
let program_string = include_str!("main_field.leo");
|
let program_string = include_str!("main_field.leo");
|
||||||
|
Loading…
Reference in New Issue
Block a user