Merge pull request #1587 from AleoHQ/docs/ast

Docs/ast
This commit is contained in:
Collin Chin 2022-02-01 12:59:59 -08:00 committed by GitHub
commit ea191ba734
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 340 additions and 203 deletions

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

@ -148,14 +148,14 @@ impl ParserContext<'_> {
/// 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 (out, ..) = self.parse_paren_comma_list(|p| p.parse_package_access().map(Some))?;
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() {
self.emit_err(ParserError::invalid_import_list(span));
self.emit_err(ParserError::invalid_import_list(&end));
}
Ok(out)
Ok((out, start + &end))
}
///
@ -262,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_is_left_par() {
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,
}))
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 }))
}
}

View File

@ -2,4 +2,4 @@
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370002]: Cannot import empty list\n --> test:3:8\n |\n 3 | import a.();\n | ^\nError [EPAR0370002]: Cannot import empty list\n --> test:5:8\n |\n 5 | import a.();\n | ^"
- "Error [EPAR0370002]: Cannot import empty list\n --> test:3:10\n |\n 3 | import a.();\n | ^^\nError [EPAR0370002]: Cannot import empty list\n --> test:5:10\n |\n 5 | import a.();\n | ^^"

View File

@ -31,18 +31,18 @@ outputs:
content: " foo,"
span:
line_start: 3
line_stop: 5
line_stop: 6
col_start: 8
col_stop: 8
col_stop: 2
path: ""
content: "import test-import.( // local import\n ...\n foo,"
content: "import test-import.( // local import\n ...\n ...\n);"
span:
line_start: 3
line_stop: 5
line_stop: 6
col_start: 8
col_stop: 8
col_stop: 2
path: ""
content: "import test-import.( // local import\n ...\n foo,"
content: "import test-import.( // local import\n ...\n ...\n);"
- package_or_packages:
Packages:
name: "{\"name\":\"bar\",\"span\":\"{\\\"line_start\\\":8,\\\"line_stop\\\":8,\\\"col_start\\\":8,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"import bar.( // imports directory import\\\"}\"}"
@ -84,7 +84,7 @@ outputs:
line_start: 10
line_stop: 10
col_start: 5
col_stop: 21
col_stop: 22
path: ""
content: " baz.(Baz, Bazzar),"
- SubPackage:
@ -119,18 +119,18 @@ outputs:
content: " bat.bat.Bat,"
span:
line_start: 8
line_stop: 11
line_stop: 12
col_start: 8
col_stop: 16
col_stop: 2
path: ""
content: "import bar.( // imports directory import\n ...\n ...\n bat.bat.Bat,"
content: "import bar.( // imports directory import\n ...\n ...\n ...\n);"
span:
line_start: 8
line_stop: 11
line_stop: 12
col_start: 8
col_stop: 16
col_stop: 2
path: ""
content: "import bar.( // imports directory import\n ...\n ...\n bat.bat.Bat,"
content: "import bar.( // imports directory import\n ...\n ...\n ...\n);"
imports: {}
aliases: {}
circuits: {}