merge testnet3 into required types, also remove identifier type

This commit is contained in:
gluax 2022-05-02 19:43:46 -07:00
commit a7c3696e90
1396 changed files with 9540 additions and 29089 deletions

View File

@ -46,7 +46,7 @@ commands:
jobs:
check-style:
docker:
- image: cimg/rust:1.56.1
- image: cimg/rust:1.59.0
resource_class: xlarge
steps:
- checkout
@ -61,7 +61,7 @@ jobs:
clippy:
docker:
- image: cimg/rust:1.56.1
- image: cimg/rust:1.59.0
resource_class: xlarge
steps:
- checkout
@ -76,7 +76,7 @@ jobs:
# code-cov:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# environment:
# RUSTC_BOOTSTRAP: 1
@ -118,7 +118,7 @@ jobs:
leo-executable:
docker:
- image: cimg/rust:1.56.1
- image: cimg/rust:1.59.0
resource_class: xlarge
steps:
- checkout
@ -136,7 +136,7 @@ jobs:
#
# leo-new:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -149,7 +149,7 @@ jobs:
#
# leo-init:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -162,7 +162,7 @@ jobs:
#
# leo-clean:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -175,7 +175,7 @@ jobs:
#
# leo-setup:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -188,7 +188,7 @@ jobs:
# leo-add-remove:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -202,7 +202,7 @@ jobs:
# todo (collin): uncomment after compiler refactor
# leo-check-constraints:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -215,7 +215,7 @@ jobs:
#
# leo-login-logout:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -228,7 +228,7 @@ jobs:
#
# leo-clone:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:
@ -241,7 +241,7 @@ jobs:
#
# leo-publish:
# docker:
# - image: cimg/rust:1.56.1
# - image: cimg/rust:1.59.0
# resource_class: xlarge
# steps:
# - attach_workspace:

3
.gitattributes vendored
View File

@ -1,4 +1,5 @@
# Force certain files to be LF
*.leo text eol=lf
*.out text eol=lf
*.rs text eol=lf
*.rs text eol=lf
*.in text eol=lf

View File

@ -18,14 +18,13 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macOS-latest, windows-latest, ubuntu-latest]
os: [macOS-latest, ubuntu-latest]
include:
- os: ubuntu-latest
sccache-path: /home/runner/.cache/sccache
- os: macos-latest
sccache-path: /Users/runner/Library/Caches/Mozilla.sccache
- os: windows-latest
sccache-path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache"
env:
RUSTC_WRAPPER: sccache
SCCACHE_CACHE_SIZE: 2G
@ -54,14 +53,6 @@ jobs:
brew update
brew install sccache
- name: Install sccache Windows
if: matrix.os == 'windows-latest'
run: |
iwr -useb get.scoop.sh | iex
Set-ExecutionPolicy RemoteSigned -scope CurrentUser
scoop install sccache
echo "C:\Users\runneradmin\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install Rust Stable
uses: actions-rs/toolchain@v1
with:
@ -169,6 +160,24 @@ jobs:
- name: Stop sccache server
run: sccache --stop-server || true
test-package-windows:
name: Test Package Windows
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Rust Stable
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Test
run: |
cargo test --all
test-docs:
name: Test Docs
runs-on: ubuntu-latest

2
.gitignore vendored
View File

@ -2,6 +2,8 @@
/tmp/
**.idea/
*.DS_Store
.vscode
leo.iml
**/process.yml

1255
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -46,10 +46,17 @@ version = "1.5.3"
path = "./leo/package"
version = "1.5.3"
[dependencies.leo-span]
path = "./leo/span"
version = "1.5.3"
[dependencies.snarkvm-utilities]
git = "https://github.com/AleoHQ/snarkVM.git"
rev = "51633e2"
[dependencies.backtrace]
version = "0.3.65"
[dependencies.clap]
version = "3.1"
@ -59,12 +66,12 @@ version = "0.5.1"
[dependencies.colored]
version = "2.0"
[dependencies.dirs]
version = "4.0.0"
[dependencies.console]
version = "0.15.0"
[dependencies.dirs]
version = "4.0.0"
[dependencies.indexmap]
version = "1.8"
features = ["serde"]
@ -82,11 +89,11 @@ version = "0.8"
version = "0.6.3"
[dependencies.reqwest]
version = "0.11.9"
version = "0.11.10"
features = [ "blocking", "json", "multipart" ]
[dependencies.self_update]
version = "0.28.0"
version = "0.30.0"
features = [ "archive-zip" ]
[dependencies.serde]
@ -99,6 +106,9 @@ version = "1.0"
[dependencies.structopt]
version = "0.3"
[dependencies.sys-info]
version = "0.9.1"
[dependencies.toml]
version = "0.5"
@ -106,11 +116,11 @@ version = "0.5"
version = "0.1"
[dependencies.tracing-subscriber]
version = "0.3.6"
version = "0.3.11"
features = [ "fmt" ]
[dependencies.zip]
version = "0.5"
version = "0.6"
[target."cfg(windows)".dependencies.ansi_term]
version = "0.12.1"
@ -122,7 +132,7 @@ version = "2.0.4"
version = "0.11.2"
[dev-dependencies.test_dir]
version = "0.1.0"
version = "0.2.0"
[features]
default = [ ]

View File

@ -18,9 +18,6 @@ license = "GPL-3.0"
edition = "2021"
rust-version = "1.56"
[dependencies]
smallvec = { version = "1.8.0", features = ["serde"] }
[dependencies.leo-errors]
path = "../../leo/errors"
version = "1.5.3"
@ -41,8 +38,9 @@ features = [ "derive", "rc" ]
version = "1.0"
features = [ "preserve_order" ]
[dependencies.tendril]
version = "0.4"
[dependencies.smallvec]
version = "1.8.0"
features = ["serde"]
[dev-dependencies.criterion]
version = "0.3"

View File

@ -1,49 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_span::Span;
use std::fmt;
use serde::{Deserialize, Serialize};
/// An array element access expression `array[index]`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArrayAccess {
/// The expression, evaluating to an array, that is being indexed.
pub array: Box<Expression>,
/// The index in `array` that is being accessed.
pub index: Box<Expression>,
/// The span of the entire expression `array[index]`.
pub span: Span,
}
impl fmt::Display for ArrayAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}[{}]", self.array, self.index)
}
}
impl Node for ArrayAccess {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,59 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_span::Span;
use std::fmt;
use serde::{Deserialize, Serialize};
/// An access to a certain range of elements in an `array`.
///
/// Examples include `array[0..3]`, `array[3..]`, `array[..3]`, and `array[..]`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ArrayRangeAccess {
/// The array to extract a range of elements from.
pub array: Box<Expression>,
/// The lower bound of the index-range, or the start of the array when `None`.
pub left: Option<Box<Expression>>,
/// The higher bound of the index-range, or the end of the array when `None`.
pub right: Option<Box<Expression>>,
/// A span for the entire expression `array[<range>]`.
pub span: Span,
}
impl fmt::Display for ArrayRangeAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}[{}..{}]",
self.array,
self.left.as_ref().map(|e| e.to_string()).unwrap_or_default(),
self.right.as_ref().map(|e| e.to_string()).unwrap_or_default()
)
}
}
impl Node for ArrayRangeAccess {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,54 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Identifier, Node};
use leo_span::Span;
use std::fmt;
use serde::{Deserialize, Serialize};
/// A field access expression `inner.name` to some structure with *named fields*.
///
/// For accesses to a positional fields in e.g., a tuple, see `TupleAccess`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MemberAccess {
/// The structure that the field `name` is being extracted from.
pub inner: Box<Expression>,
/// The name of the field to extract in `inner`.
pub name: Identifier,
/// The span covering all of `inner.name`.
pub span: Span,
// FIXME(Centril): Type information shouldn't be injected into an AST,
// so this field should eventually be removed.
pub type_: Option<crate::Type>,
}
impl fmt::Display for MemberAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.inner, self.name)
}
}
impl Node for MemberAccess {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,30 +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/>.
mod array_access;
pub use array_access::*;
mod array_range_access;
pub use array_range_access::*;
mod member_access;
pub use member_access::*;
mod tuple_access;
pub use tuple_access::*;
mod static_access;
pub use static_access::*;

View File

@ -1,49 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node, PositiveNumber};
use leo_span::Span;
use std::fmt;
use serde::{Deserialize, Serialize};
/// An tuple access expression, e.g., `tuple.index`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TupleAccess {
/// An expression evaluating to some tuple type, e.g., `(5, 2)`.
pub tuple: Box<Expression>,
/// The index to access in the tuple expression. E.g., `0` for `(5, 2)` would yield `5`.
pub index: PositiveNumber,
/// The span for the entire expression `tuple.index`.
pub span: Span,
}
impl fmt::Display for TupleAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.tuple, self.index)
}
}
impl Node for TupleAccess {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,42 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Type};
use leo_span::Span;
use std::fmt;
use serde::{Deserialize, Serialize};
/// A type alias `type name = represents;`.
///
/// That is, `name` will become another name for `represents`.
/// This does not create a new type, that is, `name` is the same type as `represents`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Alias {
/// The new name for `represents`.
pub name: Identifier,
/// A span for the entire `type name = represents;`.
pub span: Span,
/// The type that `name` will evaluate and is equal to.
pub represents: Type,
}
impl fmt::Display for Alias {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} : {}", self.name.name, self.represents)
}
}

View File

@ -1,18 +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/>.
pub mod alias;
pub use self::alias::*;

View File

@ -1,52 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::Identifier;
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)
}
}
impl fmt::Display for Annotation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "@{:}(", self.name)?;
for arg in &self.arguments {
write!(f, "{:},", arg)?;
}
write!(f, ")")
}
}

View File

@ -48,11 +48,23 @@ impl fmt::Display for Char {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Scalar(c) => write!(f, "{}", c),
Self::NonScalar(c) => write!(f, "{}", c),
Self::NonScalar(c) => write!(f, "{:X}", c),
}
}
}
pub struct Chars(pub Vec<Char>);
impl fmt::Display for Chars {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for character in self.0.iter() {
write!(f, "{}", character)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CharValue {
pub character: Char,

View File

@ -1,56 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{CircuitMember, Identifier};
use serde::{Deserialize, Serialize};
use std::fmt;
/// A record type definition, e.g., `circuit Foo { my_field: Bar }`.
/// In some languages these are called `struct`s.
///
/// Type identity is decided by the full path including `circuit_name`,
/// as the record is nominal, not structural.
/// The fields are named so `circuit Foo(u8, u16)` is not allowed.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Circuit {
/// The name of the type in the type system in this module.
pub circuit_name: Identifier,
/// The fields, constant variables, and functions of this structure.
pub members: Vec<CircuitMember>,
}
impl Circuit {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "circuit {} {{ ", self.circuit_name)?;
for field in self.members.iter() {
writeln!(f, " {}", field)?;
}
write!(f, "}}")
}
}
impl fmt::Debug for Circuit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Display for Circuit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}

