added inputerror

This commit is contained in:
damirka 2022-02-21 23:01:32 +03:00
parent e439a2fdff
commit 5586c42266
10 changed files with 185 additions and 42 deletions

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{CharValue, Expression, GroupValue, IntegerType, Node, SpreadOrExpression, Type, ValueExpression}; use crate::{CharValue, Expression, GroupValue, IntegerType, Node, SpreadOrExpression, Type, ValueExpression};
use leo_errors::{AstError, LeoError, ParserError, Result}; use leo_errors::{InputError, LeoError, ParserError, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -51,16 +51,16 @@ impl TryFrom<(Type, Expression)> for InputValue {
(Type::IntegerType(type_), ValueExpression::Implicit(value, _)) => { (Type::IntegerType(type_), ValueExpression::Implicit(value, _)) => {
Self::Integer(type_, value.to_string()) Self::Integer(type_, value.to_string())
} }
(Type::IntegerType(expected), ValueExpression::Integer(actual, value, _)) => { (Type::IntegerType(expected), ValueExpression::Integer(actual, value, span)) => {
if expected == actual { if expected == actual {
Self::Integer(expected, value.to_string()) Self::Integer(expected, value.to_string())
} else { } else {
todo!("make a decent error here"); return Err(InputError::unexpected_type(expected.to_string(), actual, &span).into());
} }
} }
(Type::Array(type_, _), ValueExpression::String(string, span)) => { (Type::Array(type_, _), ValueExpression::String(string, span)) => {
if !matches!(*type_, Type::Char) { if !matches!(*type_, Type::Char) {
todo!("string can only be used for arrays of chars"); return Err(InputError::string_is_array_of_chars(type_, &span).into());
} }
Self::Array( Self::Array(
@ -76,17 +76,15 @@ impl TryFrom<(Type, Expression)> for InputValue {
) )
} }
(x, y) => { (x, y) => {
todo!("type mismatch, expected type {}, got {}", x, y); return Err(InputError::unexpected_type(x, &y, y.span()).into());
} }
} }
} }
(Type::Array(type_, type_dimensions), Expression::ArrayInit(mut array_init)) => { (Type::Array(type_, type_dimensions), Expression::ArrayInit(mut array_init)) => {
// let mut dimensions = array_init.dimensions;
// let expression = array_init.element;
let span = array_init.span.clone(); let span = array_init.span.clone();
if type_dimensions != array_init.dimensions || array_init.dimensions.is_zero() { if type_dimensions != array_init.dimensions || array_init.dimensions.is_zero() {
return Err(AstError::invalid_array_dimension_size(&span).into()); return Err(InputError::invalid_array_dimension_size(&span).into());
} }
if let Some(dimension) = array_init.dimensions.remove_first() { if let Some(dimension) = array_init.dimensions.remove_first() {
@ -125,11 +123,7 @@ impl TryFrom<(Type, Expression)> for InputValue {
let mut elements = Vec::with_capacity(size); let mut elements = Vec::with_capacity(size);
if size != types.len() { if size != types.len() {
todo!( return Err(InputError::tuple_length_mismatch(size, types.len(), tuple_init.span()).into());
"tuple length mismatch, defined {} types, got {} values",
size,
types.len()
);
} }
for (i, element) in tuple_init.elements.into_iter().enumerate() { for (i, element) in tuple_init.elements.into_iter().enumerate() {
@ -138,23 +132,24 @@ impl TryFrom<(Type, Expression)> for InputValue {
Self::Tuple(elements) Self::Tuple(elements)
} }
(Type::Array(type_, _dimensions), Expression::ArrayInline(array_inline)) => { (Type::Array(element_type, dimensions), Expression::ArrayInline(array_inline)) => {
let mut elements = Vec::with_capacity(array_inline.elements.len()); let mut elements = Vec::with_capacity(array_inline.elements.len());
let _span = array_inline.span().clone(); // todo!: use for spanning the error let span = array_inline.span().clone();
if !dimensions.is_specified() {
return Err(InputError::array_dimensions_must_be_specified(&span).into());
}
for element in array_inline.elements.into_iter() { for element in array_inline.elements.into_iter() {
if let SpreadOrExpression::Expression(value_expression) = element { if let SpreadOrExpression::Expression(value_expression) = element {
elements.push(Self::try_from((*type_.clone(), value_expression))?); elements.push(Self::try_from((*element_type.clone(), value_expression))?);
} else { } else {
todo!("make error that only expression is allowed in inline, no spread please"); return Err(InputError::array_spread_is_not_allowed(&span).into());
} }
} }
Self::Array(elements) Self::Array(elements)
} }
(_type_, expr) => { (_type_, expr) => return Err(InputError::illegal_expression(&expr, expr.span()).into()),
dbg!(&expr);
todo!("forbidden expression in inputs");
}
}) })
} }
} }

View File

@ -36,7 +36,7 @@ pub mod section;
pub use section::*; pub use section::*;
use indexmap::IndexMap; use indexmap::IndexMap;
use leo_errors::{LeoError, Result}; use leo_errors::{InputError, LeoError, Result};
use leo_span::{sym, Span, Symbol}; use leo_span::{sym, Span, Symbol};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;

View File

@ -19,9 +19,9 @@ use super::*;
/// Processed Program input. /// Processed Program input.
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProgramInput { pub struct ProgramInput {
main: Definitions, pub main: Definitions,
registers: Definitions, pub registers: Definitions,
constants: Definitions, pub constants: Definitions,
} }
impl TryFrom<ParsedInputFile> for ProgramInput { impl TryFrom<ParsedInputFile> for ProgramInput {
@ -36,7 +36,14 @@ impl TryFrom<ParsedInputFile> for ProgramInput {
sym::main => &mut main, sym::main => &mut main,
sym::registers => &mut registers, sym::registers => &mut registers,
sym::constants => &mut constants, sym::constants => &mut constants,
_ => todo!("throw an error for illegal section"), _ => {
return Err(InputError::unexpected_section(
&["main", "registers", "constants"],
section.name,
&section.span,
)
.into())
}
}; };
for definition in section.definitions { for definition in section.definitions {

View File

@ -19,9 +19,9 @@ use super::*;
/// Processed Program state. /// Processed Program state.
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProgramState { pub struct ProgramState {
state: Definitions, pub state: Definitions,
record: Definitions, pub record: Definitions,
state_leaf: Definitions, pub state_leaf: Definitions,
} }
impl TryFrom<ParsedInputFile> for ProgramState { impl TryFrom<ParsedInputFile> for ProgramState {
@ -36,7 +36,14 @@ impl TryFrom<ParsedInputFile> for ProgramState {
sym::state => &mut state, sym::state => &mut state,
sym::record => &mut record, sym::record => &mut record,
sym::state_leaf => &mut state_leaf, sym::state_leaf => &mut state_leaf,
_ => todo!("throw an error for illegal section"), _ => {
return Err(InputError::unexpected_section(
&["state", "record", "state_leaf"],
section.name,
&section.span,
)
.into())
}
}; };
for definition in section.definitions { for definition in section.definitions {

View File

@ -0,0 +1,100 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::create_errors;
use std::{
error::Error as ErrorArg,
fmt::{Debug, Display},
};
create_errors!(
/// InputError enum that represents all the errors for the inputs part of `leo-ast` crate.
InputError,
exit_code_mask: 8000i32,
error_code_prefix: "INP",
/// For when the AST fails to be represented as a JSON string.
@formatted
unexpected_type {
args: (expected: impl Display, received: impl Display),
msg: format!(
"unexpected type, expected: '{}', received: '{}'",
expected,
received,
),
help: None,
}
@formatted
string_is_array_of_chars {
args: (expected: impl Display),
msg: format!(
"strings transforms into array of 'char', expected: {}",
expected,
),
help: None,
}
@formatted
array_dimensions_must_be_specified {
args: (),
msg: "array dimensions must be specified",
help: None,
}
@formatted
array_spread_is_not_allowed {
args: (),
msg: "array spread is not allowed in inputs",
help: None,
}
@formatted
invalid_array_dimension_size {
args: (),
msg: "received dimension size of 0, expected it to be 1 or larger.",
help: None,
}
@formatted
illegal_expression {
args: (expr: impl Display),
msg: format!("expression '{}' is not allowed in inputs", expr),
help: None,
}
@formatted
unexpected_section {
args: (expected: &[impl Display], received: impl Display),
msg: format!(
"unexpected section: expected {} -- got '{}'",
expected
.iter()
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
.join(", "),
received
),
help: None,
}
@formatted
tuple_length_mismatch {
args: (expected: impl Display, received: impl Display),
msg: format!("tuple length mismatch, defined {} types, got {} values", expected, received),
help: None,
}
);

19
errors/src/input/mod.rs Normal file
View File

@ -0,0 +1,19 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
/// This module contains the Input error definitions.
pub mod input_errors;
pub use self::input_errors::*;

View File

@ -45,6 +45,10 @@ pub use self::compiler::*;
pub mod import; pub mod import;
pub use self::import::*; pub use self::import::*;
/// Contains the Input error definitions.
pub mod input;
pub use self::input::*;
/// Contains the Package error definitions. /// Contains the Package error definitions.
pub mod package; pub mod package;
pub use self::package::*; pub use self::package::*;
@ -91,8 +95,8 @@ pub enum LeoError {
ImportError(#[from] ImportError), ImportError(#[from] ImportError),
/// Represents an Input Error in a Leo Error. /// Represents an Input Error in a Leo Error.
// #[error(transparent)] #[error(transparent)]
// InputError(#[from] InputParserError), InputError(#[from] InputError),
/// Represents an Package Error in a Leo Error. /// Represents an Package Error in a Leo Error.
#[error(transparent)] #[error(transparent)]
@ -122,7 +126,7 @@ impl LeoError {
CliError(error) => error.error_code(), CliError(error) => error.error_code(),
CompilerError(error) => error.error_code(), CompilerError(error) => error.error_code(),
ImportError(error) => error.error_code(), ImportError(error) => error.error_code(),
// InputError(_error) => Default::default(), // TODO migrate me, or not cause we want inputs to have 0 deps. InputError(error) => error.error_code(), // TODO migrate me, or not cause we want inputs to have 0 deps.
PackageError(error) => error.error_code(), PackageError(error) => error.error_code(),
ParserError(error) => error.error_code(), ParserError(error) => error.error_code(),
SnarkVMError(_error) => Default::default(), // TODO update once snarkvm implments a global top level error similar to LeoError. SnarkVMError(_error) => Default::default(), // TODO update once snarkvm implments a global top level error similar to LeoError.
@ -140,7 +144,7 @@ impl LeoError {
CliError(error) => error.exit_code(), CliError(error) => error.exit_code(),
CompilerError(error) => error.exit_code(), CompilerError(error) => error.exit_code(),
ImportError(error) => error.exit_code(), ImportError(error) => error.exit_code(),
// InputError(_error) => 1, // TODO migrate me, or not cause we want inputs to have 0 deps. InputError(error) => error.exit_code(), // TODO migrate me, or not cause we want inputs to have 0 deps.
PackageError(error) => error.exit_code(), PackageError(error) => error.exit_code(),
ParserError(error) => error.exit_code(), ParserError(error) => error.exit_code(),
SnarkVMError(_error) => 1, // TODO update once snarkvm implments a global top level error similar to LeoError. SnarkVMError(_error) => 1, // TODO update once snarkvm implments a global top level error similar to LeoError.

View File

@ -37,7 +37,8 @@ fn to_leo_tree(input_filepath: &Path, state_filepath: &Path) -> Result<String, S
let json = input.to_json_string()?; let json = input.to_json_string()?;
Ok(json) Ok(json)
}).map_err(|e| e.to_string()) })
.map_err(|e| e.to_string())
}) })
} }

