Merge pull request #1580 from AleoHQ/migrate-leo-parser

Migrate leo parser
This commit is contained in:
Collin Chin 2022-02-01 14:10:52 -08:00 committed by GitHub
commit 5d3d93efbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
188 changed files with 7894 additions and 6443 deletions

9
Cargo.lock generated
View File

@ -1532,10 +1532,13 @@ dependencies = [
"lazy_static",
"leo-ast",
"leo-errors",
"leo-input",
"leo-span",
"leo-test-framework",
"serde",
"serde_json",
"serde_yaml",
"smallvec",
"tendril",
"tracing",
]
@ -1584,13 +1587,7 @@ dependencies = [
name = "leo-test-framework"
version = "1.5.3"
dependencies = [
"leo-asg",
"leo-ast",
"leo-ast-passes",
"leo-compiler",
"leo-errors",
"leo-imports",
"leo-parser",
"regex",
"serde",
"serde_json",

View File

@ -20,16 +20,22 @@ use leo_span::{sym, Span, Symbol};
use serde::{Deserialize, Serialize};
use std::fmt;
/// An annotation `@name (arguments)?`.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Annotation {
/// The span including `name ( arguments )`.
pub span: Span,
/// The name of the annotation.
pub name: Identifier,
/// Arguments for the annotation, if any.
pub arguments: Vec<Symbol>,
}
/// The set of allowed annotations.
const ALLOWED_ANNOTATIONS: &[Symbol] = &[sym::test];
impl Annotation {
/// Is the annotation valid?
pub fn is_valid_annotation(&self) -> bool {
ALLOWED_ANNOTATIONS.iter().any(|name| self.name.name == *name)
}

View File

@ -67,6 +67,7 @@ impl Deref for ArrayDimensions {
}
impl ArrayDimensions {
/// Returns a single-dimensional array dimension.
pub fn single(dim: Dimension) -> Self {
Self(smallvec![dim])
}

View File

@ -25,6 +25,7 @@ use std::fmt;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct ConstSelfKeyword {
/// Always `const self`.
pub identifier: Identifier,
}

View File

@ -37,7 +37,9 @@ use std::{
/// to reflect the new struct instantiation.
#[derive(Clone)]
pub struct Identifier {
/// The symbol that the user wrote, e.g., `foo`.
pub name: Symbol,
/// A span locating where the identifier occured in the source.
pub span: Span,
}
@ -52,6 +54,7 @@ impl Node for Identifier {
}
impl Identifier {
/// Constructs a new identifier with `name` and a default span.
pub fn new(name: Symbol) -> Self {
Self {
name,
@ -59,7 +62,7 @@ impl Identifier {
}
}
/// Check if the Identifier name matches the other name
/// Check if the Identifier name matches the other name.
pub fn matches(&self, other: &Self) -> bool {
self.name == other.name
}
@ -121,7 +124,7 @@ impl<'de> Deserialize<'de> for Identifier {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct IdentifierVisitor;
impl<'de> Visitor<'de> for IdentifierVisitor {
impl Visitor<'_> for IdentifierVisitor {
type Value = Identifier;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {

View File

@ -24,6 +24,7 @@ use std::fmt;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct RefSelfKeyword {
/// Always `&self`.
pub identifier: Identifier,
}

View File

@ -23,14 +23,14 @@ use tendril::StrTendril;
/// A number string guaranteed to be positive by the pest grammar.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
pub struct PositiveNumber {
/// The string representation of the positive number.
// FIXME(Centril): This should become an `u128`.
#[serde(with = "leo_span::tendril_json")]
pub value: StrTendril,
}
impl PositiveNumber {
///
/// Returns `true` if this number is zero.
///
pub fn is_zero(&self) -> bool {
self.value.as_ref().eq("0")
}

View File

@ -25,6 +25,7 @@ use std::fmt;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct SelfKeyword {
/// Always just `self`.
pub identifier: Identifier,
}

View File

@ -20,10 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// Spread or expression
/// Either a spread expression or a normal expression.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SpreadOrExpression {
/// A spread expression, i.e., `...other_array`.
Spread(Expression),
/// A normal element expression.
Expression(Expression),
}

View File

@ -17,12 +17,18 @@
use super::*;
use crate::accesses::*;
/// An access expressions, extracting a smaller part out of a whole.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum AccessExpression {
/// An `array[index]` expression.
Array(ArrayAccess),
/// An expression accessing a range of an array.
ArrayRange(ArrayRangeAccess),
/// An expression accessing a field in a structure, e.g., `circuit_var.field`.
Member(MemberAccess),
/// Access to a tuple field using its position, e.g., `tuple.1`.
Tuple(TupleAccess),
/// Access to a member constant or a static function of a circuit.
Static(StaticAccess),
}

View File

@ -16,10 +16,18 @@
use super::*;
/// An array initializer expression, e.g., `[42; 5]`.
/// constructing an array of `element` repeated according to `dimensions`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArrayInitExpression {
/// The expression that all elements in the array will evaluate to.
pub element: Box<Expression>,
/// The dimensions of the array.
///
/// This could be a multi-dimensional array,
/// e.g., `[42; (2, 2)]`, giving you a matrix `[[42, 42], [42, 42]]`.
pub dimensions: ArrayDimensions,
/// The span of the entire expression from `[` to `]`.
pub span: Span,
}

View File

@ -16,9 +16,14 @@
use super::*;
/// An expression constructing an array by listing the individual elements inline,
/// for example `[4, 6, 5, 2]`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArrayInlineExpression {
/// A list, where a part can be either an element,
/// or list of elements to construct the array with.
pub elements: Vec<SpreadOrExpression>,
/// The span of the entire expression from `[` to `]`.
pub span: Span,
}

View File

@ -16,33 +16,59 @@
use super::*;
/// A binary operator.
///
/// Precedence is defined in the parser.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOperation {
/// Addition, i.e. `+`.
Add,
/// Subtraction, i.e. `-`.
Sub,
/// Multiplication, i.e. `*`.
Mul,
/// Division, i.e. `/`.
Div,
/// Exponentiation, i.e. `**` in `a ** b`.
Pow,
/// Logical-or, i.e., `||`.
Or,
/// Logical-and, i.e., `&&`.
And,
/// Equality relation, i.e., `==`.
Eq,
/// In-equality relation, i.e. `!=`.
Ne,
/// Greater-or-equal relation, i.e. `>=`.
Ge,
/// Greater-than relation, i.e. `>=`.
Gt,
/// Lesser-or-equal relation, i.e. `<=`.
Le,
/// Lesser-than relation, i.e. `<`.
Lt,
/// Bitwise-or inclusive, i.e., `|`.
BitOr,
/// Bitwise-and, i.e., `&`.
BitAnd,
/// Bitwise-or exclusive, i.e., `^`.
BitXor,
/// Shift-right, i.e `>>`.
Shr,
/// Unsigned shift-right, i.e `>>>`.
ShrSigned,
/// Shift-left, i.e `<<`.
Shl,
/// Modulus or remainder operation, i.e., `%`.
Mod,
}
/// The category a binary operation belongs to.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOperationClass {
/// A numeric one, that is, the result is numeric.
Numeric,
/// A boolean one, meaning the result is of type `bool`.
Boolean,
}
@ -74,6 +100,8 @@ impl AsRef<str> for BinaryOperation {
}
impl BinaryOperation {
/// The class ("category") that the binary operation belongs to.
/// For example, the `+` operator is numeric and `==` results in a boolean value.
pub fn class(&self) -> BinaryOperationClass {
match self {
BinaryOperation::Add
@ -100,11 +128,17 @@ impl BinaryOperation {
}
}
/// A binary expression `left op right` of two operands separated by some operator.
/// For example, `foo + bar`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BinaryExpression {
/// The left operand of the expression.
pub left: Box<Expression>,
/// The right operand of the expression.
pub right: Box<Expression>,
/// The operand defining the meaning of the resulting binary expression.
pub op: BinaryOperation,
/// The span from `left` to `right`.
pub span: Span,
}

View File

@ -16,10 +16,15 @@
use super::*;
/// A function call expression, e.g., `foo(args)` or `Foo::bar(args)`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CallExpression {
/// An expression evaluating to a callable function,
/// either a member of a structure or a free function.
pub function: Box<Expression>, // todo: make this identifier?
/// Expressions for the arguments passed to the functions parameters.
pub arguments: Vec<Expression>,
/// Span of the entire call `function(arguments)`.
pub span: Span,
}

View File

@ -18,10 +18,14 @@ use crate::Type;
use super::*;
/// A cast expression `e as U`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CastExpression {
/// The expression `e` of a type `T` that is being cast to `U`.
pub inner: Box<Expression>,
/// The type `U` to cast `e` to.
pub target_type: Type,
/// Span for the entire expression `e as U` to.
pub span: Span,
}

View File

@ -16,8 +16,10 @@
use super::*;
/// Represents a syntactically invalid expression.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ErrExpression {
/// The span of the invalid expression.
pub span: Span,
}

View File

@ -1,40 +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 super::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FromBitsExpression {
pub named_type: Box<Expression>,
pub arg: Box<Expression>,
pub span: Span,
}
impl fmt::Display for FromBitsExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.from_bits({})", self.named_type, self.arg)
}
}
impl Node for FromBitsExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,40 +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 super::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FromBytesExpression {
pub named_type: Box<Expression>,
pub arg: Box<Expression>,
pub span: Span,
}
impl fmt::Display for FromBytesExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.from_bytes({})", self.named_type, self.arg)
}
}
impl Node for FromBytesExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -46,26 +46,34 @@ pub use cast::*;
mod err;
pub use err::*;
/// Expression that evaluates to a value
/// Expression that evaluates to a value.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Expression {
/// An identifier expression.
Identifier(Identifier),
/// A literal expression.
Value(ValueExpression),
/// A binary expression, e.g., `42 + 24`.
Binary(BinaryExpression),
/// An unary expression.
Unary(UnaryExpression),
/// A ternary conditional expression `cond ? if_expr : else_expr`.
Ternary(TernaryExpression),
/// A cast expression `expr as type`.
Cast(CastExpression),
/// An access expression of some sort, e.g., `array[idx]` or `foo.bar`.
Access(AccessExpression),
/// An array expression where individual elements are listed inline,
/// for example `[4, 6, ...[5, 7], 2]`.
ArrayInline(ArrayInlineExpression),
/// An array-repeat expression, e.g., `[42; 3]` yielding `[42, 42, 42]`.
ArrayInit(ArrayInitExpression),
/// A tuple expression e.g., `(foo, 42, true)`.
TupleInit(TupleInitExpression),
/// An expression constructing a structure like `Foo { bar: 42, baz }`.
CircuitInit(CircuitInitExpression),
/// A call expression like `my_fun(args)`.
Call(CallExpression),
/// An expression of type "error".
/// Will result in a compile error eventually.
Err(ErrExpression),

View File

@ -16,11 +16,16 @@
use super::*;
/// A ternary conditional expression, that is, `condition ? if_true : if_false`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TernaryExpression {
/// The condition determining which branch to pick.
pub condition: Box<Expression>,
/// The branch the expression evaluates to if `condition` evaluates to true.
pub if_true: Box<Expression>,
/// The branch the expression evaluates to if `condition` evaluates to false.
pub if_false: Box<Expression>,
/// The span from `condition` to `if_false`.
pub span: Span,
}

View File

@ -1,39 +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 super::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ToBitsExpression {
pub value: Box<Expression>,
pub span: Span,
}
impl fmt::Display for ToBitsExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.to_bits()", self.value)
}
}
impl Node for ToBitsExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,39 +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 super::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ToBytesExpression {
pub value: Box<Expression>,
pub span: Span,
}
impl fmt::Display for ToBytesExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.to_bytes()", self.value)
}
}
impl Node for ToBytesExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -16,9 +16,13 @@
use super::*;
/// A tuple construction expression, e.g., `(foo, false, 42)`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TupleInitExpression {
/// The elements of the tuple.
/// In the example above, it would be `foo`, `false`, and `42`.
pub elements: Vec<Expression>,
/// The span from `(` to `)`.
pub span: Span,
}

View File

@ -16,10 +16,16 @@
use super::*;
/// A unary operator for a unary expression.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOperation {
/// The logical negation operator, i.e., `!`.
/// For example, it transforms `true` to `false`.
Not,
/// The arithmetic negation operator, i.e., `-`.
Negate,
/// The bitwise negation operator, i.e., `~`.
/// For example, it transforms `1010` to `0101`.
BitNot,
}
@ -33,10 +39,14 @@ impl AsRef<str> for UnaryOperation {
}
}
/// An unary expression applying an operator to an inner expression.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UnaryExpression {
/// The inner expression `op` is applied to.
pub inner: Box<Expression>,
/// The unary operator to apply to `inner`.
pub op: UnaryOperation,
/// The span covering `op inner`.
pub span: Span,
}

View File

@ -19,32 +19,43 @@ use tendril::StrTendril;
use super::*;
use crate::{Char, CharValue};
/// A literal expression.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ValueExpression {
// todo: deserialize values here
/// An address literal, e.g., `aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8`.
Address(
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// A boolean literal, either `true` or `false`.
Boolean(
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// A char literal, e.g., `'a'`, representing a single unicode code point.
Char(CharValue),
/// A field literal, e.g., `42field`.
/// That is, a signed number followed by the keyword `field`.
Field(
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// A group literal, either product or affine.
/// For example, `42group` or `(12, 52)group`.
Group(Box<GroupValue>),
/// A negated non-integer literal, e.g., `-4.2`.
Implicit(
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// An integer literal, e.g., `42`.
Integer(
IntegerType,
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// A string literal, e.g., `"foobar"`.
String(Vec<Char>, #[serde(with = "leo_span::span_json")] Span),
}

View File

@ -22,15 +22,25 @@ use serde::{Deserialize, Serialize};
use std::cell::Cell;
use std::fmt;
/// A function definition.
#[derive(Clone, Serialize, Deserialize)]
pub struct Function {
/// A map of all the annotations from their base names to the whole.
pub annotations: IndexMap<Symbol, Annotation>,
/// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
pub identifier: Identifier,
/// The function's parameters.
pub input: Vec<FunctionInput>,
/// The function returns a constant value.
pub const_: bool,
/// The function return type, if explicitly specified, or `()` if not.
pub output: Option<Type>,
/// Any mapping to the core library.
/// Always `None` when initially parsed.
pub core_mapping: Cell<Option<Symbol>>,
/// The body of the function.
pub block: Block,
/// The entire span of the function definition.
pub span: Span,
}

View File

@ -20,12 +20,18 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A function parameter.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FunctionInputVariable {
/// The name the parameter is accessible as in the function's body.
pub identifier: Identifier,
/// Is it a const parameter?
pub const_: bool,
/// Is it a mutable parameter?
pub mutable: bool,
/// What's the parameter's type?
pub type_: Type,
/// The parameters span from any annotations to its type.
pub span: Span,
}

View File

@ -23,9 +23,13 @@ use std::fmt;
/// Enumerates the possible inputs to a function.
#[derive(Clone, Serialize, Deserialize)]
pub enum FunctionInput {
/// A `self` parameter.
SelfKeyword(SelfKeyword),
/// A `const self` parameter.
ConstSelfKeyword(ConstSelfKeyword),
/// A `&self` parameter.
RefSelfKeyword(RefSelfKeyword),
/// A normal function parameter.
Variable(FunctionInputVariable),
}
@ -81,6 +85,7 @@ impl FunctionInput {
}
}
/// Formats the parameter to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionInput::SelfKeyword(keyword) => write!(f, "{}", keyword),

View File

@ -24,14 +24,19 @@ use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
/// A coordinate in a affine group literal.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GroupCoordinate {
/// A number, e.g., `42`.
Number(
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// A sign high recovery, i.e. `+`.
SignHigh,
/// A sign low recovery, i.e., `-`.
SignLow,
/// Recovery with an inferred value.
Inferred,
}

View File

@ -24,12 +24,15 @@ use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
/// A group literal.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GroupValue {
/// Product group literal, e.g., `42group`.
Single(
#[serde(with = "leo_span::tendril_json")] StrTendril,
#[serde(with = "leo_span::span_json")] Span,
),
/// An affine group literal with (x, y) coordinates.
Tuple(GroupTuple),
}
@ -69,10 +72,14 @@ impl fmt::Display for GroupValue {
}
}
/// An affine group literal, e.g., `(42, 24)group`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct GroupTuple {
/// The left component of the type, e.g., `42` in the case above.
pub x: GroupCoordinate,
/// The right component of the type, e.g., `24` in the case above.
pub y: GroupCoordinate,
/// The span from `(` to `)`.
pub span: Span,
}

View File

@ -23,7 +23,9 @@ use std::fmt;
/// Represents an import statement in a Leo program.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct ImportStatement {
/// The package or packages to import.
pub package_or_packages: PackageOrPackages,
/// The span, excluding the `;`.
pub span: Span,
}

View File

