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

View File

@ -7,10 +7,10 @@ use std::num::ParseIntError;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum ExpressionError { pub enum ExpressionError {
#[error("{}", _0)] #[error("{}", _0)]
Error(#[from] FormattedError), BooleanError(#[from] BooleanError),
#[error("{}", _0)] #[error("{}", _0)]
BooleanError(#[from] BooleanError), Error(#[from] FormattedError),
#[error("{}", _0)] #[error("{}", _0)]
IntegerError(#[from] IntegerError), IntegerError(#[from] IntegerError),
@ -18,23 +18,20 @@ pub enum ExpressionError {
#[error("{}", _0)] #[error("{}", _0)]
FieldError(#[from] FieldError), FieldError(#[from] FieldError),
#[error("{}", _0)]
FunctionError(#[from] Box<FunctionError>),
#[error("{}", _0)] #[error("{}", _0)]
GroupError(#[from] GroupError), GroupError(#[from] GroupError),
#[error("{}", _0)] #[error("{}", _0)]
ParseIntError(#[from] ParseIntError), 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)] #[error("{}", _0)]
SynthesisError(#[from] SynthesisError), SynthesisError(#[from] SynthesisError),
#[error("{}", _0)]
ValueError(#[from] ValueError),
} }
impl ExpressionError { impl ExpressionError {

View File

@ -1,17 +1,25 @@
use crate::errors::{BooleanError, ExpressionError, FieldError, GroupError, StatementError, ValueError}; use crate::errors::{
use leo_types::IntegerError; BooleanError,
Error as FormattedError,
ExpressionError,
FieldError,
GroupError,
StatementError,
ValueError,
};
use leo_types::{IntegerError, Span};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum FunctionError { pub enum FunctionError {
#[error("Function expected {} inputs, got {}", _0, _1)]
ArgumentsLength(usize, usize),
#[error("{}", _0)] #[error("{}", _0)]
BooleanError(#[from] BooleanError), BooleanError(#[from] BooleanError),
#[error("{}", _0)] #[error("{}", _0)]
ExpressionError(#[from] ExpressionError), ExpressionError(#[from] ExpressionError),
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)] #[error("{}", _0)]
FieldError(#[from] FieldError), FieldError(#[from] FieldError),
@ -21,12 +29,27 @@ pub enum FunctionError {
#[error("{}", _0)] #[error("{}", _0)]
IntegerError(#[from] IntegerError), IntegerError(#[from] IntegerError),
#[error("Expected function input array, got {}", _0)]
InvalidArray(String),
#[error("{}", _0)] #[error("{}", _0)]
StatementError(#[from] StatementError), StatementError(#[from] StatementError),
#[error("{}", _0)] #[error("{}", _0)]
ValueError(#[from] ValueError), 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 leo_ast::functions::Function as AstFunction;
use std::fmt; use std::fmt;
@ -9,6 +9,7 @@ pub struct Function {
pub inputs: Vec<FunctionInput>, pub inputs: Vec<FunctionInput>,
pub returns: Vec<Type>, pub returns: Vec<Type>,
pub statements: Vec<Statement>, pub statements: Vec<Statement>,
pub span: Span,
} }
impl<'ast> From<AstFunction<'ast>> for Function { impl<'ast> From<AstFunction<'ast>> for Function {
@ -35,6 +36,7 @@ impl<'ast> From<AstFunction<'ast>> for Function {
inputs: parameters, inputs: parameters,
returns, returns,
statements, statements,
span: Span::from(function_definition.span),
} }
} }
} }