View File

@ -1,63 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Function, Identifier, Type};
use serde::{Deserialize, Serialize};
use std::fmt;
#[allow(clippy::large_enum_variant)]
/// A member of a circuit definition.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CircuitMember {
/// A static constant in a circuit.
/// For example: `const foobar: u8 = 42;`.
CircuitConst(
/// The identifier of the constant.
Identifier,
/// The type the constant has.
Type,
/// The expression representing the constant's value.
/// Checked to be of the type above.
Expression,
),
/// A varible definition in a circuit;
/// For example: `foobar: u8;`.
CircuitVariable(
/// The identifier of the constant.
Identifier,
/// The type the constant has.
Type,
),
/// A function definition in a circuit.
/// For example: `function bar() -> u8 { return 2u8; }`.
CircuitFunction(
/// The function.
Box<Function>,
),
}
impl fmt::Display for CircuitMember {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CircuitMember::CircuitConst(ref identifier, ref type_, ref value) => {
write!(f, "{}: {} = {}", identifier, type_, value)
}
CircuitMember::CircuitVariable(ref identifier, ref type_) => write!(f, "{}: {}", identifier, type_),
CircuitMember::CircuitFunction(ref function) => write!(f, "{}", function),
}
}
}

View File

@ -1,25 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Identifier};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CircuitVariableDefinition {
pub identifier: Identifier,
pub expression: Expression,
}

View File

@ -1,86 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::PositiveNumber;
use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
use smallvec::{smallvec, SmallVec};
use std::{fmt, ops::Deref};
/// Specifies array dimensions for array [`Type`]s or in array initializer [`Expression`]s.
#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)]
pub struct ArrayDimensions(pub SmallVec<[PositiveNumber; 1]>);
impl Deref for ArrayDimensions {
type Target = [PositiveNumber];
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl ArrayDimensions {
/// Returns a single-dimensional array dimension.
pub fn single(dim: PositiveNumber) -> Self {
Self(smallvec![dim])
}
/// Returns `true` if there is an array dimension equal to zero.
pub fn is_zero(&self) -> bool {
self.iter().any(|d| d.is_zero())
}
/// Attempts to remove the first dimension from the array, or returns `None` if it doesn't.
pub fn remove_first(&mut self) -> Option<PositiveNumber> {
if self.is_empty() {
None
} else {
Some(self.0.remove(0))
}
}
/// Attempts to remove the last dimension from the array, or returns `None` if it doesn't.
pub fn remove_last(&mut self) -> Option<PositiveNumber> {
self.0.pop()
}
}
/// Custom Serializer for ArrayDimensions is required to ignore internal ArrayDimension nodes in the AST.
impl Serialize for ArrayDimensions {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
for dim in self.0.iter() {
seq.serialize_element(&dim)?;
}
seq.end()
}
}
impl fmt::Display for ArrayDimensions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &*self.0 {
[dim] => write!(f, "{}", dim),
dimensions => write!(
f,
"({})",
dimensions.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ")
),
}
}
}

View File

@ -1,46 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// The `self` keyword can view circuit values inside of a circuit function.
/// Circuit values cannot be modified. To modify values use the `mut self` [MutSelfKeyword].
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct ConstSelfKeyword {
/// Always `const self`.
pub identifier: Identifier,
}
impl fmt::Display for ConstSelfKeyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "const self")
}
}
impl Node for ConstSelfKeyword {
fn span(&self) -> &Span {
&self.identifier.span
}
fn set_span(&mut self, span: Span) {
self.identifier.span = span;
}
}

View File

@ -32,13 +32,13 @@ use std::{
/// An identifier in the constrained program.
///
/// Attention - When adding or removing fields from this struct,
/// please remember to update it's Serialize and Deserialize implementation
/// please remember to update its Serialize and Deserialize implementation
/// 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.
/// A span locating where the identifier occurred in the source.
pub span: Span,
}

View File

@ -14,12 +14,6 @@
// 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/>.
pub mod array_dimensions;
pub use array_dimensions::*;
pub mod const_self_keyword;
pub use const_self_keyword::*;
pub mod global_consts_json;
pub mod identifier;
@ -28,16 +22,5 @@ pub use identifier::*;
pub mod imported_modules;
pub use imported_modules::*;
pub mod mut_self_keyword;
pub use mut_self_keyword::*;
pub mod positive_number;
pub use positive_number::*;
pub mod self_keyword;
pub use self_keyword::*;
pub mod spread_or_expression;
pub use spread_or_expression::*;
pub mod vec_tendril_json;

View File

@ -1,45 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// The `&self` keyword can view and modify circuit values inside of a circuit function.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct RefSelfKeyword {
/// Always `&self`.
pub identifier: Identifier,
}
impl fmt::Display for RefSelfKeyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "&self")
}
}
impl Node for RefSelfKeyword {
fn span(&self) -> &Span {
&self.identifier.span
}
fn set_span(&mut self, span: Span) {
self.identifier.span = span;
}
}

View File

@ -16,21 +16,19 @@
use serde::{Deserialize, Serialize};
use std::fmt;
use tendril::StrTendril;
/// A number string guaranteed to be positive by the pest grammar.
/// A number string guaranteed to be positive.
#[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,
pub value: String,
}
impl PositiveNumber {
/// Returns `true` if this number is zero.
pub fn is_zero(&self) -> bool {
self.value.as_ref().eq("0")
self.value.eq("0")
}
}

View File

@ -1,46 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// The `self` keyword can view circuit values inside of a circuit function.
/// Circuit values cannot be modified. To modify values use the `mut self` [MutSelfKeyword].
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct SelfKeyword {
/// Always just `self`.
pub identifier: Identifier,
}
impl fmt::Display for SelfKeyword {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "self")
}
}
impl Node for SelfKeyword {
fn span(&self) -> &Span {
&self.identifier.span
}
fn set_span(&mut self, span: Span) {
self.identifier.span = span;
}
}

View File

@ -1,55 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// 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),
}
impl fmt::Display for SpreadOrExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SpreadOrExpression::Spread(ref spread) => write!(f, "...{}", spread),
SpreadOrExpression::Expression(ref expression) => write!(f, "{}", expression),
}
}
}
impl Node for SpreadOrExpression {
fn span(&self) -> &Span {
use SpreadOrExpression::*;
match self {
Spread(expression) | Expression(expression) => expression.span(),
}
}
fn set_span(&mut self, span: Span) {
use SpreadOrExpression::*;
match self {
Spread(expression) | Expression(expression) => expression.set_span(span),
}
}
}

View File

@ -1,34 +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 serde::{Deserialize, Deserializer, Serialize, Serializer};
use tendril::StrTendril;
#[allow(clippy::ptr_arg)]
pub fn serialize<S: Serializer>(tendril: &Vec<StrTendril>, serializer: S) -> Result<S::Ok, S::Error> {
tendril
.iter()
.map(|x| x.as_ref())
.collect::<Vec<_>>()
.serialize(serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<StrTendril>, D::Error> {
Ok(Vec::<String>::deserialize(deserializer)?
.into_iter()
.map(|x| x.into())
.collect())
}

View File

@ -1,73 +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::*;
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),
}
impl fmt::Display for AccessExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use AccessExpression::*;
match self {
Array(access) => access.fmt(f),
ArrayRange(access) => access.fmt(f),
Member(access) => access.fmt(f),
Tuple(access) => access.fmt(f),
Static(access) => access.fmt(f),
}
}
}
impl Node for AccessExpression {
fn span(&self) -> &Span {
use AccessExpression::*;
match &self {
Array(access) => access.span(),
ArrayRange(access) => access.span(),
Member(access) => access.span(),
Tuple(access) => access.span(),
Static(access) => access.span(),
}
}
fn set_span(&mut self, span: Span) {
use AccessExpression::*;
match self {
Array(access) => access.set_span(span),
ArrayRange(access) => access.set_span(span),
Member(access) => access.set_span(span),
Tuple(access) => access.set_span(span),
Static(access) => access.set_span(span),
}
}
}

View File

@ -1,48 +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::*;
/// 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,
}
impl fmt::Display for ArrayInitExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}; {}]", self.element, self.dimensions)
}
}
impl Node for ArrayInitExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,51 +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::*;
/// 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,
}
impl fmt::Display for ArrayInlineExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[")?;
for (i, e) in self.elements.iter().enumerate() {
write!(f, "{}", e)?;
if i < self.elements.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "]")
}
}
impl Node for ArrayInlineExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,46 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::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,
}
impl fmt::Display for CastExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} as {}", self.inner, self.target_type)
}
}
impl Node for CastExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -1,73 +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::*;
/// An initializer for a single field / variable of a circuit initializer expression.
/// That is, in `Foo { bar: 42, baz }`, this is either `bar: 42`, or `baz`.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CircuitVariableInitializer {
/// The name of the field / variable to be initialized.
pub identifier: Identifier,
/// The expression to initialize the field with.
/// When `None`, a binding, in scope, with the name will be used instead.
pub expression: Option<Expression>,
}
impl fmt::Display for CircuitVariableInitializer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(expr) = &self.expression {
write!(f, "{}: {}", self.identifier, expr)
} else {
write!(f, "{}", self.identifier)
}
}
}
/// A circuit initialization expression, e.g., `Foo { bar: 42, baz }`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CircuitInitExpression {
/// The name of the structure type to initialize.
pub name: Identifier,
/// Initializer expressions for each of the fields in the circuit.
///
/// N.B. Any functions or member constants in the circuit definition
/// are excluded from this list.
pub members: Vec<CircuitVariableInitializer>,
/// A span from `name` to `}`.
pub span: Span,
}
impl fmt::Display for CircuitInitExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {{", self.name)?;
for member in self.members.iter() {
write!(f, "{}", member)?;
write!(f, ", ")?;
}
write!(f, "}}")
}
}
impl Node for CircuitInitExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -14,35 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ArrayDimensions, GroupValue, Identifier, IntegerType, Node, SpreadOrExpression};
use crate::{GroupValue, Identifier, IntegerType, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
mod accesses;
pub use accesses::*;
mod binary;
pub use binary::*;
mod unary;
pub use unary::*;
mod ternary;
pub use ternary::*;
mod array_inline;
pub use array_inline::*;
mod array_init;
pub use array_init::*;
mod tuple_init;
pub use tuple_init::*;
mod circuit_init;
pub use circuit_init::*;
mod value;
pub use value::*;
mod call;
pub use call::*;
mod cast;
pub use cast::*;
mod err;
pub use err::*;
@ -59,19 +47,6 @@ pub enum 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".
@ -88,13 +63,7 @@ impl Node for Expression {
Binary(n) => n.span(),
Unary(n) => n.span(),
Ternary(n) => n.span(),
ArrayInline(n) => n.span(),
ArrayInit(n) => n.span(),
TupleInit(n) => n.span(),
CircuitInit(n) => n.span(),
Call(n) => n.span(),
Cast(n) => n.span(),
Access(n) => n.span(),
Err(n) => n.span(),
}
}
@ -107,13 +76,7 @@ impl Node for Expression {
Binary(n) => n.set_span(span),
Unary(n) => n.set_span(span),
Ternary(n) => n.set_span(span),
ArrayInline(n) => n.set_span(span),
ArrayInit(n) => n.set_span(span),
TupleInit(n) => n.set_span(span),
CircuitInit(n) => n.set_span(span),
Call(n) => n.set_span(span),
Cast(n) => n.set_span(span),
Access(n) => n.set_span(span),
Err(n) => n.set_span(span),
}
}
@ -128,13 +91,7 @@ impl fmt::Display for Expression {
Binary(n) => n.fmt(f),
Unary(n) => n.fmt(f),
Ternary(n) => n.fmt(f),
ArrayInline(n) => n.fmt(f),
ArrayInit(n) => n.fmt(f),
TupleInit(n) => n.fmt(f),
CircuitInit(n) => n.fmt(f),
Call(n) => n.fmt(f),
Cast(n) => n.fmt(f),
Access(n) => n.fmt(f),
Err(n) => n.fmt(f),
}
}

View File

@ -1,50 +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::*;
/// 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,
}
impl fmt::Display for TupleInitExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(")?;
for (i, member) in self.elements.iter().enumerate() {
write!(f, "{}", member)?;
if i < self.elements.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
impl Node for TupleInitExpression {
fn span(&self) -> &Span {
&self.span
}
fn set_span(&mut self, span: Span) {
self.span = span;
}
}

View File

@ -14,8 +14,6 @@
// 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::StrTendril;
use super::*;
use crate::{Char, CharValue};
@ -24,37 +22,21 @@ use crate::{Char, CharValue};
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,
),
Address(String, #[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,
),
Boolean(String, #[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,
),
Field(String, #[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,
),
Implicit(String, #[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,
),
Integer(IntegerType, String, #[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

@ -14,10 +14,9 @@
// 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::{Annotation, Block, FunctionInput, Identifier, Node, Type};
use crate::{Block, FunctionInput, Identifier, Node, Type};
use leo_span::{sym, Span, Symbol};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::cell::Cell;
use std::fmt;
@ -25,8 +24,6 @@ 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.
@ -63,29 +60,6 @@ impl Function {
self.name() == sym::main
}
///
/// Returns `true` if the function has input `self` or `mut self`.
/// Returns `false` otherwise.
///
pub fn contains_self(&self) -> bool {
self.input.iter().any(|param| param.is_self())
}
///
/// Returns `true` if the function has input `mut self`.
/// Returns `false` otherwise.
///
pub fn contains_mut_self(&self) -> bool {
self.input.iter().any(|param| param.is_mut_self())
}
///
/// Returns an iterator of [&FunctionInput] removing `self` and `mut self` inputs.
///
pub fn filter_self_inputs(&self) -> impl Iterator<Item = &FunctionInput> {
self.input.iter().filter(|input| !input.is_self())
}
///
/// Private formatting method used for optimizing [fmt::Debug] and [fmt::Display] implementations.
///

View File

@ -20,30 +20,60 @@ use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ParamMode {
Constant,
Private,
Public,
}
impl fmt::Display for ParamMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ParamMode::*;
match self {
Constant => write!(f, "constant"),
Private => write!(f, "private"),
Public => write!(f, "public"),
}
}
}
/// 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,
/// The mode of the function parameter.
mode: ParamMode,
/// What's the parameter's type?
pub type_: Type,
type_: Type,
/// The parameters span from any annotations to its type.
pub span: Span,
}
impl FunctionInputVariable {
pub fn new(identifier: Identifier, mode: ParamMode, type_: Type, span: Span) -> Self {
Self {
identifier,
mode,
type_,
span,
}
}
pub fn mode(&self) -> ParamMode {
self.mode
}
pub fn type_(&self) -> Type {
self.type_.clone()
}
}
impl FunctionInputVariable {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
// mut var: bool
if self.const_ {
write!(f, "const ")?;
}
if self.mutable {
write!(f, "mut ")?;
}
write!(f, "{} ", self.mode)?;
write!(f, "{}: ", self.identifier)?;
write!(f, "{}", self.type_)
}

View File