@ -21,10 +21,17 @@ use leo_span::{sym, Span};
use serde::{Deserialize, Serialize};
use std::fmt;
/// An import of `symbol` possibly renamed to `alias`,
/// e.g., `symbol` or `symbol as alias`.
///
/// This is the leaf of an import tree.
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ImportSymbol {
pub symbol: Identifier,
/// The name, if any, to import `symbol` as.
/// If not specified, `symbol` is the name it is imported under.
pub alias: Option<Identifier>,
/// The span including `symbol` and possibly `as alias`.
pub span: Span,
}
@ -50,6 +57,7 @@ impl fmt::Debug for ImportSymbol {
}
impl ImportSymbol {
/// Creates a glob `*` import.
pub fn star(span: &Span) -> Self {
Self {
symbol: Identifier {
@ -61,6 +69,7 @@ impl ImportSymbol {
}
}
/// Is this a glob import?
pub fn is_star(&self) -> bool {
self.symbol.name == sym::Star
}

View File

@ -20,14 +20,19 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A package import specification.
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct Package {
/// The base package to import `access` from.
pub name: Identifier,
/// A specification of what to import from `name`.
pub access: PackageAccess,
/// The span including the `name` and the `access`.
pub span: Span,
}
impl Package {
/// Formats `self` to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.name, self.access)
}

View File

@ -22,9 +22,19 @@ use std::fmt;
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum PackageAccess {
Star { span: Span },
/// A glob import `*`.
Star {
/// The span for the `*`.
span: Span,
},
/// A subpackage to import.
SubPackage(Box<Package>),
/// A leaf package to import.
Symbol(ImportSymbol),
/// Several subpackages to import.
// FIXME(Centril): This structure seems convoluted and unclear.
// Refactor and simplify the types to:
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.UseTree.html.
Multiple(Packages),
}
@ -49,6 +59,7 @@ impl Node for PackageAccess {
}
impl PackageAccess {
/// Formats `self` to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PackageAccess::Star { .. } => write!(f, "*"),

View File

@ -20,13 +20,17 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A specification of what packages to import.
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum PackageOrPackages {
/// Instruction to import a single package or item.
Package(Package),
/// Instruction to import a packages or items with a common prefix.
Packages(Packages),
}
impl PackageOrPackages {
/// Formats `self` to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PackageOrPackages::Package(ref package) => write!(f, "{}", package),

View File

@ -20,14 +20,19 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// Import of `name.(accesses)`, that is, several sub-packages or items within `name`.
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct Packages {
/// The common package that `accesses` are contained within.
pub name: Identifier,
/// The packages or items to import within the package `name`.
pub accesses: Vec<PackageAccess>,
/// The entire span for `name.(accesses)`.
pub span: Span,
}
impl Packages {
/// Formats `self` to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.(", self.name)?;
for (i, access) in self.accesses.iter().enumerate() {

View File

@ -16,10 +16,13 @@
use leo_span::Span;
/// A node in the AST.
pub trait Node:
std::fmt::Debug + std::fmt::Display + Clone + PartialEq + Eq + serde::Serialize + serde::de::DeserializeOwned
{
/// Returns the span of the node.
fn span(&self) -> &Span;
/// Sets the span of the node.
fn set_span(&mut self, span: Span);
}

View File

@ -17,6 +17,7 @@
use crate::{Ast, Program};
use leo_errors::Result;
/// A pass consuming a `Program` and possibly returning an `Ast`.
pub trait AstPass {
fn do_pass(self, ast: Program) -> Result<Ast>;
}

View File

@ -28,15 +28,25 @@ use std::fmt;
/// Stores the Leo program abstract syntax tree.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Program {
/// The name of the program.
/// Empty after parsing.
pub name: String,
/// Expected main function inputs.
/// Empty after parsing.
pub expected_input: Vec<FunctionInput>,
/// The collected import statements.
pub import_statements: Vec<ImportStatement>,
#[serde(with = "crate::common::imported_modules")]
/// A map from paths to injected programs.
pub imports: IndexMap<Vec<Symbol>, Program>,
/// A map from alias names to type aliases.
pub aliases: IndexMap<Identifier, Alias>,
/// A map from circuit names to circuit definitions.
pub circuits: IndexMap<Identifier, Circuit>,
/// A map from constant names to their definitions.
#[serde(with = "crate::common::global_consts_json")]
pub global_consts: IndexMap<Vec<Identifier>, DefinitionStatement>,
/// A map from function names to their definitions.
pub functions: IndexMap<Identifier, Function>,
}
@ -77,6 +87,7 @@ impl fmt::Display for Program {
}
impl Program {
/// Constructs an empty program with `name`.
pub fn new(name: String) -> Self {
Self {
name,
@ -90,6 +101,7 @@ impl Program {
}
}
/// Handles all internal annotations like `@CoreFunction` and `@AlwaysConst`.
pub fn handle_internal_annotations(&mut self) {
self.circuits
.iter_mut()
@ -121,10 +133,12 @@ impl Program {
});
}
/// Extract the name of the program.
pub fn get_name(&self) -> String {
self.name.to_string()
}
/// Sets the name of the program.
pub fn name(mut self, name: String) -> Self {
self.name = name;
self

View File

@ -21,24 +21,31 @@ use serde::{Deserialize, Serialize};
use std::fmt;
#[allow(clippy::large_enum_variant)]
/// A sub-place in a variable to assign to.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum AssigneeAccess {
/// Assignment to a range in an array.
ArrayRange(Option<Expression>, Option<Expression>),
/// Assignment to an element of an array identified by its index.
ArrayIndex(Expression),
/// Assignment to a tuple field by its position, e.g., `2`.
Tuple(PositiveNumber, #[serde(with = "leo_span::span_json")] Span),
/// Assignment to a field in a structure.
Member(Identifier),
}
/// Definition assignee: v, arr[0..2], Point p.x
/// Definition assignee, e.g., `v`, `arr[0..2]`, `p.x`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Assignee {
/// The base variable to assign to.
pub identifier: Identifier,
/// Sub-places within `identifier` to assign to, if any.
pub accesses: Vec<AssigneeAccess>,
pub span: Span,
}
impl Assignee {
/// Returns the name of the variable being assigned to
/// Returns the name of the variable being assigned to.
pub fn identifier(&self) -> &Identifier {
&self.identifier
}

View File

@ -24,22 +24,38 @@ use std::fmt;
mod assignee;
pub use assignee::*;
/// The assignment operator.
#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum AssignOperation {
/// Plain assignment, `=`.
Assign,
/// Adding assignment, `+=`.
Add,
/// Subtracting assignment, `-=`.
Sub,
/// Multiplying assignment, `*=`.
Mul,
/// Dividing-assignment, `/=`.
Div,
/// Exponentiating assignment `**=`.
Pow,
/// Logical or assignment.
Or,
/// Logical and assignment.
And,
/// Bitwise or assignment.
BitOr,
/// Bitwise and assignment.
BitAnd,
/// Bitwise xor assignment.
BitXor,
/// Shift right assignment.
Shr,
/// Signed shift right assignment.
ShrSigned,
/// Shift left assignment.
Shl,
/// Modulus / remainder assignment.
Mod,
}
@ -65,11 +81,17 @@ impl AsRef<str> for AssignOperation {
}
}
/// An assignment statement, `assignee operation? = value`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct AssignStatement {
/// The assignment operation.
/// For plain assignment, use `AssignOperation::Assign`.
pub operation: AssignOperation,
/// The place to assign to.
pub assignee: Assignee,
/// The value to assign to the `assignee`.
pub value: Expression,
/// The span, excluding the semicolon.
pub span: Span,
}

View File

@ -20,9 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A block `{ [stmt]* }` consisting of a list of statements to execute in order.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct Block {
/// The list of statements to execute.
pub statements: Vec<Statement>,
/// The span from `{` to `}`.
pub span: Span,
}

View File

@ -20,11 +20,16 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// An `if condition block (else next)?` statement.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ConditionalStatement {
/// The `bool`-typed condition deciding what to evaluate.
pub condition: Expression,
/// The block to evaluate in case `condition` yields `true`.
pub block: Block,
/// The statement, if any, to evaluate when `condition` yields `false`.
pub next: Option<Box<Statement>>,
/// The span from `if` to `next` or to `block`.
pub span: Span,
}

View File

@ -20,10 +20,14 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// The arguments `args` passed to `console.log(args)` or `console.error(args)`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ConsoleArgs {
/// The formatting string with `parameters` interpolated into it.
pub string: Vec<Char>,
/// Parameters to interpolate in `string`.
pub parameters: Vec<Expression>,
/// The span from `(` to `)`.
pub span: Span,
}

View File

@ -20,10 +20,17 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A console logging function to invoke.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum ConsoleFunction {
/// A `console.assert(expr)` call to invoke,
/// asserting that the expression evaluates to `true`.
Assert(Expression),
/// A `console.error(args)` call to invoke,
/// resulting in an error at runtime.
Error(ConsoleArgs),
/// A `console.log(args)` call to invoke,
/// resulting in a log message at runtime.
Log(ConsoleArgs),
}

View File

@ -20,9 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A console logging statement like `console.log(...);`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ConsoleStatement {
/// The logging function to run.
pub function: ConsoleFunction,
/// The span excluding the semicolon.
pub span: Span,
}

View File

@ -17,9 +17,12 @@
use serde::{Deserialize, Serialize};
use std::fmt;
/// The sort of bindings to introduce, either `let` or `const`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Declare {
/// This is a `const` binding.
Const,
/// This is a `let` binding.
Let,
}

View File

@ -26,12 +26,18 @@ pub use variable_name::*;
mod declare;
pub use declare::*;
/// A `let` or `const` declaration statement.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct DefinitionStatement {
/// What sort of declaration is this? `let` or `const`?.
pub declaration_type: Declare,
/// The bindings / variable names to declare.
pub variable_names: Vec<VariableName>,
/// The types of the bindings, if specified, or inferred otherwise.
pub type_: Option<Type>,
/// An initializer value for the bindings.
pub value: Expression,
/// The span excluding the semicolon.
pub span: Span,
}

View File

@ -20,9 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// An expression statement `expr;`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ExpressionStatement {
/// The expression to evaluate purely for its side-effects.
pub expression: Expression,
/// The span excluding the semicolon.
pub span: Span,
}

View File

@ -20,13 +20,21 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A bounded `for` loop statement `for variable in start .. =? stop block`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct IterationStatement {
/// The binding / variable to introduce in the body `block`.
pub variable: Identifier,
/// The start of the iteration.
pub start: Expression,
/// The end of the iteration, possibly `inclusive`.
pub stop: Expression,
/// Whether `stop` is inclusive or not.
/// Signified with `=` when parsing.
pub inclusive: bool,
/// The block to run on each iteration.
pub block: Block,
/// The span from `for` to `block`.
pub span: Span,
}

View File

@ -20,9 +20,12 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A return statement `return expression;`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ReturnStatement {
/// The expression to return to the function caller.
pub expression: Expression,
/// The span of `return expression` excluding the semicolon.
pub span: Span,
}

View File

@ -24,13 +24,22 @@ use std::fmt;
/// Program statement that defines some action (or expression) to be carried out.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub enum Statement {
/// A return statement `return expr;`.
Return(ReturnStatement),
/// A binding or set of bindings / variables to declare.
Definition(DefinitionStatement),
/// An assignment statement.
Assign(Box<AssignStatement>),
/// An `if` statement.
Conditional(ConditionalStatement),
/// A `for` statement.
Iteration(Box<IterationStatement>),
/// A console logging statement.
Console(ConsoleStatement),
/// An expression statement turning an expression into a statement,
/// using the expression only for its side-effects.
Expression(ExpressionStatement),
/// A block statement.
Block(Block),
}

View File

