stashing another set of dev changes

This commit is contained in:
damirka 2022-02-11 18:53:03 +03:00
parent 466c41809c
commit 5b4ac6b509
43 changed files with 669 additions and 776 deletions

2
Cargo.lock generated
View File

@ -1112,7 +1112,6 @@ dependencies = [
"criterion", "criterion",
"indexmap", "indexmap",
"leo-errors", "leo-errors",
"leo-input",
"leo-span", "leo-span",
"pest", "pest",
"serde", "serde",
@ -1140,7 +1139,6 @@ dependencies = [
"colored", "colored",
"derivative", "derivative",
"eyre", "eyre",
"leo-input",
"leo-span", "leo-span",
"pest", "pest",
"serde", "serde",

View File

@ -21,9 +21,9 @@ rust-version = "1.56"
[dependencies] [dependencies]
smallvec = { version = "1.8.0", features = ["serde"] } smallvec = { version = "1.8.0", features = ["serde"] }
[dependencies.leo-input] # [dependencies.leo-input]
path = "../input" # path = "../input"
version = "1.5.3" # version = "1.5.3"
[dependencies.leo-errors] [dependencies.leo-errors]
path = "../errors" path = "../errors"

View File

@ -0,0 +1,412 @@
// 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::{ArrayDimensions, Char, CharValue, GroupValue, IntegerType};
use leo_input::{
errors::InputParserError,
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, StringExpression, TupleExpression},
types::{ArrayType, CharType, DataType, IntegerType as InputIntegerType, TupleType, Type},
values::{
Address, AddressValue, BooleanValue, CharValue as InputCharValue, FieldValue, GroupValue as InputGroupValue,
IntegerValue, NumberValue, Value,
},
};
use leo_span::Span as AstSpan;
use pest::Span;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum InputValue {
Address(String),
Boolean(bool),
Char(CharValue),
Field(String),
Group(GroupValue),
Integer(IntegerType, String),
Array(Vec<InputValue>),
Tuple(Vec<InputValue>),
}
impl InputValue {
fn from_address(address: Address) -> Self {
InputValue::Address(address.value)
}
fn from_address_value(value: AddressValue) -> Self {
match value {
AddressValue::Explicit(address) => Self::from_address(address.address),
AddressValue::Implicit(address) => Self::from_address(address),
}
}
fn from_boolean(boolean: BooleanValue) -> Result<Self, InputParserError> {
let boolean = boolean.value.parse::<bool>()?;
Ok(InputValue::Boolean(boolean))
}
fn from_char(input_character: InputCharValue) -> Result<Self, InputParserError> {
let character = match input_character.value.inner()? {
leo_input::values::Char::Scalar(scalar) => Char::Scalar(scalar),
leo_input::values::Char::NonScalar(non_scalar) => Char::NonScalar(non_scalar),
};
let span = AstSpan::from(input_character.span);
Ok(InputValue::Char(CharValue { character, span }))
}
fn from_number(integer_type: InputIntegerType, number: String) -> Self {
InputValue::Integer(integer_type.into(), number)
}
fn from_group(group: InputGroupValue) -> Self {
InputValue::Group(GroupValue::from(group))
}
fn from_field(field: FieldValue) -> Self {
InputValue::Field(field.number.to_string())
}
fn from_implicit(data_type: DataType, implicit: NumberValue) -> Result<Self, InputParserError> {
match data_type {
DataType::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)),
DataType::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)),
DataType::Char(_) => Err(InputParserError::implicit_type(data_type, implicit)),
DataType::Integer(integer_type) => Ok(InputValue::from_number(integer_type, implicit.to_string())),
DataType::Group(_) => Err(InputParserError::implicit_group(implicit)),
DataType::Field(_) => Ok(InputValue::Field(implicit.to_string())),
}
}
fn from_value(data_type: DataType, value: Value) -> Result<Self, InputParserError> {
match (data_type, value) {
(DataType::Address(_), Value::Address(address)) => Ok(InputValue::from_address_value(address)),
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
(DataType::Char(_), Value::Char(character)) => InputValue::from_char(character),
(DataType::Integer(integer_type), Value::Integer(integer)) => {
match integer.clone() {
IntegerValue::Signed(signed) => {
if let InputIntegerType::Signed(inner) = integer_type.clone() {
let singed_type = signed.clone().type_;
if std::mem::discriminant(&inner) != std::mem::discriminant(&singed_type) {
return Err(InputParserError::integer_type_mismatch(
integer_type,
InputIntegerType::Signed(singed_type),
integer.span(),
));
}
}
}
IntegerValue::Unsigned(unsigned) => {
if let InputIntegerType::Unsigned(inner) = integer_type.clone() {
let unsinged_type = unsigned.clone().type_;
if std::mem::discriminant(&inner) != std::mem::discriminant(&unsinged_type) {
return Err(InputParserError::integer_type_mismatch(
integer_type,
InputIntegerType::Unsigned(unsinged_type),
integer.span(),
));
}
}
}
}
Ok(InputValue::from_number(integer_type, integer.to_string()))
}
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
(data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit),
(data_type, value) => Err(InputParserError::data_type_mismatch(data_type, value)),
}
}
pub(crate) fn from_expression(type_: Type, expression: Expression) -> Result<Self, InputParserError> {
match (type_, expression) {
(Type::Basic(data_type), Expression::Value(value)) => InputValue::from_value(data_type, value),
(Type::Array(array_type), Expression::ArrayInline(inline)) => {
InputValue::from_array_inline(array_type, inline)
}
(Type::Array(array_type), Expression::ArrayInitializer(initializer)) => {
InputValue::from_array_initializer(array_type, initializer)
}
(Type::Array(array_type), Expression::StringExpression(string)) => {
InputValue::from_string(array_type, string)
}
(Type::Tuple(tuple_type), Expression::Tuple(tuple)) => InputValue::from_tuple(tuple_type, tuple),
(type_, expression) => Err(InputParserError::expression_type_mismatch(type_, expression)),
}
}
///
/// Returns a new `InputValue` from the given `ArrayType` and `StringExpression`.
///
pub(crate) fn from_string(mut array_type: ArrayType, string: StringExpression) -> Result<Self, InputParserError> {
// Create a new `ArrayDimensions` type from the input array_type dimensions.
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
assert!(matches!(*array_type.type_, Type::Basic(DataType::Char(CharType {}))));
// Convert the array dimensions to usize.
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
// Return an error if the outer array dimension does not equal the number of array elements.
if array_dimensions[0] != string.chars.len() {
return Err(InputParserError::invalid_string_length(
array_dimensions[0],
string.chars.len(),
&string.span,
));
}
array_type.dimensions = array_type.dimensions.next_dimension();
let inner_array_type = if array_dimensions.len() == 1 {
// This is a single array
*array_type.type_
} else {
// This is a multi-dimensional array
return Err(InputParserError::invalid_string_dimensions(&array_type.span));
};
let mut elements = Vec::with_capacity(string.chars.len());
for character in string.chars.into_iter() {
let element = InputValue::from_expression(
inner_array_type.clone(),
Expression::Value(Value::Char(InputCharValue {
value: character.clone(),
span: character.span().clone(),
})),
)?;
elements.push(element)
}
Ok(InputValue::Array(elements))
}
///
/// Returns a new `InputValue` from the given `ArrayType` and `ArrayInlineExpression`.
///
pub(crate) fn from_array_inline(
mut array_type: ArrayType,
inline: ArrayInlineExpression,
) -> Result<Self, InputParserError> {
// Create a new `ArrayDimensions` type from the input array_type dimensions.
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
// Convert the array dimensions to usize.
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
// Return an error if the outer array dimension does not equal the number of array elements.
if array_dimensions[0] != inline.expressions.len() {
return Err(InputParserError::array_inline_length(array_dimensions[0], inline));
}
array_type.dimensions = array_type.dimensions.next_dimension();
let inner_array_type = if array_dimensions.len() == 1 {
// This is a single array
*array_type.type_
} else {
// This is a multi-dimensional array
Type::Array(array_type)
};
let mut elements = Vec::with_capacity(inline.expressions.len());
for expression in inline.expressions.into_iter() {
let element = InputValue::from_expression(inner_array_type.clone(), expression)?;
elements.push(element)
}
Ok(InputValue::Array(elements))
}
pub(crate) fn from_array_initializer(
array_type: ArrayType,
initializer: ArrayInitializerExpression,
) -> Result<Self, InputParserError> {
let array_dimensions_type = ArrayDimensions::from(initializer.dimensions.clone());
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
if array_dimensions.len() > 1 {
// The expression is an array initializer with tuple syntax
Self::from_array_initializer_tuple(array_type, initializer, array_dimensions)
} else {
// The expression is an array initializer with nested syntax
Self::from_array_initializer_nested(array_type, initializer, array_dimensions)
}
}
pub(crate) fn from_array_initializer_tuple(
array_type: ArrayType,
initializer: ArrayInitializerExpression,
initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> {
let (array_dimensions, array_element_type) = fetch_nested_array_type_dimensions(array_type.clone(), vec![])?;
// Return an error if the dimensions of the array are incorrect.
if array_dimensions.ne(&initializer_dimensions) {
return Err(InputParserError::array_init_length(
array_dimensions,
initializer_dimensions,
&initializer.span,
));
}
let value = InputValue::from_expression(array_element_type, *initializer.expression.clone())?;
let mut elements = vec![];
// Build the elements of the array using the `vec!` macro
for (i, dimension) in initializer_dimensions.into_iter().rev().enumerate() {
if i == 0 {
elements = vec![value.clone(); dimension];
} else {
let element = InputValue::Array(elements.clone());
elements = vec![element; dimension];
}
}
Ok(InputValue::Array(elements))
}
pub(crate) fn from_array_initializer_nested(
mut array_type: ArrayType,
initializer: ArrayInitializerExpression,
initializer_dimensions: Vec<usize>,
) -> Result<Self, InputParserError> {
// Create a new `ArrayDimensions` type from the input array_type dimensions.
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
// Convert the array dimensions to usize.
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
let current_array_dimension = array_dimensions[0];
let current_initializer_dimension = initializer_dimensions[0];
// Return an error if the outer array dimension does not equal the number of array elements.
if current_array_dimension.ne(&current_initializer_dimension) {
return Err(InputParserError::array_init_length(
array_dimensions,
initializer_dimensions,
&initializer.span,
));
}
array_type.dimensions = array_type.dimensions.next_dimension();
let inner_array_type = if array_dimensions.len() == 1 {
// This is the innermost dimension
*array_type.type_
} else {
// This is an outer dimension of a multi-dimensional array
Type::Array(array_type)
};
// Evaluate the array initializer
let element = InputValue::from_expression(inner_array_type.clone(), *initializer.expression)?;
let elements = vec![element; current_initializer_dimension];
Ok(InputValue::Array(elements))
}
pub(crate) fn from_tuple(tuple_type: TupleType, tuple: TupleExpression) -> Result<Self, InputParserError> {
let num_types = tuple_type.types_.len();
let num_values = tuple.expressions.len();
if num_types != num_values {
return Err(InputParserError::tuple_length(num_types, num_values, &tuple_type.span));
}
let mut values = Vec::with_capacity(tuple_type.types_.len());
for (type_, value) in tuple_type.types_.into_iter().zip(tuple.expressions.into_iter()) {
let value = InputValue::from_expression(type_, value)?;
values.push(value)
}
Ok(InputValue::Tuple(values))
}
}
/// Returns a new vector of usize values from an [`ArrayDimensions`] type.
///
/// Attempts to parse each dimension in the array from a `String` to a `usize` value. If parsing
/// is successful, the `usize` value is appended to the return vector. If parsing fails, an error
/// is returned.
fn parse_array_dimensions(dimensions: ArrayDimensions, span: &Span) -> Result<Vec<usize>, InputParserError> {
// Convert the array dimensions to usize.
let mut result_array_dimensions = Vec::with_capacity(dimensions.len());
for dimension in dimensions.iter() {
// Convert the dimension to a string.
let dimension_string = dimension.to_string();
// Convert the string to usize.
let dimension_usize = match dimension_string.parse::<usize>() {
Ok(dimension_usize) => dimension_usize,
Err(_) => return Err(InputParserError::array_index(dimension_string, span)),
};
// Collect dimension usize values.
result_array_dimensions.push(dimension_usize);
}
Ok(result_array_dimensions)
}
///
/// Recursively fetch all dimensions from the array type.
///
fn fetch_nested_array_type_dimensions(
array_type: ArrayType,
mut array_dimensions: Vec<usize>,
) -> Result<(Vec<usize>, Type), InputParserError> {
// Create a new `ArrayDimensions` type from the input array_type dimensions.
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
// Convert the array dimensions to usize.
let mut current_dimension = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
array_dimensions.append(&mut current_dimension);
match *array_type.type_ {
Type::Array(next_array_type) => fetch_nested_array_type_dimensions(next_array_type, array_dimensions),
type_ => Ok((array_dimensions, type_)),
}
}
impl fmt::Display for InputValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
InputValue::Address(ref address) => write!(f, "{}", address),
InputValue::Boolean(ref boolean) => write!(f, "{}", boolean),
InputValue::Char(ref character) => write!(f, "{}", character),
InputValue::Group(ref group) => write!(f, "{}", group),
InputValue::Field(ref field) => write!(f, "{}", field),
InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_),
InputValue::Array(ref array) => {
let values = array.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "array [{}]", values)
}
InputValue::Tuple(ref tuple) => {
let values = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "({})", values)
}
}
}
}

