mirror of
https://github.com/FuelLabs/sway.git
synced 2025-08-13 23:28:46 +00:00
Standardized module structure (#4232)
## Description Implement RFC 0006, fix #4191. Remove the `dep` reseved keyword in favor of `mod`. Change path resolution for submodules to use an adjascent file at the root and a folder named after the current module in other cases. Remove the need for an argument to `library`, the LSP now points to empty spans at the top of module files. The library names are now determined by the file name, or the package name at the top level. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers.
This commit is contained in:
parent
0848a887b7
commit
0eaa3a6da9
430 changed files with 994 additions and 1171 deletions
|
@ -77,7 +77,7 @@ ABI supertraits are intended to make contract implementations compositional, all
|
|||
Often, libraries and APIs have interfaces that are abstracted over a type that implements a certain trait. It is up to the consumer of the interface to implement that trait for the type they wish to use with the interface. For example, let's take a look at a trait and an interface built off of it.
|
||||
|
||||
```sway
|
||||
library games;
|
||||
library;
|
||||
|
||||
pub enum Suit {
|
||||
Hearts: (),
|
||||
|
|
|
@ -7,17 +7,17 @@ Libraries in Sway are files used to define new common behavior. The most promine
|
|||
Libraries are defined using the `library` keyword at the beginning of a file, followed by a name so that they can be imported.
|
||||
|
||||
```sway
|
||||
library my_library;
|
||||
library;
|
||||
|
||||
// library code
|
||||
```
|
||||
|
||||
A good reference library to use when learning library design is the [Sway Standard Library](../introduction/standard_library.html). For example, the standard library offers an [implementation](https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/option.sw) of `enum Option<T>` which is a generic type that represents either the existence of a value using the variant `Some(..)` or a value's absence using the variant `None`. The [Sway file implementing `Option<T>`](https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/option.sw) has the following structure:
|
||||
|
||||
- The `library` keyword followed by the name of the library:
|
||||
- The `library` keyword:
|
||||
|
||||
```sway
|
||||
library option;
|
||||
library;
|
||||
```
|
||||
|
||||
- A `use` statement that imports `revert` from another library _inside_ the standard library:
|
||||
|
@ -63,26 +63,39 @@ name = "my_library"
|
|||
|
||||
which denotes the authors, an entry file, the name by which it can be imported, and any dependencies.
|
||||
|
||||
For large libraries, it is recommended to have a `lib.sw` entry point re-export all other sub-libraries. For example, the `lib.sw` of the standard library looks like:
|
||||
For large libraries, it is recommended to have a `lib.sw` entry point re-export all other sub-libraries.
|
||||
|
||||
The `mod` keyword registers a submodule, making its items (such as functions and structs) accessible from the parent library.
|
||||
If used at the top level it will refer to a file in the `src` folder and in other cases in a folder named after the library in which it is defined.
|
||||
|
||||
For example, the `lib.sw` of the standard library looks like:
|
||||
|
||||
```sway
|
||||
library std;
|
||||
library;
|
||||
|
||||
dep block;
|
||||
dep storage;
|
||||
dep constants;
|
||||
mod block;
|
||||
mod storage;
|
||||
mod constants;
|
||||
mod vm;
|
||||
// .. Other deps
|
||||
```
|
||||
|
||||
with other libraries contained in the `src` folder, like the block library (inside of `block.sw`):
|
||||
with other libraries contained in the `src` folder, like the vm library (inside of `src/vm.sw`):
|
||||
|
||||
```sway
|
||||
library block;
|
||||
library;
|
||||
|
||||
// Implementation of the `block` library
|
||||
mod evm;
|
||||
// ...
|
||||
```
|
||||
|
||||
The `dep` keyword in the main library includes a dependency on another library, making all of its items (such as functions and structs) accessible from the main library. The `dep` keyword simply makes the library a dependency and fully accessible within the current context.
|
||||
and it's own sub-library evm located in `src/vm/evm.sw`:
|
||||
|
||||
```sway
|
||||
library;
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
## Using Libraries
|
||||
|
||||
|
@ -90,7 +103,8 @@ There are two types of Sway libraries, based on their location and how they can
|
|||
|
||||
### Internal Libraries
|
||||
|
||||
Internal libraries are located within the project's `src` directory alongside `main.sw` as shown below:
|
||||
Internal libraries are located within the project's `src` directory alongside
|
||||
`main.sw` or in the appropriate folders as shown below:
|
||||
|
||||
```bash
|
||||
$ tree
|
||||
|
@ -99,16 +113,18 @@ $ tree
|
|||
├── Forc.toml
|
||||
└── src
|
||||
├── internal_lib.sw
|
||||
└── main.sw
|
||||
├── main.sw
|
||||
└── internal_lib
|
||||
└── nested_lib.sw
|
||||
```
|
||||
|
||||
As `internal_lib` is an internal library, it can be imported into `main.sw` as follows:
|
||||
|
||||
- Use the `dep` keyword followed by the library name to make the internal library a dependancy
|
||||
- Use the `mod` keyword followed by the library name to make the internal library a dependancy
|
||||
- Use the `use` keyword with a `::` separating the name of the library and the imported item(s)
|
||||
|
||||
```sway
|
||||
dep internal_lib; // Assuming the library name in `internal_lib.sw` is `internal_lib`
|
||||
mod internal_lib; // Assuming the library name in `internal_lib.sw` is `internal_lib`
|
||||
|
||||
use internal_lib::mint;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library fizzbuzz;
|
||||
library;
|
||||
|
||||
// ANCHOR: state
|
||||
enum State {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library arrays;
|
||||
library;
|
||||
|
||||
// ANCHOR: syntax
|
||||
fn syntax() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library booleans;
|
||||
library;
|
||||
|
||||
// ANCHOR: syntax
|
||||
fn returns_true() -> bool {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library bytes;
|
||||
library;
|
||||
|
||||
fn syntax() {
|
||||
// ANCHOR: syntax
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library basic_enum;
|
||||
library;
|
||||
|
||||
// ANCHOR: definition
|
||||
enum Color {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enum_of_enums;
|
||||
library;
|
||||
|
||||
// ANCHOR: content
|
||||
enum UserError {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enum_of_structs;
|
||||
library;
|
||||
|
||||
// ANCHOR: content
|
||||
struct Item {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enums;
|
||||
library;
|
||||
|
||||
dep basic_enum;
|
||||
dep enum_of_structs;
|
||||
mod basic_enum;
|
||||
mod enum_of_structs;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library numerics;
|
||||
library;
|
||||
|
||||
fn syntax() {
|
||||
// ANCHOR: syntax
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library strings;
|
||||
library;
|
||||
|
||||
fn explicit() {
|
||||
// ANCHOR: explicit
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library structs;
|
||||
library;
|
||||
|
||||
// ANCHOR: definition
|
||||
struct Foo {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library tuples;
|
||||
library;
|
||||
|
||||
fn syntax() {
|
||||
// ANCHOR: declare
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library comments;
|
||||
library;
|
||||
|
||||
fn comment() {
|
||||
// ANCHOR: comment
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library control_flow;
|
||||
library;
|
||||
|
||||
fn conditional() {
|
||||
// ANCHOR: conditional
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library explicit;
|
||||
library;
|
||||
|
||||
// ANCHOR: main
|
||||
fn main() -> bool {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library implicit;
|
||||
library;
|
||||
|
||||
// ANCHOR: main
|
||||
fn main() -> bool {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
library functions;
|
||||
library;
|
||||
|
||||
dep explicit;
|
||||
dep implicit;
|
||||
mod explicit;
|
||||
mod implicit;
|
||||
|
||||
// ANCHOR: definition
|
||||
fn my_function(my_parameter: u64 /* ... */) -> u64 {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library interface;
|
||||
library;
|
||||
|
||||
abi Wallet {
|
||||
/// When the BASE_ASSET is sent to this function the internal contract balance is incremented
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library my_library;
|
||||
library;
|
||||
|
||||
use my_other_library::quix;
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
library my_other_library;
|
||||
library;
|
||||
|
||||
pub fn quix() {}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
library lib;
|
||||
library;
|
||||
|
||||
dep my_library;
|
||||
mod my_library;
|
||||
|
||||
use my_library::bar;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// ANCHOR: library
|
||||
// ANCHOR: module
|
||||
library my_library;
|
||||
library;
|
||||
// ANCHOR_END: module
|
||||
|
||||
// Cannot import because the `pub` keyword is missing
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library annotations;
|
||||
library;
|
||||
|
||||
// ANCHOR: type_annotation
|
||||
fn execute() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enums;
|
||||
library;
|
||||
|
||||
pub enum Error {
|
||||
StateError: StateError,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library getters;
|
||||
library;
|
||||
|
||||
// ANCHOR: avoid
|
||||
fn get_maximum_deposit() -> u64 {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// ANCHOR: module
|
||||
library letter_casing;
|
||||
library;
|
||||
// ANCHOR_END: module
|
||||
// ANCHOR: const
|
||||
const MAXIMUM_DEPOSIT = 10;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library struct_shorthand;
|
||||
library;
|
||||
|
||||
// ANCHOR: struct_shorthand_definition
|
||||
struct Structure {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library variables;
|
||||
library;
|
||||
|
||||
fn mutable() {
|
||||
// ANCHOR: mutable
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enums;
|
||||
library;
|
||||
|
||||
// ANCHOR: u64_example
|
||||
pub enum T {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library arrays;
|
||||
library;
|
||||
|
||||
// ANCHOR: syntax
|
||||
fn syntax() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library strings;
|
||||
library;
|
||||
|
||||
fn single_quotes() {
|
||||
// ANCHOR: single_quotes
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
library assertions;
|
||||
library;
|
||||
|
||||
dep req;
|
||||
mod req;
|
||||
|
||||
// ANCHOR: assert
|
||||
fn subtract(a: u64, b: u64) -> u64 {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library req;
|
||||
library;
|
||||
|
||||
// ANCHOR: require
|
||||
fn subtract(a: u64, b: u64) -> u64 {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library asset_operations;
|
||||
library;
|
||||
|
||||
// ANCHOR: mint_import
|
||||
use std::token::mint;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library call_data;
|
||||
library;
|
||||
|
||||
// ANCHOR: import_sender
|
||||
use std::auth::msg_sender;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library interface;
|
||||
library;
|
||||
|
||||
abi Vault {
|
||||
fn deposit();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library hashing;
|
||||
library;
|
||||
|
||||
// ANCHOR: import_sha256
|
||||
use std::hash::sha256;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library logging;
|
||||
library;
|
||||
|
||||
// ANCHOR: logging
|
||||
fn log_data(number: u64) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library namespace;
|
||||
library;
|
||||
|
||||
// ANCHOR: address
|
||||
pub struct Address {
|
||||
|
|
|
@ -4,7 +4,7 @@ A library is used to contain code that performs common operations in order to pr
|
|||
|
||||
## Definition
|
||||
|
||||
Libraries are defined using the `library` keyword at the beginning of a file followed by a name so that they can be identified and imported.
|
||||
Libraries are defined using the `library` keyword at the beginning of a file.
|
||||
|
||||
```sway
|
||||
{{#include ../../../../code/language/program-types/libraries/internal/my_library/src/my_library.sw:module}}
|
||||
|
|
|
@ -14,7 +14,7 @@ $ tree
|
|||
|
||||
To be able to use our library `my_library.sw` in `lib.sw` there are two steps to take:
|
||||
|
||||
1. Bring our library into scope by using the `dep` keyword followed by the library name
|
||||
1. Bring our library into scope by using the `mod` keyword followed by the library name
|
||||
2. Use the `use` keyword to selectively import various items from the library
|
||||
|
||||
```sway
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
contract;
|
||||
|
||||
dep other_contract;
|
||||
mod other_contract;
|
||||
|
||||
use other_contract::*;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library other_contract;
|
||||
library;
|
||||
|
||||
abi OtherContract {
|
||||
#[payable]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library basic_enum;
|
||||
library;
|
||||
|
||||
// Declare the enum
|
||||
enum Color {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enum_of_enums;
|
||||
library;
|
||||
|
||||
pub enum Error {
|
||||
StateError: StateError,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library enum_of_structs;
|
||||
library;
|
||||
|
||||
struct Item {
|
||||
price: u64,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
library enums_avoid;
|
||||
library;
|
||||
|
||||
dep enum_of_enums;
|
||||
use enum_of_enums::{Error, StateError, UserError};
|
||||
use ::enum_of_enums::{Error, StateError, UserError};
|
||||
|
||||
fn avoid() {
|
||||
let error1 = Error::StateError(StateError::Void);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
library enums_preferred;
|
||||
library;
|
||||
|
||||
dep enum_of_enums;
|
||||
use enum_of_enums::{StateError, UserError};
|
||||
use ::enum_of_enums::{StateError, UserError};
|
||||
|
||||
fn preferred() {
|
||||
let error1 = StateError::Void;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
library enums;
|
||||
library;
|
||||
|
||||
dep basic_enum;
|
||||
dep enums_avoid;
|
||||
dep enums_preferred;
|
||||
dep enum_of_structs;
|
||||
mod basic_enum;
|
||||
mod enum_of_structs;
|
||||
mod enum_of_enums;
|
||||
mod enums_avoid;
|
||||
mod enums_preferred;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library r#abi;
|
||||
library;
|
||||
|
||||
abi IdentityExample {
|
||||
#[storage(read)]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library errors;
|
||||
library;
|
||||
|
||||
pub enum MyError {
|
||||
UnauthorizedUser: Identity,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
contract;
|
||||
|
||||
dep r#abi;
|
||||
dep errors;
|
||||
mod r#abi;
|
||||
mod errors;
|
||||
|
||||
use abi::IdentityExample;
|
||||
use errors::MyError;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library data_structures;
|
||||
library;
|
||||
|
||||
// Declare a struct type
|
||||
pub struct Foo {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
library utils;
|
||||
library;
|
||||
|
||||
dep data_structures;
|
||||
mod data_structures;
|
||||
use data_structures::{Foo, Line, Point, TupleInStruct};
|
||||
|
||||
fn hardcoded_instantiation() -> Foo {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library tuples;
|
||||
library;
|
||||
|
||||
fn tuple() {
|
||||
// You can declare the types youself
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// ANCHOR: abi_library
|
||||
library wallet_abi;
|
||||
library;
|
||||
|
||||
// ANCHOR: abi
|
||||
abi Wallet {
|
||||
|
|
|
@ -658,7 +658,7 @@ impl BuildPlan {
|
|||
info!(" Creating a new `Forc.lock` file. (Cause: {})", cause);
|
||||
let member_names = manifests
|
||||
.iter()
|
||||
.map(|(_, manifest)| manifest.project.name.clone())
|
||||
.map(|(_, manifest)| manifest.project.name.to_string())
|
||||
.collect();
|
||||
crate::lock::print_diff(&member_names, &lock_diff);
|
||||
let string = toml::ser::to_string_pretty(&new_lock)
|
||||
|
@ -815,7 +815,11 @@ fn member_nodes(g: &Graph) -> impl Iterator<Item = NodeIx> + '_ {
|
|||
fn validate_graph(graph: &Graph, manifests: &MemberManifestFiles) -> Result<BTreeSet<EdgeIx>> {
|
||||
let mut member_pkgs: HashMap<&String, &PackageManifestFile> = manifests.iter().collect();
|
||||
let member_nodes: Vec<_> = member_nodes(graph)
|
||||
.filter_map(|n| member_pkgs.remove(&graph[n].name).map(|pkg| (n, pkg)))
|
||||
.filter_map(|n| {
|
||||
member_pkgs
|
||||
.remove(&graph[n].name.to_string())
|
||||
.map(|pkg| (n, pkg))
|
||||
})
|
||||
.collect();
|
||||
|
||||
// If no member nodes, the graph is either empty or corrupted. Remove all edges.
|
||||
|
@ -959,7 +963,7 @@ fn dep_path(
|
|||
|
||||
// Otherwise, check if it comes from a patch.
|
||||
for (_, patch_map) in node_manifest.patches() {
|
||||
if let Some(Dependency::Detailed(details)) = patch_map.get(dep_name) {
|
||||
if let Some(Dependency::Detailed(details)) = patch_map.get(&dep_name.to_string()) {
|
||||
if let Some(ref rel_path) = details.path {
|
||||
if let Ok(path) = node_manifest.dir().join(rel_path).canonicalize() {
|
||||
if path.exists() {
|
||||
|
@ -997,7 +1001,7 @@ fn remove_deps(
|
|||
) {
|
||||
// Retrieve the project nodes for workspace members.
|
||||
let member_nodes: HashSet<_> = member_nodes(graph)
|
||||
.filter(|&n| member_names.contains(&graph[n].name))
|
||||
.filter(|&n| member_names.contains(&graph[n].name.to_string()))
|
||||
.collect();
|
||||
|
||||
// Before removing edges, sort the nodes in order of dependency for the node removal pass.
|
||||
|
@ -1344,14 +1348,17 @@ fn fetch_deps(
|
|||
)
|
||||
.collect();
|
||||
for (dep_name, dep, dep_kind) in deps {
|
||||
let name = dep.package().unwrap_or(&dep_name).to_string();
|
||||
let name = dep.package().unwrap_or(&dep_name);
|
||||
let parent_manifest = &manifest_map[&parent_id];
|
||||
let source =
|
||||
Source::from_manifest_dep_patched(parent_manifest, &name, &dep, member_manifests)
|
||||
Source::from_manifest_dep_patched(parent_manifest, name, &dep, member_manifests)
|
||||
.context("Failed to source dependency")?;
|
||||
|
||||
// If we haven't yet fetched this dependency, fetch it, pin it and add it to the graph.
|
||||
let dep_pkg = Pkg { name, source };
|
||||
let dep_pkg = Pkg {
|
||||
name: name.to_string(),
|
||||
source,
|
||||
};
|
||||
let dep_node = match fetched.entry(dep_pkg) {
|
||||
hash_map::Entry::Occupied(entry) => *entry.get(),
|
||||
hash_map::Entry::Vacant(entry) => {
|
||||
|
@ -1503,9 +1510,7 @@ pub fn dependency_namespace(
|
|||
let mut namespace = namespace::Module::default_with_constants(engines, constants)?;
|
||||
|
||||
let node_idx = &graph[node];
|
||||
namespace.name = Some(Ident::new_no_span(Box::leak(
|
||||
node_idx.name.clone().into_boxed_str(),
|
||||
)));
|
||||
namespace.name = Some(Ident::new_no_span(node_idx.name.clone()));
|
||||
|
||||
// Add direct dependencies.
|
||||
let mut core_added = false;
|
||||
|
@ -1553,10 +1558,18 @@ pub fn dependency_namespace(
|
|||
}
|
||||
}
|
||||
|
||||
namespace.star_import_with_reexports(&[CORE, PRELUDE].map(Ident::new_no_span), &[], engines);
|
||||
namespace.star_import_with_reexports(
|
||||
&[CORE, PRELUDE].map(|s| Ident::new_no_span(s.into())),
|
||||
&[],
|
||||
engines,
|
||||
);
|
||||
|
||||
if has_std_dep(graph, node) {
|
||||
namespace.star_import_with_reexports(&[STD, PRELUDE].map(Ident::new_no_span), &[], engines);
|
||||
namespace.star_import_with_reexports(
|
||||
&[STD, PRELUDE].map(|s| Ident::new_no_span(s.into())),
|
||||
&[],
|
||||
engines,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(namespace)
|
||||
|
@ -1621,6 +1634,7 @@ pub fn compile_ast(
|
|||
build_target: BuildTarget,
|
||||
build_profile: &BuildProfile,
|
||||
namespace: namespace::Module,
|
||||
package_name: &str,
|
||||
) -> Result<CompileResult<ty::TyProgram>> {
|
||||
let source = manifest.entry_string()?;
|
||||
let sway_build_config = sway_build_config(
|
||||
|
@ -1629,7 +1643,13 @@ pub fn compile_ast(
|
|||
build_target,
|
||||
build_profile,
|
||||
)?;
|
||||
let ast_res = sway_core::compile_to_ast(engines, source, namespace, Some(&sway_build_config));
|
||||
let ast_res = sway_core::compile_to_ast(
|
||||
engines,
|
||||
source,
|
||||
namespace,
|
||||
Some(&sway_build_config),
|
||||
package_name,
|
||||
);
|
||||
Ok(ast_res)
|
||||
}
|
||||
|
||||
|
@ -1697,7 +1717,7 @@ pub fn compile(
|
|||
// First, compile to an AST. We'll update the namespace and check for JSON ABI output.
|
||||
let ast_res = time_expr!(
|
||||
"compile to ast",
|
||||
compile_ast(engines, manifest, *target, profile, namespace)?
|
||||
compile_ast(engines, manifest, *target, profile, namespace, &pkg.name)?
|
||||
);
|
||||
let typed_program = match ast_res.value.as_ref() {
|
||||
None => return fail(&ast_res.warnings, &ast_res.errors),
|
||||
|
@ -2048,7 +2068,7 @@ pub fn build_with_options(build_options: BuildOpts) -> Result<Built> {
|
|||
match curr_manifest {
|
||||
Some(pkg_manifest) => {
|
||||
let built_pkg = built_workspace
|
||||
.remove(&pkg_manifest.project.name)
|
||||
.remove(&pkg_manifest.project.name.to_string())
|
||||
.expect("package didn't exist in workspace");
|
||||
Ok(Built::Package(Box::new(built_pkg)))
|
||||
}
|
||||
|
@ -2270,9 +2290,18 @@ pub fn build(
|
|||
};
|
||||
let (mut built_package, namespace) =
|
||||
compile_pkg(node, &mut source_map, compile_pkg_context)?;
|
||||
if let TreeType::Library { ref name } = built_package.tree_type {
|
||||
if let TreeType::Library = built_package.tree_type {
|
||||
let mut namespace = namespace::Module::from(namespace);
|
||||
namespace.name = Some(name.clone());
|
||||
namespace.name = Some(Ident::new_no_span(pkg.name.clone()));
|
||||
namespace.span = Some(
|
||||
Span::new(
|
||||
manifest.entry_string()?,
|
||||
0,
|
||||
0,
|
||||
Some(manifest.entry_path().into()),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
lib_namespace_map.insert(node, namespace);
|
||||
}
|
||||
source_map.insert_dependency(manifest.dir());
|
||||
|
@ -2461,7 +2490,7 @@ pub fn check(
|
|||
Some(modules) => modules,
|
||||
};
|
||||
|
||||
let ast_result = sway_core::parsed_to_ast(engines, &parsed, dep_namespace, None);
|
||||
let ast_result = sway_core::parsed_to_ast(engines, &parsed, dep_namespace, None, &pkg.name);
|
||||
warnings.extend(ast_result.warnings);
|
||||
errors.extend(ast_result.errors);
|
||||
|
||||
|
@ -2474,9 +2503,18 @@ pub fn check(
|
|||
Some(typed_program) => typed_program,
|
||||
};
|
||||
|
||||
if let TreeType::Library { name } = typed_program.kind.tree_type() {
|
||||
if let TreeType::Library = typed_program.kind.tree_type() {
|
||||
let mut namespace = typed_program.root.namespace.clone();
|
||||
namespace.name = Some(name.clone());
|
||||
namespace.name = Some(Ident::new_no_span(pkg.name.clone()));
|
||||
namespace.span = Some(
|
||||
Span::new(
|
||||
manifest.entry_string()?,
|
||||
0,
|
||||
0,
|
||||
Some(manifest.entry_path().into()),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
lib_namespace_map.insert(node, namespace);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ impl Document {
|
|||
let mut new_submodule_prefix = module_prefix.to_owned();
|
||||
new_submodule_prefix
|
||||
.module_prefixes
|
||||
.push(typed_submodule.library_name.as_str().to_owned());
|
||||
.push(typed_submodule.mod_name_span.as_str().to_owned());
|
||||
for ast_node in &typed_submodule.module.all_nodes {
|
||||
if let TyAstNodeContent::Declaration(ref decl) = ast_node.content {
|
||||
let desc = Descriptor::from_typed_decl(
|
||||
|
|
|
@ -139,7 +139,7 @@ pub fn init(command: InitCommand) -> Result<()> {
|
|||
.join("src")
|
||||
.join(constants::LIB_ENTRY),
|
||||
// Library names cannot have `-` in them because the Sway compiler does not allow that
|
||||
defaults::default_library(&project_name.replace('-', "_")),
|
||||
defaults::default_library(),
|
||||
)?,
|
||||
InitType::Package(ProgramType::Predicate) => fs::write(
|
||||
Path::new(&project_dir)
|
||||
|
|
|
@ -47,13 +47,12 @@ fn main() {
|
|||
.into()
|
||||
}
|
||||
|
||||
pub(crate) fn default_library(project_name: &str) -> String {
|
||||
format!(
|
||||
"library {project_name};
|
||||
pub(crate) fn default_library() -> String {
|
||||
"library;
|
||||
|
||||
// anything `pub` here will be exported as a part of this library's API
|
||||
"
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub(crate) fn default_predicate() -> String {
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
use crate::priv_prelude::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Dependency {
|
||||
pub dep_token: DepToken,
|
||||
pub path: DependencyPath,
|
||||
pub semicolon_token: SemicolonToken,
|
||||
}
|
||||
|
||||
impl Spanned for Dependency {
|
||||
fn span(&self) -> Span {
|
||||
Span::join(self.dep_token.span(), self.semicolon_token.span())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DependencyPath {
|
||||
pub prefix: Ident,
|
||||
pub suffixes: Vec<(ForwardSlashToken, Ident)>,
|
||||
}
|
||||
|
||||
impl Spanned for DependencyPath {
|
||||
fn span(&self) -> Span {
|
||||
match self.suffixes.last() {
|
||||
Some((_forward_slash_token, suffix)) => Span::join(self.prefix.span(), suffix.span()),
|
||||
None => self.prefix.span(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ impl Spanned for Item {
|
|||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ItemKind {
|
||||
Dependency(Dependency),
|
||||
Submodule(Submodule),
|
||||
Use(ItemUse),
|
||||
Struct(ItemStruct),
|
||||
Enum(ItemEnum),
|
||||
|
@ -41,7 +41,7 @@ pub enum ItemKind {
|
|||
impl Spanned for ItemKind {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
ItemKind::Dependency(item_dep) => item_dep.span(),
|
||||
ItemKind::Submodule(item_mod) => item_mod.span(),
|
||||
ItemKind::Use(item_use) => item_use.span(),
|
||||
ItemKind::Struct(item_struct) => item_struct.span(),
|
||||
ItemKind::Enum(item_enum) => item_enum.span(),
|
||||
|
|
|
@ -49,7 +49,7 @@ define_keyword!(ScriptToken, "script");
|
|||
define_keyword!(ContractToken, "contract");
|
||||
define_keyword!(PredicateToken, "predicate");
|
||||
define_keyword!(LibraryToken, "library");
|
||||
define_keyword!(DepToken, "dep");
|
||||
define_keyword!(ModToken, "mod");
|
||||
define_keyword!(PubToken, "pub");
|
||||
define_keyword!(UseToken, "use");
|
||||
define_keyword!(AsToken, "as");
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
pub mod assignable;
|
||||
pub mod attribute;
|
||||
pub mod brackets;
|
||||
pub mod dependency;
|
||||
pub mod expr;
|
||||
pub mod generics;
|
||||
pub mod intrinsics;
|
||||
|
@ -14,6 +13,7 @@ pub mod pattern;
|
|||
mod priv_prelude;
|
||||
pub mod punctuated;
|
||||
pub mod statement;
|
||||
pub mod submodule;
|
||||
pub mod token;
|
||||
pub mod ty;
|
||||
pub mod where_clause;
|
||||
|
@ -22,7 +22,6 @@ pub use crate::{
|
|||
assignable::Assignable,
|
||||
attribute::AttributeDecl,
|
||||
brackets::{AngleBrackets, Braces, Parens},
|
||||
dependency::Dependency,
|
||||
expr::{
|
||||
asm::{AsmBlock, AsmRegisterDeclaration},
|
||||
op_code::Instruction,
|
||||
|
@ -51,6 +50,7 @@ pub use crate::{
|
|||
pattern::{Pattern, PatternStructField},
|
||||
punctuated::Punctuated,
|
||||
statement::{Statement, StatementLet},
|
||||
submodule::Submodule,
|
||||
ty::Ty,
|
||||
where_clause::{WhereBound, WhereClause},
|
||||
};
|
||||
|
|
|
@ -8,10 +8,10 @@ pub struct Module {
|
|||
}
|
||||
|
||||
impl Module {
|
||||
pub fn dependencies(&self) -> impl Iterator<Item = &Dependency> {
|
||||
pub fn submodules(&self) -> impl Iterator<Item = &Submodule> {
|
||||
self.items.iter().filter_map(|i| {
|
||||
if let ItemKind::Dependency(dep) = &i.value {
|
||||
Some(dep)
|
||||
if let ItemKind::Submodule(submod) = &i.value {
|
||||
Some(submod)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -33,19 +33,10 @@ impl Spanned for Module {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ModuleKind {
|
||||
Script {
|
||||
script_token: ScriptToken,
|
||||
},
|
||||
Contract {
|
||||
contract_token: ContractToken,
|
||||
},
|
||||
Predicate {
|
||||
predicate_token: PredicateToken,
|
||||
},
|
||||
Library {
|
||||
library_token: LibraryToken,
|
||||
name: Ident,
|
||||
},
|
||||
Script { script_token: ScriptToken },
|
||||
Contract { contract_token: ContractToken },
|
||||
Predicate { predicate_token: PredicateToken },
|
||||
Library { library_token: LibraryToken },
|
||||
}
|
||||
|
||||
impl Spanned for ModuleKind {
|
||||
|
@ -54,10 +45,7 @@ impl Spanned for ModuleKind {
|
|||
Self::Script { script_token } => script_token.span(),
|
||||
Self::Contract { contract_token } => contract_token.span(),
|
||||
Self::Predicate { predicate_token } => predicate_token.span(),
|
||||
Self::Library {
|
||||
library_token,
|
||||
name,
|
||||
} => Span::join(library_token.span(), name.span()),
|
||||
Self::Library { library_token } => library_token.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ pub use {
|
|||
assignable::Assignable,
|
||||
attribute::{Annotated, Attribute, AttributeDecl},
|
||||
brackets::{AngleBrackets, Braces, Parens, SquareBrackets},
|
||||
dependency::Dependency,
|
||||
expr::{
|
||||
asm::{AsmBlock, AsmImmediate},
|
||||
op_code::Instruction,
|
||||
|
@ -30,6 +29,7 @@ pub use {
|
|||
pattern::Pattern,
|
||||
punctuated::Punctuated,
|
||||
statement::{Statement, StatementLet},
|
||||
submodule::Submodule,
|
||||
token::{Delimiter, Group, Punct, PunctKind, Spacing, TokenStream, TokenTree},
|
||||
ty::Ty,
|
||||
where_clause::{WhereBound, WhereClause},
|
||||
|
|
14
sway-ast/src/submodule.rs
Normal file
14
sway-ast/src/submodule.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use crate::priv_prelude::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Submodule {
|
||||
pub mod_token: ModToken,
|
||||
pub name: Ident,
|
||||
pub semicolon_token: SemicolonToken,
|
||||
}
|
||||
|
||||
impl Spanned for Submodule {
|
||||
fn span(&self) -> Span {
|
||||
Span::join(self.mod_token.span(), self.semicolon_token.span())
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
mod program;
|
||||
|
||||
use crate::language::DepName;
|
||||
use crate::language::ModName;
|
||||
pub use program::LexedProgram;
|
||||
use sway_ast::Module;
|
||||
use sway_types::Ident;
|
||||
|
||||
/// A module and its submodules in the form of a tree.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -11,15 +10,13 @@ pub struct LexedModule {
|
|||
/// The content of this module in the form of a [Module].
|
||||
pub tree: Module,
|
||||
/// Submodules introduced within this module using the `dep` syntax in order of declaration.
|
||||
pub submodules: Vec<(DepName, LexedSubmodule)>,
|
||||
pub submodules: Vec<(ModName, LexedSubmodule)>,
|
||||
}
|
||||
|
||||
/// A library module that was declared as a `dep` of another module.
|
||||
/// A library module that was declared as a `mod` of another module.
|
||||
///
|
||||
/// Only submodules are guaranteed to be a `library` and have a `library_name`.
|
||||
/// Only submodules are guaranteed to be a `library`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LexedSubmodule {
|
||||
/// The name of a submodule, parsed from the `library` declaration within the module itself.
|
||||
pub library_name: Ident,
|
||||
pub module: LexedModule,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@ use sway_types::Ident;
|
|||
|
||||
/// The name used within a module to refer to one of its submodules.
|
||||
///
|
||||
/// If an alias was given to the `dep`, this will be the alias. If not, this is the submodule's
|
||||
/// If an alias was given to the `mod`, this will be the alias. If not, this is the submodule's
|
||||
/// library name.
|
||||
pub type DepName = Ident;
|
||||
pub type ModName = Ident;
|
||||
|
|
|
@ -247,7 +247,7 @@ pub(crate) struct Op {
|
|||
|
||||
impl Op {
|
||||
pub fn to_var_name(&self) -> Ident {
|
||||
Ident::new_with_override(self.op_variant.as_str(), self.span.clone())
|
||||
Ident::new_with_override(self.op_variant.as_str().to_string(), self.span.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use sway_types::{ident::Ident, span::Span};
|
||||
use sway_types::span::Span;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IncludeStatement {
|
||||
pub(crate) _alias: Option<Ident>,
|
||||
#[allow(dead_code)]
|
||||
// this span may be used for errors in the future, although it is not right now.
|
||||
pub(crate) span: Span,
|
||||
pub(crate) _path_span: Span,
|
||||
pub(crate) _span: Span,
|
||||
pub(crate) _mod_name_span: Span,
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ pub enum AstNodeContent {
|
|||
/// An implicit return expression is an [Expression] at the end of a code block which has no
|
||||
/// semicolon, denoting that it is the [Expression] to be returned from that block.
|
||||
ImplicitReturnExpression(Expression),
|
||||
/// A statement of the form `dep foo::bar;` which imports/includes another source file.
|
||||
/// A statement of the form `mod foo::bar;` which imports/includes another source file.
|
||||
IncludeStatement(IncludeStatement),
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{language::DepName, transform};
|
||||
use crate::{language::ModName, transform};
|
||||
|
||||
use super::ParseTree;
|
||||
use sway_types::{Ident, Span};
|
||||
use sway_types::Span;
|
||||
|
||||
/// A module and its submodules in the form of a tree.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -9,17 +9,17 @@ pub struct ParseModule {
|
|||
/// The content of this module in the form of a `ParseTree`.
|
||||
pub tree: ParseTree,
|
||||
/// Submodules introduced within this module using the `dep` syntax in order of declaration.
|
||||
pub submodules: Vec<(DepName, ParseSubmodule)>,
|
||||
pub submodules: Vec<(ModName, ParseSubmodule)>,
|
||||
pub attributes: transform::AttributesMap,
|
||||
/// an empty span at the beginning of the file containing the module
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// A library module that was declared as a `dep` of another module.
|
||||
/// A library module that was declared as a `mod` of another module.
|
||||
///
|
||||
/// Only submodules are guaranteed to be a `library` and have a `library_name`.
|
||||
/// Only submodules are guaranteed to be a `library`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseSubmodule {
|
||||
/// The name of a submodule, parsed from the `library` declaration within the module itself.
|
||||
pub library_name: Ident,
|
||||
pub module: ParseModule,
|
||||
pub dependency_path_span: Span,
|
||||
pub mod_name_span: Span,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use super::ParseModule;
|
||||
use sway_types::Ident;
|
||||
|
||||
/// A parsed, but not yet type-checked, Sway program.
|
||||
///
|
||||
|
@ -18,7 +17,7 @@ pub enum TreeType {
|
|||
Predicate,
|
||||
Script,
|
||||
Contract,
|
||||
Library { name: Ident },
|
||||
Library,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for TreeType {
|
||||
|
@ -30,7 +29,7 @@ impl std::fmt::Display for TreeType {
|
|||
Self::Predicate => "predicate",
|
||||
Self::Script => "script",
|
||||
Self::Contract => "contract",
|
||||
Self::Library { .. } => "library",
|
||||
Self::Library => "library",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ impl TyStorageDeclaration {
|
|||
attributes: transform::AttributesMap,
|
||||
) -> Self {
|
||||
TyStorageDeclaration {
|
||||
name: Ident::new_with_override("storage", span.clone()),
|
||||
name: Ident::new_with_override("storage".to_string(), span.clone()),
|
||||
fields,
|
||||
span,
|
||||
attributes,
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
use sway_types::{Ident, Span};
|
||||
use sway_types::Span;
|
||||
|
||||
use crate::{
|
||||
decl_engine::{DeclEngine, DeclRef, DeclRefFunction},
|
||||
language::ty::*,
|
||||
language::DepName,
|
||||
language::ModName,
|
||||
semantic_analysis::namespace,
|
||||
transform,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TyModule {
|
||||
pub submodules: Vec<(DepName, TySubmodule)>,
|
||||
pub span: Span,
|
||||
pub submodules: Vec<(ModName, TySubmodule)>,
|
||||
pub namespace: namespace::Module,
|
||||
pub all_nodes: Vec<TyAstNode>,
|
||||
pub attributes: transform::AttributesMap,
|
||||
|
@ -18,18 +19,17 @@ pub struct TyModule {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TySubmodule {
|
||||
pub library_name: Ident,
|
||||
pub module: TyModule,
|
||||
pub dependency_path_span: Span,
|
||||
pub mod_name_span: Span,
|
||||
}
|
||||
|
||||
/// Iterator type for iterating over submodules.
|
||||
///
|
||||
/// Used rather than `impl Iterator` to enable recursive submodule iteration.
|
||||
pub struct SubmodulesRecursive<'module> {
|
||||
submods: std::slice::Iter<'module, (DepName, TySubmodule)>,
|
||||
submods: std::slice::Iter<'module, (ModName, TySubmodule)>,
|
||||
current: Option<(
|
||||
&'module (DepName, TySubmodule),
|
||||
&'module (ModName, TySubmodule),
|
||||
Box<SubmodulesRecursive<'module>>,
|
||||
)>,
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ impl TyModule {
|
|||
}
|
||||
|
||||
impl<'module> Iterator for SubmodulesRecursive<'module> {
|
||||
type Item = &'module (DepName, TySubmodule);
|
||||
type Item = &'module (ModName, TySubmodule);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
self.current = match self.current.take() {
|
||||
|
|
|
@ -28,7 +28,7 @@ impl TyProgram {
|
|||
engines: Engines<'_>,
|
||||
root: &TyModule,
|
||||
kind: parsed::TreeType,
|
||||
module_span: Span,
|
||||
package_name: &str,
|
||||
) -> CompileResult<(
|
||||
TyProgramKind,
|
||||
Vec<TyDeclaration>,
|
||||
|
@ -48,10 +48,8 @@ impl TyProgram {
|
|||
Self::validate_root(
|
||||
engines,
|
||||
&submodule.module,
|
||||
parsed::TreeType::Library {
|
||||
name: submodule.library_name.clone(),
|
||||
},
|
||||
submodule.library_name.span().clone(),
|
||||
parsed::TreeType::Library,
|
||||
package_name,
|
||||
),
|
||||
continue,
|
||||
warnings,
|
||||
|
@ -204,18 +202,20 @@ impl TyProgram {
|
|||
|
||||
TyProgramKind::Contract { abi_entries }
|
||||
}
|
||||
parsed::TreeType::Library { name } => {
|
||||
parsed::TreeType::Library => {
|
||||
if !configurables.is_empty() {
|
||||
errors.push(CompileError::ConfigurableInLibrary {
|
||||
span: configurables[0].name.span(),
|
||||
});
|
||||
}
|
||||
TyProgramKind::Library { name }
|
||||
TyProgramKind::Library {
|
||||
name: package_name.to_string(),
|
||||
}
|
||||
}
|
||||
parsed::TreeType::Predicate => {
|
||||
// A predicate must have a main function and that function must return a boolean.
|
||||
if mains.is_empty() {
|
||||
errors.push(CompileError::NoPredicateMainFunction(module_span));
|
||||
errors.push(CompileError::NoPredicateMainFunction(root.span.clone()));
|
||||
return err(vec![], errors);
|
||||
}
|
||||
if mains.len() > 1 {
|
||||
|
@ -238,7 +238,7 @@ impl TyProgram {
|
|||
parsed::TreeType::Script => {
|
||||
// A script must have exactly one main function.
|
||||
if mains.is_empty() {
|
||||
errors.push(CompileError::NoScriptMainFunction(module_span));
|
||||
errors.push(CompileError::NoScriptMainFunction(root.span.clone()));
|
||||
return err(vec![], errors);
|
||||
}
|
||||
if mains.len() > 1 {
|
||||
|
@ -429,7 +429,7 @@ pub enum TyProgramKind {
|
|||
abi_entries: Vec<TyFunctionDeclaration>,
|
||||
},
|
||||
Library {
|
||||
name: Ident,
|
||||
name: String,
|
||||
},
|
||||
Predicate {
|
||||
main_function: TyFunctionDeclaration,
|
||||
|
@ -444,7 +444,7 @@ impl TyProgramKind {
|
|||
pub fn tree_type(&self) -> parsed::TreeType {
|
||||
match self {
|
||||
TyProgramKind::Contract { .. } => parsed::TreeType::Contract,
|
||||
TyProgramKind::Library { name } => parsed::TreeType::Library { name: name.clone() },
|
||||
TyProgramKind::Library { .. } => parsed::TreeType::Library,
|
||||
TyProgramKind::Predicate { .. } => parsed::TreeType::Predicate,
|
||||
TyProgramKind::Script { .. } => parsed::TreeType::Script,
|
||||
}
|
||||
|
|
|
@ -80,16 +80,15 @@ pub fn parse(
|
|||
None => parse_in_memory(h, engines, input),
|
||||
// When a `BuildConfig` is given,
|
||||
// the module source may declare `dep`s that must be parsed from other files.
|
||||
Some(config) => parse_module_tree(h, engines, input, config.canonical_root_module()).map(
|
||||
|(kind, lexed, parsed)| {
|
||||
Some(config) => parse_module_tree(h, engines, input, config.canonical_root_module(), None)
|
||||
.map(|(kind, lexed, parsed)| {
|
||||
let lexed = lexed::LexedProgram {
|
||||
kind: kind.clone(),
|
||||
root: lexed,
|
||||
};
|
||||
let parsed = parsed::ParseProgram { kind, root: parsed };
|
||||
(lexed, parsed)
|
||||
},
|
||||
),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -158,6 +157,7 @@ fn parse_in_memory(
|
|||
let submodules = Default::default();
|
||||
let attributes = module_attrs_to_map(handler, &module.attribute_list)?;
|
||||
let root = parsed::ParseModule {
|
||||
span: span::Span::dummy(),
|
||||
tree,
|
||||
submodules,
|
||||
attributes,
|
||||
|
@ -182,56 +182,52 @@ struct Submodules {
|
|||
fn parse_submodules(
|
||||
handler: &Handler,
|
||||
engines: Engines<'_>,
|
||||
module_name: Option<&str>,
|
||||
module: &sway_ast::Module,
|
||||
module_dir: &Path,
|
||||
) -> Submodules {
|
||||
// Assume the happy path, so there'll be as many submodules as dependencies, but no more.
|
||||
let mut lexed_submods = Vec::with_capacity(module.dependencies().count());
|
||||
let mut lexed_submods = Vec::with_capacity(module.submodules().count());
|
||||
let mut parsed_submods = Vec::with_capacity(lexed_submods.capacity());
|
||||
|
||||
module.dependencies().for_each(|dep| {
|
||||
module.submodules().for_each(|submod| {
|
||||
// Read the source code from the dependency.
|
||||
// If we cannot, record as an error, but continue with other files.
|
||||
let dep_path = Arc::new(module_path(module_dir, dep));
|
||||
let dep_str: Arc<str> = match std::fs::read_to_string(&*dep_path) {
|
||||
let submod_path = Arc::new(module_path(module_dir, module_name, submod));
|
||||
let submod_str: Arc<str> = match std::fs::read_to_string(&*submod_path) {
|
||||
Ok(s) => Arc::from(s),
|
||||
Err(e) => {
|
||||
handler.emit_err(CompileError::FileCouldNotBeRead {
|
||||
span: dep.path.span(),
|
||||
file_path: dep_path.to_string_lossy().to_string(),
|
||||
span: submod.name.span(),
|
||||
file_path: submod_path.to_string_lossy().to_string(),
|
||||
stringified_error: e.to_string(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok((kind, lexed_module, parse_module)) =
|
||||
parse_module_tree(handler, engines, dep_str.clone(), dep_path.clone())
|
||||
{
|
||||
let library_name = match kind {
|
||||
parsed::TreeType::Library { name } => name,
|
||||
_ => {
|
||||
let span = span::Span::new(dep_str, 0, 0, Some(dep_path)).unwrap();
|
||||
handler.emit_err(CompileError::ImportMustBeLibrary { span });
|
||||
return;
|
||||
}
|
||||
};
|
||||
// NOTE: Typed `IncludStatement`'s include an `alias` field, however its only
|
||||
// constructor site is always `None`. If we introduce dep aliases in the future, this
|
||||
// is where we should use it.
|
||||
let dep_alias = None;
|
||||
let dep_name = dep_alias.unwrap_or_else(|| library_name.clone());
|
||||
if let Ok((kind, lexed_module, parse_module)) = parse_module_tree(
|
||||
handler,
|
||||
engines,
|
||||
submod_str.clone(),
|
||||
submod_path.clone(),
|
||||
Some(submod.name.as_str()),
|
||||
) {
|
||||
if !matches!(kind, parsed::TreeType::Library) {
|
||||
let span = span::Span::new(submod_str, 0, 0, Some(submod_path)).unwrap();
|
||||
handler.emit_err(CompileError::ImportMustBeLibrary { span });
|
||||
return;
|
||||
}
|
||||
|
||||
let parse_submodule = parsed::ParseSubmodule {
|
||||
library_name: library_name.clone(),
|
||||
module: parse_module,
|
||||
dependency_path_span: dep.path.span(),
|
||||
mod_name_span: submod.name.span(),
|
||||
};
|
||||
let lexed_submodule = lexed::LexedSubmodule {
|
||||
library_name,
|
||||
module: lexed_module,
|
||||
};
|
||||
lexed_submods.push((dep_name.clone(), lexed_submodule));
|
||||
parsed_submods.push((dep_name, parse_submodule));
|
||||
lexed_submods.push((submod.name.clone(), lexed_submodule));
|
||||
parsed_submods.push((submod.name.clone(), parse_submodule));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -248,14 +244,15 @@ fn parse_module_tree(
|
|||
engines: Engines<'_>,
|
||||
src: Arc<str>,
|
||||
path: Arc<PathBuf>,
|
||||
module_name: Option<&str>,
|
||||
) -> Result<(parsed::TreeType, lexed::LexedModule, parsed::ParseModule), ErrorEmitted> {
|
||||
// Parse this module first.
|
||||
let module_dir = path.parent().expect("module file has no parent directory");
|
||||
let module = sway_parse::parse_file(handler, src, Some(path.clone()))?;
|
||||
let module = sway_parse::parse_file(handler, src.clone(), Some(path.clone()))?;
|
||||
|
||||
// Parse all submodules before converting to the `ParseTree`.
|
||||
// This always recovers on parse errors for the file itself by skipping that file.
|
||||
let submodules = parse_submodules(handler, engines, &module.value, module_dir);
|
||||
let submodules = parse_submodules(handler, engines, module_name, &module.value, module_dir);
|
||||
|
||||
// Convert from the raw parsed module to the `ParseTree` ready for type-check.
|
||||
let (kind, tree) = to_parsed_lang::convert_parse_tree(
|
||||
|
@ -271,6 +268,7 @@ fn parse_module_tree(
|
|||
submodules: submodules.lexed,
|
||||
};
|
||||
let parsed = parsed::ParseModule {
|
||||
span: span::Span::new(src, 0, 0, Some(path)).unwrap(),
|
||||
tree,
|
||||
submodules: submodules.parsed,
|
||||
attributes,
|
||||
|
@ -278,12 +276,22 @@ fn parse_module_tree(
|
|||
Ok((kind, lexed, parsed))
|
||||
}
|
||||
|
||||
fn module_path(parent_module_dir: &Path, dep: &sway_ast::Dependency) -> PathBuf {
|
||||
parent_module_dir
|
||||
.iter()
|
||||
.chain(dep.path.span().as_str().split('/').map(AsRef::as_ref))
|
||||
.collect::<PathBuf>()
|
||||
.with_extension(sway_types::constants::DEFAULT_FILE_EXTENSION)
|
||||
fn module_path(
|
||||
parent_module_dir: &Path,
|
||||
parent_module_name: Option<&str>,
|
||||
submod: &sway_ast::Submodule,
|
||||
) -> PathBuf {
|
||||
if let Some(parent_name) = parent_module_name {
|
||||
parent_module_dir
|
||||
.join(parent_name)
|
||||
.join(submod.name.to_string())
|
||||
.with_extension(sway_types::constants::DEFAULT_FILE_EXTENSION)
|
||||
} else {
|
||||
// top level module
|
||||
parent_module_dir
|
||||
.join(submod.name.to_string())
|
||||
.with_extension(sway_types::constants::DEFAULT_FILE_EXTENSION)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CompiledAsm(pub FinalizedAsm);
|
||||
|
@ -293,13 +301,14 @@ pub fn parsed_to_ast(
|
|||
parse_program: &parsed::ParseProgram,
|
||||
initial_namespace: namespace::Module,
|
||||
build_config: Option<&BuildConfig>,
|
||||
package_name: &str,
|
||||
) -> CompileResult<ty::TyProgram> {
|
||||
// Type check the program.
|
||||
let CompileResult {
|
||||
value: typed_program_opt,
|
||||
mut warnings,
|
||||
mut errors,
|
||||
} = ty::TyProgram::type_check(engines, parse_program, initial_namespace);
|
||||
} = ty::TyProgram::type_check(engines, parse_program, initial_namespace, package_name);
|
||||
let mut typed_program = match typed_program_opt {
|
||||
Some(typed_program) => typed_program,
|
||||
None => return err(warnings, errors),
|
||||
|
@ -403,6 +412,7 @@ pub fn compile_to_ast(
|
|||
input: Arc<str>,
|
||||
initial_namespace: namespace::Module,
|
||||
build_config: Option<&BuildConfig>,
|
||||
package_name: &str,
|
||||
) -> CompileResult<ty::TyProgram> {
|
||||
// Parse the program to a concrete syntax tree (CST).
|
||||
let CompileResult {
|
||||
|
@ -424,7 +434,13 @@ pub fn compile_to_ast(
|
|||
}
|
||||
|
||||
// Type check (+ other static analysis) the CST to a typed AST.
|
||||
let typed_res = parsed_to_ast(engines, &parse_program, initial_namespace, build_config);
|
||||
let typed_res = parsed_to_ast(
|
||||
engines,
|
||||
&parse_program,
|
||||
initial_namespace,
|
||||
build_config,
|
||||
package_name,
|
||||
);
|
||||
errors.extend(typed_res.errors);
|
||||
warnings.extend(typed_res.warnings);
|
||||
let typed_program = match typed_res.value {
|
||||
|
@ -447,8 +463,15 @@ pub fn compile_to_asm(
|
|||
input: Arc<str>,
|
||||
initial_namespace: namespace::Module,
|
||||
build_config: BuildConfig,
|
||||
package_name: &str,
|
||||
) -> CompileResult<CompiledAsm> {
|
||||
let ast_res = compile_to_ast(engines, input, initial_namespace, Some(&build_config));
|
||||
let ast_res = compile_to_ast(
|
||||
engines,
|
||||
input,
|
||||
initial_namespace,
|
||||
Some(&build_config),
|
||||
package_name,
|
||||
);
|
||||
ast_to_asm(engines, &ast_res, &build_config)
|
||||
}
|
||||
|
||||
|
@ -560,8 +583,15 @@ pub fn compile_to_bytecode(
|
|||
initial_namespace: namespace::Module,
|
||||
build_config: BuildConfig,
|
||||
source_map: &mut SourceMap,
|
||||
package_name: &str,
|
||||
) -> CompileResult<CompiledBytecode> {
|
||||
let asm_res = compile_to_asm(engines, input, initial_namespace, build_config);
|
||||
let asm_res = compile_to_asm(
|
||||
engines,
|
||||
input,
|
||||
initial_namespace,
|
||||
build_config,
|
||||
package_name,
|
||||
);
|
||||
asm_to_bytecode(asm_res, source_map)
|
||||
}
|
||||
|
||||
|
@ -641,8 +671,7 @@ fn module_dead_code_analysis<'eng: 'cfg, 'cfg>(
|
|||
.submodules
|
||||
.iter()
|
||||
.fold(init_res, |res, (_, submodule)| {
|
||||
let name = submodule.library_name.clone();
|
||||
let tree_type = parsed::TreeType::Library { name };
|
||||
let tree_type = parsed::TreeType::Library;
|
||||
res.flat_map(|_| {
|
||||
module_dead_code_analysis(engines, &submodule.module, &tree_type, graph)
|
||||
})
|
||||
|
|
|
@ -57,10 +57,10 @@ impl ty::TyCodeBlock {
|
|||
.unwrap_or_else(|| {
|
||||
if node_deterministically_aborts {
|
||||
let never_mod_path = vec![
|
||||
Ident::new_with_override("core", span.clone()),
|
||||
Ident::new_with_override("never", span.clone()),
|
||||
Ident::new_with_override("core".into(), span.clone()),
|
||||
Ident::new_with_override("never".into(), span.clone()),
|
||||
];
|
||||
let never_ident = Ident::new_with_override("Never", span.clone());
|
||||
let never_ident = Ident::new_with_override("Never".into(), span.clone());
|
||||
|
||||
let never_decl_opt = ctx
|
||||
.namespace
|
||||
|
|
|
@ -212,7 +212,7 @@ fn test_function_selector_behavior() {
|
|||
|
||||
let decl = ty::TyFunctionDeclaration {
|
||||
purity: Default::default(),
|
||||
name: Ident::new_no_span("foo"),
|
||||
name: Ident::new_no_span("foo".into()),
|
||||
implementing_type: None,
|
||||
body: ty::TyCodeBlock { contents: vec![] },
|
||||
parameters: vec![],
|
||||
|
@ -234,12 +234,12 @@ fn test_function_selector_behavior() {
|
|||
|
||||
let decl = ty::TyFunctionDeclaration {
|
||||
purity: Default::default(),
|
||||
name: Ident::new_with_override("bar", Span::dummy()),
|
||||
name: Ident::new_with_override("bar".into(), Span::dummy()),
|
||||
implementing_type: None,
|
||||
body: ty::TyCodeBlock { contents: vec![] },
|
||||
parameters: vec![
|
||||
ty::TyFunctionParameter {
|
||||
name: Ident::new_no_span("foo"),
|
||||
name: Ident::new_no_span("foo".into()),
|
||||
is_reference: false,
|
||||
is_mutable: false,
|
||||
mutability_span: Span::dummy(),
|
||||
|
@ -248,7 +248,7 @@ fn test_function_selector_behavior() {
|
|||
.into(),
|
||||
},
|
||||
ty::TyFunctionParameter {
|
||||
name: Ident::new_no_span("baz"),
|
||||
name: Ident::new_no_span("baz".into()),
|
||||
is_reference: false,
|
||||
is_mutable: false,
|
||||
mutability_span: Span::dummy(),
|
||||
|
|
|
@ -446,7 +446,7 @@ impl ty::TyImplTrait {
|
|||
prefixes: vec![],
|
||||
suffix: match &type_engine.get(implementing_for.type_id) {
|
||||
TypeInfo::Custom { call_path, .. } => call_path.suffix.clone(),
|
||||
_ => Ident::new_with_override("r#Self", implementing_for.span()),
|
||||
_ => Ident::new_with_override("r#Self".into(), implementing_for.span()),
|
||||
},
|
||||
is_absolute: false,
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ impl ty::TyScrutinee {
|
|||
let dummy_type_param = TypeParameter {
|
||||
type_id,
|
||||
initial_type_id: type_id,
|
||||
name_ident: BaseIdent::new_with_override("_", span.clone()),
|
||||
name_ident: BaseIdent::new_with_override("_".into(), span.clone()),
|
||||
trait_constraints: vec![],
|
||||
trait_constraints_span: Span::dummy(),
|
||||
};
|
||||
|
|
|
@ -57,8 +57,8 @@ impl ty::TyExpression {
|
|||
|
||||
let call_path = CallPath {
|
||||
prefixes: vec![
|
||||
Ident::new_with_override("core", span.clone()),
|
||||
Ident::new_with_override("ops", span.clone()),
|
||||
Ident::new_with_override("core".into(), span.clone()),
|
||||
Ident::new_with_override("ops".into(), span.clone()),
|
||||
],
|
||||
suffix: Op {
|
||||
op_variant: OpVariant::Equals,
|
||||
|
@ -1526,10 +1526,10 @@ impl ty::TyExpression {
|
|||
inner: MethodName::FromTrait {
|
||||
call_path: CallPath {
|
||||
prefixes: vec![
|
||||
Ident::new_with_override("core", span.clone()),
|
||||
Ident::new_with_override("ops", span.clone()),
|
||||
Ident::new_with_override("core".into(), span.clone()),
|
||||
Ident::new_with_override("ops".into(), span.clone()),
|
||||
],
|
||||
suffix: Ident::new_with_override("index", span.clone()),
|
||||
suffix: Ident::new_with_override("index".into(), span.clone()),
|
||||
is_absolute: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
error::*,
|
||||
language::{parsed::*, ty, DepName},
|
||||
language::{parsed::*, ty, ModName},
|
||||
semantic_analysis::*,
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@ impl ty::TyModule {
|
|||
submodules,
|
||||
tree,
|
||||
attributes,
|
||||
span,
|
||||
} = parsed;
|
||||
|
||||
// Type-check submodules first in order of declaration.
|
||||
|
@ -38,6 +39,7 @@ impl ty::TyModule {
|
|||
|
||||
submodules_res.flat_map(|submodules| {
|
||||
typed_nodes_res.map(|all_nodes| Self {
|
||||
span: span.clone(),
|
||||
submodules,
|
||||
namespace: ctx.namespace.module().clone(),
|
||||
all_nodes,
|
||||
|
@ -64,20 +66,18 @@ impl ty::TyModule {
|
|||
impl ty::TySubmodule {
|
||||
pub fn type_check(
|
||||
parent_ctx: TypeCheckContext,
|
||||
dep_name: DepName,
|
||||
mod_name: ModName,
|
||||
submodule: &ParseSubmodule,
|
||||
) -> CompileResult<Self> {
|
||||
let ParseSubmodule {
|
||||
library_name,
|
||||
module,
|
||||
dependency_path_span,
|
||||
mod_name_span,
|
||||
} = submodule;
|
||||
parent_ctx.enter_submodule(dep_name, |submod_ctx| {
|
||||
parent_ctx.enter_submodule(mod_name, module.span.clone(), |submod_ctx| {
|
||||
let module_res = ty::TyModule::type_check(submod_ctx, module);
|
||||
module_res.map(|module| ty::TySubmodule {
|
||||
library_name: library_name.clone(),
|
||||
module,
|
||||
dependency_path_span: dependency_path_span.clone(),
|
||||
mod_name_span: mod_name_span.clone(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use sway_types::{span::Span, ConfigTimeConstant, Spanned};
|
|||
/// A single `Module` within a Sway project.
|
||||
///
|
||||
/// A `Module` is most commonly associated with an individual file of Sway code, e.g. a top-level
|
||||
/// script/predicate/contract file or some library dependency whether introduced via `dep` or the
|
||||
/// script/predicate/contract file or some library dependency whether introduced via `mod` or the
|
||||
/// `[dependencies]` table of a `forc` manifest.
|
||||
///
|
||||
/// A `Module` contains a set of all items that exist within the lexical scope via declaration or
|
||||
|
@ -34,16 +34,18 @@ pub struct Module {
|
|||
/// Submodules of the current module represented as an ordered map from each submodule's name
|
||||
/// to the associated `Module`.
|
||||
///
|
||||
/// Submodules are normally introduced in Sway code with the `dep foo;` syntax where `foo` is
|
||||
/// Submodules are normally introduced in Sway code with the `mod foo;` syntax where `foo` is
|
||||
/// some library dependency that we include as a submodule.
|
||||
///
|
||||
/// Note that we *require* this map to be ordered to produce deterministic codegen results.
|
||||
pub(crate) submodules: im::OrdMap<ModuleName, Module>,
|
||||
/// The set of symbols, implementations, synonyms and aliases present within this module.
|
||||
items: Items,
|
||||
/// Name of the module, package name for root module, library name for other modules.
|
||||
/// Library name used is the same as declared in `library name;`.
|
||||
/// Name of the module, package name for root module, module name for other modules.
|
||||
/// Module name used is the same as declared in `mod name;`.
|
||||
pub name: Option<Ident>,
|
||||
/// Empty span at the beginning of the file implementing the module
|
||||
pub span: Option<Span>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
|
|
|
@ -323,17 +323,22 @@ impl Namespace {
|
|||
/// [SubmoduleNamespace] type. When dropped, the [SubmoduleNamespace] resets the `mod_path`
|
||||
/// back to the original path so that we can continue type-checking the current module after
|
||||
/// finishing with the dependency.
|
||||
pub(crate) fn enter_submodule(&mut self, dep_name: Ident) -> SubmoduleNamespace {
|
||||
pub(crate) fn enter_submodule(
|
||||
&mut self,
|
||||
mod_name: Ident,
|
||||
module_span: Span,
|
||||
) -> SubmoduleNamespace {
|
||||
let init = self.init.clone();
|
||||
self.submodules.entry(dep_name.to_string()).or_insert(init);
|
||||
self.submodules.entry(mod_name.to_string()).or_insert(init);
|
||||
let submod_path: Vec<_> = self
|
||||
.mod_path
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(Some(dep_name.clone()))
|
||||
.chain(Some(mod_name.clone()))
|
||||
.collect();
|
||||
let parent_mod_path = std::mem::replace(&mut self.mod_path, submod_path);
|
||||
self.name = Some(dep_name);
|
||||
self.name = Some(mod_name);
|
||||
self.span = Some(module_span);
|
||||
SubmoduleNamespace {
|
||||
namespace: self,
|
||||
parent_mod_path,
|
||||
|
|
|
@ -370,7 +370,7 @@ impl TraitMap {
|
|||
///
|
||||
/// `data.sw`:
|
||||
/// ```ignore
|
||||
/// library data;
|
||||
/// library;
|
||||
///
|
||||
/// enum MyResult<T, E> {
|
||||
/// Ok: T,
|
||||
|
@ -403,7 +403,7 @@ impl TraitMap {
|
|||
/// ```ignore
|
||||
/// script;
|
||||
///
|
||||
/// dep data;
|
||||
/// mod data;
|
||||
///
|
||||
/// use data::Data;
|
||||
///
|
||||
|
@ -490,7 +490,7 @@ impl TraitMap {
|
|||
///
|
||||
/// `my_double.sw`:
|
||||
/// ```ignore
|
||||
/// library my_double;
|
||||
/// library;
|
||||
///
|
||||
/// pub trait MyDouble<T> {
|
||||
/// fn my_double(self, input: T) -> T;
|
||||
|
@ -499,7 +499,7 @@ impl TraitMap {
|
|||
///
|
||||
/// `my_point.sw`:
|
||||
/// ```ignore
|
||||
/// library my_point;
|
||||
/// library;
|
||||
///
|
||||
/// use ::my_double::MyDouble;
|
||||
///
|
||||
|
@ -519,8 +519,8 @@ impl TraitMap {
|
|||
/// ```ignore
|
||||
/// script;
|
||||
///
|
||||
/// dep my_double;
|
||||
/// dep my_point;
|
||||
/// mod my_double;
|
||||
/// mod my_point;
|
||||
///
|
||||
/// use my_point::MyPoint;
|
||||
///
|
||||
|
|
|
@ -769,7 +769,7 @@ fn decl_name(type_engine: &TypeEngine, decl: &Declaration) -> Option<DependentSy
|
|||
|
||||
// These have the added complexity of converting CallPath and/or TypeInfo into a name.
|
||||
Declaration::ImplSelf(decl) => {
|
||||
let trait_name = Ident::new_with_override("self", decl.implementing_for.span());
|
||||
let trait_name = Ident::new_with_override("self".into(), decl.implementing_for.span());
|
||||
impl_sym(
|
||||
trait_name,
|
||||
&type_engine.get(decl.implementing_for.type_id),
|
||||
|
|
|
@ -19,15 +19,15 @@ impl ty::TyProgram {
|
|||
engines: Engines<'_>,
|
||||
parsed: &ParseProgram,
|
||||
initial_namespace: namespace::Module,
|
||||
package_name: &str,
|
||||
) -> CompileResult<Self> {
|
||||
let mut namespace = Namespace::init_root(initial_namespace);
|
||||
let ctx =
|
||||
TypeCheckContext::from_root(&mut namespace, engines).with_kind(parsed.kind.clone());
|
||||
let ParseProgram { root, kind } = parsed;
|
||||
let mod_span = root.tree.span.clone();
|
||||
let mod_res = ty::TyModule::type_check(ctx, root);
|
||||
mod_res.flat_map(|root| {
|
||||
let res = Self::validate_root(engines, &root, kind.clone(), mod_span);
|
||||
let res = Self::validate_root(engines, &root, kind.clone(), package_name);
|
||||
res.map(|(kind, declarations, configurables)| Self {
|
||||
kind,
|
||||
root,
|
||||
|
|
|
@ -139,14 +139,15 @@ impl<'a> TypeCheckContext<'a> {
|
|||
/// Returns the result of the given `with_submod_ctx` function.
|
||||
pub fn enter_submodule<T>(
|
||||
self,
|
||||
dep_name: Ident,
|
||||
mod_name: Ident,
|
||||
module_span: Span,
|
||||
with_submod_ctx: impl FnOnce(TypeCheckContext) -> T,
|
||||
) -> T {
|
||||
// We're checking a submodule, so no need to pass through anything other than the
|
||||
// namespace. However, we will likely want to pass through the type engine and declaration
|
||||
// engine here once they're added.
|
||||
let Self { namespace, .. } = self;
|
||||
let mut submod_ns = namespace.enter_submodule(dep_name);
|
||||
let mut submod_ns = namespace.enter_submodule(mod_name, module_span);
|
||||
let submod_ctx = TypeCheckContext::from_module_namespace(
|
||||
&mut submod_ns,
|
||||
Engines::new(self.type_engine, self.decl_engine),
|
||||
|
|
|
@ -10,13 +10,13 @@ use sway_ast::{
|
|||
expr::{ReassignmentOp, ReassignmentOpVariant},
|
||||
ty::TyTupleDescriptor,
|
||||
AbiCastArgs, AngleBrackets, AsmBlock, Assignable, AttributeDecl, Braces, CodeBlockContents,
|
||||
CommaToken, Dependency, DoubleColonToken, Expr, ExprArrayDescriptor, ExprStructField,
|
||||
ExprTupleDescriptor, FnArg, FnArgs, FnSignature, GenericArgs, GenericParams, IfCondition,
|
||||
IfExpr, Instruction, Intrinsic, Item, ItemAbi, ItemConfigurable, ItemConst, ItemEnum, ItemFn,
|
||||
ItemImpl, ItemKind, ItemStorage, ItemStruct, ItemTrait, ItemTraitItem, ItemUse, LitInt,
|
||||
LitIntType, MatchBranchKind, Module, ModuleKind, Parens, PathExpr, PathExprSegment, PathType,
|
||||
CommaToken, DoubleColonToken, Expr, ExprArrayDescriptor, ExprStructField, ExprTupleDescriptor,
|
||||
FnArg, FnArgs, FnSignature, GenericArgs, GenericParams, IfCondition, IfExpr, Instruction,
|
||||
Intrinsic, Item, ItemAbi, ItemConfigurable, ItemConst, ItemEnum, ItemFn, ItemImpl, ItemKind,
|
||||
ItemStorage, ItemStruct, ItemTrait, ItemTraitItem, ItemUse, LitInt, LitIntType,
|
||||
MatchBranchKind, Module, ModuleKind, Parens, PathExpr, PathExprSegment, PathType,
|
||||
PathTypeSegment, Pattern, PatternStructField, PubToken, Punctuated, QualifiedPathRoot,
|
||||
Statement, StatementLet, Traits, Ty, TypeField, UseTree, WhereClause,
|
||||
Statement, StatementLet, Submodule, Traits, Ty, TypeField, UseTree, WhereClause,
|
||||
};
|
||||
use sway_error::convert_parse_tree_error::ConvertParseTreeError;
|
||||
use sway_error::handler::{ErrorEmitted, Handler};
|
||||
|
@ -58,7 +58,7 @@ pub fn convert_module_kind(kind: &ModuleKind) -> TreeType {
|
|||
ModuleKind::Script { .. } => TreeType::Script,
|
||||
ModuleKind::Contract { .. } => TreeType::Contract,
|
||||
ModuleKind::Predicate { .. } => TreeType::Predicate,
|
||||
ModuleKind::Library { name, .. } => TreeType::Library { name: name.clone() },
|
||||
ModuleKind::Library { .. } => TreeType::Library,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ fn item_to_ast_nodes(
|
|||
|
||||
let span = item.span();
|
||||
let contents = match item.value {
|
||||
ItemKind::Dependency(dependency) => {
|
||||
ItemKind::Submodule(submodule) => {
|
||||
// Check that Dependency is not annotated
|
||||
if attributes.contains_key(&AttributeKind::DocComment) {
|
||||
let error = ConvertParseTreeError::CannotDocCommentDependency {
|
||||
|
@ -133,13 +133,13 @@ fn item_to_ast_nodes(
|
|||
// Check that Dependency comes after only other Dependencies
|
||||
let emit_expected_dep_at_beginning = || {
|
||||
let error = ConvertParseTreeError::ExpectedDependencyAtBeginning {
|
||||
span: dependency.span(),
|
||||
span: submodule.span(),
|
||||
};
|
||||
handler.emit_err(error.into());
|
||||
};
|
||||
match prev_item {
|
||||
Some(Annotated {
|
||||
value: ItemKind::Dependency(_),
|
||||
value: ItemKind::Submodule(_),
|
||||
..
|
||||
}) => (),
|
||||
Some(_) => emit_expected_dep_at_beginning(),
|
||||
|
@ -148,7 +148,7 @@ fn item_to_ast_nodes(
|
|||
if !is_root {
|
||||
emit_expected_dep_at_beginning();
|
||||
}
|
||||
let incl_stmt = dependency_to_include_statement(&dependency);
|
||||
let incl_stmt = submodule_to_include_statement(&submodule);
|
||||
vec![AstNodeContent::IncludeStatement(incl_stmt)]
|
||||
}
|
||||
ItemKind::Use(item_use) => item_use_to_use_statements(context, handler, item_use)?
|
||||
|
@ -1703,10 +1703,8 @@ fn expr_to_expression(
|
|||
MATCH_RETURN_VAR_NAME_PREFIX,
|
||||
context.next_match_expression_return_var_unique_suffix(),
|
||||
);
|
||||
let var_decl_name = Ident::new_with_override(
|
||||
Box::leak(match_return_var_name.into_boxed_str()),
|
||||
var_decl_span.clone(),
|
||||
);
|
||||
let var_decl_name =
|
||||
Ident::new_with_override(match_return_var_name, var_decl_span.clone());
|
||||
|
||||
let var_decl_exp = Expression {
|
||||
kind: ExpressionKind::Variable(var_decl_name.clone()),
|
||||
|
@ -2109,10 +2107,10 @@ fn op_call(
|
|||
inner: MethodName::FromTrait {
|
||||
call_path: CallPath {
|
||||
prefixes: vec![
|
||||
Ident::new_with_override("core", op_span.clone()),
|
||||
Ident::new_with_override("ops", op_span.clone()),
|
||||
Ident::new_with_override("core".into(), op_span.clone()),
|
||||
Ident::new_with_override("ops".into(), op_span.clone()),
|
||||
],
|
||||
suffix: Ident::new_with_override(name, op_span.clone()),
|
||||
suffix: Ident::new_with_override(name.into(), op_span.clone()),
|
||||
is_absolute: true,
|
||||
},
|
||||
},
|
||||
|
@ -2936,7 +2934,7 @@ fn statement_let_to_ast_nodes(
|
|||
mutable,
|
||||
name,
|
||||
} => (reference, mutable, name),
|
||||
Pattern::Wildcard { .. } => (None, None, Ident::new_no_span("_")),
|
||||
Pattern::Wildcard { .. } => (None, None, Ident::new_no_span("_".into())),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if reference.is_some() {
|
||||
|
@ -2989,10 +2987,8 @@ fn statement_let_to_ast_nodes(
|
|||
DESTRUCTURE_PREFIX,
|
||||
context.next_destructured_struct_unique_suffix()
|
||||
);
|
||||
let destructure_name = Ident::new_with_override(
|
||||
Box::leak(destructured_name.into_boxed_str()),
|
||||
path.prefix.name.span(),
|
||||
);
|
||||
let destructure_name =
|
||||
Ident::new_with_override(destructured_name, path.prefix.name.span());
|
||||
|
||||
// Parse the type ascription and the type ascription span.
|
||||
// In the event that the user did not provide a type ascription,
|
||||
|
@ -3082,8 +3078,7 @@ fn statement_let_to_ast_nodes(
|
|||
TUPLE_NAME_PREFIX,
|
||||
context.next_destructured_tuple_unique_suffix()
|
||||
);
|
||||
let tuple_name =
|
||||
Ident::new_with_override(Box::leak(tuple_name.into_boxed_str()), span.clone());
|
||||
let tuple_name = Ident::new_with_override(tuple_name, span.clone());
|
||||
|
||||
// Parse the type ascription and the type ascription span.
|
||||
// In the event that the user did not provide a type ascription,
|
||||
|
@ -3174,11 +3169,10 @@ fn statement_let_to_ast_nodes(
|
|||
)
|
||||
}
|
||||
|
||||
fn dependency_to_include_statement(dependency: &Dependency) -> IncludeStatement {
|
||||
fn submodule_to_include_statement(dependency: &Submodule) -> IncludeStatement {
|
||||
IncludeStatement {
|
||||
_alias: None,
|
||||
span: dependency.span(),
|
||||
_path_span: dependency.path.span(),
|
||||
_span: dependency.span(),
|
||||
_mod_name_span: dependency.name.span(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,9 +47,9 @@ fn generic_enum_resolution() {
|
|||
let decl_engine = DeclEngine::default();
|
||||
|
||||
let sp = Span::dummy();
|
||||
let generic_name = Ident::new_with_override("T", sp.clone());
|
||||
let a_name = Ident::new_with_override("a", sp.clone());
|
||||
let result_name = Ident::new_with_override("Result", sp.clone());
|
||||
let generic_name = Ident::new_with_override("T".into(), sp.clone());
|
||||
let a_name = Ident::new_with_override("a".into(), sp.clone());
|
||||
let result_name = Ident::new_with_override("Result".into(), sp.clone());
|
||||
|
||||
/*
|
||||
Result<_> {
|
||||
|
|
|
@ -328,7 +328,7 @@ impl<'a> Unifier<'a> {
|
|||
NumericCastCompatResult::CastableWithWarning(warn) => {
|
||||
vec![CompileWarning {
|
||||
span: span.clone(),
|
||||
warning_content: warn,
|
||||
warning_content: *warn,
|
||||
}]
|
||||
}
|
||||
NumericCastCompatResult::Compatible => {
|
||||
|
@ -502,10 +502,10 @@ fn numeric_cast_compat(
|
|||
| (Sixteen, ThirtyTwo)
|
||||
| (Sixteen, SixtyFour)
|
||||
| (ThirtyTwo, SixtyFour) => {
|
||||
NumericCastCompatResult::CastableWithWarning(Warning::LossOfPrecision {
|
||||
NumericCastCompatResult::CastableWithWarning(Box::new(Warning::LossOfPrecision {
|
||||
initial_type: old_size,
|
||||
cast_to: new_size,
|
||||
})
|
||||
}))
|
||||
}
|
||||
// Upcasting is ok, so everything else is ok.
|
||||
_ => NumericCastCompatResult::Compatible,
|
||||
|
@ -514,5 +514,5 @@ fn numeric_cast_compat(
|
|||
|
||||
enum NumericCastCompatResult {
|
||||
Compatible,
|
||||
CastableWithWarning(Warning),
|
||||
CastableWithWarning(Box<Warning>),
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ pub enum CompileError {
|
|||
file_path: String,
|
||||
stringified_error: String,
|
||||
},
|
||||
#[error("This imported file must be a library. It must start with \"library <name>\", where \"name\" is the name of the library this file contains.")]
|
||||
#[error("This imported file must be a library. It must start with \"library;\"")]
|
||||
ImportMustBeLibrary { span: Span },
|
||||
#[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
|
||||
MoreThanOneEnumInstantiator { span: Span, ty: String },
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
library core;
|
||||
library;
|
||||
|
||||
dep primitives;
|
||||
dep raw_ptr;
|
||||
dep raw_slice;
|
||||
dep ops;
|
||||
dep never;
|
||||
dep prelude;
|
||||
mod primitives;
|
||||
mod raw_ptr;
|
||||
mod raw_slice;
|
||||
mod ops;
|
||||
mod never;
|
||||
mod prelude;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library never;
|
||||
library;
|
||||
|
||||
use ::ops::{Eq, Not, Ord};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library ops;
|
||||
library;
|
||||
|
||||
use ::primitives::*;
|
||||
|
||||
|
@ -121,7 +121,7 @@ pub trait Mod {
|
|||
impl Mod for u64 {
|
||||
fn modulo(self, other: Self) -> Self {
|
||||
asm(r1: self, r2: other, r3) {
|
||||
mod r3 r1 r2;
|
||||
r#mod r3 r1 r2;
|
||||
r3: u64
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ impl Mod for u64 {
|
|||
impl Mod for u32 {
|
||||
fn modulo(self, other: Self) -> Self {
|
||||
asm(r1: self, r2: other, r3) {
|
||||
mod r3 r1 r2;
|
||||
r#mod r3 r1 r2;
|
||||
r3: u32
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ impl Mod for u32 {
|
|||
impl Mod for u16 {
|
||||
fn modulo(self, other: Self) -> Self {
|
||||
asm(r1: self, r2: other, r3) {
|
||||
mod r3 r1 r2;
|
||||
r#mod r3 r1 r2;
|
||||
r3: u16
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ impl Mod for u16 {
|
|||
impl Mod for u8 {
|
||||
fn modulo(self, other: Self) -> Self {
|
||||
asm(r1: self, r2: other, r3) {
|
||||
mod r3 r1 r2;
|
||||
r#mod r3 r1 r2;
|
||||
r3: u8
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library prelude;
|
||||
library;
|
||||
|
||||
//! Defines the Sway core library prelude.
|
||||
//! The prelude consists of implicitly available items,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue