convert functions to span with error

This commit is contained in:
collin 2020-06-19 21:49:42 -07:00
parent f3e81184c1
commit 2743b23e1e
4 changed files with 74 additions and 33 deletions

View File

@ -8,7 +8,7 @@ use crate::{
group_from_input,
GroupType,
};
use leo_types::{Expression, Function, InputValue, Integer, Program, Type};
use leo_types::{Expression, Function, InputValue, Integer, Program, Span, Type};
use snarkos_models::{
curves::{Field, PrimeField},
@ -16,10 +16,10 @@ use snarkos_models::{
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
fn check_arguments_length(expected: usize, actual: usize) -> Result<(), FunctionError> {
fn check_arguments_length(expected: usize, actual: usize, span: Span) -> Result<(), FunctionError> {
// Make sure we are given the correct number of arguments
if expected != actual {
Err(FunctionError::ArgumentsLength(expected, actual))
Err(FunctionError::arguments_length(expected, actual, span))
} else {
Ok(())
}
@ -55,7 +55,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let function_name = new_scope(scope.clone(), function.get_name());
// Make sure we are given the correct number of inputs
Self::check_arguments_length(function.inputs.len(), inputs.len())?;
Self::check_arguments_length(function.inputs.len(), inputs.len(), function.span.clone())?;
// Store input values as new variables in resolved program
for (input_model, input_expression) in function.inputs.clone().iter().zip(inputs.into_iter()) {
@ -97,7 +97,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
if let ConstrainedValue::Return(ref returns) = return_values {
Self::check_arguments_length(function.returns.len(), returns.len())?;
Self::check_arguments_length(function.returns.len(), returns.len(), function.span.clone())?;
}
Ok(return_values)
@ -110,6 +110,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
array_type: Type,
array_dimensions: Vec<usize>,
input_value: Option<InputValue>,
span: Span,
) -> Result<ConstrainedValue<F, G>, FunctionError> {
let expected_length = array_dimensions[0];
let mut array_value = vec![];
@ -117,14 +118,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match input_value {
Some(InputValue::Array(arr)) => {
// Check the dimension of the array
Self::check_arguments_length(expected_length, arr.len())?;
Self::check_arguments_length(expected_length, arr.len(), span.clone())?;
// 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.outer_dimension(&array_dimensions);
array_value.push(self.allocate_main_function_input(cs, value_type, value_name, Some(value))?)
array_value.push(self.allocate_main_function_input(
cs,
value_type,
value_name,
Some(value),
span.clone(),
)?)
}
}
None => {
@ -133,10 +140,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let value_name = new_scope(name.clone(), i.to_string());
let value_type = array_type.outer_dimension(&array_dimensions);
array_value.push(self.allocate_main_function_input(cs, value_type, value_name, None)?);
array_value.push(self.allocate_main_function_input(
cs,
value_type,
value_name,
None,
span.clone(),
)?);
}
}
_ => return Err(FunctionError::InvalidArray(input_value.unwrap().to_string())),
_ => return Err(FunctionError::invalid_array(input_value.unwrap().to_string(), span)),
}
Ok(ConstrainedValue::Array(array_value))
@ -148,6 +161,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
_type: Type,
name: String,
input_value: Option<InputValue>,
span: Span,
) -> Result<ConstrainedValue<F, G>, FunctionError> {
match _type {
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::from_input(
@ -159,7 +173,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Type::Field => Ok(field_from_input(cs, name, input_value)?),
Type::Group => Ok(group_from_input(cs, name, input_value)?),
Type::Boolean => Ok(self.bool_from_input(cs, name, input_value)?),
Type::Array(_type, dimensions) => self.allocate_array(cs, name, *_type, dimensions, input_value),
Type::Array(_type, dimensions) => self.allocate_array(cs, name, *_type, dimensions, input_value, span),
_ => unimplemented!("main function input not implemented for type"),
}
}
@ -174,14 +188,19 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let function_name = new_scope(scope.clone(), function.get_name());
// Make sure we are given the correct number of inputs
Self::check_arguments_length(function.inputs.len(), inputs.len())?;
Self::check_arguments_length(function.inputs.len(), inputs.len(), function.span.clone())?;
// Iterate over main function inputs and allocate new passed-by variable values
let mut input_variables = vec![];
for (input_model, input_option) in function.inputs.clone().into_iter().zip(inputs.into_iter()) {
let input_name = new_scope(function_name.clone(), input_model.identifier.name.clone());
let input_value =
self.allocate_main_function_input(cs, input_model._type, input_name.clone(), input_option)?;
let input_value = self.allocate_main_function_input(
cs,
input_model._type,
input_name.clone(),
input_option,
function.span.clone(),
)?;
// Store a new variable for every allocated main function input
self.store(input_name.clone(), input_value);

View File

@ -7,10 +7,10 @@ use std::num::ParseIntError;
#[derive(Debug, Error)]
pub enum ExpressionError {
#[error("{}", _0)]
Error(#[from] FormattedError),
BooleanError(#[from] BooleanError),
#[error("{}", _0)]
BooleanError(#[from] BooleanError),
Error(#[from] FormattedError),
#[error("{}", _0)]
IntegerError(#[from] IntegerError),
@ -18,23 +18,20 @@ pub enum ExpressionError {
#[error("{}", _0)]
FieldError(#[from] FieldError),
#[error("{}", _0)]
FunctionError(#[from] Box<FunctionError>),
#[error("{}", _0)]
GroupError(#[from] GroupError),
#[error("{}", _0)]
ParseIntError(#[from] ParseIntError),
#[error("{}", _0)]
ValueError(#[from] ValueError),
#[error("{}", _0)]
FunctionError(#[from] Box<FunctionError>),
// Conditionals
#[error("If, else statements.conditional must resolve to a boolean, got {}", _0)]
IfElseConditional(String),
#[error("{}", _0)]
SynthesisError(#[from] SynthesisError),
#[error("{}", _0)]
ValueError(#[from] ValueError),
}
impl ExpressionError {

View File

@ -1,17 +1,25 @@
use crate::errors::{BooleanError, ExpressionError, FieldError, GroupError, StatementError, ValueError};
use leo_types::IntegerError;
use crate::errors::{
BooleanError,
Error as FormattedError,
ExpressionError,
FieldError,
GroupError,
StatementError,
ValueError,
};
use leo_types::{IntegerError, Span};
#[derive(Debug, Error)]
pub enum FunctionError {
#[error("Function expected {} inputs, got {}", _0, _1)]
ArgumentsLength(usize, usize),
#[error("{}", _0)]
BooleanError(#[from] BooleanError),
#[error("{}", _0)]
ExpressionError(#[from] ExpressionError),
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
FieldError(#[from] FieldError),
@ -21,12 +29,27 @@ pub enum FunctionError {
#[error("{}", _0)]
IntegerError(#[from] IntegerError),
#[error("Expected function input array, got {}", _0)]
InvalidArray(String),
#[error("{}", _0)]
StatementError(#[from] StatementError),
#[error("{}", _0)]
ValueError(#[from] ValueError),
}
impl FunctionError {
fn new_from_span(message: String, span: Span) -> Self {
FunctionError::Error(FormattedError::new_from_span(message, span))
}
pub fn arguments_length(expected: usize, actual: usize, span: Span) -> Self {
let message = format!("function expected {} inputs, found {} inputs", 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);
Self::new_from_span(message, span)
}
}

View File

@ -1,4 +1,4 @@
use crate::{FunctionInput, Identifier, Statement, Type};
use crate::{FunctionInput, Identifier, Span, Statement, Type};
use leo_ast::functions::Function as AstFunction;
use std::fmt;
@ -9,6 +9,7 @@ pub struct Function {
pub inputs: Vec<FunctionInput>,
pub returns: Vec<Type>,
pub statements: Vec<Statement>,
pub span: Span,
}
impl<'ast> From<AstFunction<'ast>> for Function {
@ -35,6 +36,7 @@ impl<'ast> From<AstFunction<'ast>> for Function {
inputs: parameters,
returns,
statements,
span: Span::from(function_definition.span),
}
}
}