View File

@ -14,5 +14,23 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
mod context; #![allow(clippy::module_inception)]
pub use context::*;
#[macro_use]
pub mod macros;
pub use macros::*;
pub mod input;
pub use input::*;
pub mod input_value;
pub use input_value::*;
pub mod parameters;
pub use parameters::*;
pub mod program_input;
pub use program_input::*;
pub mod program_state;
pub use program_state::*;

View File

@ -17,7 +17,6 @@
use leo_span::Span; use leo_span::Span;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// use serde::de::{Deserialize as SerDeserialize, Deserializer};
use std::fmt; use std::fmt;
fn char_to_u32<S>(character: &char, serializer: S) -> Result<S::Ok, S::Error> fn char_to_u32<S>(character: &char, serializer: S) -> Result<S::Ok, S::Error>

View File

@ -15,7 +15,6 @@
// 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::PositiveNumber; use crate::PositiveNumber;
use leo_input::types::ArrayDimensions as InputArrayDimensions;
use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer}; use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -114,24 +113,6 @@ impl Serialize for ArrayDimensions {
} }
} }
/// Create a new [`ArrayDimensions`] from a [`InputArrayDimensions`] in a Leo program file.
impl<'ast> From<InputArrayDimensions<'ast>> for ArrayDimensions {
fn from(dimensions: InputArrayDimensions<'ast>) -> Self {
match dimensions {
InputArrayDimensions::Single(single) => {
Self(smallvec![Dimension::Number(PositiveNumber::from(single.number))])
}
InputArrayDimensions::Multiple(multiple) => Self(
multiple
.numbers
.into_iter()
.map(|num| Dimension::Number(PositiveNumber::from(num)))
.collect(),
),
}
}
}
impl fmt::Display for ArrayDimensions { impl fmt::Display for ArrayDimensions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &*self.0 { match &*self.0 {

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_input::common::Identifier as InputIdentifier;
use leo_span::{Span, Symbol}; use leo_span::{Span, Symbol};
use crate::Node; use crate::Node;
@ -68,15 +67,6 @@ impl Identifier {
} }
} }
impl<'ast> From<InputIdentifier<'ast>> for Identifier {
fn from(identifier: InputIdentifier<'ast>) -> Self {
Self {
name: Symbol::intern(&identifier.value),
span: Span::from(identifier.span),
}
}
}
impl fmt::Display for Identifier { impl fmt::Display for Identifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name) write!(f, "{}", self.name)

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_input::values::PositiveNumber as InputPositiveNumber;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use tendril::StrTendril; use tendril::StrTendril;
@ -36,15 +34,6 @@ impl PositiveNumber {
} }
} }
/// Create a new [`PositiveNumber`] from an [`InputPositiveNumber`] in a Leo input file.
impl<'ast> From<InputPositiveNumber<'ast>> for PositiveNumber {
fn from(array: InputPositiveNumber<'ast>) -> Self {
Self {
value: array.value.into(),
}
}
}
impl fmt::Display for PositiveNumber { impl fmt::Display for PositiveNumber {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value) write!(f, "{}", self.value)

View File

@ -14,10 +14,6 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_input::values::{
GroupCoordinate as InputGroupCoordinate, Inferred as InputInferred, NumberValue as InputNumberValue,
SignHigh as InputSignHigh, SignLow as InputSignLow,
};
use leo_span::Span; use leo_span::Span;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -40,17 +36,6 @@ pub enum GroupCoordinate {
Inferred, Inferred,
} }
impl<'ast> From<InputGroupCoordinate<'ast>> for GroupCoordinate {
fn from(coordinate: InputGroupCoordinate<'ast>) -> Self {
match coordinate {
InputGroupCoordinate::Number(number) => GroupCoordinate::from(number),
InputGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
InputGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
InputGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
}
}
}
impl fmt::Display for GroupCoordinate { impl fmt::Display for GroupCoordinate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -61,30 +46,3 @@ impl fmt::Display for GroupCoordinate {
} }
} }
} }
impl<'ast> From<InputNumberValue<'ast>> for GroupCoordinate {
fn from(number: InputNumberValue<'ast>) -> Self {
let value = number.to_string();
let span = Span::from(number.span().clone());
GroupCoordinate::Number(value.into(), span)
}
}
impl<'ast> From<InputSignHigh<'ast>> for GroupCoordinate {
fn from(_sign: InputSignHigh<'ast>) -> Self {
GroupCoordinate::SignHigh
}
}
impl<'ast> From<InputSignLow<'ast>> for GroupCoordinate {
fn from(_sign: InputSignLow<'ast>) -> Self {
GroupCoordinate::SignLow
}
}
impl<'ast> From<InputInferred<'ast>> for GroupCoordinate {
fn from(_sign: InputInferred<'ast>) -> Self {
GroupCoordinate::Inferred
}
}