@ -14,7 +14,7 @@
// 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::{ConstSelfKeyword, FunctionInputVariable, Node, RefSelfKeyword, SelfKeyword};
use crate::{FunctionInputVariable, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -23,74 +23,24 @@ 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),
}
impl FunctionInput {
///
/// Returns `true` if the function input is the `self` or `mut self` keyword.
/// Returns `false` otherwise.
///
pub fn is_self(&self) -> bool {
match self {
FunctionInput::SelfKeyword(_) => true,
FunctionInput::ConstSelfKeyword(_) => true,
FunctionInput::RefSelfKeyword(_) => true,
FunctionInput::Variable(_) => false,
}
}
///
/// Returns `true` if the function input is the `const self` keyword.
/// Returns `false` otherwise.
///
pub fn is_const_self(&self) -> bool {
match self {
FunctionInput::SelfKeyword(_) => false,
FunctionInput::ConstSelfKeyword(_) => true,
FunctionInput::RefSelfKeyword(_) => false,
FunctionInput::Variable(_) => false,
}
}
///
/// Returns `true` if the function input is the `mut self` keyword.
/// Returns `false` otherwise.
///
pub fn is_mut_self(&self) -> bool {
match self {
FunctionInput::SelfKeyword(_) => false,
FunctionInput::ConstSelfKeyword(_) => false,
FunctionInput::RefSelfKeyword(_) => true,
FunctionInput::Variable(_) => false,
}
}
///
/// Returns Option with FunctionInputVariable if the input is a variable.
/// Returns None otherwise.
///
pub fn get_variable(&self) -> Option<&FunctionInputVariable> {
if let FunctionInput::Variable(var) = self {
Some(var)
} else {
None
pub fn get_variable(&self) -> &FunctionInputVariable {
match self {
Self::Variable(var) => var,
}
}
/// Formats the parameter to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionInput::SelfKeyword(keyword) => write!(f, "{}", keyword),
FunctionInput::ConstSelfKeyword(keyword) => write!(f, "{}", keyword),
FunctionInput::RefSelfKeyword(keyword) => write!(f, "{}", keyword),
FunctionInput::Variable(function_input) => write!(f, "{}", function_input),
}
}
@ -112,11 +62,7 @@ impl PartialEq for FunctionInput {
/// Returns true if `self == other`. Does not compare spans.
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(FunctionInput::SelfKeyword(_), FunctionInput::SelfKeyword(_)) => true,
(FunctionInput::ConstSelfKeyword(_), FunctionInput::ConstSelfKeyword(_)) => true,
(FunctionInput::RefSelfKeyword(_), FunctionInput::RefSelfKeyword(_)) => true,
(FunctionInput::Variable(left), FunctionInput::Variable(right)) => left.eq(right),
_ => false,
}
}
}
@ -127,9 +73,6 @@ impl Node for FunctionInput {
fn span(&self) -> &Span {
use FunctionInput::*;
match self {
SelfKeyword(keyword) => &keyword.identifier.span,
ConstSelfKeyword(keyword) => &keyword.identifier.span,
RefSelfKeyword(keyword) => &keyword.identifier.span,
Variable(variable) => &variable.span,
}
}
@ -137,9 +80,6 @@ impl Node for FunctionInput {
fn set_span(&mut self, span: Span) {
use FunctionInput::*;
match self {
SelfKeyword(keyword) => keyword.identifier.span = span,
ConstSelfKeyword(keyword) => keyword.identifier.span = span,
RefSelfKeyword(keyword) => keyword.identifier.span = span,
Variable(variable) => variable.span = span,
}
}

View File

@ -18,16 +18,12 @@ use leo_span::Span;
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,
),
Number(String, #[serde(with = "leo_span::span_json")] Span),
/// A sign high recovery, i.e. `+`.
SignHigh,
/// A sign low recovery, i.e., `-`.

View File

@ -19,16 +19,12 @@ use leo_span::Span;
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,
),
Single(String, #[serde(with = "leo_span::span_json")] Span),
/// An affine group literal with (x, y) coordinates.
Tuple(GroupTuple),
}

View File

@ -1,119 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::Identifier;
use leo_span::{Span, Symbol};
use serde::{Deserialize, Serialize};
use std::fmt;
/// Represents an import statement in a Leo program.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct ImportStatement {
/// The tree specifying what items or packages to import.
pub tree: ImportTree,
/// The span, excluding the `;`.
pub span: Span,
}
impl ImportStatement {
/// Returns the the package file name of the self import statement.
pub fn get_file_name(&self) -> Symbol {
self.tree.base.first().unwrap().name
}
}
impl fmt::Display for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "import {};", self.tree)
}
}
impl fmt::Debug for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
/// An import tree specifies item(s) to import.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct ImportTree {
/// A path to the base item or package to import or import from.
/// The list is always non-empty.
pub base: Vec<Identifier>,
/// Specifies the kind of import and the meaning of `base`.
/// This includes plain imports, renames, globs (`*`), and nested imports.
pub kind: ImportTreeKind,
/// The span for the import excluding `import` and `;`.
pub span: Span,
}
impl fmt::Display for ImportTree {
/// Formats `self` to `f`.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Format the path.
for (i, part) in self.base.iter().enumerate() {
write!(f, "{}", part)?;
if i < self.base.len() - 1 {
write!(f, ".")?;
}
}
// Format the kind.
match &self.kind {
ImportTreeKind::Glob { .. } => write!(f, ".*"),
ImportTreeKind::Leaf { alias: None } => Ok(()),
ImportTreeKind::Leaf { alias: Some(alias) } => write!(f, "as {}", alias),
ImportTreeKind::Nested { tree } => {
write!(f, ".(")?;
for (i, node) in tree.iter().enumerate() {
write!(f, "{}", node)?;
if i < tree.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl fmt::Debug for ImportTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
/// Specifies the import kind and the meaning of `base`.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum ImportTreeKind {
/// A glob import `*`.
Glob {
/// The span for the `*`.
span: Span,
},
/// A leaf package to import.
Leaf {
/// When specified, the package is imported under a different name.
/// Otherwise, the `base` name is used as in the `ImportTree`.
alias: Option<Identifier>,
},
/// A nested import of items or sub-packages.
Nested {
/// The sub-tree specifying what to import from the `base`.
tree: Vec<ImportTree>,
},
}

View File

@ -15,12 +15,13 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use super::*;
use crate::{Expression, Identifier, Type};
use crate::{Expression, Identifier, ParamMode, Type};
/// A single definition inside a section in a state or an input file.
/// Definitions should be structured as: `<name>: <type_> = <value>;`
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Definition {
pub mode: ParamMode,
pub type_: Type,
pub name: Identifier,
pub value: Expression,

View File

@ -14,8 +14,10 @@
// 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::{normalize_json_value, remove_key_from_json};
use super::*;
use leo_errors::AstError;
use leo_errors::{AstError, Result};
/// Input data which includes [`ProgramInput`] and [`ProgramState`].
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
@ -24,16 +26,44 @@ pub struct Input {
pub program_state: ProgramState,
}
/// A raw unprocessed input or state file data. Used for future conversion
/// into [`ProgramInput`] or [`ProgramState`].
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ParsedInputFile {
pub sections: Vec<Section>,
}
impl Input {
/// Serializes the ast into a JSON string.
pub fn to_json_string(&self) -> Result<String> {
Ok(serde_json::to_string_pretty(&self).map_err(|e| AstError::failed_to_convert_ast_to_json_string(&e))?)
}
}
/// A raw unprocessed input or state file data. Used for future conversion
/// into [`ProgramInput`] or [`ProgramState`].
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct InputAst {
pub sections: Vec<Section>,
}
impl InputAst {
/// Serializes the `Input` into a JSON Value.
pub fn to_json_value(&self) -> Result<serde_json::Value> {
Ok(serde_json::to_value(&self).map_err(|e| AstError::failed_to_convert_ast_to_json_value(&e))?)
}
/// Serializes the `Input` into a JSON value and removes keys from object mappings before writing to a file.
pub fn to_json_file_without_keys(
&self,
mut path: std::path::PathBuf,
file_name: &str,
excluded_keys: &[&str],
) -> Result<()> {
path.push(file_name);
let file = std::fs::File::create(&path).map_err(|e| AstError::failed_to_create_ast_json_file(&path, &e))?;
let writer = std::io::BufWriter::new(file);
let mut value = self.to_json_value().unwrap();
for key in excluded_keys {
value = remove_key_from_json(value, key);
}
value = normalize_json_value(value);
Ok(serde_json::to_writer_pretty(writer, &value)
.map_err(|e| AstError::failed_to_write_ast_to_json_file(&path, &e))?)
}
}

View File

@ -14,7 +14,7 @@
// 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::{CharValue, Expression, GroupValue, IntegerType, Node, SpreadOrExpression, Type, ValueExpression};
use crate::{CharValue, Expression, GroupValue, IntegerType, Node, Type, UnaryOperation, ValueExpression};
use leo_errors::{InputError, LeoError, ParserError, Result};
use serde::{Deserialize, Serialize};
@ -28,8 +28,6 @@ pub enum InputValue {
Field(String),
Group(GroupValue),
Integer(IntegerType, String),
Array(Vec<InputValue>),
Tuple(Vec<InputValue>),
}
impl TryFrom<(Type, Expression)> for InputValue {
@ -38,108 +36,31 @@ impl TryFrom<(Type, Expression)> for InputValue {
Ok(match value {
(type_, Expression::Value(value)) => {
match (type_, value) {
(Type::Address, ValueExpression::Address(value, _)) => Self::Address(value.to_string()),
(Type::Address, ValueExpression::Address(value, _)) => Self::Address(value),
(Type::Boolean, ValueExpression::Boolean(value, span)) => {
let bool_value = value.parse::<bool>().map_err(|_| ParserError::unexpected_eof(&span))?; // TODO: change error
Self::Boolean(bool_value)
}
(Type::Char, ValueExpression::Char(value)) => Self::Char(value),
(Type::Field, ValueExpression::Field(value, _) | ValueExpression::Implicit(value, _)) => {
Self::Field(value.to_string())
Self::Field(value)
}
(Type::Group, ValueExpression::Group(value)) => Self::Group(*value),
(Type::IntegerType(type_), ValueExpression::Implicit(value, _)) => {
Self::Integer(type_, value.to_string())
}
(Type::IntegerType(type_), ValueExpression::Implicit(value, _)) => Self::Integer(type_, value),
(Type::IntegerType(expected), ValueExpression::Integer(actual, value, span)) => {
if expected == actual {
Self::Integer(expected, value.to_string())
Self::Integer(expected, value)
} else {
return Err(InputError::unexpected_type(expected.to_string(), actual, &span).into());
}
}
(Type::Array(type_, _), ValueExpression::String(string, span)) => {
if !matches!(*type_, Type::Char) {
return Err(InputError::string_is_array_of_chars(type_, &span).into());
}
Self::Array(
string
.into_iter()
.map(|c| {
Self::Char(CharValue {
character: c,
span: span.clone(),
})
})
.collect(),
)
}
(x, y) => {
return Err(InputError::unexpected_type(x, &y, y.span()).into());
}
}
}
(Type::Array(type_, type_dimensions), Expression::ArrayInit(mut array_init)) => {
let span = array_init.span.clone();
if type_dimensions != array_init.dimensions || array_init.dimensions.is_zero() {
return Err(InputError::invalid_array_dimension_size(&span).into());
}
if let Some(dimension) = array_init.dimensions.remove_first() {
let size = dimension.value.parse::<usize>().unwrap();
let mut values = Vec::with_capacity(size);
// For when Dimensions are specified in a canonical way: [[u8; 3], 2];
// Else treat as math notation: [u8; (2, 3)];
if array_init.dimensions.len() == 0 {
for _ in 0..size {
values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?);
}
// Faking canonical array init is relatively easy: instead of using a straightforward
// recursion, with each iteration we manually modify ArrayInitExpression cutting off
// dimension by dimension.
} else {
for _ in 0..size {
values.push(InputValue::try_from((
Type::Array(type_.clone(), array_init.dimensions.clone()),
Expression::ArrayInit(array_init.clone()),
))?);
}
};
Self::Array(values)
} else {
unreachable!("dimensions are checked for zero");
}
}
(Type::Tuple(types), Expression::TupleInit(tuple_init)) => {
let size = tuple_init.elements.len();
let mut elements = Vec::with_capacity(size);
if size != types.len() {
return Err(InputError::tuple_length_mismatch(size, types.len(), tuple_init.span()).into());
}
for (i, element) in tuple_init.elements.into_iter().enumerate() {
elements.push(Self::try_from((types[i].clone(), element))?);
}
Self::Tuple(elements)
}
(Type::Array(element_type, _dimensions), Expression::ArrayInline(array_inline)) => {
let mut elements = Vec::with_capacity(array_inline.elements.len());
let span = array_inline.span().clone();
for element in array_inline.elements.into_iter() {
if let SpreadOrExpression::Expression(value_expression) = element {
elements.push(Self::try_from((*element_type.clone(), value_expression))?);
} else {
return Err(InputError::array_spread_is_not_allowed(&span).into());
}
}
Self::Array(elements)
(type_, Expression::Unary(unary)) if unary.op == UnaryOperation::Negate => {
InputValue::try_from((type_, *unary.inner))?
}
(_type_, expr) => return Err(InputError::illegal_expression(&expr, expr.span()).into()),
})
@ -155,14 +76,6 @@ impl fmt::Display for InputValue {
InputValue::Group(ref group) => write!(f, "{}", group),
InputValue::Field(ref field) => write!(f, "{}", field),
InputValue::Integer(ref type_, ref number) => write!(f, "{}{:?}", number, type_),
InputValue::Array(ref array) => {
let values = array.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "array [{}]", values)
}
InputValue::Tuple(ref tuple) => {
let values = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "({})", values)
}
}
}
}

View File

@ -21,28 +21,22 @@ use super::*;
pub struct ProgramInput {
pub main: Definitions,
pub registers: Definitions,
pub constants: Definitions,
}
impl TryFrom<ParsedInputFile> for ProgramInput {
impl TryFrom<InputAst> for ProgramInput {
type Error = LeoError;
fn try_from(input: ParsedInputFile) -> Result<Self> {
fn try_from(input: InputAst) -> Result<Self> {
let mut main = IndexMap::new();
let mut registers = IndexMap::new();
let mut constants = IndexMap::new();
for section in input.sections {
let target = match section.name {
sym::main => &mut main,
sym::registers => &mut registers,
sym::constants => &mut constants,
_ => {
return Err(InputError::unexpected_section(
&["main", "registers", "constants"],
section.name,
&section.span,
return Err(
InputError::unexpected_section(&["main", "registers"], section.name, &section.span).into(),
)
.into())
}
};
@ -54,10 +48,6 @@ impl TryFrom<ParsedInputFile> for ProgramInput {
}
}
Ok(ProgramInput {
main,
registers,
constants,
})
Ok(ProgramInput { main, registers })
}
}

View File

@ -22,9 +22,9 @@ pub struct ProgramState {
pub state: Definitions,
}
impl TryFrom<ParsedInputFile> for ProgramState {
impl TryFrom<InputAst> for ProgramState {
type Error = LeoError;
fn try_from(input: ParsedInputFile) -> Result<Self> {
fn try_from(input: InputAst) -> Result<Self> {
let mut state = IndexMap::new();
for section in input.sections {

View File

@ -22,18 +22,6 @@
#![doc = include_str!("../README.md")]
pub mod accesses;
pub use self::accesses::*;
pub mod aliases;
pub use self::aliases::*;
pub mod annotation;
pub use self::annotation::*;
pub mod circuits;
pub use self::circuits::*;
pub mod chars;
pub use self::chars::*;
@ -49,21 +37,15 @@ pub use self::functions::*;
pub mod groups;
pub use self::groups::*;
pub mod imports;
pub use self::imports::*;
pub mod input;
pub use self::input::*;
pub mod pass;
pub use self::pass::*;
pub mod passes;
pub use self::passes::*;
pub mod program;
pub use self::program::*;
pub mod reducer;
pub use self::reducer::*;
pub mod statements;
pub use self::statements::*;
@ -162,7 +144,7 @@ impl AsRef<Program> for Ast {
}
/// Helper function to recursively filter keys from AST JSON
fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
pub(crate) fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
match value {
serde_json::Value::Object(map) => serde_json::Value::Object(
map.into_iter()
@ -183,7 +165,7 @@ fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Valu
/// 1. Remove empty object mappings from JSON arrays
/// 2. If there are two elements in a JSON array and one is an empty object
/// mapping and the other is not, then lift up the one that isn't
fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
pub(crate) fn normalize_json_value(value: serde_json::Value) -> serde_json::Value {
match value {
serde_json::Value::Array(vec) => {
let orig_length = vec.len();

View File

@ -14,13 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! This module contains both a Director to reconstruct the AST
//! which maps over every node of the AST and calls a reducer.
//! The Trait for a reducer are methods that can be overridden
//! to make changes to how AST nodes are rebuilt.
//! This module contains both a Reducer and Visitor design pattern.
//! These both iterate over the AST.
// todo @gluax: Move the files in this module into `leo-passes` in a future PR.
pub mod reconstructing_reducer;
pub use reconstructing_reducer::*;
pub mod reconstructing_director;
pub use reconstructing_director::*;
pub mod visitor;
pub use visitor::*;
pub mod visitor_director;
pub use visitor_director::*;

View File

@ -20,7 +20,7 @@
use crate::*;
use leo_errors::{AstError, Result};
use leo_span::{Span, Symbol};
use leo_span::Span;
use indexmap::IndexMap;
@ -34,21 +34,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
}
pub fn reduce_type(&mut self, type_: &Type, span: &Span) -> Result<Type> {
let new = match type_ {
Type::Array(type_, dimensions) => Type::Array(Box::new(self.reduce_type(type_, span)?), dimensions.clone()),
Type::Tuple(types) => {
let mut reduced_types = vec![];
for type_ in types.iter() {
reduced_types.push(self.reduce_type(type_, span)?);
}
Type::Tuple(reduced_types)
}
Type::Identifier(identifier) => Type::Identifier(self.reduce_identifier(identifier)?),
_ => type_.clone(),
};
self.reducer.reduce_type(type_, new, span)
self.reducer.reduce_type(type_, type_.clone(), span)
}
// Expressions
@ -59,16 +45,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
Expression::Binary(binary) => Expression::Binary(self.reduce_binary(binary)?),
Expression::Unary(unary) => Expression::Unary(self.reduce_unary(unary)?),
Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(ternary)?),
Expression::Cast(cast) => Expression::Cast(self.reduce_cast(cast)?),
Expression::Access(access) => Expression::Access(self.reduce_access(access)?),
Expression::ArrayInline(array_inline) => Expression::ArrayInline(self.reduce_array_inline(array_inline)?),
Expression::ArrayInit(array_init) => Expression::ArrayInit(self.reduce_array_init(array_init)?),
Expression::TupleInit(tuple_init) => Expression::TupleInit(self.reduce_tuple_init(tuple_init)?),
Expression::CircuitInit(circuit_init) => Expression::CircuitInit(self.reduce_circuit_init(circuit_init)?),
Expression::Call(call) => Expression::Call(self.reduce_call(call)?),
Expression::Err(s) => Expression::Err(s.clone()),
};
@ -130,136 +106,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
self.reducer.reduce_ternary(ternary, condition, if_true, if_false)
}
pub fn reduce_cast(&mut self, cast: &CastExpression) -> Result<CastExpression> {
let inner = self.reduce_expression(&cast.inner)?;
let target_type = self.reduce_type(&cast.target_type, &cast.span)?;
self.reducer.reduce_cast(cast, inner, target_type)
}
pub fn reduce_array_access(&mut self, array_access: &ArrayAccess) -> Result<ArrayAccess> {
let array = self.reduce_expression(&array_access.array)?;
let index = self.reduce_expression(&array_access.index)?;
self.reducer.reduce_array_access(array_access, array, index)
}
pub fn reduce_array_range_access(&mut self, array_range_access: &ArrayRangeAccess) -> Result<ArrayRangeAccess> {
let array = self.reduce_expression(&array_range_access.array)?;
let left = array_range_access
.left
.as_ref()
.map(|left| self.reduce_expression(left))
.transpose()?;
let right = array_range_access
.right
.as_ref()
.map(|right| self.reduce_expression(right))
.transpose()?;
self.reducer
.reduce_array_range_access(array_range_access, array, left, right)
}
pub fn reduce_member_access(&mut self, member_access: &MemberAccess) -> Result<MemberAccess> {
let inner = self.reduce_expression(&member_access.inner)?;
let name = self.reduce_identifier(&member_access.name)?;
let type_ = member_access
.type_
.as_ref()
.map(|type_| self.reduce_type(type_, &member_access.span))
.transpose()?;
self.reducer.reduce_member_access(member_access, inner, name, type_)
}
pub fn reduce_tuple_access(&mut self, tuple_access: &TupleAccess) -> Result<TupleAccess> {
let tuple = self.reduce_expression(&tuple_access.tuple)?;
self.reducer.reduce_tuple_access(tuple_access, tuple)
}
pub fn reduce_static_access(&mut self, static_access: &StaticAccess) -> Result<StaticAccess> {
let value = self.reduce_expression(&static_access.inner)?;
let name = self.reduce_identifier(&static_access.name)?;
let type_ = self.reduce_type(&static_access.type_.borrow(), &static_access.span)?;
self.reducer.reduce_static_access(static_access, value, type_, name)
}
pub fn reduce_access(&mut self, access: &AccessExpression) -> Result<AccessExpression> {
use AccessExpression::*;
let new = match access {
Array(access) => Array(self.reduce_array_access(access)?),
ArrayRange(access) => ArrayRange(self.reduce_array_range_access(access)?),
Member(access) => Member(self.reduce_member_access(access)?),
Tuple(access) => Tuple(self.reduce_tuple_access(access)?),
Static(access) => Static(self.reduce_static_access(access)?),
};
Ok(new)
}
pub fn reduce_array_inline(&mut self, array_inline: &ArrayInlineExpression) -> Result<ArrayInlineExpression> {
let mut elements = vec![];
for element in array_inline.elements.iter() {
let reduced_element = match element {
SpreadOrExpression::Expression(expression) => {
SpreadOrExpression::Expression(self.reduce_expression(expression)?)
}
SpreadOrExpression::Spread(expression) => {
SpreadOrExpression::Spread(self.reduce_expression(expression)?)
}
};
elements.push(reduced_element);
}
self.reducer.reduce_array_inline(array_inline, elements)
}
pub fn reduce_array_init(&mut self, array_init: &ArrayInitExpression) -> Result<ArrayInitExpression> {
let element = self.reduce_expression(&array_init.element)?;
self.reducer.reduce_array_init(array_init, element)
}
pub fn reduce_tuple_init(&mut self, tuple_init: &TupleInitExpression) -> Result<TupleInitExpression> {
let mut elements = vec![];
for element in tuple_init.elements.iter() {
elements.push(self.reduce_expression(element)?);
}
self.reducer.reduce_tuple_init(tuple_init, elements)
}
pub fn reduce_circuit_variable_initializer(
&mut self,
variable: &CircuitVariableInitializer,
) -> Result<CircuitVariableInitializer> {
let identifier = self.reduce_identifier(&variable.identifier)?;
let expression = variable
.expression
.as_ref()
.map(|expr| self.reduce_expression(expr))
.transpose()?;
self.reducer
.reduce_circuit_variable_initializer(variable, identifier, expression)
}
pub fn reduce_circuit_init(&mut self, circuit_init: &CircuitInitExpression) -> Result<CircuitInitExpression> {
let name = self.reduce_identifier(&circuit_init.name)?;
let mut members = vec![];
for member in circuit_init.members.iter() {
members.push(self.reduce_circuit_variable_initializer(member)?);
}
self.reducer.reduce_circuit_init(circuit_init, name, members)
}
pub fn reduce_call(&mut self, call: &CallExpression) -> Result<CallExpression> {
let function = self.reduce_expression(&call.function)?;
@ -416,57 +262,12 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
inputs.push(self.reduce_function_input(input)?);
}
let mut import_statements = vec![];
for import in program.import_statements.iter() {
import_statements.push(self.reduce_import_statement(import)?);
}
let mut imports = IndexMap::new();
for (identifier, program) in program.imports.iter() {
let (ident, import) = self.reduce_import(identifier, program)?;
imports.insert(ident, import);
}
let mut aliases = IndexMap::new();
for (name, alias) in program.aliases.iter() {
let represents = self.reduce_type(&alias.represents, &alias.name.span)?;
aliases.insert(
name.clone(),
Alias {
name: alias.name.clone(),
span: alias.span.clone(),
represents,
},
);
}
let mut circuits = IndexMap::new();
self.reducer.swap_in_circuit();
for (name, circuit) in program.circuits.iter() {
circuits.insert(name.clone(), self.reduce_circuit(circuit)?);
}
self.reducer.swap_in_circuit();
let mut functions = IndexMap::new();
for (name, function) in program.functions.iter() {
functions.insert(name.clone(), self.reduce_function(function)?);
}
let mut global_consts = IndexMap::new();
for (name, definition) in program.global_consts.iter() {
global_consts.insert(name.clone(), self.reduce_definition(definition)?);
}
self.reducer.reduce_program(
program,
inputs,
import_statements,
imports,
aliases,
circuits,
functions,
global_consts,
)
self.reducer.reduce_program(program, inputs, functions)
}
pub fn reduce_function_input_variable(
@ -474,7 +275,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
variable: &FunctionInputVariable,
) -> Result<FunctionInputVariable> {
let identifier = self.reduce_identifier(&variable.identifier)?;
let type_ = self.reduce_type(&variable.type_, &variable.span)?;
let type_ = self.reduce_type(&variable.type_(), &variable.span)?;
self.reducer.reduce_function_input_variable(variable, identifier, type_)
}
@ -484,91 +285,14 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
FunctionInput::Variable(function_input_variable) => {
FunctionInput::Variable(self.reduce_function_input_variable(function_input_variable)?)
}
_ => input.clone(),
};
self.reducer.reduce_function_input(input, new)
}
pub fn reduce_import_tree(&mut self, tree: &ImportTree) -> Result<ImportTree> {
let new = ImportTree {
base: tree
.base
.iter()
.map(|i| self.reduce_identifier(i))
.collect::<Result<_>>()?,
kind: match &tree.kind {
ImportTreeKind::Glob { .. } | ImportTreeKind::Leaf { alias: None } => tree.kind.clone(),
ImportTreeKind::Leaf { alias: Some(alias) } => {
let alias = self.reduce_identifier(alias)?;
ImportTreeKind::Leaf { alias: Some(alias) }
}
ImportTreeKind::Nested { tree } => ImportTreeKind::Nested {
tree: tree.iter().map(|n| self.reduce_import_tree(n)).collect::<Result<_>>()?,
},
},
span: tree.span.clone(),
};
self.reducer.reduce_import_tree(tree, new)
}
pub fn reduce_import_statement(&mut self, import: &ImportStatement) -> Result<ImportStatement> {
let tree = self.reduce_import_tree(&import.tree)?;
self.reducer.reduce_import_statement(import, tree)
}
pub fn reduce_import(&mut self, identifier: &[Symbol], import: &Program) -> Result<(Vec<Symbol>, Program)> {
let new_identifer = identifier.to_vec();
let new_import = self.reduce_program(import)?;
self.reducer.reduce_import(new_identifer, new_import)
}
pub fn reduce_circuit_member(&mut self, circuit_member: &CircuitMember) -> Result<CircuitMember> {
let new = match circuit_member {
CircuitMember::CircuitConst(identifier, type_, value) => CircuitMember::CircuitConst(
self.reduce_identifier(identifier)?,
self.reduce_type(type_, &identifier.span)?,
self.reduce_expression(value)?,
),
CircuitMember::CircuitVariable(identifier, type_) => CircuitMember::CircuitVariable(
self.reduce_identifier(identifier)?,
self.reduce_type(type_, &identifier.span)?,
),
CircuitMember::CircuitFunction(function) => {
CircuitMember::CircuitFunction(Box::new(self.reduce_function(function)?))
}
};
self.reducer.reduce_circuit_member(circuit_member, new)
}
pub fn reduce_circuit(&mut self, circuit: &Circuit) -> Result<Circuit> {
let circuit_name = self.reduce_identifier(&circuit.circuit_name)?;
let mut members = vec![];
for member in circuit.members.iter() {
members.push(self.reduce_circuit_member(member)?);
}
self.reducer.reduce_circuit(circuit, circuit_name, members)
}
fn reduce_annotation(&mut self, annotation: &Annotation) -> Result<Annotation> {
let name = self.reduce_identifier(&annotation.name)?;
self.reducer.reduce_annotation(annotation, name)
}
pub fn reduce_function(&mut self, function: &Function) -> Result<Function> {
let identifier = self.reduce_identifier(&function.identifier)?;
let mut annotations = IndexMap::new();
for (name, annotation) in function.annotations.iter() {
annotations.insert(*name, self.reduce_annotation(annotation)?);
}
let mut inputs = vec![];
for input in function.input.iter() {
inputs.push(self.reduce_function_input(input)?);
@ -578,14 +302,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let block = self.reduce_block(&function.block)?;
self.reducer.reduce_function(
function,
identifier,
annotations,
inputs,
function.const_,
output,
block,
)
self.reducer
.reduce_function(function, identifier, inputs, function.const_, output, block)
}
}

View File

@ -18,8 +18,6 @@
//! It implements default methods for each node to be made
//! given the information of the old node.
use std::cell::RefCell;
use crate::*;
use leo_errors::Result;
@ -115,136 +113,6 @@ pub trait ReconstructingReducer {
})
}
fn reduce_cast(&mut self, cast: &CastExpression, inner: Expression, target_type: Type) -> Result<CastExpression> {
Ok(CastExpression {
inner: Box::new(inner),
target_type,
span: cast.span.clone(),
})
}
fn reduce_array_access(
&mut self,
array_access: &ArrayAccess,
array: Expression,
index: Expression,
) -> Result<ArrayAccess> {
Ok(ArrayAccess {
array: Box::new(array),
index: Box::new(index),
span: array_access.span.clone(),
})
}
fn reduce_array_range_access(
&mut self,
array_rage_access: &ArrayRangeAccess,
array: Expression,
left: Option<Expression>,
right: Option<Expression>,
) -> Result<ArrayRangeAccess> {
Ok(ArrayRangeAccess {
array: Box::new(array),
left: left.map(|expr| Box::new(expr)),
right: right.map(|expr| Box::new(expr)),
span: array_rage_access.span.clone(),
})
}
fn reduce_member_access(
&mut self,
member_access: &MemberAccess,
inner: Expression,
name: Identifier,
type_: Option<Type>,
) -> Result<MemberAccess> {
Ok(MemberAccess {
inner: Box::new(inner),
name,
span: member_access.span.clone(),
type_,
})
}
fn reduce_tuple_access(&mut self, tuple_access: &TupleAccess, tuple: Expression) -> Result<TupleAccess> {
Ok(TupleAccess {
tuple: Box::new(tuple),
index: tuple_access.index.clone(),
span: tuple_access.span.clone(),
})
}
fn reduce_static_access(
&mut self,
static_access: &StaticAccess,
value: Expression,
type_: Type,
name: Identifier,
) -> Result<StaticAccess> {
Ok(StaticAccess {
inner: Box::new(value),
name,
type_: RefCell::new(type_),
span: static_access.span.clone(),
})
}
fn reduce_array_inline(
&mut self,
array_inline: &ArrayInlineExpression,
elements: Vec<SpreadOrExpression>,
) -> Result<ArrayInlineExpression> {
Ok(ArrayInlineExpression {
elements,
span: array_inline.span.clone(),
})
}
fn reduce_array_init(
&mut self,
array_init: &ArrayInitExpression,
element: Expression,
) -> Result<ArrayInitExpression> {
Ok(ArrayInitExpression {
element: Box::new(element),
dimensions: array_init.dimensions.clone(),
span: array_init.span.clone(),
})
}
fn reduce_tuple_init(
&mut self,
tuple_init: &TupleInitExpression,
elements: Vec<Expression>,
) -> Result<TupleInitExpression> {
Ok(TupleInitExpression {
elements,
span: tuple_init.span.clone(),
})
}
fn reduce_circuit_variable_initializer(
&mut self,
_variable: &CircuitVariableInitializer,
identifier: Identifier,
expression: Option<Expression>,
) -> Result<CircuitVariableInitializer> {
Ok(CircuitVariableInitializer { identifier, expression })
}
fn reduce_circuit_init(
&mut self,
circuit_init: &CircuitInitExpression,
name: Identifier,
members: Vec<CircuitVariableInitializer>,
) -> Result<CircuitInitExpression> {
Ok(CircuitInitExpression {
name,
members,
span: circuit_init.span.clone(),
})
}
fn reduce_call(
&mut self,
call: &CallExpression,
@ -286,9 +154,8 @@ pub trait ReconstructingReducer {
value: Expression,
) -> Result<DefinitionStatement> {
Ok(DefinitionStatement {
declaration_type: definition.declaration_type.clone(),
declaration_type: definition.declaration_type,
variable_names,
parened: definition.parened,
type_,
value,
span: definition.span.clone(),
@ -392,22 +259,12 @@ pub trait ReconstructingReducer {
&mut self,
program: &Program,
expected_input: Vec<FunctionInput>,
import_statements: Vec<ImportStatement>,
imports: IndexMap<Vec<Symbol>, Program>,
aliases: IndexMap<Identifier, Alias>,
circuits: IndexMap<Identifier, Circuit>,
functions: IndexMap<Identifier, Function>,
global_consts: IndexMap<Vec<Identifier>, DefinitionStatement>,
) -> Result<Program> {
Ok(Program {
name: program.name.clone(),
expected_input,
import_statements,
imports,
aliases,
circuits,
functions,
global_consts,
})
}
@ -417,61 +274,27 @@ pub trait ReconstructingReducer {
identifier: Identifier,
type_: Type,
) -> Result<FunctionInputVariable> {
Ok(FunctionInputVariable {
Ok(FunctionInputVariable::new(
identifier,
const_: variable.const_,
mutable: variable.mutable,
variable.mode(),
type_,
span: variable.span.clone(),
})
variable.span.clone(),
))
}
fn reduce_function_input(&mut self, _input: &FunctionInput, new: FunctionInput) -> Result<FunctionInput> {
Ok(new)
}
fn reduce_import_tree(&mut self, _tree: &ImportTree, new: ImportTree) -> Result<ImportTree> {
Ok(new)
}
fn reduce_import_statement(&mut self, import: &ImportStatement, tree: ImportTree) -> Result<ImportStatement> {
Ok(ImportStatement {
tree,
span: import.span.clone(),
})
}
fn reduce_import(&mut self, identifier: Vec<Symbol>, import: Program) -> Result<(Vec<Symbol>, Program)> {
Ok((identifier, import))
}
fn reduce_circuit_member(&mut self, _circuit_member: &CircuitMember, new: CircuitMember) -> Result<CircuitMember> {
Ok(new)
}
fn reduce_circuit(
&mut self,
_circuit: &Circuit,
circuit_name: Identifier,
members: Vec<CircuitMember>,
) -> Result<Circuit> {
Ok(Circuit { circuit_name, members })
}
fn reduce_annotation(&mut self, annotation: &Annotation, name: Identifier) -> Result<Annotation> {
Ok(Annotation {
span: annotation.span.clone(),
name,
arguments: annotation.arguments.clone(),
})
}
#[allow(clippy::too_many_arguments)]
fn reduce_function(
&mut self,
function: &Function,
identifier: Identifier,
annotations: IndexMap<Symbol, Annotation>,
input: Vec<FunctionInput>,
const_: bool,
output: Type,
@ -479,7 +302,6 @@ pub trait ReconstructingReducer {
) -> Result<Function> {
Ok(Function {
identifier,
annotations,
input,
const_,
output,

View File

@ -0,0 +1,112 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! This module contains Visitor traits for the AST.
use crate::*;
pub enum VisitResult {
VisitChildren,
SkipChildren,
}
impl Default for VisitResult {
fn default() -> Self {
VisitResult::VisitChildren
}
}
pub trait ExpressionVisitor<'a> {
fn visit_expression(&mut self, _input: &'a Expression) -> VisitResult {
Default::default()
}
fn visit_identifier(&mut self, _input: &'a Identifier) -> VisitResult {
Default::default()
}
fn visit_value(&mut self, _input: &'a ValueExpression) -> VisitResult {
Default::default()
}
fn visit_binary(&mut self, _input: &'a BinaryExpression) -> VisitResult {
Default::default()
}
fn visit_unary(&mut self, _input: &'a UnaryExpression) -> VisitResult {
Default::default()
}
fn visit_ternary(&mut self, _input: &'a TernaryExpression) -> VisitResult {
Default::default()
}
fn visit_call(&mut self, _input: &'a CallExpression) -> VisitResult {
Default::default()
}
fn visit_err(&mut self, _input: &'a ErrExpression) -> VisitResult {
Default::default()
}
}
pub trait StatementVisitor<'a> {
fn visit_statement(&mut self, _input: &'a Statement) -> VisitResult {
Default::default()
}
fn visit_return(&mut self, _input: &'a ReturnStatement) -> VisitResult {
Default::default()
}
fn visit_definition(&mut self, _input: &'a DefinitionStatement) -> VisitResult {
Default::default()
}
fn visit_assign(&mut self, _input: &'a AssignStatement) -> VisitResult {
Default::default()
}
fn visit_conditional(&mut self, _input: &'a ConditionalStatement) -> VisitResult {
Default::default()
}
fn visit_iteration(&mut self, _input: &'a IterationStatement) -> VisitResult {
Default::default()
}
fn visit_console(&mut self, _input: &'a ConsoleStatement) -> VisitResult {
Default::default()
}
fn visit_expression_statement(&mut self, _input: &'a ExpressionStatement) -> VisitResult {
Default::default()
}
fn visit_block(&mut self, _input: &'a Block) -> VisitResult {
Default::default()
}
}
pub trait ProgramVisitor<'a> {
fn visit_program(&mut self, _input: &'a Program) -> VisitResult {
Default::default()
}
fn visit_function(&mut self, _input: &'a Function) -> VisitResult {
Default::default()
}
}

View File

@ -0,0 +1,176 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
//! This module contains Visitor trait implementations for the AST.
//! It implements default methods for each node to be made
//! given the type of node its visiting.
use std::marker::PhantomData;
use crate::*;
pub struct VisitorDirector<'a, V: ExpressionVisitor<'a>> {
visitor: V,
lifetime: PhantomData<&'a ()>,
}
impl<'a, V: ExpressionVisitor<'a>> VisitorDirector<'a, V> {
pub fn new(visitor: V) -> Self {
Self {
visitor,
lifetime: PhantomData,
}
}
pub fn visitor(self) -> V {
self.visitor
}
pub fn visit_expression(&mut self, input: &'a Expression) {
if let VisitResult::VisitChildren = self.visitor.visit_expression(input) {
match input {
Expression::Identifier(_) => {}
Expression::Value(_) => {}
Expression::Binary(expr) => self.visit_binary(expr),
Expression::Unary(expr) => self.visit_unary(expr),
Expression::Ternary(expr) => self.visit_ternary(expr),
Expression::Call(expr) => self.visit_call(expr),
Expression::Err(_) => {}
}
}
}
pub fn visit_binary(&mut self, input: &'a BinaryExpression) {
if let VisitResult::VisitChildren = self.visitor.visit_binary(input) {
self.visit_expression(&input.left);
self.visit_expression(&input.right);
}
}
pub fn visit_unary(&mut self, input: &'a UnaryExpression) {
if let VisitResult::VisitChildren = self.visitor.visit_unary(input) {
self.visit_expression(&input.inner);
}
}
pub fn visit_ternary(&mut self, input: &'a TernaryExpression) {
if let VisitResult::VisitChildren = self.visitor.visit_ternary(input) {
self.visit_expression(&input.condition);
self.visit_expression(&input.if_true);
self.visit_expression(&input.if_false);
}
}
pub fn visit_call(&mut self, input: &'a CallExpression) {
if let VisitResult::VisitChildren = self.visitor.visit_call(input) {
self.visit_expression(&input.function);
for expr in input.arguments.iter() {
self.visit_expression(expr);
}
}
}
}
impl<'a, V: ExpressionVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V> {
pub fn visit_statement(&mut self, input: &'a Statement) {
if let VisitResult::VisitChildren = self.visitor.visit_statement(input) {
match input {
Statement::Return(stmt) => self.visit_return(stmt),
Statement::Definition(stmt) => self.visit_definition(stmt),
Statement::Assign(stmt) => self.visit_assign(stmt),
Statement::Conditional(stmt) => self.visit_conditional(stmt),
Statement::Iteration(stmt) => self.visit_iteration(stmt),
Statement::Console(stmt) => self.visit_console(stmt),
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
Statement::Block(stmt) => self.visit_block(stmt),
}
}
}
pub fn visit_return(&mut self, input: &'a ReturnStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_return(input) {
self.visit_expression(&input.expression);
}
}
pub fn visit_definition(&mut self, input: &'a DefinitionStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_definition(input) {
self.visit_expression(&input.value);
}
}
pub fn visit_assign(&mut self, input: &'a AssignStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_assign(input) {
self.visit_expression(&input.value);
}
}
pub fn visit_conditional(&mut self, input: &'a ConditionalStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_conditional(input) {
self.visit_expression(&input.condition);
self.visit_block(&input.block);
if let Some(stmt) = input.next.as_ref() {
self.visit_statement(stmt);
}
}
}
pub fn visit_iteration(&mut self, input: &'a IterationStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_iteration(input) {
self.visit_expression(&input.start);
self.visit_expression(&input.stop);
self.visit_block(&input.block);
}
}
pub fn visit_console(&mut self, input: &'a ConsoleStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_console(input) {
if let ConsoleFunction::Assert(expr) = &input.function {
self.visit_expression(expr);
}
}
}
pub fn visit_expression_statement(&mut self, input: &'a ExpressionStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_expression_statement(input) {
self.visit_expression(&input.expression);
}
}
pub fn visit_block(&mut self, input: &'a Block) {
if let VisitResult::VisitChildren = self.visitor.visit_block(input) {
for stmt in input.statements.iter() {
self.visit_statement(stmt);
}
}
}
}
impl<'a, V: ExpressionVisitor<'a> + ProgramVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V> {
pub fn visit_program(&mut self, input: &'a Program) {
if let VisitResult::VisitChildren = self.visitor.visit_program(input) {
for function in input.functions.values() {
self.visit_function(function);
}
}
}
pub fn visit_function(&mut self, input: &'a Function) {
if let VisitResult::VisitChildren = self.visitor.visit_function(input) {
self.visit_block(&input.block);
}
}
}

View File

@ -17,9 +17,7 @@
//! A Leo program consists of import, circuit, and function definitions.
//! Each defined type consists of ast statements and expressions.
use crate::{Alias, Circuit, CircuitMember, DefinitionStatement, Function, FunctionInput, Identifier, ImportStatement};
use leo_span::{sym, Symbol};
use crate::{Function, FunctionInput, Identifier};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
@ -34,18 +32,6 @@ pub struct Program {
/// 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>,
}
@ -58,26 +44,6 @@ impl AsRef<Program> for Program {
impl fmt::Display for Program {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for import in self.import_statements.iter() {
import.fmt(f)?;
writeln!(f,)?;
}
writeln!(f,)?;
for (_, alias) in self.aliases.iter() {
alias.fmt(f)?;
writeln!(f,)?;
}
writeln!(f,)?;
for (_, import) in self.imports.iter() {
import.fmt(f)?;
writeln!(f,)?;
}
writeln!(f,)?;
for (_, circuit) in self.circuits.iter() {
circuit.fmt(f)?;
writeln!(f,)?;
}
writeln!(f,)?;
for (_, function) in self.functions.iter() {
function.fmt(f)?;
writeln!(f,)?;
@ -92,47 +58,10 @@ impl Program {
Self {
name,
expected_input: vec![],
import_statements: vec![],
imports: IndexMap::new(),
aliases: IndexMap::new(),
circuits: IndexMap::new(),
global_consts: IndexMap::new(),
functions: IndexMap::new(),
}
}
/// Handles all internal annotations like `@CoreFunction` and `@AlwaysConst`.
pub fn handle_internal_annotations(&mut self) {
self.circuits
.iter_mut()
.flat_map(|(_, circuit)| &mut circuit.members)
.filter_map(|member| {
if let CircuitMember::CircuitFunction(function) = member {
Some(function)
} else {
None
}
})
.for_each(|function| {
function.annotations.retain(|name, core_map| {
match *name {
sym::CoreFunction => {
let new = core_map.arguments.get(0).copied().or(Some(function.identifier.name));
function.core_mapping.replace(new);
false
}
sym::AlwaysConst => {
function.const_ = true;
false
}
// Could still be a valid annotation.
// Carry on and let ASG handle.
_ => true,
}
})
});
}
/// Extract the name of the program.
pub fn get_name(&self) -> String {
self.name.to_string()

View File

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

View File

@ -33,8 +33,6 @@ pub struct DefinitionStatement {
pub declaration_type: Declare,
/// The bindings / variable names to declare.
pub variable_names: Vec<VariableName>,
/// Tracks whether the variable(s) are in parens.
pub parened: bool,
/// The types of the bindings, if specified, or inferred otherwise.
pub type_: Type,
/// An initializer value for the bindings.

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ArrayDimensions, Identifier, IntegerType};
use crate::IntegerType;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -36,39 +36,12 @@ pub enum Type {
/// 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>),
/// 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.
/// Will eventually lead to a compile error.
Err,
}
impl Type {
///
/// Returns `true` if the self `Type` is the `SelfType`.
///
pub fn is_self(&self) -> bool {
matches!(self, Type::SelfType)
}
///
/// Returns `true` if the self `Type` is a `Circuit`.
///
pub fn is_circuit(&self) -> bool {
matches!(self, Type::Identifier(_))
}
///
/// Returns `true` if the self `Type` is equal to the other `Type`.
///
@ -82,33 +55,6 @@ impl Type {
(Type::Field, Type::Field) => true,
(Type::Group, Type::Group) => true,
(Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right),
(Type::Identifier(left), Type::Identifier(right)) => left.eq(right),
(Type::SelfType, Type::SelfType) => true,
(Type::Array(left_type, left_dims), Type::Array(right_type, right_dims)) => {
// Convert array dimensions to owned.
let mut left_dims = left_dims.to_owned();
let mut right_dims = right_dims.to_owned();
// Remove the first element from both dimensions.
let left_first = left_dims.remove_first();
let right_first = right_dims.remove_first();
// Compare the first dimensions.
if left_first.ne(&right_first) {
return false;
}
// Create a new array type from the remaining array dimensions.
let left_new_type = inner_array_type(*left_type.to_owned(), left_dims);
let right_new_type = inner_array_type(*right_type.to_owned(), right_dims);
// Call eq_flat() on the new left and right types.
left_new_type.eq_flat(&right_new_type)
}
(Type::Tuple(left), Type::Tuple(right)) => left
.iter()
.zip(right)
.all(|(left_type, right_type)| left_type.eq_flat(right_type)),
_ => false,
}
}
@ -123,33 +69,7 @@ impl fmt::Display for Type {
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::Identifier(ref variable) => write!(f, "circuit {}", variable),
Type::SelfType => write!(f, "SelfType"),
Type::Array(ref array, ref dimensions) => write!(f, "[{}; {}]", *array, dimensions),
Type::Tuple(ref tuple) => {
let types = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
write!(f, "({})", types)
}
Type::Err => write!(f, "error"),
}
}
}
/// Returns the type of the inner array given an array element and array dimensions.
///
/// If the array has no dimensions, then an inner array does not exist. Simply return the given
/// element type.
///
/// If the array has dimensions, then an inner array exists. Create a new type for the
/// inner array. The element type of the new array should be the same as the old array. The
/// dimensions of the new array should be the old array dimensions with the first dimension removed.
pub fn inner_array_type(element_type: Type, dimensions: ArrayDimensions) -> Type {
if dimensions.is_empty() {
// The array has one dimension.
element_type
} else {
// The array has multiple dimensions.
Type::Array(Box::new(element_type), dimensions)
}
}

View File

@ -22,24 +22,36 @@ rust-version = "1.56.1"
path = "../ast"
version = "1.5.3"
[dependencies.leo-ast-passes]
path = "../ast-passes"
version = "1.5.3"
[dependencies.leo-errors]
path = "../../leo/errors"
version = "1.5.3"
[dependencies.leo-passes]
path = "../passes"
version = "1.5.3"
[dependencies.leo-parser]
path = "../parser"
version = "1.5.3"
[dependencies.leo-span]
[dependencies.sha2]
version = "0.10"
[dev-dependencies.leo-span]
path = "../../leo/span"
version = "1.5.3"
[dependencies.sha2]
version = "0.10"
[dev-dependencies.leo-test-framework]
path = "../../tests/test-framework"
version = "1.4.0"
[dev-dependencies.serde]
version = "1.0.136"
features = ["derive"]
[dev-dependencies.serde_yaml]
version = "0.8.23"
[features]
default = [ ]

View File

@ -22,21 +22,28 @@
#![allow(clippy::upper_case_acronyms)]
#![doc = include_str!("../README.md")]
pub use leo_ast::Ast;
use leo_ast::AstPass;
#[cfg(test)]
mod test;
use leo_ast::Program;
pub use leo_ast::{Ast, InputAst};
use leo_errors::emitter::Handler;
use leo_errors::{CompilerError, Result};
use leo_span::symbol::create_session_if_not_set_then;
pub use leo_passes::SymbolTable;
use leo_passes::*;
use sha2::{Digest, Sha256};
use std::fs;
use std::path::PathBuf;
#[derive(Clone)]
/// The primary entry point of the Leo compiler.
pub struct Compiler<'a> {
handler: &'a Handler,
main_file_path: PathBuf,
output_directory: PathBuf,
pub ast: Ast,
pub input_ast: Option<InputAst>,
}
impl<'a> Compiler<'a> {
@ -48,6 +55,8 @@ impl<'a> Compiler<'a> {
handler,
main_file_path,
output_directory,
ast: Ast::new(Program::new("Initial".to_string())),
input_ast: None,
}
}
@ -67,16 +76,10 @@ impl<'a> Compiler<'a> {
Ok(format!("{:x}", hash))
}
///
/// Runs the compiler stages.
///
fn compiler_stages(self) -> Result<leo_ast::Ast> {
// Load the program file.
let program_string = fs::read_to_string(&self.main_file_path)
.map_err(|e| CompilerError::file_read_error(self.main_file_path.clone(), e))?;
// Parses and stores a program file content from a string, constructs a syntax tree, and generates a program.
pub fn parse_program_from_string(&mut self, program_string: &str) -> Result<()> {
// Use the parser to construct the abstract syntax tree (ast).
let mut ast: leo_ast::Ast = leo_parser::parse_ast(
let ast: leo_ast::Ast = leo_parser::parse_ast(
self.handler,
self.main_file_path.to_str().unwrap_or_default(),
program_string,
@ -84,18 +87,56 @@ impl<'a> Compiler<'a> {
// Write the AST snapshot post parsing.
ast.to_json_file_without_keys(self.output_directory.clone(), "initial_ast.json", &["span"])?;
// Canonicalize the AST.
ast = leo_ast_passes::Canonicalizer::do_pass(Default::default(), ast.into_repr())?;
// Write the AST snapshot post parsing
ast.to_json_file_without_keys(self.output_directory, "canonicalization_ast.json", &["span"])?;
self.ast = ast;
Ok(ast)
Ok(())
}
/// Parses and stores the main program file, constructs a syntax tree, and generates a program.
pub fn parse_program(&mut self) -> Result<()> {
// Load the program file.
let program_string = fs::read_to_string(&self.main_file_path)
.map_err(|e| CompilerError::file_read_error(self.main_file_path.clone(), e))?;
self.parse_program_from_string(&program_string)
}
/// Parses and stores the input file, constructs a syntax tree, and generates a program input.
pub fn parse_input_from_string(&mut self, input_file_path: PathBuf, input_string: &str) -> Result<()> {
let input_ast =
leo_parser::parse_input(self.handler, input_file_path.to_str().unwrap_or_default(), input_string)?;
input_ast.to_json_file_without_keys(self.output_directory.clone(), "inital_input_ast.json", &["span"])?;
self.input_ast = Some(input_ast);
Ok(())
}
/// Parses and stores the input file, constructs a syntax tree, and generates a program input.
pub fn parse_input(&mut self, input_file_path: PathBuf) -> Result<()> {
// Load the input file if it exists.
if input_file_path.exists() {
let input_string = fs::read_to_string(&input_file_path)
.map_err(|e| CompilerError::file_read_error(input_file_path.clone(), e))?;
self.parse_input_from_string(input_file_path, &input_string)?;
}
Ok(())
}
///
/// Runs the compiler stages.
///
fn compiler_stages(&self) -> Result<SymbolTable<'_>> {
let symbol_table = CreateSymbolTable::do_pass((&self.ast, self.handler))?;
Ok(symbol_table)
}
///
/// Returns a compiled Leo program.
///
pub fn compile(self) -> Result<leo_ast::Ast> {
create_session_if_not_set_then(|_| self.compiler_stages())
pub fn compile(&self) -> Result<SymbolTable<'_>> {
self.compiler_stages()
}
}

View File

@ -0,0 +1,224 @@
// 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 std::{
cell::RefCell,
fmt, fs,
path::{Path, PathBuf},
rc::Rc,
};
use crate::Compiler;
use leo_errors::{
emitter::{Buffer, Emitter, Handler},
LeoError, LeoWarning,
};
use leo_passes::SymbolTable;
use leo_span::symbol::create_session_if_not_set_then;
use leo_test_framework::{
runner::{Namespace, ParseType, Runner},
Test,
};
use serde::{Deserialize, Serialize};
use serde_yaml::Value;
fn new_compiler(handler: &Handler, main_file_path: PathBuf) -> Compiler<'_> {
let output_dir = PathBuf::from("/tmp/output/");
fs::create_dir_all(output_dir.clone()).unwrap();
Compiler::new(handler, main_file_path, output_dir)
}
fn parse_program<'a>(
handler: &'a Handler,
program_string: &str,
cwd: Option<PathBuf>,
) -> Result<Compiler<'a>, LeoError> {
let mut compiler = new_compiler(handler, cwd.unwrap_or_else(|| "compiler-test".into()));
compiler.parse_program_from_string(program_string)?;
Ok(compiler)
}
fn hash_content(content: &str) -> String {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(content);
let hash = hasher.finalize();
format!("{:x}", hash)
}
fn hash_file(path: &str) -> String {
let file = fs::read_to_string(&Path::new(path)).unwrap();
hash_content(&file)
}
struct CompileNamespace;
impl Namespace for CompileNamespace {
fn parse_type(&self) -> ParseType {
ParseType::Whole
}
fn run_test(&self, test: Test) -> Result<Value, String> {
let buf = BufferEmitter(Rc::default(), Rc::default());
let handler = Handler::new(Box::new(buf.clone()));
create_session_if_not_set_then(|_| run_test(test, &handler, &buf).map_err(|()| buf.0.take().to_string()))
}
}
#[derive(Deserialize, PartialEq, Serialize)]
struct OutputItem {
pub initial_input_ast: String,
pub symbol_table: String,
}
#[derive(Deserialize, PartialEq, Serialize)]
struct CompileOutput {
pub output: Vec<OutputItem>,
pub initial_ast: String,
}
/// Get the path of the `input_file` given in `input` into `list`.
fn get_input_file_paths(list: &mut Vec<PathBuf>, test: &Test, input: &Value) {
let input_file: PathBuf = test.path.parent().expect("no test parent dir").into();
if input.as_str().is_some() {
let mut input_file = input_file;
input_file.push(input.as_str().expect("input_file was not a string or array"));
list.push(input_file.clone());
}
}
/// Collect and return all inputs, if possible.
fn collect_all_inputs(test: &Test) -> Result<Vec<PathBuf>, String> {
let mut list = vec![];
if let Some(input) = test.config.get("input_file") {
get_input_file_paths(&mut list, test, input);
}
Ok(list)
}
fn compile_and_process<'a>(
parsed: &'a mut Compiler<'a>,
input_file_path: PathBuf,
) -> Result<SymbolTable<'a>, LeoError> {
parsed.parse_input(input_file_path)?;
parsed.compiler_stages()
}
// Errors used in this module.
enum LeoOrString {
Leo(LeoError),
String(String),
}
impl fmt::Display for LeoOrString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Leo(x) => x.fmt(f),
Self::String(x) => x.fmt(f),
}
}
}
/// A buffer used to emit errors into.
#[derive(Clone)]
struct BufferEmitter(Rc<RefCell<Buffer<LeoOrString>>>, Rc<RefCell<Buffer<LeoWarning>>>);
impl Emitter for BufferEmitter {
fn emit_err(&mut self, err: LeoError) {
self.0.borrow_mut().push(LeoOrString::Leo(err));
}
fn last_emited_err(&self) -> Option<LeoError> {
let temp = &*self.0.borrow();
temp.last_entry().map(|entry| match entry {
LeoOrString::Leo(err) => err.clone(),
_ => unimplemented!(),
})
}
fn emit_warning(&mut self, warning: leo_errors::LeoWarning) {
self.1.borrow_mut().push(warning);
}
}
fn buffer_if_err<T>(buf: &BufferEmitter, res: Result<T, String>) -> Result<T, ()> {
res.map_err(|err| buf.0.borrow_mut().push(LeoOrString::String(err)))
}
fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Value, ()> {
// Check for CWD option:
// ``` cwd: import ```
// When set, uses different working directory for current file.
// If not, uses file path as current working directory.
let cwd = test.config.get("cwd").map(|val| {
let mut cwd = test.path.clone();
cwd.pop();
cwd.join(&val.as_str().unwrap())
});
let parsed = handler.extend_if_error(parse_program(handler, &test.content, cwd))?;
// (name, content)
let inputs = buffer_if_err(err_buf, collect_all_inputs(&test))?;
let mut output_items = Vec::with_capacity(inputs.len());
for input in inputs {
let mut parsed = parsed.clone();
let symbol_table = handler.extend_if_error(compile_and_process(&mut parsed, input))?;
let initial_input_ast = hash_file("/tmp/output/inital_input_ast.json");
output_items.push(OutputItem {
initial_input_ast,
symbol_table: hash_content(&symbol_table.to_string()),
});
}
let initial_ast = hash_file("/tmp/output/initial_ast.json");
if fs::read_dir("/tmp/output").is_ok() {
fs::remove_dir_all(Path::new("/tmp/output")).expect("Error failed to clean up output dir.");
}
let final_output = CompileOutput {
output: output_items,
initial_ast,
};
Ok(serde_yaml::to_value(&final_output).expect("serialization failed"))
}
struct TestRunner;
impl Runner for TestRunner {
fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>> {
Some(match name {
"Compile" => Box::new(CompileNamespace),
_ => return None,
})
}
}
#[test]
pub fn compiler_tests() {
leo_test_framework::run_tests(&TestRunner, "compiler");
}

View File

@ -1,37 +0,0 @@
[package]
name = "leo-input"
version = "1.5.3"
authors = [ "The Aleo Team <hello@aleo.org>" ]
description = "Input parser of the Leo programming language"
homepage = "https://aleo.org"
repository = "https://github.com/AleoHQ/leo"
keywords = [
"aleo",
"cryptography",
"leo",
"programming-language",
"zero-knowledge"
]
categories = [ "cryptography::cryptocurrencies", "web-programming" ]
include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
license = "GPL-3.0"
edition = "2021"
rust-version = "1.56.1"
[dependencies.from-pest]
version = "0.3.1"
[dependencies.pest]
version = "2.0"
[dependencies.pest-ast]
version = "0.3.3"
[dependencies.pest_derive]
version = "2.0"
[dependencies.thiserror]
version = "1.0"
[dependencies.tracing]
version = "0.1"

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