imports: refactor AST repr

This commit is contained in:
Mazdak Farrokhzad 2022-02-02 00:20:29 +01:00
parent 5d3d93efbc
commit 567def9e2f
7 changed files with 98 additions and 424 deletions

View File

@ -1,58 +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::PackageOrPackages;
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 package or packages to import.
pub package_or_packages: PackageOrPackages,
/// 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 {
match self.package_or_packages {
PackageOrPackages::Package(ref package) => package.name.name,
PackageOrPackages::Packages(ref packages) => packages.name.name,
}
}
}
impl ImportStatement {
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "import {};", self.package_or_packages)
}
}
impl fmt::Display for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Debug for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}

View File

@ -1,76 +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};
use serde::{Deserialize, Serialize};
use std::fmt;
/// An import of `symbol` possibly renamed to `alias`,
/// e.g., `symbol` or `symbol as alias`.
///
/// This is the leaf of an import tree.
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ImportSymbol {
pub symbol: Identifier,
/// The name, if any, to import `symbol` as.
/// If not specified, `symbol` is the name it is imported under.
pub alias: Option<Identifier>,
/// The span including `symbol` and possibly `as alias`.
pub span: Span,
}
impl fmt::Display for ImportSymbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.alias.is_some() {
write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap())
} else {
write!(f, "{}", self.symbol)
}
}
}
// TODO (collin): remove this
impl fmt::Debug for ImportSymbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.alias.is_some() {
write!(f, "{} as {}", self.symbol, self.alias.as_ref().unwrap())
} else {
write!(f, "{}", self.symbol)
}
}
}
impl ImportSymbol {
/// Creates a glob `*` import.
pub fn star(span: &Span) -> Self {
Self {
symbol: Identifier {
name: sym::Star,
span: span.clone(),
},
alias: None,
span: span.clone(),
}
}
/// Is this a glob import?
pub fn is_star(&self) -> bool {
self.symbol.name == sym::Star
}
}

View File

@ -14,20 +14,106 @@
// 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 import;
pub use import::*;
use crate::Identifier;
use leo_span::{Span, Symbol};
pub mod import_symbol;
pub use import_symbol::*;
use serde::{Deserialize, Serialize};
use std::fmt;
pub mod package;
pub use package::*;
/// 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,
}
pub mod packages;
pub use packages::*;
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
}
}
pub mod package_or_packages;
pub use package_or_packages::*;
impl fmt::Display for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "import {};", self.tree)
}
}
pub mod package_access;
pub use package_access::*;
impl fmt::Debug for ImportStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::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::Debug::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

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

View File

@ -1,92 +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::{ImportSymbol, Node, Package, Packages};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum PackageAccess {
/// A glob import `*`.
Star {
/// The span for the `*`.
span: Span,
},
/// A subpackage to import.
SubPackage(Box<Package>),
/// A leaf package to import.
Symbol(ImportSymbol),
/// Several subpackages to import.
// FIXME(Centril): This structure seems convoluted and unclear.
// Refactor and simplify the types to:
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.UseTree.html.
Multiple(Packages),
}
impl Node for PackageAccess {
fn span(&self) -> &Span {
match self {
PackageAccess::Star { span } => span,
PackageAccess::SubPackage(package) => &package.span,
PackageAccess::Symbol(package) => &package.span,
PackageAccess::Multiple(package) => &package.span,
}
}
fn set_span(&mut self, span: Span) {
match self {
PackageAccess::Star { span } => *span = span.clone(),
PackageAccess::SubPackage(package) => package.span = span,
PackageAccess::Symbol(package) => package.span = span,
PackageAccess::Multiple(package) => package.span = span,
}
}
}
impl PackageAccess {
/// Formats `self` to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PackageAccess::Star { .. } => write!(f, "*"),
PackageAccess::SubPackage(ref package) => write!(f, "{}", package),
PackageAccess::Symbol(ref symbol) => write!(f, "{}", symbol),
PackageAccess::Multiple(ref packages) => {
write!(f, "(")?;
for (i, access) in packages.accesses.iter().enumerate() {
write!(f, "{}", access)?;
if i < packages.accesses.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl fmt::Debug for PackageAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Display for PackageAccess {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}

View File

@ -1,77 +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::{Node, Package, Packages};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// A specification of what packages to import.
#[derive(Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum PackageOrPackages {
/// Instruction to import a single package or item.
Package(Package),
/// Instruction to import a packages or items with a common prefix.
Packages(Packages),
}
impl PackageOrPackages {
/// Formats `self` to `f`.
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PackageOrPackages::Package(ref package) => write!(f, "{}", package),
PackageOrPackages::Packages(ref packages) => {
write!(f, "(")?;
for (i, access) in packages.accesses.iter().enumerate() {
write!(f, "{}", access)?;
if i < packages.accesses.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ")")
}
}
}
}
impl fmt::Debug for PackageOrPackages {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl fmt::Display for PackageOrPackages {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
}
}
impl Node for PackageOrPackages {
fn span(&self) -> &Span {
match self {
PackageOrPackages::Package(package) => &package.span,
PackageOrPackages::Packages(packages) => &packages.span,
}
}
fn set_span(&mut self, span: Span) {
match self {
PackageOrPackages::Package(package) => package.span = span,
PackageOrPackages::Packages(packages) => packages.span = span,
}
}
}

View File

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