View File

@ -15,9 +15,6 @@
// 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::groups::GroupCoordinate; use crate::groups::GroupCoordinate;
use leo_input::values::{
GroupRepresentation as InputGroupRepresentation, GroupTuple as InputGroupTuple, GroupValue as InputGroupValue,
};
use leo_span::Span; use leo_span::Span;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -52,17 +49,6 @@ impl GroupValue {
} }
} }
impl<'ast> From<InputGroupValue<'ast>> for GroupValue {
fn from(ast_group: InputGroupValue) -> Self {
let span = Span::from(ast_group.span);
match ast_group.value {
InputGroupRepresentation::Single(number) => GroupValue::Single(number.to_string().into(), span),
InputGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
}
}
}
impl fmt::Display for GroupValue { impl fmt::Display for GroupValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -83,19 +69,6 @@ pub struct GroupTuple {
pub span: Span, pub span: Span,
} }
impl<'ast> From<InputGroupTuple<'ast>> for GroupTuple {
fn from(ast_group: InputGroupTuple<'ast>) -> Self {
let ast_x = ast_group.x;
let ast_y = ast_group.y;
Self {
x: GroupCoordinate::from(ast_x),
y: GroupCoordinate::from(ast_y),
span: Span::from(ast_group.span),
}
}
}
impl fmt::Display for GroupTuple { impl fmt::Display for GroupTuple {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y) write!(f, "({}, {})", self.x, self.y)

View File

@ -15,15 +15,6 @@
// 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::{ArrayDimensions, Char, CharValue, GroupValue, IntegerType}; use crate::{ArrayDimensions, Char, CharValue, GroupValue, IntegerType};
use leo_input::{
errors::InputParserError,
expressions::{ArrayInitializerExpression, ArrayInlineExpression, Expression, StringExpression, TupleExpression},
types::{ArrayType, CharType, DataType, IntegerType as InputIntegerType, TupleType, Type},
values::{
Address, AddressValue, BooleanValue, CharValue as InputCharValue, FieldValue, GroupValue as InputGroupValue,
IntegerValue, NumberValue, Value,
},
};
use leo_span::Span as AstSpan; use leo_span::Span as AstSpan;
use pest::Span; use pest::Span;
@ -80,23 +71,23 @@ impl InputValue {
InputValue::Field(field.number.to_string()) InputValue::Field(field.number.to_string())
} }
fn from_implicit(data_type: DataType, implicit: NumberValue) -> Result<Self, InputParserError> { fn from_implicit(data_type: Type, implicit: NumberValue) -> Result<Self, InputParserError> {
match data_type { match data_type {
DataType::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)), Type::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)),
DataType::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)), Type::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)),
DataType::Char(_) => Err(InputParserError::implicit_type(data_type, implicit)), Type::Char(_) => Err(InputParserError::implicit_type(data_type, implicit)),
DataType::Integer(integer_type) => Ok(InputValue::from_number(integer_type, implicit.to_string())), Type::Integer(integer_type) => Ok(InputValue::from_number(integer_type, implicit.to_string())),
DataType::Group(_) => Err(InputParserError::implicit_group(implicit)), Type::Group(_) => Err(InputParserError::implicit_group(implicit)),
DataType::Field(_) => Ok(InputValue::Field(implicit.to_string())), Type::Field(_) => Ok(InputValue::Field(implicit.to_string())),
} }
} }
fn from_value(data_type: DataType, value: Value) -> Result<Self, InputParserError> { fn from_value(data_type: Type, value: Value) -> Result<Self, InputParserError> {
match (data_type, value) { match (data_type, value) {
(DataType::Address(_), Value::Address(address)) => Ok(InputValue::from_address_value(address)), (Type::Address(_), Value::Address(address)) => Ok(InputValue::from_address_value(address)),
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean), (Type::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
(DataType::Char(_), Value::Char(character)) => InputValue::from_char(character), (Type::Char(_), Value::Char(character)) => InputValue::from_char(character),
(DataType::Integer(integer_type), Value::Integer(integer)) => { (Type::Integer(integer_type), Value::Integer(integer)) => {
match integer.clone() { match integer.clone() {
IntegerValue::Signed(signed) => { IntegerValue::Signed(signed) => {
if let InputIntegerType::Signed(inner) = integer_type.clone() { if let InputIntegerType::Signed(inner) = integer_type.clone() {
@ -125,8 +116,8 @@ impl InputValue {
} }
Ok(InputValue::from_number(integer_type, integer.to_string())) Ok(InputValue::from_number(integer_type, integer.to_string()))
} }
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)), (Type::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)), (Type::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
(data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit), (data_type, Value::Implicit(implicit)) => InputValue::from_implicit(data_type, implicit),
(data_type, value) => Err(InputParserError::data_type_mismatch(data_type, value)), (data_type, value) => Err(InputParserError::data_type_mismatch(data_type, value)),
} }
@ -155,7 +146,7 @@ impl InputValue {
pub(crate) fn from_string(mut array_type: ArrayType, string: StringExpression) -> Result<Self, InputParserError> { pub(crate) fn from_string(mut array_type: ArrayType, string: StringExpression) -> Result<Self, InputParserError> {
// Create a new `ArrayDimensions` type from the input array_type dimensions. // Create a new `ArrayDimensions` type from the input array_type dimensions.
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone()); let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
assert!(matches!(*array_type.type_, Type::Basic(DataType::Char(CharType {})))); assert!(matches!(*array_type.type_, Type::Basic(Type::Char(CharType {}))));
// Convert the array dimensions to usize. // Convert the array dimensions to usize.
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?; let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;

View File

@ -14,23 +14,146 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
#![allow(clippy::module_inception)] use crate::{
CharValue, Expression, GroupValue, Identifier, IntegerType, Node, SpreadOrExpression, Type, ValueExpression,
};
use indexmap::IndexMap;
use leo_errors::{AstError, LeoError, ParserError, Result};
use pest::Parser;
#[macro_use] #[derive(Clone, Debug)]
pub mod macros; pub struct Input {
pub use macros::*; values: IndexMap<Identifier, IndexMap<Identifier, (Type, Expression)>>,
}
pub mod input; impl Input {
pub use input::*; pub fn new(values: IndexMap<Identifier, IndexMap<Identifier, (Type, Expression)>>) -> Self {
for (ident, definitions) in values.iter() {
// println!("ident: {}", ident);
for (_var, (type_, value)) in definitions.iter() {
let _ = InputValue::create(type_.clone(), value.clone())
.map_err(|_| ParserError::unexpected_eof(value.span()));
}
}
pub mod input_value; Input { values }
pub use input_value::*; }
}
pub mod parameters; impl InputValue {
pub use parameters::*; pub fn create(type_: Type, expression: Expression) -> Result<Self> {
dbg!(InputValue::try_from((type_, expression))?);
Ok(InputValue::Boolean(true))
}
}
pub mod program_input; #[derive(Clone, Debug, PartialEq, Eq)]
pub use program_input::*; pub enum InputValue {
Address(String),
Boolean(bool),
Char(CharValue),
Field(String),
Group(GroupValue),
Integer(IntegerType, String),
Array(Vec<InputValue>),
Tuple(Vec<InputValue>),
pub mod program_state; // Should be removed later
pub use program_state::*; Implicit(String),
}
impl InputValue {
fn verify_type(self, type_: Type) -> Result<Self> {
Ok(self)
}
}
impl TryFrom<(Type, Expression)> for InputValue {
type Error = LeoError;
fn try_from(value: (Type, Expression)) -> Result<Self> {
Ok(match value {
(type_, Expression::Value(value)) => {
match value {
ValueExpression::Address(value, _) => Self::Address(value.to_string()),
ValueExpression::Boolean(value, span) => {
let bool_value = value.parse::<bool>().map_err(|_| ParserError::unexpected_eof(&span))?; // TODO: change error
Self::Boolean(bool_value)
}
ValueExpression::Char(value) => Self::Char(value),
ValueExpression::Field(value, _) => Self::Field(value.to_string()),
ValueExpression::Group(value) => Self::Group(*value),
ValueExpression::Implicit(value, _) => Self::Implicit(value.to_string()),
ValueExpression::Integer(type_, value, _) => Self::Integer(type_, value.to_string()),
ValueExpression::String(string, span) => Self::Array(
string
.into_iter()
.map(|c| {
Self::Char(CharValue {
character: c,
span: span.clone(),
})
})
.collect(),
),
}
.verify_type(type_)?
}
(Type::Array(type_, type_dimensions), Expression::ArrayInit(array_init)) => {
let mut dimensions = array_init.dimensions;
let expression = array_init.element;
let span = array_init.span.clone();
if type_dimensions != dimensions || dimensions.is_zero() {
return Err(AstError::invalid_array_dimension_size(&span).into());
}
if dimensions.len() > 1 {
while let Some(dimension) = dimensions.remove_first() {
if let Some(number) = dimension.as_specified() {
let size = number.value.parse::<usize>().unwrap();
// let elements = Vec::with_capacity(size);
// for i in 0..size {
// // elements.push()
// }
} else {
return Err(AstError::invalid_array_dimension_size(&span).into());
}
}
} else {
}
// let elements = Vec::with_capacity(dimensions.len());
dbg!(dimensions);
dbg!(expression);
// TBD
Self::Boolean(false).verify_type(*type_)?
}
(type_, Expression::TupleInit(tuple_init)) => {
let mut elements = Vec::with_capacity(tuple_init.elements.len());
for element in tuple_init.elements.into_iter() {
elements.push(Self::try_from((type_.clone(), element))?);
}
Self::Tuple(elements).verify_type(type_)?
}
(type_, Expression::ArrayInline(array_inline)) => {
let mut elements = Vec::with_capacity(array_inline.elements.len());
let span = array_inline.span().clone();
for element in array_inline.elements.into_iter() {
if let SpreadOrExpression::Expression(value_expression) = element {
elements.push(Self::try_from((type_.clone(), value_expression))?);
} else {
return Err(ParserError::unexpected_eof(&span).into());
}
}
Self::Array(elements).verify_type(type_)?
}
(_type_, expr) => {
dbg!(&expr);
return Err(ParserError::unexpected_eof(expr.span()).into());
}
})
}
}

View File

@ -14,10 +14,6 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_input::types::{
IntegerType as InputIntegerType, SignedIntegerType as InputSignedIntegerType,
UnsignedIntegerType as InputUnsignedIntegerType,
};
use leo_span::{sym, Symbol}; use leo_span::{sym, Symbol};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -63,39 +59,6 @@ impl IntegerType {
} }
} }
impl From<InputIntegerType> for IntegerType {
fn from(integer_type: InputIntegerType) -> Self {
match integer_type {
InputIntegerType::Signed(signed) => Self::from(signed),
InputIntegerType::Unsigned(unsigned) => Self::from(unsigned),
}
}
}
impl From<InputUnsignedIntegerType> for IntegerType {
fn from(integer_type: InputUnsignedIntegerType) -> Self {
match integer_type {
InputUnsignedIntegerType::U8Type(_type) => IntegerType::U8,
InputUnsignedIntegerType::U16Type(_type) => IntegerType::U16,
InputUnsignedIntegerType::U32Type(_type) => IntegerType::U32,
InputUnsignedIntegerType::U64Type(_type) => IntegerType::U64,
InputUnsignedIntegerType::U128Type(_type) => IntegerType::U128,
}
}
}
impl From<InputSignedIntegerType> for IntegerType {
fn from(integer_type: InputSignedIntegerType) -> Self {
match integer_type {
InputSignedIntegerType::I8Type(_type) => IntegerType::I8,
InputSignedIntegerType::I16Type(_type) => IntegerType::I16,
InputSignedIntegerType::I32Type(_type) => IntegerType::I32,
InputSignedIntegerType::I64Type(_type) => IntegerType::I64,
InputSignedIntegerType::I128Type(_type) => IntegerType::I128,
}
}
}
impl fmt::Display for IntegerType { impl fmt::Display for IntegerType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {

View File

@ -15,9 +15,6 @@
// 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::{ArrayDimensions, Identifier, IntegerType}; use crate::{ArrayDimensions, Identifier, IntegerType};
use leo_input::types::{
ArrayType as InputArrayType, DataType as InputDataType, TupleType as InputTupleType, Type as InputType,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -122,48 +119,6 @@ impl Type {
} }
} }
/// input pest ast -> Explicit Type
impl From<InputDataType> for Type {
fn from(data_type: InputDataType) -> Self {
match data_type {
InputDataType::Address(_type) => Type::Address,
InputDataType::Boolean(_type) => Type::Boolean,
InputDataType::Char(_type) => Type::Char,
InputDataType::Field(_type) => Type::Field,
InputDataType::Group(_type) => Type::Group,
InputDataType::Integer(type_) => Type::IntegerType(IntegerType::from(type_)),
}
}
}
impl<'ast> From<InputArrayType<'ast>> for Type {
fn from(array_type: InputArrayType<'ast>) -> Self {
let element_type = Box::new(Type::from(*array_type.type_));
let dimensions = ArrayDimensions::from(array_type.dimensions);
Type::Array(element_type, dimensions)
}
}
impl<'ast> From<InputTupleType<'ast>> for Type {
fn from(tuple_type: InputTupleType<'ast>) -> Self {
let types = tuple_type.types_.into_iter().map(Type::from).collect();
Type::Tuple(types)
}
}
impl<'ast> From<InputType<'ast>> for Type {
fn from(type_: InputType<'ast>) -> Self {
match type_ {
InputType::Basic(type_) => Type::from(type_),
InputType::Array(type_) => Type::from(type_),
InputType::Tuple(type_) => Type::from(type_),
}
}
}
impl fmt::Display for Type { impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {

View File

@ -1 +0,0 @@
ok

View File

@ -25,9 +25,9 @@ version = "0.3.62"
path = "../span" path = "../span"
version = "1.5.3" version = "1.5.3"
[dependencies.leo-input] # [dependencies.leo-input]
path = "../input" # path = "../input"
version = "1.5.3" # version = "1.5.3"
[dependencies.colored] [dependencies.colored]
version = "2.0.0" version = "2.0.0"

View File

@ -64,7 +64,7 @@ pub use self::state::*;
#[macro_use] #[macro_use]
extern crate thiserror; extern crate thiserror;
use leo_input::InputParserError; // use leo_input::InputParserError;
/// The LeoError type that contains all sub error types. /// The LeoError type that contains all sub error types.
/// This allows a unified error type throughout the Leo crates. /// This allows a unified error type throughout the Leo crates.
@ -91,8 +91,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] InputParserError),
/// Represents an Package Error in a Leo Error. /// Represents an Package Error in a Leo Error.
#[error(transparent)] #[error(transparent)]
@ -122,7 +122,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) => Default::default(), // 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 +140,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) => 1, // 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

@ -18,8 +18,8 @@ use crate::{commands::Command, context::Context};
use leo_compiler::Compiler; use leo_compiler::Compiler;
use leo_errors::{CliError, Result}; use leo_errors::{CliError, Result};
use leo_package::{ use leo_package::{
inputs::*, // inputs::*,
outputs::{ChecksumFile, CircuitFile, OutputsDirectory, OUTPUTS_DIRECTORY_NAME}, outputs::{ChecksumFile, /* CircuitFile, */ OutputsDirectory, OUTPUTS_DIRECTORY_NAME},
source::{MainFile, MAIN_FILENAME, SOURCE_DIRECTORY_NAME}, source::{MainFile, MAIN_FILENAME, SOURCE_DIRECTORY_NAME},
}; };
@ -93,8 +93,8 @@ pub struct BuildOptions {
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)] #[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
pub struct Build { pub struct Build {
#[structopt(flatten)] // #[structopt(flatten)]
pub(crate) compiler_options: BuildOptions, // pub(crate) compiler_options: BuildOptions,
} }
impl Command for Build { impl Command for Build {

View File

@ -29,7 +29,7 @@ use commands::{
// Deploy, Init, Lint, New, Prove, Run, Setup, Test, Update, Watch, // Deploy, Init, Lint, New, Prove, Run, Setup, Test, Update, Watch,
}; };
use leo_errors::Result; use leo_errors::Result;
use snarkvm_utilities::Write; // use snarkvm_utilities::Write;
use std::{path::PathBuf, process::exit}; use std::{path::PathBuf, process::exit};
use structopt::{clap::AppSettings, StructOpt}; use structopt::{clap::AppSettings, StructOpt};

View File

@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::Input;
use leo_errors::{emitter::Handler, Result}; use leo_errors::{emitter::Handler, Result};
use leo_span::symbol::create_session_if_not_set_then; use leo_span::symbol::create_session_if_not_set_then;
@ -28,12 +27,12 @@ fn to_leo_tree(filepath: &Path) -> Result<String> {
// Parses the Leo file constructing an ast which is then serialized. // Parses the Leo file constructing an ast which is then serialized.
create_session_if_not_set_then(|_| { create_session_if_not_set_then(|_| {
let handler = Handler::default(); let handler = Handler::default();
let _ast = leo_parser::parse_program_input( let _ast = leo_parser::parse_program_input(
&handler, &handler,
program_string.clone(), program_string.clone(),
filepath.to_str().unwrap(), filepath.to_str().unwrap(),
program_string, program_string,
filepath.to_str().unwrap() filepath.to_str().unwrap(),
)?; )?;
// Ok(Input::to_json_string(&ast).expect("serialization failed")) // Ok(Input::to_json_string(&ast).expect("serialization failed"))
Ok("aa".to_string()) Ok("aa".to_string())

View File

@ -1,450 +0,0 @@
// 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::{assert_no_whitespace, tokenizer::*, Token, KEYWORD_TOKENS};
use leo_ast::*;
use leo_errors::emitter::Handler;
use leo_errors::{LeoError, ParserError, Result};
use leo_span::{Span, Symbol};
use std::{borrow::Cow, unreachable};
use tendril::format_tendril;
/// Stores a program in tokenized format plus additional context.
/// May be converted into a [`Program`] AST by parsing all tokens.
pub struct ParserContext<'a> {
#[allow(dead_code)]
pub(crate) handler: &'a Handler,
tokens: Vec<SpannedToken>,
end_span: Span,
// true if parsing an expression for an if statement -- means circuit inits are not legal
pub(crate) fuzzy_struct_state: bool,
}
impl Iterator for ParserContext<'_> {
type Item = SpannedToken;
fn next(&mut self) -> Option<SpannedToken> {
self.bump()
}
}
impl<'a> ParserContext<'a> {
///
/// Returns a new [`ParserContext`] type given a vector of tokens.
///
pub fn new(handler: &'a Handler, mut tokens: Vec<SpannedToken>) -> Self {
tokens.reverse();
// todo: performance optimization here: drain filter
tokens = tokens
.into_iter()
.filter(|x| !matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
.collect();
Self {
handler,
end_span: tokens
.iter()
.find(|x| !x.span.content.trim().is_empty())
.map(|x| x.span.clone())
.unwrap_or_default(),
tokens,
fuzzy_struct_state: false,
}
}
/// Returns the current token if there is one.
pub fn peek_option(&self) -> Option<&SpannedToken> {
self.tokens.last()
}
/// Emit the error `err`.
pub(crate) fn emit_err(&self, err: ParserError) {
self.handler.emit_err(err.into());
}
///
/// Returns an unexpected end of function [`SyntaxError`].
///
pub fn eof(&self) -> LeoError {
ParserError::unexpected_eof(&self.end_span).into()
}
///
/// Returns a reference to the next SpannedToken or error if it does not exist.
///
pub fn peek_next(&self) -> Result<&SpannedToken> {
self.tokens.get(self.tokens.len() - 2).ok_or_else(|| self.eof())
}
///
/// Returns a reference to the current SpannedToken or error if it does not exist.
///
pub fn peek(&self) -> Result<&SpannedToken> {
self.tokens.last().ok_or_else(|| self.eof())
}
///
/// Returns a reference to the next Token.
///
pub fn peek_token(&self) -> Cow<'_, Token> {
self.peek_option()
.map(|x| &x.token)
.map(Cow::Borrowed)
.unwrap_or_else(|| Cow::Owned(Token::Eof))
}
///
/// Returns true if the next token exists.
///
pub fn has_next(&self) -> bool {
!self.tokens.is_empty()
}
/// Advances the current token.
pub fn bump(&mut self) -> Option<SpannedToken> {
self.tokens.pop()
}
///
/// Removes the next token if it exists and returns it, or [None] if
/// the next token does not exist.
///
pub fn eat(&mut self, token: Token) -> Option<SpannedToken> {
if let Some(SpannedToken { token: inner, .. }) = self.peek_option() {
if &token == inner {
return self.bump();
}
}
None
}
///
/// Appends a token to the back of the vector.
///
pub fn backtrack(&mut self, token: SpannedToken) {
self.tokens.push(token);
}
///
/// Removes the next token if it is a [`Token::Ident(_)`] and returns it, or [None] if
/// the next token is not a [`Token::Ident(_)`] or if the next token does not exist.
///
pub fn eat_identifier(&mut self) -> Option<Identifier> {
if let Some(SpannedToken {
token: Token::Ident(_), ..
}) = self.peek_option()
{
if let SpannedToken {
token: Token::Ident(name),
span,
} = self.bump().unwrap()
{
return Some(Identifier { name, span });
} else {
unreachable!("eat_identifier_ shouldn't produce this")
}
}
None
}
///
/// Returns a reference to the next token if it is a [`GroupCoordinate`], or [None] if
/// the next token is not a [`GroupCoordinate`].
///
fn peek_group_coordinate(&self, i: &mut usize) -> Option<GroupCoordinate> {
if *i < 1 {
return None;
}
let token = self.tokens.get(*i - 1)?;
*i -= 1;
Some(match &token.token {
Token::Add => GroupCoordinate::SignHigh,
Token::Minus if *i > 0 => match self.tokens.get(*i - 1) {
Some(SpannedToken {
token: Token::Int(value),
span,
}) => {
if *i < 1 {
return None;
}
*i -= 1;
GroupCoordinate::Number(format_tendril!("-{}", value), span.clone())
}
_ => GroupCoordinate::SignLow,
},
Token::Underscore => GroupCoordinate::Inferred,
Token::Int(value) => GroupCoordinate::Number(value.clone(), token.span.clone()),
_ => return None,
})
}
/// Returns `true` if the next token is Function or if it is a Const followed by Function.
/// Returns `false` otherwise.
pub fn peek_is_function(&self) -> Result<bool> {
let first = &self.peek()?.token;
let next = if self.tokens.len() >= 2 {
&self.peek_next()?.token
} else {
return Ok(false);
};
Ok(matches!(
(first, next),
(Token::Function | Token::At, _) | (Token::Const, Token::Function)
))
}
///
/// Removes the next two tokens if they are a pair of [`GroupCoordinate`] and returns them,
/// or [None] if the next token is not a [`GroupCoordinate`].
///
pub fn eat_group_partial(&mut self) -> Option<Result<(GroupCoordinate, GroupCoordinate, Span)>> {
let mut i = self.tokens.len();
if i < 1 {
return None;
}
let start_span = self.tokens.get(i - 1)?.span.clone();
let first = self.peek_group_coordinate(&mut i)?;
if i < 1 {
return None;
}
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::Comma, ..
}) => {
i -= 1;
}
_ => {
return None;
}
}
let second = self.peek_group_coordinate(&mut i)?;
if i < 1 {
return None;
}
let right_paren_span;
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::RightParen,
span,
}) => {
right_paren_span = span.clone();
i -= 1;
}
_ => {
return None;
}
}
if i < 1 {
return None;
}
let end_span;
match self.tokens.get(i - 1) {
Some(SpannedToken {
token: Token::Group,
span,
}) => {
end_span = span.clone();
i -= 1;
}
_ => {
return None;
}
}
self.tokens.drain(i..);
if let Err(e) = assert_no_whitespace(
&right_paren_span,
&end_span,
&format!("({},{})", first, second),
"group",
) {
return Some(Err(e));
}
Some(Ok((first, second, start_span + end_span)))
}
///
/// Removes the next token if it is a [`Token::Int(_)`] and returns it, or [None] if
/// the next token is not a [`Token::Int(_)`] or if the next token does not exist.
///
pub fn eat_int(&mut self) -> Option<(PositiveNumber, Span)> {
if let Some(SpannedToken {
token: Token::Int(_), ..
}) = self.peek_option()
{
if let SpannedToken {
token: Token::Int(value),
span,
} = self.bump().unwrap()
{
return Some((PositiveNumber { value }, span));
} else {
unreachable!("eat_int_ shouldn't produce this")
}
}
None
}
///
/// Removes the next token if it exists and returns it, or [None] if
/// the next token does not exist.
///
pub fn eat_any(&mut self, token: &[Token]) -> Option<SpannedToken> {
if let Some(SpannedToken { token: inner, .. }) = self.peek_option() {
if token.iter().any(|x| x == inner) {
return self.bump();
}
}
None
}
///
/// Returns the span of the next token if it is equal to the given [`Token`], or error.
///
pub fn expect(&mut self, token: Token) -> Result<Span> {
if let Some(SpannedToken { token: inner, span }) = self.peek_option() {
if &token == inner {
Ok(self.bump().unwrap().span)
} else {
Err(ParserError::unexpected(inner, token, span).into())
}
} else {
Err(self.eof())
}
}
///
/// Returns the span of the next token if it is equal to one of the given [`Token`]s, or error.
///
pub fn expect_oneof(&mut self, token: &[Token]) -> Result<SpannedToken> {
if let Some(SpannedToken { token: inner, span }) = self.peek_option() {
if token.iter().any(|x| x == inner) {
Ok(self.bump().unwrap())
} else {
return Err(ParserError::unexpected(
inner,
token.iter().map(|x| format!("'{}'", x)).collect::<Vec<_>>().join(", "),
span,
)
.into());
}
} else {
Err(self.eof())
}
}
///
/// Returns the [`Identifier`] of the next token if it is a keyword,
/// [`Token::Int(_)`], or an [`Identifier`], or error.
///
pub fn expect_loose_identifier(&mut self) -> Result<Identifier> {
if let Some(token) = self.eat_any(KEYWORD_TOKENS) {
return Ok(Identifier {
name: token.token.keyword_to_symbol().unwrap(),
span: token.span,
});
}
if let Some((int, span)) = self.eat_int() {
let name = Symbol::intern(&int.value);
return Ok(Identifier { name, span });
}
self.expect_ident()
}
/// Returns the [`Identifier`] of the next token if it is an [`Identifier`], or error.
pub fn expect_ident(&mut self) -> Result<Identifier> {
if let Some(SpannedToken { token: inner, span }) = self.peek_option() {
if let Token::Ident(_) = inner {
if let SpannedToken {
token: Token::Ident(name),
span,
} = self.bump().unwrap()
{
Ok(Identifier { name, span })
} else {
unreachable!("expect_ident_ shouldn't produce this")
}
} else {
Err(ParserError::unexpected_str(inner, "ident", span).into())
}
} else {
Err(self.eof())
}
}
///
/// Returns the next token if it exists or return end of function.
///
pub fn expect_any(&mut self) -> Result<SpannedToken> {
if let Some(x) = self.tokens.pop() {
Ok(x)
} else {
Err(self.eof())
}
}
/// Parses a list of `T`s using `inner`
/// The opening and closing delimiters are `bra` and `ket`,
/// and elements in the list are separated by `sep`.
/// When `(list, true)` is returned, `sep` was a terminator.
pub(crate) fn parse_list<T>(
&mut self,
open: Token,
close: Token,
sep: Token,
mut inner: impl FnMut(&mut Self) -> Result<Option<T>>,
) -> Result<(Vec<T>, bool, Span)> {
let mut list = Vec::new();
let mut trailing = false;
// Parse opening delimiter.
let open_span = self.expect(open)?;
while self.peek()?.token != close {
// Parse the element. We allow inner parser recovery through the `Option`.
if let Some(elem) = inner(self)? {
list.push(elem);
}
// Parse the separator.
if self.eat(sep.clone()).is_none() {
trailing = false;
break;
}
trailing = true;
}
// Parse closing delimiter.
let close_span = self.expect(close)?;
Ok((list, trailing, open_span + close_span))
}
/// Parse a list separated by `,` and delimited by parens.
pub(crate) fn parse_paren_comma_list<T>(
&mut self,
f: impl FnMut(&mut Self) -> Result<Option<T>>,
) -> Result<(Vec<T>, bool, Span)> {
self.parse_list(Token::LeftParen, Token::RightParen, Token::Comma, f)
}
/// Returns true if the current token is `(`.
pub(crate) fn peek_is_left_par(&self) -> bool {
matches!(self.peek_option().map(|t| &t.token), Some(Token::LeftParen))
}
}

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{assert_no_whitespace, tokenizer::*, Token, KEYWORD_TOKENS}; use crate::{assert_no_whitespace, tokenizer::*, Token};
use leo_ast::*; use leo_ast::*;
use leo_errors::emitter::Handler; use leo_errors::emitter::Handler;
use leo_errors::{LeoError, ParserError, Result}; use leo_errors::{LeoError, ParserError, Result};
use leo_span::{Span, Symbol}; use leo_span::{Span, Symbol};
use std::{borrow::Cow, unreachable}; use std::unreachable;
use tendril::format_tendril; use tendril::format_tendril;
/// Stores a program in tokenized format plus additional context. /// Stores a program in tokenized format plus additional context.
@ -31,8 +31,6 @@ pub struct InputParserContext<'a> {
pub(crate) handler: &'a Handler, pub(crate) handler: &'a Handler,
tokens: Vec<SpannedToken>, tokens: Vec<SpannedToken>,
end_span: Span, end_span: Span,
// true if parsing an expression for an if statement -- means circuit inits are not legal
pub(crate) fuzzy_struct_state: bool,
} }
impl Iterator for InputParserContext<'_> { impl Iterator for InputParserContext<'_> {
@ -62,7 +60,7 @@ impl<'a> InputParserContext<'a> {
.map(|x| x.span.clone()) .map(|x| x.span.clone())
.unwrap_or_default(), .unwrap_or_default(),
tokens, tokens,
fuzzy_struct_state: false, // fuzzy_struct_state: false,
} }
} }
@ -86,9 +84,9 @@ impl<'a> InputParserContext<'a> {
/// ///
/// Returns a reference to the next SpannedToken or error if it does not exist. /// Returns a reference to the next SpannedToken or error if it does not exist.
/// ///
pub fn peek_next(&self) -> Result<&SpannedToken> { // pub fn peek_next(&self) -> Result<&SpannedToken> {
self.tokens.get(self.tokens.len() - 2).ok_or_else(|| self.eof()) // self.tokens.get(self.tokens.len() - 2).ok_or_else(|| self.eof())
} // }
/// ///
/// Returns a reference to the current SpannedToken or error if it does not exist. /// Returns a reference to the current SpannedToken or error if it does not exist.
@ -100,12 +98,12 @@ impl<'a> InputParserContext<'a> {
/// ///
/// Returns a reference to the next Token. /// Returns a reference to the next Token.
/// ///
pub fn peek_token(&self) -> Cow<'_, Token> { // pub fn peek_token(&self) -> Cow<'_, Token> {
self.peek_option() // self.peek_option()
.map(|x| &x.token) // .map(|x| &x.token)
.map(Cow::Borrowed) // .map(Cow::Borrowed)
.unwrap_or_else(|| Cow::Owned(Token::Eof)) // .unwrap_or_else(|| Cow::Owned(Token::Eof))
} // }
/// ///
/// Returns true if the next token exists. /// Returns true if the next token exists.
@ -135,9 +133,9 @@ impl<'a> InputParserContext<'a> {
/// ///
/// Appends a token to the back of the vector. /// Appends a token to the back of the vector.
/// ///
pub fn backtrack(&mut self, token: SpannedToken) { // pub fn backtrack(&mut self, token: SpannedToken) {
self.tokens.push(token); // self.tokens.push(token);
} // }
/// ///
/// Removes the next token if it is a [`Token::Ident(_)`] and returns it, or [None] if /// Removes the next token if it is a [`Token::Ident(_)`] and returns it, or [None] if
@ -194,18 +192,18 @@ impl<'a> InputParserContext<'a> {
/// Returns `true` if the next token is Function or if it is a Const followed by Function. /// Returns `true` if the next token is Function or if it is a Const followed by Function.
/// Returns `false` otherwise. /// Returns `false` otherwise.
pub fn peek_is_function(&self) -> Result<bool> { // pub fn peek_is_function(&self) -> Result<bool> {
let first = &self.peek()?.token; // let first = &self.peek()?.token;
let next = if self.tokens.len() >= 2 { // let next = if self.tokens.len() >= 2 {
&self.peek_next()?.token // &self.peek_next()?.token
} else { // } else {
return Ok(false); // return Ok(false);
}; // };
Ok(matches!( // Ok(matches!(
(first, next), // (first, next),
(Token::Function | Token::At, _) | (Token::Const, Token::Function) // (Token::Function | Token::At, _) | (Token::Const, Token::Function)
)) // ))
} // }
/// ///
/// Removes the next two tokens if they are a pair of [`GroupCoordinate`] and returns them, /// Removes the next two tokens if they are a pair of [`GroupCoordinate`] and returns them,
@ -351,19 +349,19 @@ impl<'a> InputParserContext<'a> {
/// Returns the [`Identifier`] of the next token if it is a keyword, /// Returns the [`Identifier`] of the next token if it is a keyword,
/// [`Token::Int(_)`], or an [`Identifier`], or error. /// [`Token::Int(_)`], or an [`Identifier`], or error.
/// ///
pub fn expect_loose_identifier(&mut self) -> Result<Identifier> { // pub fn expect_loose_identifier(&mut self) -> Result<Identifier> {
if let Some(token) = self.eat_any(KEYWORD_TOKENS) { // if let Some(token) = self.eat_any(KEYWORD_TOKENS) {
return Ok(Identifier { // return Ok(Identifier {
name: token.token.keyword_to_symbol().unwrap(), // name: token.token.keyword_to_symbol().unwrap(),
span: token.span, // span: token.span,
}); // });
} // }
if let Some((int, span)) = self.eat_int() { // if let Some((int, span)) = self.eat_int() {
let name = Symbol::intern(&int.value); // let name = Symbol::intern(&int.value);
return Ok(Identifier { name, span }); // return Ok(Identifier { name, span });
} // }
self.expect_ident() // self.expect_ident()
} // }
/// Returns the [`Identifier`] of the next token if it is an [`Identifier`], or error. /// Returns the [`Identifier`] of the next token if it is an [`Identifier`], or error.
pub fn expect_ident(&mut self) -> Result<Identifier> { pub fn expect_ident(&mut self) -> Result<Identifier> {

View File

@ -15,13 +15,10 @@
// 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 super::*; use super::*;
use crate::KEYWORD_TOKENS; use crate::{SpannedToken, Token};
use leo_errors::{ParserError, Result};
use smallvec::smallvec; use smallvec::smallvec;
use leo_errors::{ParserError, Result};
use leo_span::sym;
use crate::{Token, SpannedToken};
use tendril::format_tendril;
const INT_TYPES: &[Token] = &[ const INT_TYPES: &[Token] = &[
Token::I8, Token::I8,
@ -57,7 +54,6 @@ pub(crate) const TYPE_TOKENS: &[Token] = &[
]; ];
impl InputParserContext<'_> { impl InputParserContext<'_> {
pub fn token_to_int_type(token: Token) -> Option<IntegerType> { pub fn token_to_int_type(token: Token) -> Option<IntegerType> {
Some(match token { Some(match token {
Token::I8 => IntegerType::I8, Token::I8 => IntegerType::I8,
@ -74,27 +70,25 @@ impl InputParserContext<'_> {
}) })
} }
/// /// Returns an [`Input`] struct filled with the data acquired in the file.
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
///
pub fn parse_input(&mut self) -> Result<Input> { pub fn parse_input(&mut self) -> Result<Input> {
let mut values = IndexMap::new();
while self.has_next() { while self.has_next() {
let token = self.peek()?; let token = self.peek()?;
match token.token { match token.token {
Token::LeftSquare => { Token::LeftSquare => {
let (section, definitions) = self.parse_section()?; let (section, definitions) = self.parse_section()?;
println!("Section: {}, Definitions (len): {}", section, definitions.len()); println!("Section: {}, Definitions (len): {}", section, definitions.len());
}, values.insert(section, definitions);
_ => () }
_ => return Err(ParserError::unexpected_token(token.token.clone(), &token.span).into()),
}; };
} }
Ok(Input::new(values))
Ok(Input::new())
} }
/// Parses particular section in the Input file or the State file.
pub fn parse_section(&mut self) -> Result<(Identifier, IndexMap<Identifier, (Type, Expression)>)> { pub fn parse_section(&mut self) -> Result<(Identifier, IndexMap<Identifier, (Type, Expression)>)> {
self.expect(Token::LeftSquare)?; self.expect(Token::LeftSquare)?;
let section = self.expect_ident()?; let section = self.expect_ident()?;
@ -110,8 +104,8 @@ impl InputParserContext<'_> {
break; break;
} }
} }
Ok((section, assignments)) Ok((section, assignments))
} }
pub fn parse_assignment(&mut self) -> Result<(Identifier, (Type, Expression))> { pub fn parse_assignment(&mut self) -> Result<(Identifier, (Type, Expression))> {
@ -125,7 +119,6 @@ impl InputParserContext<'_> {
Ok((var, (type_, value))) Ok((var, (type_, value)))
} }
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type. /// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type.
/// Also returns the span of the parsed token. /// Also returns the span of the parsed token.
pub fn parse_type(&mut self) -> Result<(Type, Span)> { pub fn parse_type(&mut self) -> Result<(Type, Span)> {
@ -246,12 +239,12 @@ impl InputParserContext<'_> {
Token::StringLit(value) => Expression::Value(ValueExpression::String(value, span)), Token::StringLit(value) => Expression::Value(ValueExpression::String(value, span)),
Token::LeftParen => self.parse_tuple_expression(&span)?, Token::LeftParen => self.parse_tuple_expression(&span)?,
Token::LeftSquare => self.parse_array_expression(&span)?, Token::LeftSquare => self.parse_array_expression(&span)?,
Token::Ident(name) => Expression::Identifier(Identifier { name, span }), // Token::Ident(name) => Expression::Identifier(Identifier { name, span }),
Token::Input => Expression::Identifier(Identifier { name: sym::input, span }), // Token::Input => Expression::Identifier(Identifier { name: sym::input, span }),
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier { // t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
name: t.keyword_to_symbol().unwrap(), // name: t.keyword_to_symbol().unwrap(),
span, // span,
}), // }),
token => { token => {
return Err(ParserError::unexpected_str(token, "expression", &span).into()); return Err(ParserError::unexpected_str(token, "expression", &span).into());
} }
@ -337,7 +330,10 @@ impl InputParserContext<'_> {
} }
} }
Ok(Expression::ArrayInline(ArrayInlineExpression { Ok(Expression::ArrayInline(ArrayInlineExpression {
elements: elements.into_iter().map(|expr| SpreadOrExpression::Expression(expr)).collect(), elements: elements
.into_iter()
.map(|expr| SpreadOrExpression::Expression(expr))
.collect(),
span: span + &end_span, span: span + &end_span,
})) }))
} }

View File

@ -21,8 +21,8 @@ pub mod file;
use leo_ast::*; use leo_ast::*;
use leo_errors::emitter::Handler; use leo_errors::emitter::Handler;
use leo_errors::{ParserError, Result}; use leo_errors::Result;
use leo_span::{Span, Symbol}; use leo_span::Span;
use indexmap::IndexMap; use indexmap::IndexMap;

View File

@ -53,8 +53,9 @@ pub fn parse_program_input<T: AsRef<str>, Y: AsRef<str>, T2: AsRef<str>, Y2: AsR
_state_string: T2, _state_string: T2,
_state_path: Y2, _state_path: Y2,
) -> Result<Input> { ) -> Result<Input> {
let input = input_parser::parse(handler, input_path.as_ref(), input_string.as_ref())?;
input_parser::parse(handler, input_path.as_ref(), input_string.as_ref())
Ok(input)
// let input_syntax_tree = LeoInputParser::parse_file(input_string.as_ref()).map_err(|mut e| { // let input_syntax_tree = LeoInputParser::parse_file(input_string.as_ref()).map_err(|mut e| {
// e.set_path( // e.set_path(