@ -40,11 +40,13 @@ pub enum IntegerType {
}
impl IntegerType {
/// Is the integer type a signed one?
pub fn is_signed(&self) -> bool {
use IntegerType::*;
matches!(self, I8 | I16 | I32 | I64 | I128)
}
/// Returns the symbol for the integer type.
pub fn symbol(self) -> Symbol {
match self {
Self::I8 => sym::i8,

View File

@ -26,17 +26,30 @@ use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Type {
// Data types
/// The `address` type.
Address,
/// The `bool` type.
Boolean,
/// The `char` type.
Char,
/// The `field` type.
Field,
/// The `group` type.
Group,
/// An integer type.
IntegerType(IntegerType),
// Data type wrappers
/// An array type `[element; dimensions]`.
Array(Box<Type>, ArrayDimensions),
/// A tuple type `(T_0, T_1, ...)` made up of a list of types.
Tuple(Vec<Type>),
Identifier(Identifier), // ex Circuit or Alias
/// A reference to either a nominal type (e.g., a `circuit`) or a type alias.
Identifier(Identifier),
/// The `Self` type, allowed within `circuit` definitions.
SelfType,
/// Placeholder for a type that could not be resolved or was not well-formed.

View File

@ -16,13 +16,16 @@ categories = [ "cryptography::cryptocurrencies", "web-programming" ]
include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
license = "GPL-3.0"
edition = "2021"
rust-version = "1.56.1"
rust-version = "1.56"
[[bench]]
name = "leo_ast"
path = "benches/leo_ast.rs"
harness = false
[dependencies]
smallvec = "1.8"
[dependencies.leo-ast]
path = "../ast"
version = "1.5.3"
@ -31,6 +34,14 @@ version = "1.5.3"
path = "../errors"
version = "1.5.3"
[dependencies.leo-input]
path = "../input"
version = "1.5.1"
[dependencies.leo-span]
path = "../span"
version = "1.5.3"
[dependencies.indexmap]
version = "1.8"

View File

@ -30,7 +30,8 @@ Bolded ones are also keywords.
#### Symbols
- At
- Not
- And
- And (`&&`)
- Ampersand (`&`)
- Or
- Eq
- NotEq
@ -98,7 +99,6 @@ Bolded ones are also keywords.
- **If**
- **In**
- **Let**
- **Mut**
- **Return**
- **Static**
- **String**

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -14,55 +14,51 @@
// 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 leo_ast::Ast;
use leo_errors::emitter::Handler;
use leo_span::symbol::create_session_if_not_set_then;
use criterion::{criterion_group, criterion_main, Criterion};
use std::time::Duration;
fn bench_big_if_else(c: &mut Criterion) {
let program_string = include_str!("./big_if_else.leo");
let ast = leo_parser::parse_ast("./big_if_else.leo", program_string).expect("failed to parse benchmark");
fn parse_ast(path: &str, input: &str) -> Ast {
create_session_if_not_set_then(|_| {
leo_parser::parse_ast(&Handler::default(), path, input).expect("failed to parse benchmark")
})
}
fn bench_big_if_else(c: &mut Criterion) {
let ast = parse_ast("./big_if_else.leo", include_str!("./big_if_else.leo"));
c.bench_function("Ast::big_if_else", |b| b.iter(|| &ast));
}
fn bench_big_ternary(c: &mut Criterion) {
let program_string = include_str!("./big_ternary.leo");
let ast = leo_parser::parse_ast("./big_ternary.leo", program_string).expect("failed to parse benchmark");
let ast = parse_ast("./big_ternary.leo", include_str!("./big_ternary.leo"));
c.bench_function("Ast::big_ternary", |b| b.iter(|| &ast));
}
fn bench_big_circuit(c: &mut Criterion) {
let program_string = include_str!("./big_circuit.leo");
let ast = leo_parser::parse_ast("./big_circuit.leo", program_string).expect("failed to parse benchmark");
let ast = parse_ast("./big_circuit.leo", include_str!("./big_circuit.leo"));
c.bench_function("Ast::big_circuit", |b| b.iter(|| &ast));
}
fn bench_long_expr(c: &mut Criterion) {
let program_string = include_str!("./long_expr.leo");
let ast = leo_parser::parse_ast("./long_expr.leo", program_string).expect("failed to parse benchmark");
let ast = parse_ast("./long_expr.leo", include_str!("./long_expr.leo"));
c.bench_function("Ast::long_expr", |b| b.iter(|| &ast));
}
fn bench_long_array(c: &mut Criterion) {
let program_string = include_str!("./long_array.leo");
let ast = leo_parser::parse_ast("./long_array.leo", program_string).expect("failed to parse benchmark");
let ast = parse_ast("./long_array.leo", include_str!("./long_array.leo"));
c.bench_function("Ast::long_array", |b| b.iter(|| &ast));
}
fn bench_many_foos(c: &mut Criterion) {
let program_string = include_str!("./many_foos.leo");
let ast = leo_parser::parse_ast("./many_foos.leo", program_string).expect("failed to parse benchmark");
let ast = parse_ast("./many_foos.leo", include_str!("./many_foos.leo"));
c.bench_function("Ast::many_foos", |b| b.iter(|| &ast));
}
fn bench_many_assigns(c: &mut Criterion) {
let program_string = include_str!("./many_assigns.leo");
let ast = leo_parser::parse_ast("./many_assigns.leo", program_string).expect("failed to parse benchmark");
let ast = parse_ast("./many_assigns.leo", include_str!("./many_assigns.leo"));
c.bench_function("Ast::many_assigns", |b| b.iter(|| &ast));
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -15,7 +15,9 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::Ast;
use leo_errors::Result;
use leo_errors::{emitter::Handler, Result};
use leo_span::symbol::create_session_if_not_set_then;
use std::{env, fs, path::Path};
fn to_leo_tree(filepath: &Path) -> Result<String> {
@ -23,12 +25,12 @@ fn to_leo_tree(filepath: &Path) -> Result<String> {
let program_filepath = filepath.to_path_buf();
let program_string = fs::read_to_string(&program_filepath).expect("failed to open input file");
// Parses the Leo file and constructs an ast.
let ast = leo_parser::parse_ast(filepath.to_str().unwrap(), &program_string)?;
let serialized_leo_ast = Ast::to_json_string(&ast).expect("serialization failed");
Ok(serialized_leo_ast)
// Parses the Leo file constructing an ast which is then serialized.
create_session_if_not_set_then(|_| {
let handler = Handler::default();
let ast = leo_parser::parse_ast(&handler, filepath.to_str().unwrap(), &program_string)?;
Ok(Ast::to_json_string(&ast).expect("serialization failed"))
})
}
fn main() -> Result<()> {

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -23,19 +23,82 @@
#![doc = include_str!("../README.md")]
pub(crate) mod tokenizer;
use leo_input::LeoInputParser;
pub use tokenizer::KEYWORD_TOKENS;
pub(crate) use tokenizer::*;
pub mod parser;
pub use parser::*;
use leo_ast::Ast;
use leo_ast::{Ast, Input};
use leo_errors::emitter::Handler;
use leo_errors::Result;
#[cfg(test)]
mod test;
/// Creates a new AST from a given file path and source code text.
pub fn parse_ast<T: AsRef<str>, Y: AsRef<str>>(path: T, source: Y) -> Result<Ast> {
Ok(Ast::new(parser::parse(path.as_ref(), source.as_ref())?))
pub fn parse_ast<T: AsRef<str>, Y: AsRef<str>>(handler: &Handler, path: T, source: Y) -> Result<Ast> {
Ok(Ast::new(parser::parse(handler, path.as_ref(), source.as_ref())?))
}
/// Parses program input from from the input file path and state file path
pub fn parse_program_input<T: AsRef<str>, Y: AsRef<str>, T2: AsRef<str>, Y2: AsRef<str>>(
input_string: T,
input_path: Y,
state_string: T2,
state_path: Y2,
) -> Result<Input> {
let input_syntax_tree = LeoInputParser::parse_file(input_string.as_ref()).map_err(|mut e| {
e.set_path(
input_path.as_ref(),
&input_string
.as_ref()
.lines()
.map(|x| x.to_string())
.collect::<Vec<String>>()[..],
);
e
})?;
let state_syntax_tree = LeoInputParser::parse_file(state_string.as_ref()).map_err(|mut e| {
e.set_path(
state_path.as_ref(),
&state_string
.as_ref()
.lines()
.map(|x| x.to_string())
.collect::<Vec<String>>()[..],
);
e
})?;
let mut input = Input::new();
input.parse_input(input_syntax_tree).map_err(|mut e| {
e.set_path(
input_path.as_ref(),
&input_string
.as_ref()
.lines()
.map(|x| x.to_string())
.collect::<Vec<String>>()[..],
);
e
})?;
input.parse_state(state_syntax_tree).map_err(|mut e| {
e.set_path(
state_path.as_ref(),
&state_string
.as_ref()
.lines()
.map(|x| x.to_string())
.collect::<Vec<String>>()[..],
);
e
})?;
Ok(input)
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -14,42 +14,48 @@
// 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 std::{borrow::Cow, unimplemented};
use crate::{assert_no_whitespace, tokenizer::*, Token, KEYWORD_TOKENS};
use leo_ast::*;
use leo_errors::{LeoError, ParserError, Result, Span};
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 {
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 {
impl Iterator for ParserContext<'_> {
type Item = SpannedToken;
fn next(&mut self) -> Option<SpannedToken> {
self.tokens.pop()
self.bump()
}
}
impl ParserContext {
impl<'a> ParserContext<'a> {
///
/// Returns a new [`ParserContext`] type given a vector of tokens.
///
pub fn new(mut tokens: Vec<SpannedToken>) -> Self {
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();
ParserContext {
Self {
handler,
end_span: tokens
.iter()
.find(|x| !x.span.content.trim().is_empty())
@ -60,6 +66,16 @@ impl ParserContext {
}
}
/// 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`].
///
@ -68,43 +84,29 @@ impl ParserContext {
}
///
/// Returns a reference to the next next token 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> {
self.tokens.get(self.tokens.len() - 2).ok_or_else(|| self.eof())
}
///
/// Returns a reference to the next token or error if it does not exist.
/// 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.tokens
.last()
self.peek_option()
.map(|x| &x.token)
.map(Cow::Borrowed)
.unwrap_or_else(|| Cow::Owned(Token::Eof))
}
// pub fn peek_oneof(&self, token: &[Token]) -> Result<&SpannedToken> {
// if let Some(spanned_token) = self.inner.last() {
// if token.iter().any(|x| x == &spanned_token.token) {
// Ok(spanned_token)
// } else {
// Err(SyntaxError::unexpected(
// &spanned_token.token,
// token,
// &spanned_token.span,
// ))
// }
// } else {
// Err(self.eof())
// }
// }
///
/// Returns true if the next token exists.
///
@ -112,14 +114,19 @@ impl ParserContext {
!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.tokens.last() {
if let Some(SpannedToken { token: inner, .. }) = self.peek_option() {
if &token == inner {
return self.tokens.pop();
return self.bump();
}
}
None
@ -139,17 +146,16 @@ impl ParserContext {
pub fn eat_identifier(&mut self) -> Option<Identifier> {
if let Some(SpannedToken {
token: Token::Ident(_), ..
}) = self.tokens.last()
}) = self.peek_option()
{
let token = self.tokens.pop().unwrap();
if let SpannedToken {
token: Token::Ident(name),
span,
} = token
} = self.bump().unwrap()
{
return Some(Identifier { name, span });
} else {
unimplemented!()
unreachable!("eat_identifier_ shouldn't produce this")
}
}
None
@ -186,6 +192,21 @@ impl ParserContext {
})
}
/// 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`].
@ -263,17 +284,16 @@ impl ParserContext {
pub fn eat_int(&mut self) -> Option<(PositiveNumber, Span)> {
if let Some(SpannedToken {
token: Token::Int(_), ..
}) = self.tokens.last()
}) = self.peek_option()
{
let token = self.tokens.pop().unwrap();
if let SpannedToken {
token: Token::Int(value),
span,
} = token
} = self.bump().unwrap()
{
return Some((PositiveNumber { value }, span));
} else {
unimplemented!()
unreachable!("eat_int_ shouldn't produce this")
}
}
None
@ -284,9 +304,9 @@ impl ParserContext {
/// the next token does not exist.
///
pub fn eat_any(&mut self, token: &[Token]) -> Option<SpannedToken> {
if let Some(SpannedToken { token: inner, .. }) = self.tokens.last() {
if let Some(SpannedToken { token: inner, .. }) = self.peek_option() {
if token.iter().any(|x| x == inner) {
return self.tokens.pop();
return self.bump();
}
}
None
@ -296,9 +316,9 @@ impl ParserContext {
/// 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.tokens.last() {
if let Some(SpannedToken { token: inner, span }) = self.peek_option() {
if &token == inner {
Ok(self.tokens.pop().unwrap().span)
Ok(self.bump().unwrap().span)
} else {
Err(ParserError::unexpected(inner, token, span).into())
}
@ -311,9 +331,9 @@ impl ParserContext {
/// 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.tokens.last() {
if let Some(SpannedToken { token: inner, span }) = self.peek_option() {
if token.iter().any(|x| x == inner) {
Ok(self.tokens.pop().unwrap())
Ok(self.bump().unwrap())
} else {
return Err(ParserError::unexpected(
inner,
@ -334,31 +354,29 @@ impl ParserContext {
pub fn expect_loose_identifier(&mut self) -> Result<Identifier> {
if let Some(token) = self.eat_any(KEYWORD_TOKENS) {
return Ok(Identifier {
name: token.token.to_string().into(),
name: token.token.keyword_to_symbol().unwrap(),
span: token.span,
});
}
if let Some((int, span)) = self.eat_int() {
return Ok(Identifier { name: int.value, span });
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.tokens.last() {
if let Some(SpannedToken { token: inner, span }) = self.peek_option() {
if let Token::Ident(_) = inner {
let token = self.tokens.pop().unwrap();
if let SpannedToken {
token: Token::Ident(name),
span,
} = token
} = self.bump().unwrap()
{
Ok(Identifier { name, span })
} else {
unimplemented!()
unreachable!("expect_ident_ shouldn't produce this")
}
} else {
Err(ParserError::unexpected_str(inner, "ident", span).into())
@ -378,4 +396,53 @@ impl ParserContext {
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(super) 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;
}
}
// 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(super) 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(super) fn peek_is_left_par(&self) -> bool {
matches!(self.peek_option().map(|t| &t.token), Some(Token::LeftParen))
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -14,11 +14,12 @@
// 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 tendril::format_tendril;
use super::*;
use leo_errors::{ParserError, Result};
use leo_span::sym;
use super::*;
use tendril::format_tendril;
const INT_TYPES: &[Token] = &[
Token::I8,
@ -35,7 +36,7 @@ const INT_TYPES: &[Token] = &[
Token::Group,
];
impl ParserContext {
impl ParserContext<'_> {
///
/// Returns an [`Expression`] AST node if the next token is an expression.
/// Includes circuit init expressions.
@ -81,252 +82,134 @@ impl ParserContext {
Ok(expr)
}
///
/// Constructs a binary expression `left op right`.
fn bin_expr(left: Expression, right: Expression, op: BinaryOperation) -> Expression {
Expression::Binary(BinaryExpression {
span: left.span() + right.span(),
op,
left: Box::new(left),
right: Box::new(right),
})
}
/// Parses a left-associative binary expression `<left> token <right>` using `f` for left/right.
/// The `token` is translated to `op` in the AST.
fn parse_bin_expr(
&mut self,
token: Token,
op: BinaryOperation,
mut f: impl FnMut(&mut Self) -> Result<Expression>,
) -> Result<Expression> {
let mut expr = f(self)?;
while self.eat(token.clone()).is_some() {
expr = Self::bin_expr(expr, f(self)?, op);
}
Ok(expr)
}
/// Returns an [`Expression`] AST node if the next tokens represent
/// a binary or expression.
///
/// Otherwise, tries to parse the next token using [`parse_conjunctive_expression`].
///
pub fn parse_disjunctive_expression(&mut self) -> Result<Expression> {
let mut expr = self.parse_conjunctive_expression()?;
while self.eat(Token::Or).is_some() {
let right = self.parse_conjunctive_expression()?;
expr = Expression::Binary(BinaryExpression {
span: expr.span() + right.span(),
op: BinaryOperation::Or,
left: Box::new(expr),
right: Box::new(right),
})
}
Ok(expr)
self.parse_bin_expr(Token::Or, BinaryOperation::Or, Self::parse_conjunctive_expression)
}
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary and expression.
///
/// Otherwise, tries to parse the next token using [`parse_bit_or_expression`].
///
/// Otherwise, tries to parse the next token using [`parse_equality_expression`].
pub fn parse_conjunctive_expression(&mut self) -> Result<Expression> {
let mut expr = self.parse_equality_expression()?;
while self.eat(Token::And).is_some() {
let right = self.parse_equality_expression()?;
expr = Expression::Binary(BinaryExpression {
span: expr.span() + right.span(),
op: BinaryOperation::And,
left: Box::new(expr),
right: Box::new(right),
})
}
Ok(expr)
self.parse_bin_expr(Token::And, BinaryOperation::And, Self::parse_equality_expression)
}
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary bitwise or expression.
///
/// Otherwise, tries to parse the next token using [`parse_bit_xor_expression`].
///
// pub fn parse_bit_or_expression(&mut self) -> Result<Expression> {
// let mut expr = self.parse_bit_xor_expression()?;
// while self.eat(Token::BitOr).is_some() {
// let right = self.parse_bit_xor_expression()?;
// expr = Expression::Binary(BinaryExpression {
// span: expr.span() + right.span(),
// op: BinaryOperation::BitOr,
// left: Box::new(expr),
// right: Box::new(right),
// })
// }
// Ok(expr)
// }
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary bitwise xor expression.
///
/// Otherwise, tries to parse the next token using [`parse_bit_and_expression`].
///
// pub fn parse_bit_xor_expression(&mut self) -> Result<Expression> {
// let mut expr = self.parse_bit_and_expression()?;
// while self.eat(Token::BitXor).is_some() {
// let right = self.parse_bit_and_expression()?;
// expr = Expression::Binary(BinaryExpression {
// span: expr.span() + right.span(),
// op: BinaryOperation::BitXor,
// left: Box::new(expr),
// right: Box::new(right),
// })
// }
// Ok(expr)
// }
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary bitwise and expression.
///
/// Otherwise, tries to parse the next token using [`parse_equality_expression`].
///
// pub fn parse_bit_and_expression(&mut self) -> Result<Expression> {
// let mut expr = self.parse_equality_expression()?;
// while self.eat(Token::BitAnd).is_some() {
// let right = self.parse_equality_expression()?;
// expr = Expression::Binary(BinaryExpression {
// span: expr.span() + right.span(),
// op: BinaryOperation::BitAnd,
// left: Box::new(expr),
// right: Box::new(right),
// })
// }
// Ok(expr)
// }
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary equals or not equals expression.
///
/// Otherwise, tries to parse the next token using [`parse_ordering_expression`].
///
pub fn parse_equality_expression(&mut self) -> Result<Expression> {
let mut expr = self.parse_ordering_expression()?;
if let Some(SpannedToken { token: op, .. }) = self.eat_any(&[Token::Eq, Token::NotEq]) {
let right = self.parse_ordering_expression()?;
expr = Expression::Binary(BinaryExpression {
span: expr.span() + right.span(),
op: match op {
Token::Eq => BinaryOperation::Eq,
Token::NotEq => BinaryOperation::Ne,
_ => unimplemented!(),
},
left: Box::new(expr),
right: Box::new(right),
})
let op = match op {
Token::Eq => BinaryOperation::Eq,
Token::NotEq => BinaryOperation::Ne,
_ => unreachable!("parse_equality_expression_ shouldn't produce this"),
};
expr = Self::bin_expr(expr, right, op);
}
Ok(expr)
}
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary relational expression: less than, less than or equals, greater than, greater than or equals.
///
/// Otherwise, tries to parse the next token using [`parse_shift_expression`].
///
pub fn parse_ordering_expression(&mut self) -> Result<Expression> {
let mut expr = self.parse_additive_expression()?;
while let Some(SpannedToken { token: op, .. }) = self.eat_any(&[Token::Lt, Token::LtEq, Token::Gt, Token::GtEq])
{
let right = self.parse_additive_expression()?;
expr = Expression::Binary(BinaryExpression {
span: expr.span() + right.span(),
op: match op {
Token::Lt => BinaryOperation::Lt,
Token::LtEq => BinaryOperation::Le,
Token::Gt => BinaryOperation::Gt,
Token::GtEq => BinaryOperation::Ge,
_ => unimplemented!(),
},
left: Box::new(expr),
right: Box::new(right),
})
let op = match op {
Token::Lt => BinaryOperation::Lt,
Token::LtEq => BinaryOperation::Le,
Token::Gt => BinaryOperation::Gt,
Token::GtEq => BinaryOperation::Ge,
_ => unreachable!("parse_ordering_expression_ shouldn't produce this"),
};
expr = Self::bin_expr(expr, right, op);
}
Ok(expr)
}
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary shift expression.
///
/// Otherwise, tries to parse the next token using [`parse_additive_expression`].
///
// pub fn parse_shift_expression(&mut self) -> Result<Expression> {
// let mut expr = self.parse_additive_expression()?;
// while let Some(SpannedToken { token: op, .. }) = self.eat_any(&[Token::Shl, Token::Shr, Token::ShrSigned]) {
// let right = self.parse_additive_expression()?;
// expr = Expression::Binary(BinaryExpression {
// span: expr.span() + right.span(),
// op: match op {
// Token::Shl => BinaryOperation::Shl,
// Token::Shr => BinaryOperation::Shr,
// Token::ShrSigned => BinaryOperation::ShrSigned,
// _ => unimplemented!(),
// },
// left: Box::new(expr),
// right: Box::new(right),
// })
// }
// Ok(expr)
// }
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary addition or subtraction expression.
///
/// Otherwise, tries to parse the next token using [`parse_mul_div_pow_expression`].
///
pub fn parse_additive_expression(&mut self) -> Result<Expression> {
let mut expr = self.parse_multiplicative_expression()?;
while let Some(SpannedToken { token: op, .. }) = self.eat_any(&[Token::Add, Token::Minus]) {
let right = self.parse_multiplicative_expression()?;
expr = Expression::Binary(BinaryExpression {
span: expr.span() + right.span(),
op: match op {
Token::Add => BinaryOperation::Add,
Token::Minus => BinaryOperation::Sub,
_ => unimplemented!(),
},
left: Box::new(expr),
right: Box::new(right),
})
let op = match op {
Token::Add => BinaryOperation::Add,
Token::Minus => BinaryOperation::Sub,
_ => unreachable!("parse_additive_expression_ shouldn't produce this"),
};
expr = Self::bin_expr(expr, right, op);
}
Ok(expr)
}
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary multiplication, division, or modulus expression.
///
/// Otherwise, tries to parse the next token using [`parse_exponential_expression`].
///
pub fn parse_multiplicative_expression(&mut self) -> Result<Expression> {
let mut expr = self.parse_exponential_expression()?;
while let Some(SpannedToken { token: op, .. }) = self.eat_any(&[Token::Mul, Token::Div]) {
let right = self.parse_exponential_expression()?;
expr = Expression::Binary(BinaryExpression {
span: expr.span() + right.span(),
op: match op {
Token::Mul => BinaryOperation::Mul,
Token::Div => BinaryOperation::Div,
// Token::Mod => BinaryOperation::Mod,
_ => unimplemented!(),
},
left: Box::new(expr),
right: Box::new(right),
})
let op = match op {
Token::Mul => BinaryOperation::Mul,
Token::Div => BinaryOperation::Div,
_ => unreachable!("parse_multiplicative_expression_ shouldn't produce this"),
};
expr = Self::bin_expr(expr, right, op);
}
Ok(expr)
}
///
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary exponentiation expression.
///
/// Otherwise, tries to parse the next token using [`parse_cast_expression`].
///
pub fn parse_exponential_expression(&mut self) -> Result<Expression> {
let mut exprs = vec![self.parse_cast_expression()?];
while self.eat(Token::Exp).is_some() {
exprs.push(self.parse_cast_expression()?);
}
let mut expr = exprs.remove(exprs.len() - 1);
while !exprs.is_empty() {
let sub_expr = exprs.remove(exprs.len() - 1);
expr = Expression::Binary(BinaryExpression {
span: expr.span() + sub_expr.span(),
op: BinaryOperation::Pow,
left: Box::new(sub_expr),
right: Box::new(expr),
})
let mut expr = self.parse_cast_expression()?;
if self.eat(Token::Exp).is_some() {
let right = self.parse_exponential_expression()?;
expr = Self::bin_expr(expr, right, BinaryOperation::Pow);
}
Ok(expr)
}
@ -365,8 +248,7 @@ impl ParserContext {
let operation = match op.token {
Token::Not => UnaryOperation::Not,
Token::Minus => UnaryOperation::Negate,
// Token::BitNot => UnaryOperation::BitNot,
_ => unimplemented!(),
_ => unreachable!("parse_unary_expression_ shouldn't produce this"),
};
// hack for const signed integer overflow issues
if matches!(operation, UnaryOperation::Negate) {
@ -401,21 +283,12 @@ impl ParserContext {
/// Otherwise, tries to parse the next token using [`parse_primary_expression`].
///
pub fn parse_postfix_expression(&mut self) -> Result<Expression> {
// We don't directly parse named-type's and Identifier's here as
// the ABNF states. Rather the primary expression already
// handle those. The ABNF is more specific for language reasons.
let mut expr = self.parse_primary_expression()?;
while let Some(token) = self.eat_any(&[
Token::LeftSquare,
Token::Dot,
Token::LeftParen,
Token::DoubleColon,
Token::LengthOf,
]) {
while let Some(token) = self.eat_any(&[Token::LeftSquare, Token::Dot, Token::LeftParen, Token::DoubleColon]) {
match token.token {
Token::LengthOf => {
expr = Expression::LengthOf(LengthOfExpression {
span: expr.span().clone(),
inner: Box::new(expr),
})
}
Token::LeftSquare => {
if self.eat(Token::DotDot).is_some() {
let right = if self.peek_token().as_ref() != &Token::RightSquare {
@ -425,12 +298,12 @@ impl ParserContext {
};
let end = self.expect(Token::RightSquare)?;
expr = Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
expr = Expression::Access(AccessExpression::ArrayRange(ArrayRangeAccess {
span: expr.span() + &end,
array: Box::new(expr),
left: None,
right,
});
}));
continue;
}
@ -443,35 +316,35 @@ impl ParserContext {
};
let end = self.expect(Token::RightSquare)?;
expr = Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
expr = Expression::Access(AccessExpression::ArrayRange(ArrayRangeAccess {
span: expr.span() + &end,
array: Box::new(expr),
left: Some(Box::new(left)),
right,
});
}));
} else {
let end = self.expect(Token::RightSquare)?;
expr = Expression::ArrayAccess(ArrayAccessExpression {
expr = Expression::Access(AccessExpression::Array(ArrayAccess {
span: expr.span() + &end,
array: Box::new(expr),
index: Box::new(left),
});
}));
}
}
Token::Dot => {
if let Some(ident) = self.eat_identifier() {
expr = Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
expr = Expression::Access(AccessExpression::Member(MemberAccess {
span: expr.span() + &ident.span,
circuit: Box::new(expr),
inner: Box::new(expr),
name: ident,
type_: None,
});
}));
} else if let Some((num, span)) = self.eat_int() {
expr = Expression::TupleAccess(TupleAccessExpression {
expr = Expression::Access(AccessExpression::Tuple(TupleAccess {
span: expr.span() + &span,
tuple: Box::new(expr),
index: num,
});
}));
} else {
let next = self.peek()?;
return Err(ParserError::unexpected_str(&next.token, "int or ident", &next.span).into());
@ -481,8 +354,7 @@ impl ParserContext {
let mut arguments = Vec::new();
let end_span;
loop {
let end = self.eat(Token::RightParen);
if let Some(end) = end {
if let Some(end) = self.eat(Token::RightParen) {
end_span = end.span;
break;
}
@ -500,13 +372,14 @@ impl ParserContext {
}
Token::DoubleColon => {
let ident = self.expect_ident()?;
expr = Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
expr = Expression::Access(AccessExpression::Static(StaticAccess {
span: expr.span() + &ident.span,
circuit: Box::new(expr),
inner: Box::new(expr),
type_: None,
name: ident,
});
}));
}
_ => unimplemented!(),
_ => unreachable!("parse_postfix_expression_ shouldn't produce this"),
}
}
Ok(expr)
@ -526,39 +399,17 @@ impl ParserContext {
})
}
///
/// Returns an [`Expression`] AST node if the next tokens represent an
/// Returns an [`Expression`] AST node if the next tokens represent a
/// circuit initialization expression.
///
pub fn parse_circuit_expression(&mut self, identifier: Identifier) -> Result<Expression> {
self.expect(Token::LeftCurly)?;
let mut members = Vec::new();
let end_span;
loop {
if let Some(end) = self.eat(Token::RightCurly) {
end_span = end.span;
break;
}
let name = self.expect_ident()?;
if self.eat(Token::Colon).is_some() {
let expression = self.parse_expression()?;
members.push(CircuitImpliedVariableDefinition {
identifier: name,
expression: Some(expression),
});
} else {
members.push(CircuitImpliedVariableDefinition {
identifier: name.clone(),
expression: None,
});
}
if self.eat(Token::Comma).is_none() {
end_span = self.expect(Token::RightCurly)?;
break;
}
}
let (members, _, span) = self.parse_list(Token::LeftCurly, Token::RightCurly, Token::Comma, |p| {
Ok(Some(CircuitVariableInitializer {
identifier: p.expect_ident()?,
expression: p.eat(Token::Colon).map(|_| p.parse_expression()).transpose()?,
}))
})?;
Ok(Expression::CircuitInit(CircuitInitExpression {
span: &identifier.span + &end_span,
span: &identifier.span + &span,
name: identifier,
members,
}))
@ -617,8 +468,8 @@ impl ParserContext {
let first = self.parse_spread_or_expression()?;
if self.eat(Token::Semicolon).is_some() {
let dimensions = self
.parse_array_dimensions()?
.ok_or_else(|| ParserError::unable_to_parse_array_dimensions(span))?;
.parse_array_dimensions()
.map_err(|_| ParserError::unable_to_parse_array_dimensions(span))?;
let end = self.expect(Token::RightSquare)?;
let first = match first {
SpreadOrExpression::Spread(first) => {
@ -723,7 +574,7 @@ impl ParserContext {
}
Token::BigSelf => {
let ident = Identifier {
name: token.to_string().into(),
name: sym::SelfUpper,
span,
};
if !self.fuzzy_struct_state && self.peek_token().as_ref() == &Token::LeftCurly {
@ -732,17 +583,15 @@ impl ParserContext {
Expression::Identifier(ident)
}
}
Token::Input | Token::LittleSelf => {
let ident = Identifier {
name: token.to_string().into(),
span,
};
Expression::Identifier(ident)
}
// Token::LengthOf => Expression::LengthOf(LengthOfExpression {
// span,
// inner: Box::new(self.parse_primary_expression()?),
// }),
Token::LittleSelf => Expression::Identifier(Identifier {
name: sym::SelfLower,
span,
}),
Token::Input => Expression::Identifier(Identifier { name: sym::input, span }),
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
name: t.keyword_to_symbol().unwrap(),
span,
}),
token => {
return Err(ParserError::unexpected_str(token, "expression", &span).into());
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -14,15 +14,13 @@
// 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 tendril::format_tendril;
use leo_errors::{ParserError, Result, Span};
use super::*;
use crate::KEYWORD_TOKENS;
use super::*;
use leo_errors::{ParserError, Result};
use leo_span::{sym, Span};
impl ParserContext {
impl ParserContext<'_> {
///
/// Returns a [`Program`] AST if all tokens can be consumed and represent a valid Leo program.
///
@ -41,42 +39,38 @@ impl ParserContext {
import_statements.push(self.parse_import_statement()?);
}
Token::Circuit => {
self.expect(Token::Circuit)?;
let (id, circuit) = self.parse_circuit()?;
circuits.insert(id, circuit);
}
Token::Function | Token::At => {
Token::Ident(ident) => match *ident {
sym::test => return Err(ParserError::test_function(&token.span).into()),
kw @ (sym::Struct | sym::Class) => {
self.emit_err(ParserError::unexpected(kw, "circuit", &token.span));
self.bump().unwrap();
let (id, circuit) = self.parse_circuit()?;
circuits.insert(id, circuit);
}
_ => return Err(Self::unexpected_item(token).into()),
},
// Const functions share the first token with the global Const.
Token::Const if self.peek_is_function()? => {
let (id, function) = self.parse_function_declaration()?;
functions.insert(id, function);
}
Token::Ident(ident) if ident.as_ref() == "test" => {
return Err(ParserError::test_function(&token.span).into());
}
Token::Const => {
let (name, global_const) = self.parse_global_const_declaration()?;
global_consts.insert(name, global_const);
}
Token::Function | Token::At => {
let (id, function) = self.parse_function_declaration()?;
functions.insert(id, function);
}
Token::Type => {
let (name, alias) = self.parse_type_alias()?;
aliases.insert(name, alias);
}
_ => {
return Err(ParserError::unexpected(
&token.token,
[
Token::Import,
Token::Circuit,
Token::Function,
Token::Ident("test".into()),
Token::At,
]
.iter()
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
.join(", "),
&token.span,
)
.into());
}
_ => return Err(Self::unexpected_item(token).into()),
}
}
Ok(Program {
@ -91,58 +85,46 @@ impl ParserContext {
})
}
///
fn unexpected_item(token: &SpannedToken) -> ParserError {
ParserError::unexpected(
&token.token,
[
Token::Import,
Token::Circuit,
Token::Function,
Token::Ident(sym::test),
Token::At,
]
.iter()
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
.join(", "),
&token.span,
)
}
/// Returns an [`Annotation`] AST node if the next tokens represent a supported annotation.
///
pub fn parse_annotation(&mut self) -> Result<Annotation> {
let start = self.expect(Token::At)?;
let name = self.expect_ident()?;
if name.name.as_ref() == "context" {
return Err(ParserError::context_annotation(&name.span).into());
}
let name = self.parse_annotation_name()?;
assert_no_whitespace(&start, &name.span, &name.name, "@")?;
assert_no_whitespace(&start, &name.span, &name.name.as_str(), "@")?;
let end_span;
let arguments = if self.eat(Token::LeftParen).is_some() {
let mut args = Vec::new();
let mut comma = false;
loop {
if let Some(end) = self.eat(Token::RightParen) {
if comma {
return Err(ParserError::unexpected(
Token::RightParen,
[Token::Ident("identifier".into()), Token::Int("number".into())]
.iter()
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
.join(", "),
&end.span,
)
.into());
}
end_span = end.span;
break;
}
comma = false;
if let Some(ident) = self.eat_identifier() {
args.push(ident.name);
} else if let Some((int, _)) = self.eat_int() {
args.push(int.value);
let (end_span, arguments) = if self.peek_is_left_par() {
let (args, _, span) = self.parse_paren_comma_list(|p| {
Ok(if let Some(ident) = p.eat_identifier() {
Some(ident.name)
} else if let Some((int, _)) = p.eat_int() {
Some(Symbol::intern(&int.value))
} else {
let token = self.peek()?;
return Err(ParserError::unexpected_str(&token.token, "ident or int", &token.span).into());
}
if self.eat(Token::Comma).is_none() && !comma {
end_span = self.expect(Token::RightParen)?;
break;
}
comma = true;
}
args
let token = p.expect_any()?;
p.emit_err(ParserError::unexpected_str(&token.token, "ident or int", &token.span));
None
})
})?;
(span, args)
} else {
end_span = name.span.clone();
Vec::new()
(name.span.clone(), Vec::new())
};
Ok(Annotation {
name,
@ -151,27 +133,29 @@ impl ParserContext {
})
}
///
/// Parses `foo` in an annotation `@foo . That is, the name of the annotation.
fn parse_annotation_name(&mut self) -> Result<Identifier> {
let mut name = self.expect_ident()?;
// Recover `context` instead of `test`.
if name.name == sym::context {
self.emit_err(ParserError::context_annotation(&name.span));
name.name = sym::test;
}
Ok(name)
}
/// Returns a vector of [`PackageAccess`] AST nodes if the next tokens represent package access
/// expressions within an import statement.
///
pub fn parse_package_accesses(&mut self, span: &Span) -> Result<Vec<PackageAccess>> {
let mut out = Vec::new();
self.expect(Token::LeftParen)?;
while self.eat(Token::RightParen).is_none() {
let access = self.parse_package_access()?;
out.push(access);
if self.eat(Token::Comma).is_none() {
self.expect(Token::RightParen)?;
break;
}
}
pub fn parse_package_accesses(&mut self, start: &Span) -> Result<(Vec<PackageAccess>, Span)> {
let (out, _, end) = self.parse_paren_comma_list(|p| p.parse_package_access().map(Some))?;
if out.is_empty() {
return Err(ParserError::invalid_import_list(span).into());
self.emit_err(ParserError::invalid_import_list(&end));
}
Ok(out)
Ok((out, start + &end))
}
///
@ -191,7 +175,7 @@ impl ParserContext {
name.span = name.span + span;
let next = self.expect_ident()?;
name.span = name.span + next.span;
name.name = format_tendril!("{}-{}", name.name, next.name);
name.name = Symbol::intern(&format!("{}-{}", name.name, next.name));
}
if self.peek_token().as_ref() == &Token::Dot {
@ -220,9 +204,7 @@ impl ParserContext {
}
}
///
/// Returns an [`Identifier`] AST node if the next tokens represent a valid package name.
///
pub fn parse_package_name(&mut self) -> Result<Identifier> {
// Build the package name, starting with valid characters up to a dash `-` (Token::Minus).
let mut base = self.expect_loose_identifier()?;
@ -234,22 +216,22 @@ impl ParserContext {
let span = self.expect(Token::Minus)?;
base.span = base.span + span;
let next = self.expect_loose_identifier()?;
base.name = format_tendril!("{}-{}", base.name, next.name);
base.name = Symbol::intern(&format!("{}-{}", base.name, next.name));
base.span = base.span + next.span;
}
Token::Int(_) => {
let (num, span) = self.eat_int().unwrap();
base.name = format_tendril!("{}{}", base.name, num.value);
base.name = Symbol::intern(&format!("{}{}", base.name, num.value));
base.span = base.span + span;
}
Token::Ident(_) => {
let next = self.expect_ident()?;
base.name = format_tendril!("{}{}", base.name, next.name);
base.name = Symbol::intern(&format!("{}{}", base.name, next.name));
base.span = base.span + next.span;
}
x if KEYWORD_TOKENS.contains(x) => {
let next = self.expect_loose_identifier()?;
base.name = format_tendril!("{}{}", base.name, next.name);
base.name = Symbol::intern(&format!("{}{}", base.name, next.name));
base.span = base.span + next.span;
}
_ => break,
@ -257,17 +239,18 @@ impl ParserContext {
}
// Return an error if the package name contains a keyword.
if let Some(token) = KEYWORD_TOKENS.iter().find(|x| x.to_string() == base.name.as_ref()) {
return Err(ParserError::unexpected_str(token, "package name", &base.span).into());
if let Some(token) = KEYWORD_TOKENS.iter().find(|x| x.keyword_to_symbol() == Some(base.name)) {
self.emit_err(ParserError::unexpected_str(token, "package name", &base.span));
}
// Return an error if the package name contains invalid characters.
if !base
.name
.as_str()
.chars()
.all(|x| x.is_ascii_lowercase() || x.is_ascii_digit() || x == '-' || x == '_')
{
return Err(ParserError::invalid_package_name(&base.span).into());
self.emit_err(ParserError::invalid_package_name(&base.span));
}
// Return the package name.
@ -279,22 +262,15 @@ impl ParserContext {
/// with accesses.
///
pub fn parse_package_path(&mut self) -> Result<PackageOrPackages> {
let package_name = self.parse_package_name()?;
let name = self.parse_package_name()?;
self.expect(Token::Dot)?;
if self.peek()?.token == Token::LeftParen {
let accesses = self.parse_package_accesses(&package_name.span)?;
Ok(PackageOrPackages::Packages(Packages {
span: &package_name.span + accesses.last().map(|x| x.span()).unwrap_or(&package_name.span),
name: package_name,
accesses,
}))
if self.peek_is_left_par() {
let (accesses, span) = self.parse_package_accesses(&name.span)?;
Ok(PackageOrPackages::Packages(Packages { span, name, accesses }))
} else {
let access = self.parse_package_access()?;
Ok(PackageOrPackages::Package(Package {
span: &package_name.span + access.span(),
name: package_name,
access,
}))
let span = &name.span + access.span();
Ok(PackageOrPackages::Package(Package { span, name, access }))
}
}
@ -311,83 +287,112 @@ impl ParserContext {
})
}
///
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable
/// or circuit member function.
///
pub fn parse_circuit_declaration(&mut self) -> Result<Vec<CircuitMember>> {
let mut members = Vec::new();
let peeked = &self.peek()?.token;
let mut last_variable = peeked == &Token::Function || peeked == &Token::At;
let (mut semi_colons, mut commas) = (false, false);
while self.eat(Token::RightCurly).is_none() {
if !last_variable {
let (variable, last) = self.parse_member_variable_declaration()?;
members.push(variable);
let peeked = &self.peek()?;
if peeked.token == Token::Semicolon {
if commas {
return Err(ParserError::mixed_commas_and_semicolons(&peeked.span).into());
}
semi_colons = true;
self.expect(Token::Semicolon)?;
} else {
if semi_colons {
return Err(ParserError::mixed_commas_and_semicolons(&peeked.span).into());
}
commas = true;
self.eat(Token::Comma);
}
if last {
last_variable = last;
}
members.push(if self.peek_is_function()? {
// function
self.parse_member_function_declaration()?
} else if *self.peek_token() == Token::Static {
// static const
self.parse_const_member_variable_declaration()?
} else {
let function = self.parse_member_function_declaration()?;
members.push(function);
}
// variable
let variable = self.parse_member_variable_declaration()?;
if let Some(semi) = self.eat(Token::Semicolon) {
if commas {
self.emit_err(ParserError::mixed_commas_and_semicolons(&semi.span));
}
semi_colons = true;
}
if let Some(comma) = self.eat(Token::Comma) {
if semi_colons {
self.emit_err(ParserError::mixed_commas_and_semicolons(&comma.span));
}
commas = true;
}
variable
});
}
self.ban_mixed_member_order(&members);
Ok(members)
}
/// Emits errors if order isn't `consts variables functions`.
fn ban_mixed_member_order(&self, members: &[CircuitMember]) {
let mut had_var = false;
let mut had_fun = false;
for member in members {
match member {
CircuitMember::CircuitConst(id, _, e) if had_var => {
self.emit_err(ParserError::member_const_after_var(&(id.span() + e.span())));
}
CircuitMember::CircuitConst(id, _, e) if had_fun => {
self.emit_err(ParserError::member_const_after_fun(&(id.span() + e.span())));
}
CircuitMember::CircuitVariable(id, _) if had_fun => {
self.emit_err(ParserError::member_var_after_fun(id.span()));
}
CircuitMember::CircuitConst(..) => {}
CircuitMember::CircuitVariable(..) => had_var = true,
CircuitMember::CircuitFunction(..) => had_fun = true,
}
}
}
/// Parses `IDENT: TYPE`.
fn parse_typed_field_name(&mut self) -> Result<(Identifier, Type)> {
let name = self.expect_ident()?;
self.expect(Token::Colon)?;
let type_ = self.parse_type()?.0;
Ok((name, type_))
}
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member static constant.
pub fn parse_const_member_variable_declaration(&mut self) -> Result<CircuitMember> {
self.expect(Token::Static)?;
self.expect(Token::Const)?;
// `IDENT: TYPE = EXPR`:
let (name, type_) = self.parse_typed_field_name()?;
self.expect(Token::Assign)?;
let literal = self.parse_primary_expression()?;
self.expect(Token::Semicolon)?;
Ok(CircuitMember::CircuitConst(name, type_, literal))
}
///
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member variable.
///
pub fn parse_member_variable_declaration(&mut self) -> Result<(CircuitMember, bool)> {
let name = self.expect_ident()?;
self.expect(Token::Colon)?;
let type_ = self.parse_type()?.0;
pub fn parse_member_variable_declaration(&mut self) -> Result<CircuitMember> {
let (name, type_) = self.parse_typed_field_name()?;
let peeked = &self.peek()?.token;
if peeked == &Token::Function || peeked == &Token::At || peeked == &Token::RightCurly {
return Ok((CircuitMember::CircuitVariable(name, type_), true));
} else if peeked == &Token::Comma || peeked == &Token::Semicolon {
let peeked = &self.peek_next()?.token;
if peeked == &Token::Function || peeked == &Token::At || peeked == &Token::RightCurly {
return Ok((CircuitMember::CircuitVariable(name, type_), true));
}
}
Ok((CircuitMember::CircuitVariable(name, type_), false))
Ok(CircuitMember::CircuitVariable(name, type_))
}
///
/// Returns a [`CircuitMember`] AST node if the next tokens represent a circuit member function.
///
pub fn parse_member_function_declaration(&mut self) -> Result<CircuitMember> {
let peeked = self.peek()?.clone();
if peeked.token == Token::Function || peeked.token == Token::At {
if self.peek_is_function()? {
let function = self.parse_function_declaration()?;
Ok(CircuitMember::CircuitFunction(function.1))
Ok(CircuitMember::CircuitFunction(Box::new(function.1)))
} else {
return Err(ParserError::unexpected(
&peeked.token,
[Token::Function, Token::At]
[Token::Function, Token::At, Token::Const]
.iter()
.map(|x| format!("'{}'", x))
.collect::<Vec<_>>()
@ -403,8 +408,18 @@ impl ParserContext {
/// circuit name and definition statement.
///
pub fn parse_circuit(&mut self) -> Result<(Identifier, Circuit)> {
self.expect(Token::Circuit)?;
let name = self.expect_ident()?;
let name = if let Some(ident) = self.eat_identifier() {
ident
} else if let Some(scalar_type) = self.eat_any(crate::type_::TYPE_TOKENS) {
Identifier {
name: scalar_type.token.keyword_to_symbol().unwrap(),
span: scalar_type.span,
}
} else {
let next = self.peek()?;
return Err(ParserError::unexpected_str(&next.token, "ident", &next.span).into());
};
self.expect(Token::LeftCurly)?;
let members = self.parse_circuit_declaration()?;
@ -412,7 +427,6 @@ impl ParserContext {
name.clone(),
Circuit {
circuit_name: name,
core_mapping: std::cell::RefCell::new(None),
members,
},
))
@ -424,24 +438,26 @@ impl ParserContext {
pub fn parse_function_parameters(&mut self) -> Result<FunctionInput> {
let const_ = self.eat(Token::Const);
let mutable = self.eat(Token::Mut);
let reference = self.eat(Token::Ampersand);
let mut name = if let Some(token) = self.eat(Token::LittleSelf) {
Identifier {
name: token.token.to_string().into(),
name: sym::SelfLower,
span: token.span,
}
} else {
self.expect_ident()?
};
if name.name.as_ref() == "self" {
if name.name == sym::SelfLower {
if let Some(mutable) = &mutable {
// Handle `mut self`.
name.span = &mutable.span + &name.span;
name.name = "mut self".to_string().into();
return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { identifier: name }));
self.emit_err(ParserError::mut_self_parameter(&(&mutable.span + &name.span)));
return Ok(Self::build_ref_self(name, mutable));
} else if let Some(reference) = &reference {
// Handle `&self`.
return Ok(Self::build_ref_self(name, reference));
} else if let Some(const_) = &const_ {
// Handle `const self`.
name.span = &const_.span + &name.span;
name.name = "const self".to_string().into();
name.name = Symbol::intern("const self");
return Ok(FunctionInput::ConstSelfKeyword(ConstSelfKeyword { identifier: name }));
}
// Handle `self`.
@ -449,7 +465,7 @@ impl ParserContext {
}
if let Some(mutable) = &mutable {
return Err(ParserError::mut_function_input(&(&mutable.span + &name.span)).into());
self.emit_err(ParserError::mut_function_input(&(&mutable.span + &name.span)));
}
self.expect(Token::Colon)?;
@ -463,42 +479,55 @@ impl ParserContext {
}))
}
///
/// Builds a function parameter `&self`.
fn build_ref_self(mut name: Identifier, reference: &SpannedToken) -> FunctionInput {
name.span = &reference.span + &name.span;
// FIXME(Centril): This should be *two* tokens, NOT one!
name.name = Symbol::intern("&self");
FunctionInput::RefSelfKeyword(RefSelfKeyword { identifier: name })
}
/// Returns an [`(Identifier, Function)`] AST node if the next tokens represent a function name
/// and function definition.
///
pub fn parse_function_declaration(&mut self) -> Result<(Identifier, Function)> {
let mut annotations = Vec::new();
// Parse any annotations.
let mut annotations = IndexMap::new();
while self.peek_token().as_ref() == &Token::At {
annotations.push(self.parse_annotation()?);
let annotation = self.parse_annotation()?;
annotations.insert(annotation.name.name, annotation);
}
// Parse optional const modifier.
let const_ = self.eat(Token::Const).is_some();
// Parse `function IDENT`.
let start = self.expect(Token::Function)?;
let name = self.expect_ident()?;
self.expect(Token::LeftParen)?;
let mut inputs = Vec::new();
while self.eat(Token::RightParen).is_none() {
let input = self.parse_function_parameters()?;
inputs.push(input);
if self.eat(Token::Comma).is_none() {
self.expect(Token::RightParen)?;
break;
}
}
// Parse parameters.
let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_function_parameters().map(Some))?;
// Parse return type.
let output = if self.eat(Token::Arrow).is_some() {
Some(self.parse_type()?.0)
} else {
None
};
// Parse the function body.
let block = self.parse_block()?;
Ok((
name.clone(),
Function {
annotations,
identifier: name,
input: inputs,
const_,
output,
span: start + block.span.clone(),
block,
core_mapping: <_>::default(),
},
))
}
@ -513,7 +542,7 @@ impl ParserContext {
.variable_names
.iter()
.map(|variable_name| variable_name.identifier.clone())
.collect::<Vec<Identifier>>();
.collect();
Ok((variable_names, statement))
}
@ -523,19 +552,12 @@ impl ParserContext {
/// const definition statement and assignment.
///
pub fn parse_type_alias(&mut self) -> Result<(Identifier, Alias)> {
self.expect(Token::Type)?;
let start = self.expect(Token::Type)?;
let name = self.expect_ident()?;
self.expect(Token::Assign)?;
let (type_, _) = self.parse_type()?;
self.expect(Token::Semicolon)?;
let (represents, _) = self.parse_type()?;
let span = start + self.expect(Token::Semicolon)?;
Ok((
name.clone(),
Alias {
represents: type_,
span: name.span.clone(),
name,
},
))
Ok((name.clone(), Alias { represents, span, name }))
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -19,6 +19,16 @@
//! This module contains the [`parse()`] method which calls the underlying [`tokenize()`]
//! method to create a new program ast.
use crate::{tokenizer::*, Token};
use leo_ast::*;
use leo_errors::emitter::Handler;
use leo_errors::{ParserError, Result};
use leo_span::{Span, Symbol};
use indexmap::IndexMap;
use std::unreachable;
mod context;
pub use context::*;
@ -27,13 +37,6 @@ pub mod file;
pub mod statement;
pub mod type_;
use std::unimplemented;
use crate::{tokenizer::*, Token};
use indexmap::IndexMap;
use leo_ast::*;
use leo_errors::{ParserError, Result, Span};
pub(crate) fn assert_no_whitespace(left_span: &Span, right_span: &Span, left: &str, right: &str) -> Result<()> {
if left_span.col_stop != right_span.col_start {
let mut error_span = left_span + right_span;
@ -46,8 +49,8 @@ pub(crate) fn assert_no_whitespace(left_span: &Span, right_span: &Span, left: &s
}
/// Creates a new program from a given file path and source code text.
pub fn parse(path: &str, source: &str) -> Result<Program> {
let mut tokens = ParserContext::new(crate::tokenize(path, source.into())?);
pub fn parse(handler: &Handler, path: &str, source: &str) -> Result<Program> {
let mut tokens = ParserContext::new(handler, crate::tokenize(path, source.into())?);
tokens.parse_program()
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -17,6 +17,7 @@
use super::*;
use leo_errors::{ParserError, Result};
use leo_span::sym;
const ASSIGN_TOKENS: &[Token] = &[
Token::Assign,
@ -25,18 +26,9 @@ const ASSIGN_TOKENS: &[Token] = &[
Token::MulEq,
Token::DivEq,
Token::ExpEq,
// Token::BitAndEq,
// Token::BitOrEq,
// Token::BitXorEq,
// Token::ShlEq,
// Token::ShrEq,
// Token::ShrSignedEq,
// Token::ModEq,
// Token::OrEq,
// Token::AndEq,
];
impl ParserContext {
impl ParserContext<'_> {
///
/// Returns an [`Identifier`] AST node if the given [`Expression`] AST node evaluates to an
/// identifier access. The access is stored in the given accesses.
@ -44,25 +36,29 @@ impl ParserContext {
pub fn construct_assignee_access(expr: Expression, accesses: &mut Vec<AssigneeAccess>) -> Result<Identifier> {
let identifier;
match expr {
Expression::CircuitMemberAccess(expr) => {
identifier = Self::construct_assignee_access(*expr.circuit, accesses)?;
accesses.push(AssigneeAccess::Member(expr.name));
}
Expression::TupleAccess(expr) => {
identifier = Self::construct_assignee_access(*expr.tuple, accesses)?;
accesses.push(AssigneeAccess::Tuple(expr.index, expr.span));
}
Expression::ArrayRangeAccess(expr) => {
identifier = Self::construct_assignee_access(*expr.array, accesses)?;
accesses.push(AssigneeAccess::ArrayRange(
expr.left.map(|x| *x),
expr.right.map(|x| *x),
));
}
Expression::ArrayAccess(expr) => {
identifier = Self::construct_assignee_access(*expr.array, accesses)?;
accesses.push(AssigneeAccess::ArrayIndex(*expr.index));
}
Expression::Access(access) => match access {
AccessExpression::Member(expr) => {
identifier = Self::construct_assignee_access(*expr.inner, accesses)?;
accesses.push(AssigneeAccess::Member(expr.name));
}
AccessExpression::Tuple(expr) => {
identifier = Self::construct_assignee_access(*expr.tuple, accesses)?;
accesses.push(AssigneeAccess::Tuple(expr.index, expr.span));
}
AccessExpression::ArrayRange(expr) => {
identifier = Self::construct_assignee_access(*expr.array, accesses)?;
accesses.push(AssigneeAccess::ArrayRange(
expr.left.map(|x| *x),
expr.right.map(|x| *x),
));
}
AccessExpression::Array(expr) => {
identifier = Self::construct_assignee_access(*expr.array, accesses)?;
accesses.push(AssigneeAccess::ArrayIndex(*expr.index));
}
_ => return Err(ParserError::invalid_assignment_target(access.span()).into()),
},
Expression::Identifier(id) => identifier = id,
_ => return Err(ParserError::invalid_assignment_target(expr.span()).into()),
}
@ -119,16 +115,7 @@ impl ParserContext {
Token::MulEq => AssignOperation::Mul,
Token::DivEq => AssignOperation::Div,
Token::ExpEq => AssignOperation::Pow,
// Token::OrEq => AssignOperation::Or,
// Token::AndEq => AssignOperation::And,
// Token::BitOrEq => AssignOperation::BitOr,
// Token::BitAndEq => AssignOperation::BitAnd,
// Token::BitXorEq => AssignOperation::BitXor,
// Token::ShrEq => AssignOperation::Shr,
// Token::ShrSignedEq => AssignOperation::ShrSigned,
// Token::ShlEq => AssignOperation::Shl,
// Token::ModEq => AssignOperation::Mod,
_ => unimplemented!(),
_ => unreachable!("parse_assign_statement_ shouldn't produce this"),
},
value,
})))
@ -177,9 +164,7 @@ impl ParserContext {
})
}
///
/// Returns a [`ConditionalStatement`] AST node if the next tokens represent a conditional statement.
///
pub fn parse_conditional_statement(&mut self) -> Result<ConditionalStatement> {
let start = self.expect(Token::If)?;
self.fuzzy_struct_state = true;
@ -188,12 +173,10 @@ impl ParserContext {
let body = self.parse_block()?;
let next = if self.eat(Token::Else).is_some() {
let s = self.parse_statement()?;
match s {
Statement::Block(_) | Statement::Conditional(_) => Some(Box::new(s)),
s => {
return Err(ParserError::unexpected_statement(&s, "Block or Conditional", s.span()).into());
}
if !matches!(s, Statement::Block(_) | Statement::Conditional(_)) {
self.emit_err(ParserError::unexpected_statement(&s, "Block or Conditional", s.span()));
}
Some(Box::new(s))
} else {
None
};
@ -206,19 +189,20 @@ impl ParserContext {
})
}
///
/// Returns an [`IterationStatement`] AST node if the next tokens represent an iteration statement.
///
pub fn parse_loop_statement(&mut self) -> Result<IterationStatement> {
let start_span = self.expect(Token::For)?;
let ident = self.expect_ident()?;
self.expect(Token::In)?;
// Parse iteration range.
let start = self.parse_expression()?;
self.expect(Token::DotDot)?;
let inclusive = self.eat(Token::Assign).is_some();
self.fuzzy_struct_state = true;
let stop = self.parse_conditional_expression()?;
self.fuzzy_struct_state = false;
let block = self.parse_block()?;
Ok(IterationStatement {
@ -231,59 +215,56 @@ impl ParserContext {
})
}
///
/// Returns a [`ConsoleArgs`] AST node if the next tokens represent a formatted string.
///
pub fn parse_console_args(&mut self) -> Result<ConsoleArgs> {
let start_span;
let string = match self.expect_any()? {
SpannedToken {
token: Token::StringLit(chars),
span,
} => {
start_span = span;
chars
let mut string = None;
let (parameters, _, span) = self.parse_paren_comma_list(|p| {
if string.is_none() {
let SpannedToken { token, span } = p.expect_any()?;
string = Some(match token {
Token::StringLit(chars) => chars,
_ => {
p.emit_err(ParserError::unexpected_str(token, "formatted string", &span));
Vec::new()
}
});
Ok(None)
} else {
p.parse_expression().map(Some)
}
SpannedToken { token, span } => {
return Err(ParserError::unexpected_str(token, "formatted string", &span).into());
}
};
// let parts = FormatStringPart::from_string(string);
let mut parameters = Vec::new();
while self.eat(Token::Comma).is_some() {
let param = self.parse_expression()?;
parameters.push(param);
}
})?;
Ok(ConsoleArgs {
string,
span: &start_span + parameters.last().map(|x| x.span()).unwrap_or(&start_span),
string: string.unwrap_or_default(),
span,
parameters,
})
}
///
/// Returns a [`ConsoleStatement`] AST node if the next tokens represent a console statement.
///
pub fn parse_console_statement(&mut self) -> Result<ConsoleStatement> {
let keyword = self.expect(Token::Console)?;
self.expect(Token::Dot)?;
let function = self.expect_ident()?;
self.expect(Token::LeftParen)?;
let function = match &*function.name {
"assert" => {
let function = match function.name {
sym::assert => {
self.expect(Token::LeftParen)?;
let expr = self.parse_expression()?;
self.expect(Token::RightParen)?;
ConsoleFunction::Assert(expr)
}
"error" => ConsoleFunction::Error(self.parse_console_args()?),
"log" => ConsoleFunction::Log(self.parse_console_args()?),
sym::error => ConsoleFunction::Error(self.parse_console_args()?),
sym::log => ConsoleFunction::Log(self.parse_console_args()?),
x => {
return Err(ParserError::unexpected_ident(x, &["assert", "error", "log"], &function.span).into());
// Not sure what it is, assume it's `log`.
self.emit_err(ParserError::unexpected_ident(
x,
&["assert", "error", "log"],
&function.span,
));
ConsoleFunction::Log(self.parse_console_args()?)
}
};
self.expect(Token::RightParen)?;
self.expect(Token::Semicolon)?;
Ok(ConsoleStatement {
@ -292,14 +273,13 @@ impl ParserContext {
})
}
///
/// Returns a [`VariableName`] AST node if the next tokens represent a variable name with
/// valid keywords.
///
pub fn parse_variable_name(&mut self, span: &SpannedToken) -> Result<VariableName> {
let mutable = self.eat(Token::Mut);
if let Some(mutable) = &mutable {
return Err(ParserError::let_mut_statement(&(&mutable.span + &span.span)).into());
self.emit_err(ParserError::let_mut_statement(&(&mutable.span + &span.span)));
}
let name = self.expect_ident()?;
@ -310,35 +290,24 @@ impl ParserContext {
})
}
///
/// Returns a [`DefinitionStatement`] AST node if the next tokens represent a definition statement.
///
pub fn parse_definition_statement(&mut self) -> Result<DefinitionStatement> {
let declare = self.expect_oneof(&[Token::Let, Token::Const])?;
let mut variable_names = Vec::new();
let next = self.eat(Token::LeftParen);
variable_names.push(self.parse_variable_name(&declare)?);
if next.is_some() {
let mut eaten_ending = false;
while self.eat(Token::Comma).is_some() {
if self.eat(Token::RightParen).is_some() {
eaten_ending = true;
break;
}
variable_names.push(self.parse_variable_name(&declare)?);
}
if !eaten_ending {
self.expect(Token::RightParen)?;
}
}
let type_ = if self.eat(Token::Colon).is_some() {
Some(self.parse_type()?.0)
// Parse variable names.
let variable_names = if self.peek_is_left_par() {
self.parse_paren_comma_list(|p| p.parse_variable_name(&declare).map(Some))
.map(|(vars, ..)| vars)?
} else {
None
vec![self.parse_variable_name(&declare)?]
};
// Parse an optional type ascription.
let type_ = self
.eat(Token::Colon)
.map(|_| self.parse_type().map(|t| t.0))
.transpose()?;
self.expect(Token::Assign)?;
let expr = self.parse_expression()?;
self.expect(Token::Semicolon)?;
@ -348,7 +317,7 @@ impl ParserContext {
declaration_type: match declare.token {
Token::Let => Declare::Let,
Token::Const => Declare::Const,
_ => unimplemented!(),
_ => unreachable!("parse_definition_statement_ shouldn't produce this"),
},
variable_names,
type_,

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -17,7 +17,9 @@
use super::*;
use leo_errors::{ParserError, Result};
const TYPE_TOKENS: &[Token] = &[
use smallvec::smallvec;
pub(crate) const TYPE_TOKENS: &[Token] = &[
Token::I8,
Token::I16,
Token::I32,
@ -35,7 +37,7 @@ const TYPE_TOKENS: &[Token] = &[
Token::Char,
];
impl ParserContext {
impl ParserContext<'_> {
///
/// Returns a [`IntegerType`] AST node if the given token is a supported integer type, or [`None`].
///
@ -55,58 +57,51 @@ impl ParserContext {
})
}
///
/// Returns an [`ArrayDimensions`] AST node if the next tokens represent dimensions for an array type.
///
pub fn parse_array_dimensions(&mut self) -> Result<Option<ArrayDimensions>> {
Ok(if let Some((int, _)) = self.eat_int() {
Some(ArrayDimensions(vec![int]))
} else if self.eat(Token::Underscore).is_some() {
None
pub fn parse_array_dimensions(&mut self) -> Result<ArrayDimensions> {
Ok(if let Some(dim) = self.parse_array_dimension() {
ArrayDimensions(smallvec![dim])
} else {
self.expect(Token::LeftParen)?;
let mut dimensions = Vec::new();
loop {
if let Some((int, _)) = self.eat_int() {
dimensions.push(int);
let mut had_item_err = false;
let (dims, _, span) = self.parse_paren_comma_list(|p| {
Ok(if let Some(dim) = p.parse_array_dimension() {
Some(dim)
} else {
let token = self.peek()?;
return Err(ParserError::unexpected_str(&token.token, "int", &token.span).into());
}
if self.eat(Token::Comma).is_none() {
break;
}
let token = p.expect_any()?;
p.emit_err(ParserError::unexpected_str(&token.token, "int", &token.span));
had_item_err = true;
None
})
})?;
if dims.is_empty() && !had_item_err {
self.emit_err(ParserError::array_tuple_dimensions_empty(&span));
}
self.expect(Token::RightParen)?;
Some(ArrayDimensions(dimensions))
ArrayDimensions(dims.into())
})
}
///
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type. Also
/// returns the span of the parsed token.
///
/// Parses a basic array dimension, i.e., an integer or `_`.
fn parse_array_dimension(&mut self) -> Option<Dimension> {
if let Some((int, _)) = self.eat_int() {
Some(Dimension::Number(int))
} else if self.eat(Token::Underscore).is_some() {
Some(Dimension::Unspecified)
} else {
None
}
}
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type.
/// Also returns the span of the parsed token.
pub fn parse_type(&mut self) -> Result<(Type, Span)> {
Ok(if let Some(token) = self.eat(Token::BigSelf) {
(Type::SelfType, token.span)
} else if let Some(ident) = self.eat_identifier() {
let span = ident.span.clone();
(Type::Identifier(ident), span)
} else if let Some(token) = self.eat(Token::LeftParen) {
let mut types = Vec::new();
let end_span;
loop {
if let Some(end) = self.eat(Token::RightParen) {
end_span = end.span;
break;
}
types.push(self.parse_type()?.0);
if self.eat(Token::Comma).is_none() {
end_span = self.expect(Token::RightParen)?;
break;
}
}
(Type::Tuple(types), token.span + end_span)
} else if self.peek_is_left_par() {
let (types, _, span) = self.parse_paren_comma_list(|p| p.parse_type().map(|t| Some(t.0)))?;
(Type::Tuple(types), span)
} else if let Some(token) = self.eat(Token::LeftSquare) {
let (inner, _) = self.parse_type()?;
self.expect(Token::Semicolon)?;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -14,17 +14,18 @@
// 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::{tokenizer, ParserContext, SpannedToken};
use leo_ast::{Expression, ExpressionStatement, Statement, ValueExpression};
use leo_errors::Span;
use leo_errors::{emitter::Handler, LeoError};
use leo_span::{symbol::create_session_if_not_set_then, Span};
use leo_test_framework::{
runner::{Namespace, ParseType, Runner},
Test,
};
use serde::Serialize;
use serde_yaml::Value;
use tokenizer::Token;
use crate::{tokenizer, ParserContext};
struct TokenNamespace;
impl Namespace for TokenNamespace {
@ -33,18 +34,19 @@ impl Namespace for TokenNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
let output = tokenizer::tokenize("test", test.content.into());
output
.map(|tokens| {
Value::String(
tokens
.into_iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(","),
)
})
.map_err(|x| x.to_string())
create_session_if_not_set_then(|_| {
tokenizer::tokenize("test", test.content.into())
.map(|tokens| {
Value::String(
tokens
.into_iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(","),
)
})
.map_err(|x| x.to_string())
})
}
}
@ -60,6 +62,37 @@ fn not_fully_consumed(tokens: &mut ParserContext) -> Result<(), String> {
Err(out)
}
fn with_handler<T>(
tokens: Vec<SpannedToken>,
logic: impl FnOnce(&mut ParserContext<'_>) -> Result<T, LeoError>,
) -> Result<T, String> {
let (handler, buf) = Handler::new_with_buf();
let mut tokens = ParserContext::new(&handler, tokens);
let parsed = handler
.extend_if_error(logic(&mut tokens))
.map_err(|_| buf.extract().to_string())?;
not_fully_consumed(&mut tokens)?;
Ok(parsed)
}
fn implcit_value_expr() -> Expression {
Expression::Value(ValueExpression::Implicit("".into(), Span::default()))
}
fn tokenize(test: Test) -> Result<Vec<SpannedToken>, String> {
tokenizer::tokenize("test", test.content.into()).map_err(|x| x.to_string())
}
fn all_are_comments(tokens: &[SpannedToken]) -> bool {
tokens
.iter()
.all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
}
fn yaml_or_fail<T: Serialize>(value: T) -> Value {
serde_yaml::to_value(value).expect("serialization failed")
}
struct ParseExpressionNamespace;
impl Namespace for ParseExpressionNamespace {
@ -68,23 +101,13 @@ impl Namespace for ParseExpressionNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
let tokenizer = tokenizer::tokenize("test", test.content.into()).map_err(|x| x.to_string())?;
if tokenizer
.iter()
.all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
{
return Ok(serde_yaml::to_value(&Expression::Value(ValueExpression::Implicit(
"".into(),
Span::default(),
)))
.expect("serialization failed"));
}
let mut tokens = ParserContext::new(tokenizer);
let parsed = tokens.parse_expression().map_err(|x| x.to_string())?;
not_fully_consumed(&mut tokens)?;
Ok(serde_yaml::to_value(&parsed).expect("serialization failed"))
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(implcit_value_expr()));
}
with_handler(tokenizer, |p| p.parse_expression()).map(yaml_or_fail)
})
}
}
@ -96,23 +119,16 @@ impl Namespace for ParseStatementNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
let tokenizer = tokenizer::tokenize("test", test.content.into()).map_err(|x| x.to_string())?;
if tokenizer
.iter()
.all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
{
return Ok(serde_yaml::to_value(&Statement::Expression(ExpressionStatement {
expression: Expression::Value(ValueExpression::Implicit("".into(), Span::default())),
span: Span::default(),
}))
.expect("serialization failed"));
}
let mut tokens = ParserContext::new(tokenizer);
let parsed = tokens.parse_statement().map_err(|x| x.to_string())?;
not_fully_consumed(&mut tokens)?;
Ok(serde_yaml::to_value(&parsed).expect("serialization failed"))
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(Statement::Expression(ExpressionStatement {
expression: implcit_value_expr(),
span: Span::default(),
})));
}
with_handler(tokenizer, |p| p.parse_statement()).map(yaml_or_fail)
})
}
}
@ -124,13 +140,72 @@ impl Namespace for ParseNamespace {
}
fn run_test(&self, test: Test) -> Result<Value, String> {
let tokenizer = tokenizer::tokenize("test", test.content.into()).map_err(|x| x.to_string())?;
let mut tokens = ParserContext::new(tokenizer);
create_session_if_not_set_then(|_| with_handler(tokenize(test)?, |p| p.parse_program()).map(yaml_or_fail))
}
}
let parsed = tokens.parse_program().map_err(|x| x.to_string())?;
not_fully_consumed(&mut tokens)?;
struct SerializeNamespace;
Ok(serde_yaml::to_value(&parsed).expect("serialization failed"))
// Helper functions to recursively filter keys from AST JSON.
// Redeclaring here since we don't want to make this public.
fn remove_key_from_json(value: &mut serde_json::Value, key: &str) {
match value {
serde_json::value::Value::Object(map) => {
map.remove(key);
for val in map.values_mut() {
remove_key_from_json(val, key);
}
}
serde_json::value::Value::Array(values) => {
for val in values.iter_mut() {
remove_key_from_json(val, key);
}
}
_ => (),
}
}
// Helper function to normalize AST
// Redeclaring here because we don't want to make this public
fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
match value {
serde_json::Value::Array(vec) => {
let orig_length = vec.len();
let mut new_vec: Vec<serde_json::Value> = vec
.into_iter()
.filter(|v| !matches!(v, serde_json::Value::Object(map) if map.is_empty()))
.map(normalize_json_value)
.collect();
if orig_length == 2 && new_vec.len() == 1 {
new_vec.pop().unwrap()
} else {
serde_json::Value::Array(new_vec)
}
}
serde_json::Value::Object(map) => {
serde_json::Value::Object(map.into_iter().map(|(k, v)| (k, normalize_json_value(v))).collect())
}
_ => value,
}
}
impl Namespace for SerializeNamespace {
fn parse_type(&self) -> ParseType {
ParseType::Whole
}
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|_| {
let tokenizer = tokenize(test)?;
let parsed = with_handler(tokenizer, |p| p.parse_program())?;
let mut json = serde_json::to_value(parsed).expect("failed to convert to json value");
remove_key_from_json(&mut json, "span");
json = normalize_json_value(json);
Ok(serde_json::from_value::<serde_yaml::Value>(json).expect("failed serialization"))
})
}
}
@ -143,6 +218,7 @@ impl Runner for TestRunner {
"ParseStatement" => Box::new(ParseStatementNamespace),
"ParseExpression" => Box::new(ParseExpressionNamespace),
"Token" => Box::new(TokenNamespace),
"Serialize" => Box::new(SerializeNamespace),
_ => return None,
})
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -15,7 +15,8 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::tokenizer::{Char, Token};
use leo_errors::Span;
use leo_span::{Span, Symbol};
use serde::{Deserialize, Serialize};
use tendril::StrTendril;
@ -344,15 +345,9 @@ impl Token {
}
b'&' => {
if let Some(len) = eat(input, "&&") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::AndEq));
// }
return (len, Some(Token::And));
}
// else if let Some(len) = eat(input, "&=") {
// return (len, Some(Token::BitAndEq));
// }
// return (1, Some(Token::BitAnd));
return (1, Some(Token::Ampersand));
}
b'(' => return (1, Some(Token::LeftParen)),
b')' => return (1, Some(Token::RightParen)),
@ -388,9 +383,6 @@ impl Token {
return (len, Some(Token::DotDotDot));
} else if let Some(len) = eat(input, "..") {
return (len, Some(Token::DotDot));
} else if let Some(len) = eat(input, ".len()") {
// FIXME: remove this code once we allow method calls
return (len, Some(Token::LengthOf));
}
return (1, Some(Token::Dot));
}
@ -423,29 +415,12 @@ impl Token {
if let Some(len) = eat(input, "<=") {
return (len, Some(Token::LtEq));
}
// else if let Some(len) = eat(input, "<<") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::ShlEq));
// }
// return (len, Some(Token::Shl));
// }
return (1, Some(Token::Lt));
}
b'>' => {
if let Some(len) = eat(input, ">=") {
return (len, Some(Token::GtEq));
}
// else if let Some(len) = eat(input, ">>") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::ShrEq));
// } else if let Some(inner_len) = eat(&input[len..], ">") {
// if let Some(eq_len) = eat(&input[len + inner_len..], "=") {
// return (len + inner_len + eq_len, Some(Token::ShrSignedEq));
// }
// return (len + inner_len, Some(Token::ShrSigned));
// }
// return (len, Some(Token::Shr));
// }
return (1, Some(Token::Gt));
}
b'=' => {
@ -461,29 +436,9 @@ impl Token {
b'}' => return (1, Some(Token::RightCurly)),
b'|' => {
if let Some(len) = eat(input, "||") {
// if let Some(inner_len) = eat(&input[len..], "=") {
// return (len + inner_len, Some(Token::OrEq));
// }
return (len, Some(Token::Or));
}
// else if let Some(len) = eat(input, "|=") {
// return (len, Some(Token::BitOrEq));
// }
// return (1, Some(Token::BitOr));
}
// b'^' => {
// if let Some(len) = eat(input, "^=") {
// return (len, Some(Token::BitXorEq));
// }
// return (1, Some(Token::BitXor));
// }
// b'~' => return (1, Some(Token::BitNot)),
// b'%' => {
// if let Some(len) = eat(input, "%=") {
// return (len, Some(Token::ModEq));
// }
// return (1, Some(Token::Mod));
// }
_ => (),
}
if let Some(ident) = eat_identifier(&input_tendril) {
@ -526,7 +481,7 @@ impl Token {
"u32" => Token::U32,
"u64" => Token::U64,
"u128" => Token::U128,
_ => Token::Ident(ident),
_ => Token::Ident(Symbol::intern(&ident)),
}),
);
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -28,7 +28,8 @@ pub(crate) use self::token::*;
pub(crate) mod lexer;
pub(crate) use self::lexer::*;
use leo_errors::{LeoError, ParserError, Span};
use leo_errors::{LeoError, ParserError};
use leo_span::Span;
use tendril::StrTendril;
@ -112,30 +113,14 @@ pub(crate) fn tokenize(path: &str, input: StrTendril) -> Result<Vec<SpannedToken
#[cfg(test)]
mod tests {
use super::*;
use leo_span::symbol::create_session_if_not_set_then;
#[test]
fn test_tokenizer() {
// &
// &=
// |
// |=
// ^
// ^=
// ~
// <<
// <<=
// >>
// >>=
// >>>
// >>>=
// %
// %=
// ||=
// &&=
let tokens = tokenize(
"test_path",
r#"
create_session_if_not_set_then(|_| {
let tokens = tokenize(
"test_path",
r#"
"test"
"test{}test"
"test{}"
@ -170,6 +155,7 @@ mod tests {
input
let
mut
&
return
static
string
@ -223,25 +209,26 @@ mod tests {
// test
/* test */
//"#
.into(),
)
.unwrap();
let mut output = String::new();
for SpannedToken { token, .. } in tokens.iter() {
output += &format!("{} ", token.to_string());
}
.into(),
)
.unwrap();
let mut output = String::new();
for SpannedToken { token, .. } in tokens.iter() {
output += &format!("{} ", token.to_string());
}
// & &= | |= ^ ^= ~ << <<= >> >>= >>> >>>= % %= ||= &&=
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8 test_ident 12345 address as bool circuit const else false field for function group i128 i64 i32 i16 i8 if import in input let mut return static string test true u128 u64 u32 u16 u8 self Self console ! != && ( ) * ** **= *= + += , - -= -> _ . .. ... / /= : :: ; < <= = == > >= @ [ ] { { } } || ? // test
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8 test_ident 12345 address as bool circuit const else false field for function group i128 i64 i32 i16 i8 if import in input let mut & return static string test true u128 u64 u32 u16 u8 self Self console ! != && ( ) * ** **= *= + += , - -= -> _ . .. ... / /= : :: ; < <= = == > >= @ [ ] { { } } || ? // test
/* test */ // "#
);
);
});
}
#[test]
fn test_spans() {
let raw = r#"
create_session_if_not_set_then(|_| {
let raw = r#"
test
// test
test
@ -251,20 +238,20 @@ mod tests {
test */
test
"#;
let tokens = tokenize("test_path", raw.into()).unwrap();
let mut line_indicies = vec![0];
for (i, c) in raw.chars().enumerate() {
if c == '\n' {
line_indicies.push(i + 1);
let tokens = tokenize("test_path", raw.into()).unwrap();
let mut line_indicies = vec![0];
for (i, c) in raw.chars().enumerate() {
if c == '\n' {
line_indicies.push(i + 1);
}
}
}
for token in tokens.iter() {
let token_raw = token.token.to_string();
let start = line_indicies.get(token.span.line_start - 1).unwrap();
let stop = line_indicies.get(token.span.line_stop - 1).unwrap();
let original = &raw[*start + token.span.col_start - 1..*stop + token.span.col_stop - 1];
assert_eq!(original, &token_raw);
}
// println!("{}", serde_json::to_string_pretty(&tokens).unwrap());
for token in tokens.iter() {
let token_raw = token.token.to_string();
let start = line_indicies.get(token.span.line_start - 1).unwrap();
let stop = line_indicies.get(token.span.line_stop - 1).unwrap();
let original = &raw[*start + token.span.col_start - 1..*stop + token.span.col_stop - 1];
assert_eq!(original, &token_raw);
}
})
}
}

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -14,6 +14,8 @@
// 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 leo_span::{sym, Symbol};
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
@ -48,14 +50,14 @@ impl fmt::Display for Char {
pub enum Token {
// Lexical Grammar
// Literals
CommentLine(#[serde(with = "leo_errors::common::tendril_json")] StrTendril),
CommentBlock(#[serde(with = "leo_errors::common::tendril_json")] StrTendril),
CommentLine(#[serde(with = "leo_span::tendril_json")] StrTendril),
CommentBlock(#[serde(with = "leo_span::tendril_json")] StrTendril),
StringLit(Vec<leo_ast::Char>),
Ident(#[serde(with = "leo_errors::common::tendril_json")] StrTendril),
Int(#[serde(with = "leo_errors::common::tendril_json")] StrTendril),
Ident(Symbol),
Int(#[serde(with = "leo_span::tendril_json")] StrTendril),
True,
False,
AddressLit(#[serde(with = "leo_errors::common::tendril_json")] StrTendril),
AddressLit(#[serde(with = "leo_span::tendril_json")] StrTendril),
CharLit(Char),
// Symbols
@ -127,6 +129,7 @@ pub enum Token {
As,
Circuit,
Console,
/// Const variable and a const function.
Const,
Else,
For,
@ -135,33 +138,13 @@ pub enum Token {
In,
Let,
Mut,
/// Represents `&`.
/// Used for `Reference` and `BitAnd`.
Ampersand,
Return,
Static,
Type,
// Not yet in ABNF
// arr.len() token - hacky zone
LengthOf,
// Not yet in ABNF
// BitAnd,
// BitAndEq,
// BitOr,
// BitOrEq,
// BitXor,
// BitXorEq,
// BitNot,
// Shl,
// ShlEq,
// Shr,
// ShrEq,
// ShrSigned,
// ShrSignedEq,
// Mod,
// ModEq,
// OrEq,
// AndEq,
// Meta Tokens
Eof,
}
@ -192,13 +175,13 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Input,
Token::Let,
Token::Mut,
Token::Ampersand,
Token::Return,
Token::BigSelf,
Token::LittleSelf,
Token::Static,
Token::True,
Token::Type,
Token::LengthOf,
Token::U8,
Token::U16,
Token::U32,
@ -207,11 +190,52 @@ pub const KEYWORD_TOKENS: &[Token] = &[
];
impl Token {
///
/// Returns `true` if the `self` token equals a Leo keyword.
///
pub fn is_keyword(&self) -> bool {
KEYWORD_TOKENS.iter().any(|x| x == self)
KEYWORD_TOKENS.contains(self)
}
/// Converts `self` to the corresponding `Symbol` if it `is_keyword`.
pub fn keyword_to_symbol(&self) -> Option<Symbol> {
Some(match self {
Token::Address => sym::address,
Token::As => sym::As,
Token::Bool => sym::bool,
Token::Char => sym::char,
Token::Circuit => sym::circuit,
Token::Console => sym::console,
Token::Const => sym::Const,
Token::Else => sym::Else,
Token::False => sym::False,
Token::Field => sym::field,
Token::For => sym::For,
Token::Function => sym::function,
Token::Group => sym::group,
Token::I8 => sym::i8,
Token::I16 => sym::i16,
Token::I32 => sym::i32,
Token::I64 => sym::i64,
Token::I128 => sym::i128,
Token::If => sym::If,
Token::Import => sym::import,
Token::In => sym::In,
Token::Input => sym::input,
Token::Let => sym::Let,
Token::Mut => sym::Mut,
Token::Ampersand => sym::Ampersand,
Token::Return => sym::Return,
Token::BigSelf => sym::SelfUpper,
Token::LittleSelf => sym::SelfLower,
Token::Static => sym::Static,
Token::True => sym::True,
Token::Type => sym::Type,
Token::U8 => sym::u8,
Token::U16 => sym::u16,
Token::U32 => sym::u32,
Token::U64 => sym::u64,
Token::U128 => sym::u128,
_ => return None,
})
}
}
@ -307,28 +331,11 @@ impl fmt::Display for Token {
In => write!(f, "in"),
Let => write!(f, "let"),
Mut => write!(f, "mut"),
Ampersand => write!(f, "&"), // Used for `Reference` and `BitAnd`
Return => write!(f, "return"),
Static => write!(f, "static"),
Type => write!(f, "type"),
LengthOf => write!(f, ".len()"), // FIXME
Eof => write!(f, ""),
// BitAnd => write!(f, "&"),
// BitAndEq => write!(f, "&="),
// BitOr => write!(f, "|"),
// BitOrEq => write!(f, "|="),
// BitXor => write!(f, "^"),
// BitXorEq => write!(f, "^="),
// BitNot => write!(f, "~"),
// Shl => write!(f, "<<"),
// ShlEq => write!(f, "<<="),
// Shr => write!(f, ">>"),
// ShrEq => write!(f, ">>="),
// ShrSigned => write!(f, ">>>"),
// ShrSignedEq => write!(f, ">>>="),
// Mod => write!(f, "%"),
// ModEq => write!(f, "%="),
// OrEq => write!(f, "||="),
// AndEq => write!(f, "&&="),
}
}
}

View File

@ -1,17 +0,0 @@
// Copyright (C) 2019-2021 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/>.
mod serialization;

View File

@ -1,100 +0,0 @@
{
"name": "",
"expected_input": [],
"import_statements": [],
"imports": {},
"aliases": {},
"circuits": {},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() -> u8 {\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() -> u8 {\\\"}\"}",
"input": [],
"output": {
"IntegerType": "U8"
},
"block": {
"statements": [
{
"Return": {
"expression": {
"Binary": {
"left": {
"Value": {
"Integer": [
"U8",
"1",
{
"span" : {
"line_start": 2,
"line_stop": 2,
"col_start": 12,
"col_stop": 15,
"path": "",
"content": " return 1u8 + 1u8;"
}
}
]
}
},
"right": {
"Value": {
"Integer": [
"U8",
"1",
{
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 18,
"col_stop": 21,
"path": "",
"content": " return 1u8 + 1u8;"
}
}
]
}
},
"op": "Add",
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 12,
"col_stop": 21,
"path": "",
"content": " return 1u8 + 1u8;"
}
}
},
"span": {
"line_start": 2,
"line_stop": 2,
"col_start": 5,
"col_stop": 21,
"path": "",
"content": " return 1u8 + 1u8;"
}
}
}
],
"span": {
"line_start": 1,
"line_stop": 3,
"col_start": 23,
"col_stop": 2,
"path": "",
"content": "function main() -> u8 {\n ...\n}"
}
},
"span": {
"line_start": 1,
"line_stop": 3,
"col_start": 1,
"col_stop": 2,
"path": "",
"content": "function main() -> u8 {\n ...\n}"
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,299 +0,0 @@
{
"name": "",
"expected_input": [],
"import_statements": [],
"imports": {},
"aliases": {},
"circuits": {
"{\"name\":\"PedersenHash\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit PedersenHash {\\\"}\"}": {
"circuit_name": "{\"name\":\"PedersenHash\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit PedersenHash {\\\"}\"}",
"core_mapping": null,
"members": [
{
"CircuitVariable": [
"{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":5,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" parameters: [group; 256];\\\"}\"}",
{
"Array": [
"Group",
[
{
"value": "256"
}
]
]
}
]
},
{
"CircuitFunction": {
"annotations": [],
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":14,\\\"col_stop\\\":17,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function new(parameters: [group; 256]) -> Self {\\\"}\"}",
"input": [
{
"Variable": {
"identifier": "{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":18,\\\"col_stop\\\":28,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function new(parameters: [group; 256]) -> Self {\\\"}\"}",
"const_": false,
"mutable": true,
"type_": {
"Array": [
"Group",
[
{
"value": "256"
}
]
]
}
}
}
],
"output": "SelfType",
"block": {
"statements": [
{
"Return": {
"expression": {
"CircuitInit": {
"name": "{\"name\":\"Self\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":16,\\\"col_stop\\\":20,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return Self { parameters: parameters };\\\"}\"}",
"members": [
{
"identifier": "{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":23,\\\"col_stop\\\":33,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return Self { parameters: parameters };\\\"}\"}",
"expression": {
"Identifier": "{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":35,\\\"col_stop\\\":45,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return Self { parameters: parameters };\\\"}\"}"
}
}
]
}
}
}
}
]
}
}
},
{
"CircuitFunction": {
"annotations": [],
"identifier": "{\"name\":\"hash\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":14,\\\"col_stop\\\":18,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function hash(self, bits: [bool; 256]) -> group {\\\"}\"}",
"input": [
{
"SelfKeyword": "{\"name\":\"self\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":19,\\\"col_stop\\\":23,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function hash(self, bits: [bool; 256]) -> group {\\\"}\"}"
},
{
"Variable": {
"identifier": "{\"name\":\"bits\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":25,\\\"col_stop\\\":29,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function hash(self, bits: [bool; 256]) -> group {\\\"}\"}",
"const_": false,
"mutable": true,
"type_": {
"Array": [
"Boolean",
[
{
"value": "256"
}
]
]
}
}
}
],
"output": "Group",
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Let",
"variable_names": [
{
"mutable": true,
"identifier": "{\"name\":\"digest\",\"span\":\"{\\\"line_start\\\":10,\\\"line_stop\\\":10,\\\"col_start\\\":13,\\\"col_stop\\\":19,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let digest: group = 0group;\\\"}\"}"
}
],
"type_": "Group",
"value": {
"Value": {
"Group": {
"Single": "0"
}
}
}
}
},
{
"Iteration": {
"variable": "{\"name\":\"i\",\"span\":\"{\\\"line_start\\\":11,\\\"line_stop\\\":11,\\\"col_start\\\":13,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" for i in 0..256 {\\\"}\"}",
"start": {
"Value": {
"Implicit": "0"
}
},
"stop": {
"Value": {
"Implicit": "256"
}
},
"inclusive": false,
"block": {
"statements": [
{
"Conditional": {
"condition": {
"ArrayAccess": {
"array": {
"Identifier": "{\"name\":\"bits\",\"span\":\"{\\\"line_start\\\":12,\\\"line_stop\\\":12,\\\"col_start\\\":16,\\\"col_stop\\\":20,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" if bits[i] {\\\"}\"}"
},
"index": {
"Identifier": "{\"name\":\"i\",\"span\":\"{\\\"line_start\\\":12,\\\"line_stop\\\":12,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" if bits[i] {\\\"}\"}"
}
}
},
"block": {
"statements": [
{
"Assign": {
"operation": "Add",
"assignee": {
"identifier": "{\"name\":\"digest\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":17,\\\"col_stop\\\":23,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" digest += self.parameters[i];\\\"}\"}",
"accesses": []
},
"value": {
"ArrayAccess": {
"array": {
"CircuitMemberAccess": {
"circuit": {
"Identifier": "{\"name\":\"self\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":27,\\\"col_stop\\\":31,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" digest += self.parameters[i];\\\"}\"}"
},
"name": "{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":32,\\\"col_stop\\\":42,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" digest += self.parameters[i];\\\"}\"}",
"type_": null
}
},
"index": {
"Identifier": "{\"name\":\"i\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":43,\\\"col_stop\\\":44,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" digest += self.parameters[i];\\\"}\"}"
}
}
}
}
}
]
},
"next": null
}
}
]
}
}
},
{
"Return": {
"expression": {
"Identifier": "{\"name\":\"digest\",\"span\":\"{\\\"line_start\\\":16,\\\"line_stop\\\":16,\\\"col_start\\\":16,\\\"col_stop\\\":22,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return digest;\\\"}\"}"
}
}
}
]
}
}
}
]
}
},
"global_consts": {},
"functions": {
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":21,\\\"line_stop\\\":21,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(hash_input: [bool; 256], const parameters: [group; 256]) -> group {\\\"}\"}": {
"annotations": [],
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":21,\\\"line_stop\\\":21,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(hash_input: [bool; 256], const parameters: [group; 256]) -> group {\\\"}\"}",
"input": [
{
"Variable": {
"identifier": "{\"name\":\"hash_input\",\"span\":\"{\\\"line_start\\\":21,\\\"line_stop\\\":21,\\\"col_start\\\":15,\\\"col_stop\\\":25,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(hash_input: [bool; 256], const parameters: [group; 256]) -> group {\\\"}\"}",
"const_": false,
"mutable": true,
"type_": {
"Array": [
"Boolean",
[
{
"value": "256"
}
]
]
}
}
},
{
"Variable": {
"identifier": "{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":21,\\\"line_stop\\\":21,\\\"col_start\\\":46,\\\"col_stop\\\":56,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(hash_input: [bool; 256], const parameters: [group; 256]) -> group {\\\"}\"}",
"const_": true,
"mutable": false,
"type_": {
"Array": [
"Group",
[
{
"value": "256"
}
]
]
}
}
}
],
"output": "Group",
"block": {
"statements": [
{
"Definition": {
"declaration_type": "Const",
"variable_names": [
{
"mutable": false,
"identifier": "{\"name\":\"pedersen\",\"span\":\"{\\\"line_start\\\":22,\\\"line_stop\\\":22,\\\"col_start\\\":11,\\\"col_stop\\\":19,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const pedersen = PedersenHash::new(parameters);\\\"}\"}"
}
],
"type_": null,
"value": {
"Call": {
"function": {
"CircuitStaticFunctionAccess": {
"circuit": {
"Identifier": "{\"name\":\"PedersenHash\",\"span\":\"{\\\"line_start\\\":22,\\\"line_stop\\\":22,\\\"col_start\\\":22,\\\"col_stop\\\":34,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const pedersen = PedersenHash::new(parameters);\\\"}\"}"
},
"name": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":22,\\\"line_stop\\\":22,\\\"col_start\\\":36,\\\"col_stop\\\":39,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const pedersen = PedersenHash::new(parameters);\\\"}\"}"
}
},
"arguments": [
{
"Identifier": "{\"name\":\"parameters\",\"span\":\"{\\\"line_start\\\":22,\\\"line_stop\\\":22,\\\"col_start\\\":40,\\\"col_stop\\\":50,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const pedersen = PedersenHash::new(parameters);\\\"}\"}"
}
]
}
}
}
},
{
"Return": {
"expression": {
"Call": {
"function": {
"CircuitMemberAccess": {
"circuit": {
"Identifier": "{\"name\":\"pedersen\",\"span\":\"{\\\"line_start\\\":23,\\\"line_stop\\\":23,\\\"col_start\\\":12,\\\"col_stop\\\":20,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return pedersen.hash(hash_input);\\\"}\"}"
},
"name": "{\"name\":\"hash\",\"span\":\"{\\\"line_start\\\":23,\\\"line_stop\\\":23,\\\"col_start\\\":21,\\\"col_stop\\\":25,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return pedersen.hash(hash_input);\\\"}\"}",
"type_": null
}
},
"arguments": [
{
"Identifier": "{\"name\":\"hash_input\",\"span\":\"{\\\"line_start\\\":23,\\\"line_stop\\\":23,\\\"col_start\\\":26,\\\"col_stop\\\":36,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return pedersen.hash(hash_input);\\\"}\"}"
}
]
}
}
}
}
]
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// 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
@ -17,7 +17,7 @@
use leo_ast::Ast;
#[cfg(not(feature = "ci_skip"))]
use leo_ast::Program;
use leo_errors::{LeoError, Result};
use leo_errors::{emitter::Handler, LeoError, Result};
use std::fs::File;
use std::io::BufReader;
@ -28,7 +28,7 @@ fn to_ast(program_filepath: &Path) -> Result<Ast> {
let program_string = std::fs::read_to_string(program_filepath).expect("failed to open test");
// Parses the Leo file and constructs a leo ast.
leo_parser::parse_ast("", &program_string)
leo_parser::parse_ast(&Handler::default(), "", &program_string)
}
fn setup() {

View File

@ -1,7 +0,0 @@
function main() {
return 1 + 1;
}
test function old {
console.log("old");
}

View File

@ -1 +0,0 @@
invalid

View File

@ -1,17 +0,0 @@
// Copyright (C) 2019-2021 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/>.
mod json;

View File

@ -29,29 +29,30 @@ features = [ "preserve_order" ]
version = "0.8"
# List of dependencies for tgc binary;
[dependencies.leo-asg]
path = "../asg"
version = "1.5.2"
# disabled for now while porting modules from staging
# [dependencies.leo-ast]
# path = "../ast"
# version = "1.5.2"
[dependencies.leo-ast]
path = "../ast"
version = "1.5.2"
# [dependencies.leo-ast-passes]
# path = "../ast-passes"
# version = "1.5.2"
[dependencies.leo-ast-passes]
path = "../ast-passes"
version = "1.5.2"
# [dependencies.leo-parser]
# path = "../parser"
# version = "1.5.2"
[dependencies.leo-compiler]
path = "../compiler"
version = "1.5.2"
# [dependencies.leo-imports]
# path = "../imports"
# version = "1.5.2"
[dependencies.leo-imports]
path = "../imports"
version = "1.5.2"
# [dependencies.leo-asg]
# path = "../asg"
# version = "1.5.2"
[dependencies.leo-parser]
path = "../parser"
version = "1.5.2"
# [dependencies.leo-compiler]
# path = "../compiler"
# version = "1.5.2"
[dependencies.structopt]
version = "0.3"

View File

@ -10,13 +10,14 @@ outputs:
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
core_mapping: ~
members:
- CircuitFunction:
annotations: []
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x() -> Self {\\\"}\"}"
input: []
const_: false
output: SelfType
core_mapping: ~
block:
statements:
- Return:

View File

@ -0,0 +1,253 @@
---
namespace: Parse
expectation: Pass
outputs:
- name: ""
expected_input: []
import_statements: []
imports: {}
aliases: {}
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
members:
- CircuitVariable:
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: u32\\\"}\"}"
- IntegerType: U32
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function x() { \\\"}\"}"
input: []
const_: true
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 6
line_stop: 6
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 6
line_stop: 6
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 5
line_stop: 7
col_start: 24
col_stop: 6
path: ""
content: " const function x() { \n ...\n }"
span:
line_start: 5
line_stop: 7
col_start: 11
col_stop: 6
path: ""
content: " const function x() { \n ...\n }"
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":8,\\\"line_stop\\\":8,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function x(self) { \\\"}\"}"
input:
- SelfKeyword: "{\"name\":\"self\",\"span\":\"{\\\"line_start\\\":8,\\\"line_stop\\\":8,\\\"col_start\\\":22,\\\"col_stop\\\":26,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function x(self) { \\\"}\"}"
const_: true
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 9
line_stop: 9
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 9
line_stop: 9
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 8
line_stop: 10
col_start: 28
col_stop: 6
path: ""
content: " const function x(self) { \n ...\n }"
span:
line_start: 8
line_stop: 10
col_start: 11
col_stop: 6
path: ""
content: " const function x(self) { \n ...\n }"
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"c\",\"span\":\"{\\\"line_start\\\":11,\\\"line_stop\\\":11,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function c(const self) { \\\"}\"}"
input:
- ConstSelfKeyword: "{\"name\":\"const self\",\"span\":\"{\\\"line_start\\\":11,\\\"line_stop\\\":11,\\\"col_start\\\":22,\\\"col_stop\\\":32,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function c(const self) { \\\"}\"}"
const_: true
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 12
line_stop: 12
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 12
line_stop: 12
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 11
line_stop: 13
col_start: 34
col_stop: 6
path: ""
content: " const function c(const self) { \n ...\n }"
span:
line_start: 11
line_stop: 13
col_start: 11
col_stop: 6
path: ""
content: " const function c(const self) { \n ...\n }"
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function b(const self, x: u32) {\\\"}\"}"
input:
- ConstSelfKeyword: "{\"name\":\"const self\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":22,\\\"col_stop\\\":32,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function b(const self, x: u32) {\\\"}\"}"
- Variable:
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":14,\\\"line_stop\\\":14,\\\"col_start\\\":34,\\\"col_stop\\\":35,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function b(const self, x: u32) {\\\"}\"}"
const_: false
mutable: true
type_:
IntegerType: U32
span:
line_start: 14
line_stop: 14
col_start: 34
col_stop: 35
path: ""
content: " const function b(const self, x: u32) {"
const_: true
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 15
line_stop: 15
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 15
line_stop: 15
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 14
line_stop: 16
col_start: 42
col_stop: 6
path: ""
content: " const function b(const self, x: u32) {\n ...\n }"
span:
line_start: 14
line_stop: 16
col_start: 11
col_stop: 6
path: ""
content: " const function b(const self, x: u32) {\n ...\n }"
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function b(const self, const x: u32) {\\\"}\"}"
input:
- ConstSelfKeyword: "{\"name\":\"const self\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":22,\\\"col_stop\\\":32,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function b(const self, const x: u32) {\\\"}\"}"
- Variable:
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":40,\\\"col_stop\\\":41,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function b(const self, const x: u32) {\\\"}\"}"
const_: true
mutable: false
type_:
IntegerType: U32
span:
line_start: 17
line_stop: 17
col_start: 40
col_stop: 41
path: ""
content: " const function b(const self, const x: u32) {"
const_: true
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 18
line_stop: 18
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 18
line_stop: 18
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 17
line_stop: 19
col_start: 48
col_stop: 6
path: ""
content: " const function b(const self, const x: u32) {\n ...\n }"
span:
line_start: 17
line_stop: 19
col_start: 11
col_stop: 6
path: ""
content: " const function b(const self, const x: u32) {\n ...\n }"
global_consts: {}
functions: {}

View File

@ -0,0 +1,41 @@
---
namespace: Parse
expectation: Pass
outputs:
- name: ""
expected_input: []
import_statements: []
imports: {}
aliases: {}
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
members:
- CircuitConst:
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":18,\\\"col_stop\\\":19,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" static const x: u32 = 2;\\\"}\"}"
- IntegerType: U32
- Value:
Implicit:
- "2"
- span:
line_start: 4
line_stop: 4
col_start: 27
col_stop: 28
path: ""
content: " static const x: u32 = 2;"
- CircuitConst:
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":18,\\\"col_stop\\\":19,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" static const y: u32 = 5;\\\"}\"}"
- IntegerType: U32
- Value:
Implicit:
- "5"
- span:
line_start: 5
line_stop: 5
col_start: 27
col_stop: 28
path: ""
content: " static const y: u32 = 5;"
global_consts: {}
functions: {}

View File

@ -10,7 +10,6 @@ outputs:
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
core_mapping: ~
members: []
global_consts: {}
functions: {}

View File

@ -10,19 +10,33 @@ outputs:
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
core_mapping: ~
members:
- CircuitConst:
- "{\"name\":\"a\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":18,\\\"col_stop\\\":19,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" static const a: u8 = 10;\\\"}\"}"
- IntegerType: U8
- Value:
Implicit:
- "10"
- span:
line_start: 4
line_stop: 4
col_start: 26
col_stop: 28
path: ""
content: " static const a: u8 = 10;"
- CircuitVariable:
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: u32,\\\"}\"}"
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: u32,\\\"}\"}"
- IntegerType: U32
- CircuitVariable:
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y: u32\\\"}\"}"
- "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y: u32\\\"}\"}"
- IntegerType: U32
- CircuitFunction:
annotations: []
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x() {\\\"}\"}"
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":7,\\\"line_stop\\\":7,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x() {\\\"}\"}"
input: []
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:
@ -30,38 +44,40 @@ outputs:
TupleInit:
elements: []
span:
line_start: 7
line_stop: 7
line_start: 8
line_stop: 8
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 7
line_stop: 7
line_start: 8
line_stop: 8
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 6
line_stop: 8
line_start: 7
line_stop: 9
col_start: 18
col_stop: 6
path: ""
content: " function x() {\n ...\n }"
span:
line_start: 6
line_stop: 8
line_start: 7
line_stop: 9
col_start: 5
col_stop: 6
path: ""
content: " function x() {\n ...\n }"
- CircuitFunction:
annotations: []
identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function y() {\\\"}\"}"
annotations: {}
identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":10,\\\"line_stop\\\":10,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function y() {\\\"}\"}"
input: []
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:
@ -69,29 +85,29 @@ outputs:
TupleInit:
elements: []
span:
line_start: 10
line_stop: 10
line_start: 11
line_stop: 11
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 10
line_stop: 10
line_start: 11
line_stop: 11
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 9
line_stop: 11
line_start: 10
line_stop: 12
col_start: 18
col_stop: 6
path: ""
content: " function y() {\n ...\n }"
span:
line_start: 9
line_stop: 11
line_start: 10
line_stop: 12
col_start: 5
col_stop: 6
path: ""

View File

@ -10,7 +10,6 @@ outputs:
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
core_mapping: ~
members:
- CircuitVariable:
- "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: u32;\\\"}\"}"

View File

@ -2,4 +2,4 @@
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370006]: Cannot mix use of commas and semi-colons for circuit member variable declarations.\n --> test:10:11\n |\n 10 | y: u32;\n | ^"
- "Error [EPAR0370006]: Cannot mix use of commas and semi-colons for circuit member variable declarations.\n --> test:10:11\n |\n 10 | y: u32;\n | ^\nError [EPAR0370006]: Cannot mix use of commas and semi-colons for circuit member variable declarations.\n --> test:11:5\n |\n 11 | , // recovery witness\n | ^"

View File

@ -10,13 +10,14 @@ outputs:
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
core_mapping: ~
members:
- CircuitFunction:
annotations: []
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x() {\\\"}\"}"
input: []
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:
@ -52,10 +53,12 @@ outputs:
path: ""
content: " function x() {\n ...\n }"
- CircuitFunction:
annotations: []
annotations: {}
identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":7,\\\"line_stop\\\":7,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function y() {\\\"}\"}"
input: []
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:
@ -90,5 +93,46 @@ outputs:
col_stop: 6
path: ""
content: " function y() {\n ...\n }"
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":10,\\\"line_stop\\\":10,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" const function z() {\\\"}\"}"
input: []
const_: true
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 11
line_stop: 11
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 11
line_stop: 11
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 10
line_stop: 12
col_start: 24
col_stop: 6
path: ""
content: " const function z() {\n ...\n }"
span:
line_start: 10
line_stop: 12
col_start: 11
col_stop: 6
path: ""
content: " const function z() {\n ...\n }"
global_consts: {}
functions: {}

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370022]: Member functions must come after member variables.\n --> test:7:5\n |\n 7 | foo: u8,\n | ^^^\nError [EPAR0370021]: Member functions must come after member consts.\n --> test:9:18\n |\n 9 | static const BAR: u8 = 0u8;\n | ^^^^^^^^^^^^^\nError [EPAR0370020]: Member variables must come after member consts.\n --> test:15:18\n |\n 15 | static const BAR: u8 = 0u8;\n | ^^^^^^^^^^^^^"

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370019]: `mut self` is no longer accepted. Use `&self` if you would like to pass in a mutable reference to `self`\n --> test:4:16\n |\n 4 | function x(mut self) {\n | ^^^^^^^^"

View File

@ -0,0 +1,57 @@
---
namespace: Parse
expectation: Pass
outputs:
- name: ""
expected_input: []
import_statements: []
imports: {}
aliases: {}
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
members:
- CircuitFunction:
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x(&self) {\\\"}\"}"
input:
- RefSelfKeyword: "{\"name\":\"&self\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":16,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x(&self) {\\\"}\"}"
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 5
line_stop: 5
col_start: 16
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 5
line_stop: 5
col_start: 9
col_stop: 18
path: ""
content: " return ();"
span:
line_start: 4
line_stop: 6
col_start: 23
col_stop: 6
path: ""
content: " function x(&self) {\n ...\n }"
span:
line_start: 4
line_stop: 6
col_start: 5
col_stop: 6
path: ""
content: " function x(&self) {\n ...\n }"
global_consts: {}
functions: {}

View File

@ -10,14 +10,15 @@ outputs:
circuits:
"{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}":
circuit_name: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit X {\\\"}\"}"
core_mapping: ~
members:
- CircuitFunction:
annotations: []
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x(self) {\\\"}\"}"
input:
- SelfKeyword: "{\"name\":\"self\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":16,\\\"col_stop\\\":20,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function x(self) {\\\"}\"}"
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370005]: expected circuit -- got 'struct'\n --> test:3:1\n |\n 3 | struct A {}\n | ^^^^^^\nError [EPAR0370005]: expected circuit -- got 'class'\n --> test:5:1\n |\n 5 | class C {}\n | ^^^^^"

View File

@ -2,170 +2,179 @@
namespace: ParseExpression
expectation: Pass
outputs:
- ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0]\\\"}\"}"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[0]"
- ArrayAccess:
array:
Identifier: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X[1]\\\"}\"}"
index:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "X[1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "X[1]"
- ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0u8]\\\"}\"}"
index:
Value:
Integer:
- U8
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[0u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[0u8]"
- ArrayAccess:
array:
ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[1u8][2u8]\\\"}\"}"
index:
Value:
Integer:
- U8
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[1u8][2u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[1u8][2u8]"
index:
Value:
Integer:
- U8
- "2"
- span:
line_start: 1
line_stop: 1
col_start: 8
col_stop: 11
path: ""
content: "x[1u8][2u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 12
path: ""
content: "x[1u8][2u8]"
- ArrayAccess:
array:
ArrayAccess:
array:
ArrayAccess:
- Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0]\\\"}\"}"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[0]"
- Access:
Array:
array:
Identifier: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X[1]\\\"}\"}"
index:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "X[1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "X[1]"
- Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0u8]\\\"}\"}"
index:
Value:
Integer:
- U8
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[0u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[0u8]"
- Access:
Array:
array:
Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[1u8][2u8]\\\"}\"}"
index:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
Value:
Integer:
- U8
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[1u8][2u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
col_stop: 7
path: ""
content: "x[1u8][2u8]"
index:
Value:
Integer:
- U8
- "2"
- span:
line_start: 1
line_stop: 1
col_start: 8
col_stop: 11
path: ""
content: "x[1u8][2u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 12
path: ""
content: "x[1u8][2u8]"
- Access:
Array:
array:
Access:
Array:
array:
Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
index:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[x][y][z]"
index:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":6,\\\"col_stop\\\":7,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x[x][y][z]"
index:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":6,\\\"col_stop\\\":7,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x[x][y][z]"
index:
Identifier: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 11
path: ""
content: "x[x][y][z]"
index:
Identifier: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x][y][z]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 11
path: ""
content: "x[x][y][z]"
- Call:
function:
ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0]()\\\"}\"}"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0]()"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[0]()"
Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0]()\\\"}\"}"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0]()"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[0]()"
arguments: []
span:
line_start: 1
@ -174,61 +183,64 @@ outputs:
col_stop: 7
path: ""
content: "x[0]()"
- ArrayAccess:
array:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x()[0]\\\"}\"}"
arguments: []
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: "x()[0]"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "x()[0]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x()[0]"
- Access:
Array:
array:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x()[0]\\\"}\"}"
arguments: []
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: "x()[0]"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "x()[0]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x()[0]"
- Call:
function:
CircuitStaticFunctionAccess:
circuit:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
arguments:
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x(y)::y(x)"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x(y)::y(x)"
Access:
Static:
inner:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
arguments:
- Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x(y)::y(x)"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x(y)::y(x)"
arguments:
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x(y)::y(x)\\\"}\"}"
span:
@ -238,37 +250,40 @@ outputs:
col_stop: 11
path: ""
content: "x(y)::y(x)"
- ArrayAccess:
array:
TupleAccess:
tuple:
ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x].0[x]\\\"}\"}"
- Access:
Array:
array:
Access:
Tuple:
tuple:
Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x].0[x]\\\"}\"}"
index:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x].0[x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[x].0[x]"
index:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x].0[x]\\\"}\"}"
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
col_stop: 7
path: ""
content: "x[x].0[x]"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[x].0[x]"
index:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":8,\\\"col_stop\\\":9,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x].0[x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 10
path: ""
content: "x[x].0[x]"
index:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":8,\\\"col_stop\\\":9,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x].0[x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 10
path: ""
content: "x[x].0[x]"

View File

@ -2,133 +2,171 @@
namespace: ParseExpression
expectation: Pass
outputs:
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..]\\\"}\"}"
left: ~
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: "x[..]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[1..]\\\"}\"}"
left:
Value:
Implicit:
- "1"
- span:
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..]\\\"}\"}"
left: ~
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: "x[..]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[1..]\\\"}\"}"
left:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[1..]"
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[1..]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..1]\\\"}\"}"
left: ~
right:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "x[..1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[..1]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[1..1]\\\"}\"}"
left:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[1..1]"
right:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 6
col_stop: 7
path: ""
content: "x[1..1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x[1..1]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0..100]\\\"}\"}"
left:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0..100]"
right:
Value:
Implicit:
- "100"
- span:
line_start: 1
line_stop: 1
col_start: 6
col_stop: 9
path: ""
content: "x[0..100]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 10
path: ""
content: "x[0..100]"
- Access:
Array:
array:
Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[323452345.2345234523453453][323452345.2345234523453453]\\\"}\"}"
index:
Access:
Tuple:
tuple:
Value:
Implicit:
- "323452345"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 12
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
index:
value: "2345234523453453"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 29
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
col_start: 1
col_stop: 30
path: ""
content: "x[1..]"
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[1..]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..1]\\\"}\"}"
left: ~
right:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "x[..1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x[..1]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[1..1]\\\"}\"}"
left:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[1..1]"
right:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 6
col_stop: 7
path: ""
content: "x[1..1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x[1..1]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0..100]\\\"}\"}"
left:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0..100]"
right:
Value:
Implicit:
- "100"
- span:
line_start: 1
line_stop: 1
col_start: 6
col_stop: 9
path: ""
content: "x[0..100]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 10
path: ""
content: "x[0..100]"
- ArrayAccess:
array:
ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[323452345.2345234523453453][323452345.2345234523453453]\\\"}\"}"
index:
TupleAccess:
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
index:
Access:
Tuple:
tuple:
Value:
Implicit:
@ -136,8 +174,8 @@ outputs:
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 12
col_start: 31
col_stop: 40
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
index:
@ -145,277 +183,264 @@ outputs:
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 29
col_start: 31
col_stop: 57
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 30
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
index:
TupleAccess:
tuple:
Value:
Implicit:
- "323452345"
- span:
line_start: 1
line_stop: 1
col_start: 31
col_stop: 40
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
index:
value: "2345234523453453"
span:
line_start: 1
line_stop: 1
col_start: 31
col_stop: 57
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 58
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0u8..1u8]\\\"}\"}"
left:
Value:
Integer:
- U8
- "0"
- span:
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 58
path: ""
content: "x[323452345.2345234523453453][323452345.2345234523453453]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0u8..1u8]\\\"}\"}"
left:
Value:
Integer:
- U8
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[0u8..1u8]"
right:
Value:
Integer:
- U8
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 8
col_stop: 11
path: ""
content: "x[0u8..1u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 12
path: ""
content: "x[0u8..1u8]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0u8..]\\\"}\"}"
left:
Value:
Integer:
- U8
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[0u8..]"
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[0u8..]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..0u8]\\\"}\"}"
left: ~
right:
Value:
Integer:
- U8
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 8
path: ""
content: "x[..0u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[..0u8]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..]\\\"}\"}"
left: ~
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: "x[..]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..]\\\"}\"}"
left:
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[0u8..1u8]"
right:
Value:
Integer:
- U8
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 8
col_stop: 11
path: ""
content: "x[0u8..1u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 12
path: ""
content: "x[0u8..1u8]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0u8..]\\\"}\"}"
left:
Value:
Integer:
- U8
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[0u8..]"
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[0u8..]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..0u8]\\\"}\"}"
left: ~
right:
Value:
Integer:
- U8
- "0"
- span:
content: "x[x.y..]"
type_: ~
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[x.y..]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..y.x]\\\"}\"}"
left: ~
right:
Access:
Member:
inner:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..y.x]\\\"}\"}"
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..y.x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 8
path: ""
content: "x[..0u8]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[..0u8]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..]\\\"}\"}"
left: ~
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: "x[..]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..]\\\"}\"}"
left:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[x.y..]"
type_: ~
right: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[x.y..]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..y.x]\\\"}\"}"
left: ~
right:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..y.x]\\\"}\"}"
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[..y.x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 8
path: ""
content: "x[..y.x]"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[..y.x]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
left:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[x.y..y.x]"
type_: ~
right:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":8,\\\"col_stop\\\":9,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 8
col_stop: 11
path: ""
content: "x[x.y..y.x]"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 12
path: ""
content: "x[x.y..y.x]"
- ArrayRangeAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
left:
CircuitMemberAccess:
circuit:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
content: "x[..y.x]"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 9
path: ""
content: "x[..y.x]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
left:
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[x.y..y.x]"
type_: ~
right:
Access:
Member:
inner:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":8,\\\"col_stop\\\":9,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y..y.x]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 8
col_stop: 11
path: ""
content: "x[x.y..y.x]"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 12
path: ""
content: "x[x.y..y.x]"
- Access:
ArrayRange:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
left:
Access:
Member:
inner:
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 6
path: ""
content: "x[x.y.x..y.x.y]"
type_: ~
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 8
path: ""
content: "x[x.y.x..y.x.y]"
type_: ~
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 8
path: ""
content: "x[x.y.x..y.x.y]"
type_: ~
right:
CircuitMemberAccess:
circuit:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":12,\\\"col_stop\\\":13,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
right:
Access:
Member:
inner:
Access:
Member:
inner:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
name: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":12,\\\"col_stop\\\":13,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 10
col_stop: 13
path: ""
content: "x[x.y.x..y.x.y]"
type_: ~
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 10
col_stop: 13
col_stop: 15
path: ""
content: "x[x.y.x..y.x.y]"
type_: ~
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[x.y.x..y.x.y]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 10
col_stop: 15
path: ""
content: "x[x.y.x..y.x.y]"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 16
path: ""
content: "x[x.y.x..y.x.y]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 16
path: ""
content: "x[x.y.x..y.x.y]"

View File

@ -65,17 +65,19 @@ outputs:
content: "x(x, y, z)"
- Call:
function:
CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y()"
Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y()"
arguments: []
span:
line_start: 1
@ -86,17 +88,19 @@ outputs:
content: "x::y()"
- Call:
function:
CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y(x)\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y(x)\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y(x)"
Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y(x)\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y(x)\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y(x)"
arguments:
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":6,\\\"col_stop\\\":7,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y(x)\\\"}\"}"
span:
@ -108,18 +112,19 @@ outputs:
content: "x::y(x)"
- Call:
function:
TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0(x)\\\"}\"}"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.0(x)
Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0(x)\\\"}\"}"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.0(x)
arguments:
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0(x)\\\"}\"}"
span:
@ -131,27 +136,28 @@ outputs:
content: x.0(x)
- Call:
function:
ArrayAccess:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0](x)\\\"}\"}"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0](x)"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[0](x)"
Access:
Array:
array:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0](x)\\\"}\"}"
index:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 3
col_stop: 4
path: ""
content: "x[0](x)"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x[0](x)"
arguments:
- Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":6,\\\"col_stop\\\":7,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x[0](x)\\\"}\"}"
span:

View File

@ -2,67 +2,72 @@
namespace: ParseExpression
expectation: Pass
outputs:
- CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y
type_: ~
- CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X.Y\\\"}\"}"
name: "{\"name\":\"Y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X.Y\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: X.Y
type_: ~
- CircuitMemberAccess:
circuit:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.z\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.z\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y.z
type_: ~
name: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.z\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.y.z
type_: ~
- Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y
type_: ~
- Access:
Member:
inner:
Identifier: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X.Y\\\"}\"}"
name: "{\"name\":\"Y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X.Y\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: X.Y
type_: ~
- Access:
Member:
inner:
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.z\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.z\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y.z
type_: ~
name: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.z\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.y.z
type_: ~
- Call:
function:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y()\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y()\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y()
type_: ~
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y()\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y()\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y()
type_: ~
arguments: []
span:
line_start: 1
@ -71,58 +76,62 @@ outputs:
col_stop: 6
path: ""
content: x.y()
- TupleAccess:
tuple:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.0\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.0\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.y.0
type_: ~
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.y.0
- ArrayAccess:
array:
CircuitMemberAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y[1]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y[1]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: "x.y[1]"
type_: ~
index:
Value:
Implicit:
- "1"
- span:
- Access:
Tuple:
tuple:
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.0\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y.0\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
col_start: 1
col_stop: 4
path: ""
content: x.y.0
type_: ~
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.y.0
- Access:
Array:
array:
Access:
Member:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y[1]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.y[1]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: "x.y[1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x.y[1]"
type_: ~
index:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "x.y[1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x.y[1]"

View File

@ -2,62 +2,72 @@
namespace: ParseExpression
expectation: Pass
outputs:
- CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y"
- CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X::Y\\\"}\"}"
name: "{\"name\":\"Y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X::Y\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "X::Y"
- CircuitStaticFunctionAccess:
circuit:
CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y::z\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y::z\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y::z"
name: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y::z\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x::y::z"
- Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y"
- Access:
Static:
inner:
Identifier: "{\"name\":\"X\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X::Y\\\"}\"}"
name: "{\"name\":\"Y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"X::Y\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "X::Y"
- Access:
Static:
inner:
Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y::z\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y::z\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y::z"
name: "{\"name\":\"z\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y::z\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x::y::z"
- Call:
function:
CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y()"
Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y()\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y()"
arguments: []
span:
line_start: 1
@ -66,56 +76,62 @@ outputs:
col_stop: 7
path: ""
content: "x::y()"
- TupleAccess:
tuple:
CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y.0\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y.0\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y.0"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x::y.0"
- ArrayAccess:
array:
CircuitStaticFunctionAccess:
circuit:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y[1]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y[1]\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y[1]"
index:
Value:
Implicit:
- "1"
- span:
- Access:
Tuple:
tuple:
Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y.0\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y.0\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 6
col_stop: 7
col_start: 1
col_stop: 5
path: ""
content: "x::y.0"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 7
path: ""
content: "x::y.0"
- Access:
Array:
array:
Access:
Static:
inner:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y[1]\\\"}\"}"
name: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":4,\\\"col_stop\\\":5,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x::y[1]\\\"}\"}"
type_: ~
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 5
path: ""
content: "x::y[1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x::y[1]"
index:
Value:
Implicit:
- "1"
- span:
line_start: 1
line_stop: 1
col_start: 6
col_stop: 7
path: ""
content: "x::y[1]"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 8
path: ""
content: "x::y[1]"

View File

@ -2,108 +2,117 @@
namespace: ParseExpression
expectation: Pass
outputs:
- TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0\\\"}\"}"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.0
- TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.1\\\"}\"}"
index:
value: "1"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.1
- TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.2\\\"}\"}"
index:
value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.2
- TupleAccess:
tuple:
TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0.0\\\"}\"}"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.0.0
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.0.0
- TupleAccess:
tuple:
TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.1.1\\\"}\"}"
index:
value: "1"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.1.1
index:
value: "1"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.1.1
- TupleAccess:
tuple:
TupleAccess:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.2.2\\\"}\"}"
index:
value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.2.2
index:
value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.2.2
- Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0\\\"}\"}"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.0
- Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.1\\\"}\"}"
index:
value: "1"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.1
- Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.2\\\"}\"}"
index:
value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.2
- Access:
Tuple:
tuple:
Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.0.0\\\"}\"}"
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.0.0
index:
value: "0"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.0.0
- Access:
Tuple:
tuple:
Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.1.1\\\"}\"}"
index:
value: "1"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.1.1
index:
value: "1"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.1.1
- Access:
Tuple:
tuple:
Access:
Tuple:
tuple:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":1,\\\"col_stop\\\":2,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"x.2.2\\\"}\"}"
index:
value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 4
path: ""
content: x.2.2
index:
value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 6
path: ""
content: x.2.2

View File

@ -88,6 +88,28 @@ outputs:
col_stop: 12
path: ""
content: "[0; (1, 2)]"
- ArrayInit:
element:
Value:
Implicit:
- "0"
- span:
line_start: 1
line_stop: 1
col_start: 2
col_stop: 3
path: ""
content: "[0; (1, 2,)]"
dimensions:
- value: "1"
- value: "2"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 13
path: ""
content: "[0; (1, 2,)]"
- ArrayInit:
element:
Value:

Some files were not shown because too many files have changed in this diff Show More