View File

@ -50,14 +50,21 @@ impl ParserContext<'_> {
pub fn parse_visibility(&mut self) -> Result<bool> { pub fn parse_visibility(&mut self) -> Result<bool> {
self.expect(Token::LeftSquare)?; self.expect(Token::LeftSquare)?;
self.expect(Token::LeftSquare)?; self.expect(Token::LeftSquare)?;
let visiblity = self.expect_ident()?; let visibility = self.expect_ident()?;
self.expect(Token::RightSquare)?; self.expect(Token::RightSquare)?;
self.expect(Token::RightSquare)?; self.expect(Token::RightSquare)?;
Ok(match visiblity.name { Ok(match visibility.name {
sym::public => true, sym::public => true,
sym::private => false, sym::private => false,
_ => todo!("illegal visibility modifier"), _ => {
self.emit_err(ParserError::unexpected_ident(
visibility.name,
&["public", "private"],
visibility.span(),
));
true
}
}) })
} }
@ -74,7 +81,10 @@ impl ParserContext<'_> {
let mut definitions = Vec::new(); let mut definitions = Vec::new();
while let Some(SpannedToken{ token: Token::Ident(_), .. }) = self.peek_option() { while let Some(SpannedToken {
token: Token::Ident(_), ..
}) = self.peek_option()
{
definitions.push(self.parse_input_definition()?); definitions.push(self.parse_input_definition()?);
} }