mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 15:41:36 +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)
|
||||
}
|
||||
|
||||
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 {
|
||||
let message = format!("Expected function input tuple, found `{}`", actual);
|
||||
|
||||
@ -141,4 +150,10 @@ impl FunctionError {
|
||||
|
||||
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::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.
|
||||
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,
|
||||
// TODO: remove unnecessary arguments
|
||||
_cs: &mut CS,
|
||||
_type_: &Type,
|
||||
type_: &Type,
|
||||
name: &str,
|
||||
input_option: Option<InputValue>,
|
||||
span: &Span,
|
||||
@ -101,18 +101,48 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
|
||||
ConstrainedValue::Integer(Integer::new(&const_int))
|
||||
}
|
||||
InputValue::Array(values) => ConstrainedValue::Array(
|
||||
values
|
||||
.iter()
|
||||
.map(|x| self.parse_constant_main_function_input(_cs, _type_, name, Some(x.clone()), span))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
),
|
||||
InputValue::Tuple(values) => ConstrainedValue::Tuple(
|
||||
values
|
||||
.iter()
|
||||
.map(|x| self.parse_constant_main_function_input(_cs, _type_, name, Some(x.clone()), span))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
),
|
||||
InputValue::Array(values) => {
|
||||
// Get ASG type and array length to compare with provided inputs.
|
||||
let (type_, arr_len) = if let Type::Array(type_, len) = type_ {
|
||||
(type_, *len)
|
||||
} else {
|
||||
return Err(FunctionError::input_not_found("expected".to_string(), &span));
|
||||
};
|
||||
|
||||
if arr_len != values.len() {
|
||||
return Err(FunctionError::invalid_input_array_dimensions(
|
||||
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 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.
|
||||
(Some(input_option), _) => self.parse_constant_main_function_input(
|
||||
(Some(input_option), _) => self.allocate_main_function_input(
|
||||
cs,
|
||||
&input_variable.type_.clone(),
|
||||
&name,
|
||||
@ -72,7 +79,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
&function.span.clone().unwrap_or_default(),
|
||||
)?,
|
||||
// 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,
|
||||
&input_variable.type_.clone(),
|
||||
&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);
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn test_field_input() {
|
||||
let program_string = include_str!("main_field.leo");
|
||||
|
Loading…
Reference in New Issue
Block a user