mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 07:32:26 +03:00
covered type mismatch in constant inputs
This commit is contained in:
parent
a516f36e4f
commit
40f4b1cb65
@ -23,7 +23,7 @@ use leo_input::{
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Input {
|
||||
name: String,
|
||||
pub program_input: ProgramInput,
|
||||
program_input: ProgramInput,
|
||||
program_state: ProgramState,
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,12 @@ impl FunctionError {
|
||||
FunctionError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn input_type_mismatch(expected: String, actual: String, variable: String, span: &Span) -> Self {
|
||||
let message = format!("Expected {} to be {} not {}", variable, expected, actual);
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn invalid_array(actual: String, span: &Span) -> Self {
|
||||
let message = format!("Expected function input array, found `{}`", actual);
|
||||
|
||||
|
@ -76,73 +76,110 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
input_option: Option<InputValue>,
|
||||
span: &Span,
|
||||
) -> Result<ConstrainedValue<'a, F, G>, FunctionError> {
|
||||
let value = input_option.unwrap();
|
||||
let input = input_option.ok_or_else(|| FunctionError::input_not_found(name.to_string(), span))?;
|
||||
|
||||
Ok(match value {
|
||||
InputValue::Address(value) => ConstrainedValue::Address(Address::constant(value, span)?),
|
||||
InputValue::Boolean(value) => ConstrainedValue::Boolean(Boolean::constant(value)),
|
||||
InputValue::Field(value) => ConstrainedValue::Field(FieldType::constant(value, span)?),
|
||||
InputValue::Group(value) => ConstrainedValue::Group(G::constant(&value.into(), span)?),
|
||||
InputValue::Integer(integer_type, value) => {
|
||||
let integer = IntegerType::from(integer_type);
|
||||
let const_int = match integer {
|
||||
IntegerType::U8 => ConstInt::U8(value.parse::<u8>().unwrap()),
|
||||
IntegerType::U16 => ConstInt::U16(value.parse::<u16>().unwrap()),
|
||||
IntegerType::U32 => ConstInt::U32(value.parse::<u32>().unwrap()),
|
||||
IntegerType::U64 => ConstInt::U64(value.parse::<u64>().unwrap()),
|
||||
IntegerType::U128 => ConstInt::U128(value.parse::<u128>().unwrap()),
|
||||
match type_ {
|
||||
Type::Address => match input {
|
||||
InputValue::Address(addr) => Ok(ConstrainedValue::Address(Address::constant(addr, span)?)),
|
||||
_ => Err(FunctionError::input_type_mismatch(
|
||||
type_.to_string(),
|
||||
input.to_string(),
|
||||
name.to_string(),
|
||||
span,
|
||||
)),
|
||||
},
|
||||
Type::Boolean => match input {
|
||||
InputValue::Boolean(value) => Ok(ConstrainedValue::Boolean(Boolean::constant(value))),
|
||||
_ => Err(FunctionError::input_not_found(name.to_string(), span)),
|
||||
},
|
||||
Type::Field => match input {
|
||||
InputValue::Field(value) => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
|
||||
_ => Err(FunctionError::input_type_mismatch(
|
||||
type_.to_string(),
|
||||
input.to_string(),
|
||||
name.to_string(),
|
||||
span,
|
||||
)),
|
||||
},
|
||||
Type::Group => match input {
|
||||
InputValue::Group(value) => Ok(ConstrainedValue::Group(G::constant(&value.into(), span)?)),
|
||||
_ => Err(FunctionError::input_type_mismatch(
|
||||
type_.to_string(),
|
||||
input.to_string(),
|
||||
name.to_string(),
|
||||
span,
|
||||
)),
|
||||
},
|
||||
Type::Integer(integer_type) => match input {
|
||||
InputValue::Integer(_, value) => {
|
||||
let const_int = match integer_type {
|
||||
IntegerType::U8 => ConstInt::U8(value.parse::<u8>().unwrap()),
|
||||
IntegerType::U16 => ConstInt::U16(value.parse::<u16>().unwrap()),
|
||||
IntegerType::U32 => ConstInt::U32(value.parse::<u32>().unwrap()),
|
||||
IntegerType::U64 => ConstInt::U64(value.parse::<u64>().unwrap()),
|
||||
IntegerType::U128 => ConstInt::U128(value.parse::<u128>().unwrap()),
|
||||
|
||||
IntegerType::I8 => ConstInt::I8(value.parse::<i8>().unwrap()),
|
||||
IntegerType::I16 => ConstInt::I16(value.parse::<i16>().unwrap()),
|
||||
IntegerType::I32 => ConstInt::I32(value.parse::<i32>().unwrap()),
|
||||
IntegerType::I64 => ConstInt::I64(value.parse::<i64>().unwrap()),
|
||||
IntegerType::I128 => ConstInt::I128(value.parse::<i128>().unwrap()),
|
||||
};
|
||||
IntegerType::I8 => ConstInt::I8(value.parse::<i8>().unwrap()),
|
||||
IntegerType::I16 => ConstInt::I16(value.parse::<i16>().unwrap()),
|
||||
IntegerType::I32 => ConstInt::I32(value.parse::<i32>().unwrap()),
|
||||
IntegerType::I64 => ConstInt::I64(value.parse::<i64>().unwrap()),
|
||||
IntegerType::I128 => ConstInt::I128(value.parse::<i128>().unwrap()),
|
||||
};
|
||||
|
||||
ConstrainedValue::Integer(Integer::new(&const_int))
|
||||
}
|
||||
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,
|
||||
));
|
||||
Ok(ConstrainedValue::Integer(Integer::new(&const_int)))
|
||||
}
|
||||
_ => Err(FunctionError::input_type_mismatch(
|
||||
type_.to_string(),
|
||||
input.to_string(),
|
||||
name.to_string(),
|
||||
span,
|
||||
)),
|
||||
},
|
||||
Type::Array(type_, arr_len) => match input {
|
||||
InputValue::Array(values) => {
|
||||
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));
|
||||
Ok(ConstrainedValue::Array(
|
||||
values
|
||||
.iter()
|
||||
.map(|x| self.constant_main_function_input(_cs, type_, name, Some(x.clone()), span))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
))
|
||||
}
|
||||
_ => Err(FunctionError::input_type_mismatch(
|
||||
type_.to_string(),
|
||||
input.to_string(),
|
||||
name.to_string(),
|
||||
span,
|
||||
)),
|
||||
},
|
||||
Type::Tuple(types) => match input {
|
||||
InputValue::Tuple(values) => {
|
||||
if values.len() != types.len() {
|
||||
return Err(FunctionError::tuple_size_mismatch(types.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<_>, _>>()?,
|
||||
)
|
||||
}
|
||||
})
|
||||
Ok(ConstrainedValue::Tuple(
|
||||
values
|
||||
.iter()
|
||||
.map(|x| self.constant_main_function_input(_cs, type_, name, Some(x.clone()), span))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
))
|
||||
}
|
||||
_ => Err(FunctionError::input_type_mismatch(
|
||||
type_.to_string(),
|
||||
input.to_string(),
|
||||
name.to_string(),
|
||||
span,
|
||||
)),
|
||||
},
|
||||
_ => unimplemented!("main function input not implemented for type {}", type_),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,11 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
|
||||
match input_value {
|
||||
Some(InputValue::Tuple(values)) => {
|
||||
// Allocate each value in the tuple
|
||||
if values.len() != types.len() {
|
||||
return Err(FunctionError::tuple_size_mismatch(types.len(), values.len(), span));
|
||||
}
|
||||
|
||||
// Allocate each value in the tuple.
|
||||
for (i, (value, type_)) in values.into_iter().zip(types.iter()).enumerate() {
|
||||
let value_name = format!("{}_{}", &name, &i.to_string());
|
||||
|
||||
|
@ -0,0 +1,2 @@
|
||||
[main]
|
||||
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,16 @@ fn test_input_array_dimensions_mismatch() {
|
||||
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");
|
||||
|
@ -0,0 +1,2 @@
|
||||
[constants]
|
||||
a: u8 = 10;
|
@ -1,3 +1,3 @@
|
||||
function main(x: (u8, bool, u8)) {
|
||||
function main(const x: (u8, bool, u8)) {
|
||||
console.log("x: {}", x);
|
||||
}
|
Loading…
Reference in New Issue
Block a user