From 2743b23e1e08e57ba4d72d246f12512b8b66f45f Mon Sep 17 00:00:00 2001 From: collin Date: Fri, 19 Jun 2020 21:49:42 -0700 Subject: [PATCH] convert functions to span with error --- compiler/src/constraints/function.rs | 45 +++++++++++++------ compiler/src/errors/constraints/expression.rs | 19 ++++---- compiler/src/errors/constraints/function.rs | 39 ++++++++++++---- types/src/functions/function.rs | 4 +- 4 files changed, 74 insertions(+), 33 deletions(-) diff --git a/compiler/src/constraints/function.rs b/compiler/src/constraints/function.rs index aa62c8e102..bfc8c435ac 100644 --- a/compiler/src/constraints/function.rs +++ b/compiler/src/constraints/function.rs @@ -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> ConstrainedProgram { - 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> ConstrainedProgram { 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> ConstrainedProgram { } 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> ConstrainedProgram { array_type: Type, array_dimensions: Vec, input_value: Option, + span: Span, ) -> Result, FunctionError> { let expected_length = array_dimensions[0]; let mut array_value = vec![]; @@ -117,14 +118,20 @@ impl> ConstrainedProgram { 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> ConstrainedProgram { 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> ConstrainedProgram { _type: Type, name: String, input_value: Option, + span: Span, ) -> Result, FunctionError> { match _type { Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::from_input( @@ -159,7 +173,7 @@ impl> ConstrainedProgram { 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> ConstrainedProgram { 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); diff --git a/compiler/src/errors/constraints/expression.rs b/compiler/src/errors/constraints/expression.rs index c1de122b8a..3b1a487755 100644 --- a/compiler/src/errors/constraints/expression.rs +++ b/compiler/src/errors/constraints/expression.rs @@ -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), + #[error("{}", _0)] GroupError(#[from] GroupError), #[error("{}", _0)] ParseIntError(#[from] ParseIntError), - #[error("{}", _0)] - ValueError(#[from] ValueError), - - #[error("{}", _0)] - FunctionError(#[from] Box), - // 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 { diff --git a/compiler/src/errors/constraints/function.rs b/compiler/src/errors/constraints/function.rs index a0062e000f..adf05e0c74 100644 --- a/compiler/src/errors/constraints/function.rs +++ b/compiler/src/errors/constraints/function.rs @@ -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) + } +} diff --git a/types/src/functions/function.rs b/types/src/functions/function.rs index a5e2e61db2..1f09329e14 100644 --- a/types/src/functions/function.rs +++ b/types/src/functions/function.rs @@ -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, pub returns: Vec, pub statements: Vec, + pub span: Span, } impl<'ast> From> for Function { @@ -35,6 +36,7 @@ impl<'ast> From> for Function { inputs: parameters, returns, statements, + span: Span::from(function_definition.span), } } }