mirror of
https://github.com/FuelLabs/sway.git
synced 2025-08-12 14:48:35 +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.
|
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
|
```sway
|
||||||
library games;
|
library;
|
||||||
|
|
||||||
pub enum Suit {
|
pub enum Suit {
|
||||||
Hearts: (),
|
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.
|
Libraries are defined using the `library` keyword at the beginning of a file, followed by a name so that they can be imported.
|
||||||
|
|
||||||
```sway
|
```sway
|
||||||
library my_library;
|
library;
|
||||||
|
|
||||||
// library code
|
// 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:
|
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
|
```sway
|
||||||
library option;
|
library;
|
||||||
```
|
```
|
||||||
|
|
||||||
- A `use` statement that imports `revert` from another library _inside_ the standard 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.
|
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
|
```sway
|
||||||
library std;
|
library;
|
||||||
|
|
||||||
dep block;
|
mod block;
|
||||||
dep storage;
|
mod storage;
|
||||||
dep constants;
|
mod constants;
|
||||||
|
mod vm;
|
||||||
// .. Other deps
|
// .. 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
|
```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
|
## 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
|
||||||
|
|
||||||
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
|
```bash
|
||||||
$ tree
|
$ tree
|
||||||
|
@ -99,16 +113,18 @@ $ tree
|
||||||
├── Forc.toml
|
├── Forc.toml
|
||||||
└── src
|
└── src
|
||||||
├── internal_lib.sw
|
├── 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:
|
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)
|
- Use the `use` keyword with a `::` separating the name of the library and the imported item(s)
|
||||||
|
|
||||||
```sway
|
```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;
|
use internal_lib::mint;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library fizzbuzz;
|
library;
|
||||||
|
|
||||||
// ANCHOR: state
|
// ANCHOR: state
|
||||||
enum State {
|
enum State {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library arrays;
|
library;
|
||||||
|
|
||||||
// ANCHOR: syntax
|
// ANCHOR: syntax
|
||||||
fn syntax() {
|
fn syntax() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library booleans;
|
library;
|
||||||
|
|
||||||
// ANCHOR: syntax
|
// ANCHOR: syntax
|
||||||
fn returns_true() -> bool {
|
fn returns_true() -> bool {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library bytes;
|
library;
|
||||||
|
|
||||||
fn syntax() {
|
fn syntax() {
|
||||||
// ANCHOR: syntax
|
// ANCHOR: syntax
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library basic_enum;
|
library;
|
||||||
|
|
||||||
// ANCHOR: definition
|
// ANCHOR: definition
|
||||||
enum Color {
|
enum Color {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enum_of_enums;
|
library;
|
||||||
|
|
||||||
// ANCHOR: content
|
// ANCHOR: content
|
||||||
enum UserError {
|
enum UserError {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enum_of_structs;
|
library;
|
||||||
|
|
||||||
// ANCHOR: content
|
// ANCHOR: content
|
||||||
struct Item {
|
struct Item {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enums;
|
library;
|
||||||
|
|
||||||
dep basic_enum;
|
mod basic_enum;
|
||||||
dep enum_of_structs;
|
mod enum_of_structs;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library numerics;
|
library;
|
||||||
|
|
||||||
fn syntax() {
|
fn syntax() {
|
||||||
// ANCHOR: syntax
|
// ANCHOR: syntax
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library strings;
|
library;
|
||||||
|
|
||||||
fn explicit() {
|
fn explicit() {
|
||||||
// ANCHOR: explicit
|
// ANCHOR: explicit
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library structs;
|
library;
|
||||||
|
|
||||||
// ANCHOR: definition
|
// ANCHOR: definition
|
||||||
struct Foo {
|
struct Foo {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library tuples;
|
library;
|
||||||
|
|
||||||
fn syntax() {
|
fn syntax() {
|
||||||
// ANCHOR: declare
|
// ANCHOR: declare
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library comments;
|
library;
|
||||||
|
|
||||||
fn comment() {
|
fn comment() {
|
||||||
// ANCHOR: comment
|
// ANCHOR: comment
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library control_flow;
|
library;
|
||||||
|
|
||||||
fn conditional() {
|
fn conditional() {
|
||||||
// ANCHOR: conditional
|
// ANCHOR: conditional
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library explicit;
|
library;
|
||||||
|
|
||||||
// ANCHOR: main
|
// ANCHOR: main
|
||||||
fn main() -> bool {
|
fn main() -> bool {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library implicit;
|
library;
|
||||||
|
|
||||||
// ANCHOR: main
|
// ANCHOR: main
|
||||||
fn main() -> bool {
|
fn main() -> bool {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
library functions;
|
library;
|
||||||
|
|
||||||
dep explicit;
|
mod explicit;
|
||||||
dep implicit;
|
mod implicit;
|
||||||
|
|
||||||
// ANCHOR: definition
|
// ANCHOR: definition
|
||||||
fn my_function(my_parameter: u64 /* ... */) -> u64 {
|
fn my_function(my_parameter: u64 /* ... */) -> u64 {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library interface;
|
library;
|
||||||
|
|
||||||
abi Wallet {
|
abi Wallet {
|
||||||
/// When the BASE_ASSET is sent to this function the internal contract balance is incremented
|
/// 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;
|
use my_other_library::quix;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
library my_other_library;
|
library;
|
||||||
|
|
||||||
pub fn quix() {}
|
pub fn quix() {}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
library lib;
|
library;
|
||||||
|
|
||||||
dep my_library;
|
mod my_library;
|
||||||
|
|
||||||
use my_library::bar;
|
use my_library::bar;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// ANCHOR: library
|
// ANCHOR: library
|
||||||
// ANCHOR: module
|
// ANCHOR: module
|
||||||
library my_library;
|
library;
|
||||||
// ANCHOR_END: module
|
// ANCHOR_END: module
|
||||||
|
|
||||||
// Cannot import because the `pub` keyword is missing
|
// Cannot import because the `pub` keyword is missing
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library annotations;
|
library;
|
||||||
|
|
||||||
// ANCHOR: type_annotation
|
// ANCHOR: type_annotation
|
||||||
fn execute() {
|
fn execute() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enums;
|
library;
|
||||||
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
StateError: StateError,
|
StateError: StateError,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library getters;
|
library;
|
||||||
|
|
||||||
// ANCHOR: avoid
|
// ANCHOR: avoid
|
||||||
fn get_maximum_deposit() -> u64 {
|
fn get_maximum_deposit() -> u64 {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// ANCHOR: module
|
// ANCHOR: module
|
||||||
library letter_casing;
|
library;
|
||||||
// ANCHOR_END: module
|
// ANCHOR_END: module
|
||||||
// ANCHOR: const
|
// ANCHOR: const
|
||||||
const MAXIMUM_DEPOSIT = 10;
|
const MAXIMUM_DEPOSIT = 10;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library struct_shorthand;
|
library;
|
||||||
|
|
||||||
// ANCHOR: struct_shorthand_definition
|
// ANCHOR: struct_shorthand_definition
|
||||||
struct Structure {
|
struct Structure {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library variables;
|
library;
|
||||||
|
|
||||||
fn mutable() {
|
fn mutable() {
|
||||||
// ANCHOR: mutable
|
// ANCHOR: mutable
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enums;
|
library;
|
||||||
|
|
||||||
// ANCHOR: u64_example
|
// ANCHOR: u64_example
|
||||||
pub enum T {
|
pub enum T {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library arrays;
|
library;
|
||||||
|
|
||||||
// ANCHOR: syntax
|
// ANCHOR: syntax
|
||||||
fn syntax() {
|
fn syntax() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library strings;
|
library;
|
||||||
|
|
||||||
fn single_quotes() {
|
fn single_quotes() {
|
||||||
// ANCHOR: single_quotes
|
// ANCHOR: single_quotes
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
library assertions;
|
library;
|
||||||
|
|
||||||
dep req;
|
mod req;
|
||||||
|
|
||||||
// ANCHOR: assert
|
// ANCHOR: assert
|
||||||
fn subtract(a: u64, b: u64) -> u64 {
|
fn subtract(a: u64, b: u64) -> u64 {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library req;
|
library;
|
||||||
|
|
||||||
// ANCHOR: require
|
// ANCHOR: require
|
||||||
fn subtract(a: u64, b: u64) -> u64 {
|
fn subtract(a: u64, b: u64) -> u64 {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library asset_operations;
|
library;
|
||||||
|
|
||||||
// ANCHOR: mint_import
|
// ANCHOR: mint_import
|
||||||
use std::token::mint;
|
use std::token::mint;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library call_data;
|
library;
|
||||||
|
|
||||||
// ANCHOR: import_sender
|
// ANCHOR: import_sender
|
||||||
use std::auth::msg_sender;
|
use std::auth::msg_sender;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library interface;
|
library;
|
||||||
|
|
||||||
abi Vault {
|
abi Vault {
|
||||||
fn deposit();
|
fn deposit();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library hashing;
|
library;
|
||||||
|
|
||||||
// ANCHOR: import_sha256
|
// ANCHOR: import_sha256
|
||||||
use std::hash::sha256;
|
use std::hash::sha256;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library logging;
|
library;
|
||||||
|
|
||||||
// ANCHOR: logging
|
// ANCHOR: logging
|
||||||
fn log_data(number: u64) {
|
fn log_data(number: u64) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library namespace;
|
library;
|
||||||
|
|
||||||
// ANCHOR: address
|
// ANCHOR: address
|
||||||
pub struct Address {
|
pub struct Address {
|
||||||
|
|
|
@ -4,7 +4,7 @@ A library is used to contain code that performs common operations in order to pr
|
||||||
|
|
||||||
## Definition
|
## 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
|
```sway
|
||||||
{{#include ../../../../code/language/program-types/libraries/internal/my_library/src/my_library.sw:module}}
|
{{#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:
|
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
|
2. Use the `use` keyword to selectively import various items from the library
|
||||||
|
|
||||||
```sway
|
```sway
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
contract;
|
contract;
|
||||||
|
|
||||||
dep other_contract;
|
mod other_contract;
|
||||||
|
|
||||||
use other_contract::*;
|
use other_contract::*;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library other_contract;
|
library;
|
||||||
|
|
||||||
abi OtherContract {
|
abi OtherContract {
|
||||||
#[payable]
|
#[payable]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library basic_enum;
|
library;
|
||||||
|
|
||||||
// Declare the enum
|
// Declare the enum
|
||||||
enum Color {
|
enum Color {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enum_of_enums;
|
library;
|
||||||
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
StateError: StateError,
|
StateError: StateError,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library enum_of_structs;
|
library;
|
||||||
|
|
||||||
struct Item {
|
struct Item {
|
||||||
price: u64,
|
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() {
|
fn avoid() {
|
||||||
let error1 = Error::StateError(StateError::Void);
|
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() {
|
fn preferred() {
|
||||||
let error1 = StateError::Void;
|
let error1 = StateError::Void;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
library enums;
|
library;
|
||||||
|
|
||||||
dep basic_enum;
|
mod basic_enum;
|
||||||
dep enums_avoid;
|
mod enum_of_structs;
|
||||||
dep enums_preferred;
|
mod enum_of_enums;
|
||||||
dep enum_of_structs;
|
mod enums_avoid;
|
||||||
|
mod enums_preferred;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library r#abi;
|
library;
|
||||||
|
|
||||||
abi IdentityExample {
|
abi IdentityExample {
|
||||||
#[storage(read)]
|
#[storage(read)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library errors;
|
library;
|
||||||
|
|
||||||
pub enum MyError {
|
pub enum MyError {
|
||||||
UnauthorizedUser: Identity,
|
UnauthorizedUser: Identity,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
contract;
|
contract;
|
||||||
|
|
||||||
dep r#abi;
|
mod r#abi;
|
||||||
dep errors;
|
mod errors;
|
||||||
|
|
||||||
use abi::IdentityExample;
|
use abi::IdentityExample;
|
||||||
use errors::MyError;
|
use errors::MyError;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library data_structures;
|
library;
|
||||||
|
|
||||||
// Declare a struct type
|
// Declare a struct type
|
||||||
pub struct Foo {
|
pub struct Foo {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
library utils;
|
library;
|
||||||
|
|
||||||
dep data_structures;
|
mod data_structures;
|
||||||
use data_structures::{Foo, Line, Point, TupleInStruct};
|
use data_structures::{Foo, Line, Point, TupleInStruct};
|
||||||
|
|
||||||
fn hardcoded_instantiation() -> Foo {
|
fn hardcoded_instantiation() -> Foo {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library tuples;
|
library;
|
||||||
|
|
||||||
fn tuple() {
|
fn tuple() {
|
||||||
// You can declare the types youself
|
// You can declare the types youself
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// ANCHOR: abi_library
|
// ANCHOR: abi_library
|
||||||
library wallet_abi;
|
library;
|
||||||
|
|
||||||
// ANCHOR: abi
|
// ANCHOR: abi
|
||||||
abi Wallet {
|
abi Wallet {
|
||||||
|
|
|
@ -658,7 +658,7 @@ impl BuildPlan {
|
||||||
info!(" Creating a new `Forc.lock` file. (Cause: {})", cause);
|
info!(" Creating a new `Forc.lock` file. (Cause: {})", cause);
|
||||||
let member_names = manifests
|
let member_names = manifests
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, manifest)| manifest.project.name.clone())
|
.map(|(_, manifest)| manifest.project.name.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
crate::lock::print_diff(&member_names, &lock_diff);
|
crate::lock::print_diff(&member_names, &lock_diff);
|
||||||
let string = toml::ser::to_string_pretty(&new_lock)
|
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>> {
|
fn validate_graph(graph: &Graph, manifests: &MemberManifestFiles) -> Result<BTreeSet<EdgeIx>> {
|
||||||
let mut member_pkgs: HashMap<&String, &PackageManifestFile> = manifests.iter().collect();
|
let mut member_pkgs: HashMap<&String, &PackageManifestFile> = manifests.iter().collect();
|
||||||
let member_nodes: Vec<_> = member_nodes(graph)
|
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();
|
.collect();
|
||||||
|
|
||||||
// If no member nodes, the graph is either empty or corrupted. Remove all edges.
|
// 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.
|
// Otherwise, check if it comes from a patch.
|
||||||
for (_, patch_map) in node_manifest.patches() {
|
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 Some(ref rel_path) = details.path {
|
||||||
if let Ok(path) = node_manifest.dir().join(rel_path).canonicalize() {
|
if let Ok(path) = node_manifest.dir().join(rel_path).canonicalize() {
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
|
@ -997,7 +1001,7 @@ fn remove_deps(
|
||||||
) {
|
) {
|
||||||
// Retrieve the project nodes for workspace members.
|
// Retrieve the project nodes for workspace members.
|
||||||
let member_nodes: HashSet<_> = member_nodes(graph)
|
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();
|
.collect();
|
||||||
|
|
||||||
// Before removing edges, sort the nodes in order of dependency for the node removal pass.
|
// Before removing edges, sort the nodes in order of dependency for the node removal pass.
|
||||||
|
@ -1344,14 +1348,17 @@ fn fetch_deps(
|
||||||
)
|
)
|
||||||
.collect();
|
.collect();
|
||||||
for (dep_name, dep, dep_kind) in deps {
|
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 parent_manifest = &manifest_map[&parent_id];
|
||||||
let source =
|
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")?;
|
.context("Failed to source dependency")?;
|
||||||
|
|
||||||
// If we haven't yet fetched this dependency, fetch it, pin it and add it to the graph.
|
// 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) {
|
let dep_node = match fetched.entry(dep_pkg) {
|
||||||
hash_map::Entry::Occupied(entry) => *entry.get(),
|
hash_map::Entry::Occupied(entry) => *entry.get(),
|
||||||
hash_map::Entry::Vacant(entry) => {
|
hash_map::Entry::Vacant(entry) => {
|
||||||
|
@ -1503,9 +1510,7 @@ pub fn dependency_namespace(
|
||||||
let mut namespace = namespace::Module::default_with_constants(engines, constants)?;
|
let mut namespace = namespace::Module::default_with_constants(engines, constants)?;
|
||||||
|
|
||||||
let node_idx = &graph[node];
|
let node_idx = &graph[node];
|
||||||
namespace.name = Some(Ident::new_no_span(Box::leak(
|
namespace.name = Some(Ident::new_no_span(node_idx.name.clone()));
|
||||||
node_idx.name.clone().into_boxed_str(),
|
|
||||||
)));
|
|
||||||
|
|
||||||
// Add direct dependencies.
|
// Add direct dependencies.
|
||||||
let mut core_added = false;
|
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) {
|
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)
|
Ok(namespace)
|
||||||
|
@ -1621,6 +1634,7 @@ pub fn compile_ast(
|
||||||
build_target: BuildTarget,
|
build_target: BuildTarget,
|
||||||
build_profile: &BuildProfile,
|
build_profile: &BuildProfile,
|
||||||
namespace: namespace::Module,
|
namespace: namespace::Module,
|
||||||
|
package_name: &str,
|
||||||
) -> Result<CompileResult<ty::TyProgram>> {
|
) -> Result<CompileResult<ty::TyProgram>> {
|
||||||
let source = manifest.entry_string()?;
|
let source = manifest.entry_string()?;
|
||||||
let sway_build_config = sway_build_config(
|
let sway_build_config = sway_build_config(
|
||||||
|
@ -1629,7 +1643,13 @@ pub fn compile_ast(
|
||||||
build_target,
|
build_target,
|
||||||
build_profile,
|
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)
|
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.
|
// First, compile to an AST. We'll update the namespace and check for JSON ABI output.
|
||||||
let ast_res = time_expr!(
|
let ast_res = time_expr!(
|
||||||
"compile to ast",
|
"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() {
|
let typed_program = match ast_res.value.as_ref() {
|
||||||
None => return fail(&ast_res.warnings, &ast_res.errors),
|
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 {
|
match curr_manifest {
|
||||||
Some(pkg_manifest) => {
|
Some(pkg_manifest) => {
|
||||||
let built_pkg = built_workspace
|
let built_pkg = built_workspace
|
||||||
.remove(&pkg_manifest.project.name)
|
.remove(&pkg_manifest.project.name.to_string())
|
||||||
.expect("package didn't exist in workspace");
|
.expect("package didn't exist in workspace");
|
||||||
Ok(Built::Package(Box::new(built_pkg)))
|
Ok(Built::Package(Box::new(built_pkg)))
|
||||||
}
|
}
|
||||||
|
@ -2270,9 +2290,18 @@ pub fn build(
|
||||||
};
|
};
|
||||||
let (mut built_package, namespace) =
|
let (mut built_package, namespace) =
|
||||||
compile_pkg(node, &mut source_map, compile_pkg_context)?;
|
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);
|
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);
|
lib_namespace_map.insert(node, namespace);
|
||||||
}
|
}
|
||||||
source_map.insert_dependency(manifest.dir());
|
source_map.insert_dependency(manifest.dir());
|
||||||
|
@ -2461,7 +2490,7 @@ pub fn check(
|
||||||
Some(modules) => modules,
|
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);
|
warnings.extend(ast_result.warnings);
|
||||||
errors.extend(ast_result.errors);
|
errors.extend(ast_result.errors);
|
||||||
|
|
||||||
|
@ -2474,9 +2503,18 @@ pub fn check(
|
||||||
Some(typed_program) => typed_program,
|
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();
|
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);
|
lib_namespace_map.insert(node, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ impl Document {
|
||||||
let mut new_submodule_prefix = module_prefix.to_owned();
|
let mut new_submodule_prefix = module_prefix.to_owned();
|
||||||
new_submodule_prefix
|
new_submodule_prefix
|
||||||
.module_prefixes
|
.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 {
|
for ast_node in &typed_submodule.module.all_nodes {
|
||||||
if let TyAstNodeContent::Declaration(ref decl) = ast_node.content {
|
if let TyAstNodeContent::Declaration(ref decl) = ast_node.content {
|
||||||
let desc = Descriptor::from_typed_decl(
|
let desc = Descriptor::from_typed_decl(
|
||||||
|
|
|
@ -139,7 +139,7 @@ pub fn init(command: InitCommand) -> Result<()> {
|
||||||
.join("src")
|
.join("src")
|
||||||
.join(constants::LIB_ENTRY),
|
.join(constants::LIB_ENTRY),
|
||||||
// Library names cannot have `-` in them because the Sway compiler does not allow that
|
// 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(
|
InitType::Package(ProgramType::Predicate) => fs::write(
|
||||||
Path::new(&project_dir)
|
Path::new(&project_dir)
|
||||||
|
|
|
@ -47,13 +47,12 @@ fn main() {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_library(project_name: &str) -> String {
|
pub(crate) fn default_library() -> String {
|
||||||
format!(
|
"library;
|
||||||
"library {project_name};
|
|
||||||
|
|
||||||
// anything `pub` here will be exported as a part of this library's API
|
// anything `pub` here will be exported as a part of this library's API
|
||||||
"
|
"
|
||||||
)
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_predicate() -> String {
|
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)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ItemKind {
|
pub enum ItemKind {
|
||||||
Dependency(Dependency),
|
Submodule(Submodule),
|
||||||
Use(ItemUse),
|
Use(ItemUse),
|
||||||
Struct(ItemStruct),
|
Struct(ItemStruct),
|
||||||
Enum(ItemEnum),
|
Enum(ItemEnum),
|
||||||
|
@ -41,7 +41,7 @@ pub enum ItemKind {
|
||||||
impl Spanned for ItemKind {
|
impl Spanned for ItemKind {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
ItemKind::Dependency(item_dep) => item_dep.span(),
|
ItemKind::Submodule(item_mod) => item_mod.span(),
|
||||||
ItemKind::Use(item_use) => item_use.span(),
|
ItemKind::Use(item_use) => item_use.span(),
|
||||||
ItemKind::Struct(item_struct) => item_struct.span(),
|
ItemKind::Struct(item_struct) => item_struct.span(),
|
||||||
ItemKind::Enum(item_enum) => item_enum.span(),
|
ItemKind::Enum(item_enum) => item_enum.span(),
|
||||||
|
|
|
@ -49,7 +49,7 @@ define_keyword!(ScriptToken, "script");
|
||||||
define_keyword!(ContractToken, "contract");
|
define_keyword!(ContractToken, "contract");
|
||||||
define_keyword!(PredicateToken, "predicate");
|
define_keyword!(PredicateToken, "predicate");
|
||||||
define_keyword!(LibraryToken, "library");
|
define_keyword!(LibraryToken, "library");
|
||||||
define_keyword!(DepToken, "dep");
|
define_keyword!(ModToken, "mod");
|
||||||
define_keyword!(PubToken, "pub");
|
define_keyword!(PubToken, "pub");
|
||||||
define_keyword!(UseToken, "use");
|
define_keyword!(UseToken, "use");
|
||||||
define_keyword!(AsToken, "as");
|
define_keyword!(AsToken, "as");
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
pub mod assignable;
|
pub mod assignable;
|
||||||
pub mod attribute;
|
pub mod attribute;
|
||||||
pub mod brackets;
|
pub mod brackets;
|
||||||
pub mod dependency;
|
|
||||||
pub mod expr;
|
pub mod expr;
|
||||||
pub mod generics;
|
pub mod generics;
|
||||||
pub mod intrinsics;
|
pub mod intrinsics;
|
||||||
|
@ -14,6 +13,7 @@ pub mod pattern;
|
||||||
mod priv_prelude;
|
mod priv_prelude;
|
||||||
pub mod punctuated;
|
pub mod punctuated;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
|
pub mod submodule;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
pub mod ty;
|
pub mod ty;
|
||||||
pub mod where_clause;
|
pub mod where_clause;
|
||||||
|
@ -22,7 +22,6 @@ pub use crate::{
|
||||||
assignable::Assignable,
|
assignable::Assignable,
|
||||||
attribute::AttributeDecl,
|
attribute::AttributeDecl,
|
||||||
brackets::{AngleBrackets, Braces, Parens},
|
brackets::{AngleBrackets, Braces, Parens},
|
||||||
dependency::Dependency,
|
|
||||||
expr::{
|
expr::{
|
||||||
asm::{AsmBlock, AsmRegisterDeclaration},
|
asm::{AsmBlock, AsmRegisterDeclaration},
|
||||||
op_code::Instruction,
|
op_code::Instruction,
|
||||||
|
@ -51,6 +50,7 @@ pub use crate::{
|
||||||
pattern::{Pattern, PatternStructField},
|
pattern::{Pattern, PatternStructField},
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
statement::{Statement, StatementLet},
|
statement::{Statement, StatementLet},
|
||||||
|
submodule::Submodule,
|
||||||
ty::Ty,
|
ty::Ty,
|
||||||
where_clause::{WhereBound, WhereClause},
|
where_clause::{WhereBound, WhereClause},
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,10 +8,10 @@ pub struct Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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| {
|
self.items.iter().filter_map(|i| {
|
||||||
if let ItemKind::Dependency(dep) = &i.value {
|
if let ItemKind::Submodule(submod) = &i.value {
|
||||||
Some(dep)
|
Some(submod)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -33,19 +33,10 @@ impl Spanned for Module {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ModuleKind {
|
pub enum ModuleKind {
|
||||||
Script {
|
Script { script_token: ScriptToken },
|
||||||
script_token: ScriptToken,
|
Contract { contract_token: ContractToken },
|
||||||
},
|
Predicate { predicate_token: PredicateToken },
|
||||||
Contract {
|
Library { library_token: LibraryToken },
|
||||||
contract_token: ContractToken,
|
|
||||||
},
|
|
||||||
Predicate {
|
|
||||||
predicate_token: PredicateToken,
|
|
||||||
},
|
|
||||||
Library {
|
|
||||||
library_token: LibraryToken,
|
|
||||||
name: Ident,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spanned for ModuleKind {
|
impl Spanned for ModuleKind {
|
||||||
|
@ -54,10 +45,7 @@ impl Spanned for ModuleKind {
|
||||||
Self::Script { script_token } => script_token.span(),
|
Self::Script { script_token } => script_token.span(),
|
||||||
Self::Contract { contract_token } => contract_token.span(),
|
Self::Contract { contract_token } => contract_token.span(),
|
||||||
Self::Predicate { predicate_token } => predicate_token.span(),
|
Self::Predicate { predicate_token } => predicate_token.span(),
|
||||||
Self::Library {
|
Self::Library { library_token } => library_token.span(),
|
||||||
library_token,
|
|
||||||
name,
|
|
||||||
} => Span::join(library_token.span(), name.span()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ pub use {
|
||||||
assignable::Assignable,
|
assignable::Assignable,
|
||||||
attribute::{Annotated, Attribute, AttributeDecl},
|
attribute::{Annotated, Attribute, AttributeDecl},
|
||||||
brackets::{AngleBrackets, Braces, Parens, SquareBrackets},
|
brackets::{AngleBrackets, Braces, Parens, SquareBrackets},
|
||||||
dependency::Dependency,
|
|
||||||
expr::{
|
expr::{
|
||||||
asm::{AsmBlock, AsmImmediate},
|
asm::{AsmBlock, AsmImmediate},
|
||||||
op_code::Instruction,
|
op_code::Instruction,
|
||||||
|
@ -30,6 +29,7 @@ pub use {
|
||||||
pattern::Pattern,
|
pattern::Pattern,
|
||||||
punctuated::Punctuated,
|
punctuated::Punctuated,
|
||||||
statement::{Statement, StatementLet},
|
statement::{Statement, StatementLet},
|
||||||
|
submodule::Submodule,
|
||||||
token::{Delimiter, Group, Punct, PunctKind, Spacing, TokenStream, TokenTree},
|
token::{Delimiter, Group, Punct, PunctKind, Spacing, TokenStream, TokenTree},
|
||||||
ty::Ty,
|
ty::Ty,
|
||||||
where_clause::{WhereBound, WhereClause},
|
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;
|
mod program;
|
||||||
|
|
||||||
use crate::language::DepName;
|
use crate::language::ModName;
|
||||||
pub use program::LexedProgram;
|
pub use program::LexedProgram;
|
||||||
use sway_ast::Module;
|
use sway_ast::Module;
|
||||||
use sway_types::Ident;
|
|
||||||
|
|
||||||
/// A module and its submodules in the form of a tree.
|
/// A module and its submodules in the form of a tree.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -11,15 +10,13 @@ pub struct LexedModule {
|
||||||
/// The content of this module in the form of a [Module].
|
/// The content of this module in the form of a [Module].
|
||||||
pub tree: Module,
|
pub tree: Module,
|
||||||
/// Submodules introduced within this module using the `dep` syntax in order of declaration.
|
/// 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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LexedSubmodule {
|
pub struct LexedSubmodule {
|
||||||
/// The name of a submodule, parsed from the `library` declaration within the module itself.
|
|
||||||
pub library_name: Ident,
|
|
||||||
pub module: LexedModule,
|
pub module: LexedModule,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@ use sway_types::Ident;
|
||||||
|
|
||||||
/// The name used within a module to refer to one of its submodules.
|
/// 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.
|
/// library name.
|
||||||
pub type DepName = Ident;
|
pub type ModName = Ident;
|
||||||
|
|
|
@ -247,7 +247,7 @@ pub(crate) struct Op {
|
||||||
|
|
||||||
impl Op {
|
impl Op {
|
||||||
pub fn to_var_name(&self) -> Ident {
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct IncludeStatement {
|
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.
|
// this span may be used for errors in the future, although it is not right now.
|
||||||
pub(crate) span: Span,
|
pub(crate) _span: Span,
|
||||||
pub(crate) _path_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
|
/// 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.
|
/// semicolon, denoting that it is the [Expression] to be returned from that block.
|
||||||
ImplicitReturnExpression(Expression),
|
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),
|
IncludeStatement(IncludeStatement),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{language::DepName, transform};
|
use crate::{language::ModName, transform};
|
||||||
|
|
||||||
use super::ParseTree;
|
use super::ParseTree;
|
||||||
use sway_types::{Ident, Span};
|
use sway_types::Span;
|
||||||
|
|
||||||
/// A module and its submodules in the form of a tree.
|
/// A module and its submodules in the form of a tree.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -9,17 +9,17 @@ pub struct ParseModule {
|
||||||
/// The content of this module in the form of a `ParseTree`.
|
/// The content of this module in the form of a `ParseTree`.
|
||||||
pub tree: ParseTree,
|
pub tree: ParseTree,
|
||||||
/// Submodules introduced within this module using the `dep` syntax in order of declaration.
|
/// 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,
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ParseSubmodule {
|
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 module: ParseModule,
|
||||||
pub dependency_path_span: Span,
|
pub mod_name_span: Span,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use super::ParseModule;
|
use super::ParseModule;
|
||||||
use sway_types::Ident;
|
|
||||||
|
|
||||||
/// A parsed, but not yet type-checked, Sway program.
|
/// A parsed, but not yet type-checked, Sway program.
|
||||||
///
|
///
|
||||||
|
@ -18,7 +17,7 @@ pub enum TreeType {
|
||||||
Predicate,
|
Predicate,
|
||||||
Script,
|
Script,
|
||||||
Contract,
|
Contract,
|
||||||
Library { name: Ident },
|
Library,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for TreeType {
|
impl std::fmt::Display for TreeType {
|
||||||
|
@ -30,7 +29,7 @@ impl std::fmt::Display for TreeType {
|
||||||
Self::Predicate => "predicate",
|
Self::Predicate => "predicate",
|
||||||
Self::Script => "script",
|
Self::Script => "script",
|
||||||
Self::Contract => "contract",
|
Self::Contract => "contract",
|
||||||
Self::Library { .. } => "library",
|
Self::Library => "library",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl TyStorageDeclaration {
|
||||||
attributes: transform::AttributesMap,
|
attributes: transform::AttributesMap,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
TyStorageDeclaration {
|
TyStorageDeclaration {
|
||||||
name: Ident::new_with_override("storage", span.clone()),
|
name: Ident::new_with_override("storage".to_string(), span.clone()),
|
||||||
fields,
|
fields,
|
||||||
span,
|
span,
|
||||||
attributes,
|
attributes,
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
use sway_types::{Ident, Span};
|
use sway_types::Span;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
decl_engine::{DeclEngine, DeclRef, DeclRefFunction},
|
decl_engine::{DeclEngine, DeclRef, DeclRefFunction},
|
||||||
language::ty::*,
|
language::ty::*,
|
||||||
language::DepName,
|
language::ModName,
|
||||||
semantic_analysis::namespace,
|
semantic_analysis::namespace,
|
||||||
transform,
|
transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TyModule {
|
pub struct TyModule {
|
||||||
pub submodules: Vec<(DepName, TySubmodule)>,
|
pub span: Span,
|
||||||
|
pub submodules: Vec<(ModName, TySubmodule)>,
|
||||||
pub namespace: namespace::Module,
|
pub namespace: namespace::Module,
|
||||||
pub all_nodes: Vec<TyAstNode>,
|
pub all_nodes: Vec<TyAstNode>,
|
||||||
pub attributes: transform::AttributesMap,
|
pub attributes: transform::AttributesMap,
|
||||||
|
@ -18,18 +19,17 @@ pub struct TyModule {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TySubmodule {
|
pub struct TySubmodule {
|
||||||
pub library_name: Ident,
|
|
||||||
pub module: TyModule,
|
pub module: TyModule,
|
||||||
pub dependency_path_span: Span,
|
pub mod_name_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator type for iterating over submodules.
|
/// Iterator type for iterating over submodules.
|
||||||
///
|
///
|
||||||
/// Used rather than `impl Iterator` to enable recursive submodule iteration.
|
/// Used rather than `impl Iterator` to enable recursive submodule iteration.
|
||||||
pub struct SubmodulesRecursive<'module> {
|
pub struct SubmodulesRecursive<'module> {
|
||||||
submods: std::slice::Iter<'module, (DepName, TySubmodule)>,
|
submods: std::slice::Iter<'module, (ModName, TySubmodule)>,
|
||||||
current: Option<(
|
current: Option<(
|
||||||
&'module (DepName, TySubmodule),
|
&'module (ModName, TySubmodule),
|
||||||
Box<SubmodulesRecursive<'module>>,
|
Box<SubmodulesRecursive<'module>>,
|
||||||
)>,
|
)>,
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ impl TyModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'module> Iterator for SubmodulesRecursive<'module> {
|
impl<'module> Iterator for SubmodulesRecursive<'module> {
|
||||||
type Item = &'module (DepName, TySubmodule);
|
type Item = &'module (ModName, TySubmodule);
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
self.current = match self.current.take() {
|
self.current = match self.current.take() {
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl TyProgram {
|
||||||
engines: Engines<'_>,
|
engines: Engines<'_>,
|
||||||
root: &TyModule,
|
root: &TyModule,
|
||||||
kind: parsed::TreeType,
|
kind: parsed::TreeType,
|
||||||
module_span: Span,
|
package_name: &str,
|
||||||
) -> CompileResult<(
|
) -> CompileResult<(
|
||||||
TyProgramKind,
|
TyProgramKind,
|
||||||
Vec<TyDeclaration>,
|
Vec<TyDeclaration>,
|
||||||
|
@ -48,10 +48,8 @@ impl TyProgram {
|
||||||
Self::validate_root(
|
Self::validate_root(
|
||||||
engines,
|
engines,
|
||||||
&submodule.module,
|
&submodule.module,
|
||||||
parsed::TreeType::Library {
|
parsed::TreeType::Library,
|
||||||
name: submodule.library_name.clone(),
|
package_name,
|
||||||
},
|
|
||||||
submodule.library_name.span().clone(),
|
|
||||||
),
|
),
|
||||||
continue,
|
continue,
|
||||||
warnings,
|
warnings,
|
||||||
|
@ -204,18 +202,20 @@ impl TyProgram {
|
||||||
|
|
||||||
TyProgramKind::Contract { abi_entries }
|
TyProgramKind::Contract { abi_entries }
|
||||||
}
|
}
|
||||||
parsed::TreeType::Library { name } => {
|
parsed::TreeType::Library => {
|
||||||
if !configurables.is_empty() {
|
if !configurables.is_empty() {
|
||||||
errors.push(CompileError::ConfigurableInLibrary {
|
errors.push(CompileError::ConfigurableInLibrary {
|
||||||
span: configurables[0].name.span(),
|
span: configurables[0].name.span(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TyProgramKind::Library { name }
|
TyProgramKind::Library {
|
||||||
|
name: package_name.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parsed::TreeType::Predicate => {
|
parsed::TreeType::Predicate => {
|
||||||
// A predicate must have a main function and that function must return a boolean.
|
// A predicate must have a main function and that function must return a boolean.
|
||||||
if mains.is_empty() {
|
if mains.is_empty() {
|
||||||
errors.push(CompileError::NoPredicateMainFunction(module_span));
|
errors.push(CompileError::NoPredicateMainFunction(root.span.clone()));
|
||||||
return err(vec![], errors);
|
return err(vec![], errors);
|
||||||
}
|
}
|
||||||
if mains.len() > 1 {
|
if mains.len() > 1 {
|
||||||
|
@ -238,7 +238,7 @@ impl TyProgram {
|
||||||
parsed::TreeType::Script => {
|
parsed::TreeType::Script => {
|
||||||
// A script must have exactly one main function.
|
// A script must have exactly one main function.
|
||||||
if mains.is_empty() {
|
if mains.is_empty() {
|
||||||
errors.push(CompileError::NoScriptMainFunction(module_span));
|
errors.push(CompileError::NoScriptMainFunction(root.span.clone()));
|
||||||
return err(vec![], errors);
|
return err(vec![], errors);
|
||||||
}
|
}
|
||||||
if mains.len() > 1 {
|
if mains.len() > 1 {
|
||||||
|
@ -429,7 +429,7 @@ pub enum TyProgramKind {
|
||||||
abi_entries: Vec<TyFunctionDeclaration>,
|
abi_entries: Vec<TyFunctionDeclaration>,
|
||||||
},
|
},
|
||||||
Library {
|
Library {
|
||||||
name: Ident,
|
name: String,
|
||||||
},
|
},
|
||||||
Predicate {
|
Predicate {
|
||||||
main_function: TyFunctionDeclaration,
|
main_function: TyFunctionDeclaration,
|
||||||
|
@ -444,7 +444,7 @@ impl TyProgramKind {
|
||||||
pub fn tree_type(&self) -> parsed::TreeType {
|
pub fn tree_type(&self) -> parsed::TreeType {
|
||||||
match self {
|
match self {
|
||||||
TyProgramKind::Contract { .. } => parsed::TreeType::Contract,
|
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::Predicate { .. } => parsed::TreeType::Predicate,
|
||||||
TyProgramKind::Script { .. } => parsed::TreeType::Script,
|
TyProgramKind::Script { .. } => parsed::TreeType::Script,
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,16 +80,15 @@ pub fn parse(
|
||||||
None => parse_in_memory(h, engines, input),
|
None => parse_in_memory(h, engines, input),
|
||||||
// When a `BuildConfig` is given,
|
// When a `BuildConfig` is given,
|
||||||
// the module source may declare `dep`s that must be parsed from other files.
|
// 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(
|
Some(config) => parse_module_tree(h, engines, input, config.canonical_root_module(), None)
|
||||||
|(kind, lexed, parsed)| {
|
.map(|(kind, lexed, parsed)| {
|
||||||
let lexed = lexed::LexedProgram {
|
let lexed = lexed::LexedProgram {
|
||||||
kind: kind.clone(),
|
kind: kind.clone(),
|
||||||
root: lexed,
|
root: lexed,
|
||||||
};
|
};
|
||||||
let parsed = parsed::ParseProgram { kind, root: parsed };
|
let parsed = parsed::ParseProgram { kind, root: parsed };
|
||||||
(lexed, parsed)
|
(lexed, parsed)
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +157,7 @@ fn parse_in_memory(
|
||||||
let submodules = Default::default();
|
let submodules = Default::default();
|
||||||
let attributes = module_attrs_to_map(handler, &module.attribute_list)?;
|
let attributes = module_attrs_to_map(handler, &module.attribute_list)?;
|
||||||
let root = parsed::ParseModule {
|
let root = parsed::ParseModule {
|
||||||
|
span: span::Span::dummy(),
|
||||||
tree,
|
tree,
|
||||||
submodules,
|
submodules,
|
||||||
attributes,
|
attributes,
|
||||||
|
@ -182,56 +182,52 @@ struct Submodules {
|
||||||
fn parse_submodules(
|
fn parse_submodules(
|
||||||
handler: &Handler,
|
handler: &Handler,
|
||||||
engines: Engines<'_>,
|
engines: Engines<'_>,
|
||||||
|
module_name: Option<&str>,
|
||||||
module: &sway_ast::Module,
|
module: &sway_ast::Module,
|
||||||
module_dir: &Path,
|
module_dir: &Path,
|
||||||
) -> Submodules {
|
) -> Submodules {
|
||||||
// Assume the happy path, so there'll be as many submodules as dependencies, but no more.
|
// 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());
|
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.
|
// Read the source code from the dependency.
|
||||||
// If we cannot, record as an error, but continue with other files.
|
// If we cannot, record as an error, but continue with other files.
|
||||||
let dep_path = Arc::new(module_path(module_dir, dep));
|
let submod_path = Arc::new(module_path(module_dir, module_name, submod));
|
||||||
let dep_str: Arc<str> = match std::fs::read_to_string(&*dep_path) {
|
let submod_str: Arc<str> = match std::fs::read_to_string(&*submod_path) {
|
||||||
Ok(s) => Arc::from(s),
|
Ok(s) => Arc::from(s),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
handler.emit_err(CompileError::FileCouldNotBeRead {
|
handler.emit_err(CompileError::FileCouldNotBeRead {
|
||||||
span: dep.path.span(),
|
span: submod.name.span(),
|
||||||
file_path: dep_path.to_string_lossy().to_string(),
|
file_path: submod_path.to_string_lossy().to_string(),
|
||||||
stringified_error: e.to_string(),
|
stringified_error: e.to_string(),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok((kind, lexed_module, parse_module)) =
|
if let Ok((kind, lexed_module, parse_module)) = parse_module_tree(
|
||||||
parse_module_tree(handler, engines, dep_str.clone(), dep_path.clone())
|
handler,
|
||||||
{
|
engines,
|
||||||
let library_name = match kind {
|
submod_str.clone(),
|
||||||
parsed::TreeType::Library { name } => name,
|
submod_path.clone(),
|
||||||
_ => {
|
Some(submod.name.as_str()),
|
||||||
let span = span::Span::new(dep_str, 0, 0, Some(dep_path)).unwrap();
|
) {
|
||||||
handler.emit_err(CompileError::ImportMustBeLibrary { span });
|
if !matches!(kind, parsed::TreeType::Library) {
|
||||||
return;
|
let span = span::Span::new(submod_str, 0, 0, Some(submod_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());
|
|
||||||
let parse_submodule = parsed::ParseSubmodule {
|
let parse_submodule = parsed::ParseSubmodule {
|
||||||
library_name: library_name.clone(),
|
|
||||||
module: parse_module,
|
module: parse_module,
|
||||||
dependency_path_span: dep.path.span(),
|
mod_name_span: submod.name.span(),
|
||||||
};
|
};
|
||||||
let lexed_submodule = lexed::LexedSubmodule {
|
let lexed_submodule = lexed::LexedSubmodule {
|
||||||
library_name,
|
|
||||||
module: lexed_module,
|
module: lexed_module,
|
||||||
};
|
};
|
||||||
lexed_submods.push((dep_name.clone(), lexed_submodule));
|
lexed_submods.push((submod.name.clone(), lexed_submodule));
|
||||||
parsed_submods.push((dep_name, parse_submodule));
|
parsed_submods.push((submod.name.clone(), parse_submodule));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -248,14 +244,15 @@ fn parse_module_tree(
|
||||||
engines: Engines<'_>,
|
engines: Engines<'_>,
|
||||||
src: Arc<str>,
|
src: Arc<str>,
|
||||||
path: Arc<PathBuf>,
|
path: Arc<PathBuf>,
|
||||||
|
module_name: Option<&str>,
|
||||||
) -> Result<(parsed::TreeType, lexed::LexedModule, parsed::ParseModule), ErrorEmitted> {
|
) -> Result<(parsed::TreeType, lexed::LexedModule, parsed::ParseModule), ErrorEmitted> {
|
||||||
// Parse this module first.
|
// Parse this module first.
|
||||||
let module_dir = path.parent().expect("module file has no parent directory");
|
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`.
|
// Parse all submodules before converting to the `ParseTree`.
|
||||||
// This always recovers on parse errors for the file itself by skipping that file.
|
// 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.
|
// Convert from the raw parsed module to the `ParseTree` ready for type-check.
|
||||||
let (kind, tree) = to_parsed_lang::convert_parse_tree(
|
let (kind, tree) = to_parsed_lang::convert_parse_tree(
|
||||||
|
@ -271,6 +268,7 @@ fn parse_module_tree(
|
||||||
submodules: submodules.lexed,
|
submodules: submodules.lexed,
|
||||||
};
|
};
|
||||||
let parsed = parsed::ParseModule {
|
let parsed = parsed::ParseModule {
|
||||||
|
span: span::Span::new(src, 0, 0, Some(path)).unwrap(),
|
||||||
tree,
|
tree,
|
||||||
submodules: submodules.parsed,
|
submodules: submodules.parsed,
|
||||||
attributes,
|
attributes,
|
||||||
|
@ -278,12 +276,22 @@ fn parse_module_tree(
|
||||||
Ok((kind, lexed, parsed))
|
Ok((kind, lexed, parsed))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn module_path(parent_module_dir: &Path, dep: &sway_ast::Dependency) -> PathBuf {
|
fn module_path(
|
||||||
parent_module_dir
|
parent_module_dir: &Path,
|
||||||
.iter()
|
parent_module_name: Option<&str>,
|
||||||
.chain(dep.path.span().as_str().split('/').map(AsRef::as_ref))
|
submod: &sway_ast::Submodule,
|
||||||
.collect::<PathBuf>()
|
) -> PathBuf {
|
||||||
.with_extension(sway_types::constants::DEFAULT_FILE_EXTENSION)
|
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);
|
pub struct CompiledAsm(pub FinalizedAsm);
|
||||||
|
@ -293,13 +301,14 @@ pub fn parsed_to_ast(
|
||||||
parse_program: &parsed::ParseProgram,
|
parse_program: &parsed::ParseProgram,
|
||||||
initial_namespace: namespace::Module,
|
initial_namespace: namespace::Module,
|
||||||
build_config: Option<&BuildConfig>,
|
build_config: Option<&BuildConfig>,
|
||||||
|
package_name: &str,
|
||||||
) -> CompileResult<ty::TyProgram> {
|
) -> CompileResult<ty::TyProgram> {
|
||||||
// Type check the program.
|
// Type check the program.
|
||||||
let CompileResult {
|
let CompileResult {
|
||||||
value: typed_program_opt,
|
value: typed_program_opt,
|
||||||
mut warnings,
|
mut warnings,
|
||||||
mut errors,
|
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 {
|
let mut typed_program = match typed_program_opt {
|
||||||
Some(typed_program) => typed_program,
|
Some(typed_program) => typed_program,
|
||||||
None => return err(warnings, errors),
|
None => return err(warnings, errors),
|
||||||
|
@ -403,6 +412,7 @@ pub fn compile_to_ast(
|
||||||
input: Arc<str>,
|
input: Arc<str>,
|
||||||
initial_namespace: namespace::Module,
|
initial_namespace: namespace::Module,
|
||||||
build_config: Option<&BuildConfig>,
|
build_config: Option<&BuildConfig>,
|
||||||
|
package_name: &str,
|
||||||
) -> CompileResult<ty::TyProgram> {
|
) -> CompileResult<ty::TyProgram> {
|
||||||
// Parse the program to a concrete syntax tree (CST).
|
// Parse the program to a concrete syntax tree (CST).
|
||||||
let CompileResult {
|
let CompileResult {
|
||||||
|
@ -424,7 +434,13 @@ pub fn compile_to_ast(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type check (+ other static analysis) the CST to a typed 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);
|
errors.extend(typed_res.errors);
|
||||||
warnings.extend(typed_res.warnings);
|
warnings.extend(typed_res.warnings);
|
||||||
let typed_program = match typed_res.value {
|
let typed_program = match typed_res.value {
|
||||||
|
@ -447,8 +463,15 @@ pub fn compile_to_asm(
|
||||||
input: Arc<str>,
|
input: Arc<str>,
|
||||||
initial_namespace: namespace::Module,
|
initial_namespace: namespace::Module,
|
||||||
build_config: BuildConfig,
|
build_config: BuildConfig,
|
||||||
|
package_name: &str,
|
||||||
) -> CompileResult<CompiledAsm> {
|
) -> 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)
|
ast_to_asm(engines, &ast_res, &build_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,8 +583,15 @@ pub fn compile_to_bytecode(
|
||||||
initial_namespace: namespace::Module,
|
initial_namespace: namespace::Module,
|
||||||
build_config: BuildConfig,
|
build_config: BuildConfig,
|
||||||
source_map: &mut SourceMap,
|
source_map: &mut SourceMap,
|
||||||
|
package_name: &str,
|
||||||
) -> CompileResult<CompiledBytecode> {
|
) -> 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)
|
asm_to_bytecode(asm_res, source_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,8 +671,7 @@ fn module_dead_code_analysis<'eng: 'cfg, 'cfg>(
|
||||||
.submodules
|
.submodules
|
||||||
.iter()
|
.iter()
|
||||||
.fold(init_res, |res, (_, submodule)| {
|
.fold(init_res, |res, (_, submodule)| {
|
||||||
let name = submodule.library_name.clone();
|
let tree_type = parsed::TreeType::Library;
|
||||||
let tree_type = parsed::TreeType::Library { name };
|
|
||||||
res.flat_map(|_| {
|
res.flat_map(|_| {
|
||||||
module_dead_code_analysis(engines, &submodule.module, &tree_type, graph)
|
module_dead_code_analysis(engines, &submodule.module, &tree_type, graph)
|
||||||
})
|
})
|
||||||
|
|
|
@ -57,10 +57,10 @@ impl ty::TyCodeBlock {
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
if node_deterministically_aborts {
|
if node_deterministically_aborts {
|
||||||
let never_mod_path = vec![
|
let never_mod_path = vec![
|
||||||
Ident::new_with_override("core", span.clone()),
|
Ident::new_with_override("core".into(), span.clone()),
|
||||||
Ident::new_with_override("never", 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
|
let never_decl_opt = ctx
|
||||||
.namespace
|
.namespace
|
||||||
|
|
|
@ -212,7 +212,7 @@ fn test_function_selector_behavior() {
|
||||||
|
|
||||||
let decl = ty::TyFunctionDeclaration {
|
let decl = ty::TyFunctionDeclaration {
|
||||||
purity: Default::default(),
|
purity: Default::default(),
|
||||||
name: Ident::new_no_span("foo"),
|
name: Ident::new_no_span("foo".into()),
|
||||||
implementing_type: None,
|
implementing_type: None,
|
||||||
body: ty::TyCodeBlock { contents: vec![] },
|
body: ty::TyCodeBlock { contents: vec![] },
|
||||||
parameters: vec![],
|
parameters: vec![],
|
||||||
|
@ -234,12 +234,12 @@ fn test_function_selector_behavior() {
|
||||||
|
|
||||||
let decl = ty::TyFunctionDeclaration {
|
let decl = ty::TyFunctionDeclaration {
|
||||||
purity: Default::default(),
|
purity: Default::default(),
|
||||||
name: Ident::new_with_override("bar", Span::dummy()),
|
name: Ident::new_with_override("bar".into(), Span::dummy()),
|
||||||
implementing_type: None,
|
implementing_type: None,
|
||||||
body: ty::TyCodeBlock { contents: vec![] },
|
body: ty::TyCodeBlock { contents: vec![] },
|
||||||
parameters: vec![
|
parameters: vec![
|
||||||
ty::TyFunctionParameter {
|
ty::TyFunctionParameter {
|
||||||
name: Ident::new_no_span("foo"),
|
name: Ident::new_no_span("foo".into()),
|
||||||
is_reference: false,
|
is_reference: false,
|
||||||
is_mutable: false,
|
is_mutable: false,
|
||||||
mutability_span: Span::dummy(),
|
mutability_span: Span::dummy(),
|
||||||
|
@ -248,7 +248,7 @@ fn test_function_selector_behavior() {
|
||||||
.into(),
|
.into(),
|
||||||
},
|
},
|
||||||
ty::TyFunctionParameter {
|
ty::TyFunctionParameter {
|
||||||
name: Ident::new_no_span("baz"),
|
name: Ident::new_no_span("baz".into()),
|
||||||
is_reference: false,
|
is_reference: false,
|
||||||
is_mutable: false,
|
is_mutable: false,
|
||||||
mutability_span: Span::dummy(),
|
mutability_span: Span::dummy(),
|
||||||
|
|
|
@ -446,7 +446,7 @@ impl ty::TyImplTrait {
|
||||||
prefixes: vec![],
|
prefixes: vec![],
|
||||||
suffix: match &type_engine.get(implementing_for.type_id) {
|
suffix: match &type_engine.get(implementing_for.type_id) {
|
||||||
TypeInfo::Custom { call_path, .. } => call_path.suffix.clone(),
|
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,
|
is_absolute: false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@ impl ty::TyScrutinee {
|
||||||
let dummy_type_param = TypeParameter {
|
let dummy_type_param = TypeParameter {
|
||||||
type_id,
|
type_id,
|
||||||
initial_type_id: 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: vec![],
|
||||||
trait_constraints_span: Span::dummy(),
|
trait_constraints_span: Span::dummy(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,8 +57,8 @@ impl ty::TyExpression {
|
||||||
|
|
||||||
let call_path = CallPath {
|
let call_path = CallPath {
|
||||||
prefixes: vec![
|
prefixes: vec![
|
||||||
Ident::new_with_override("core", span.clone()),
|
Ident::new_with_override("core".into(), span.clone()),
|
||||||
Ident::new_with_override("ops", span.clone()),
|
Ident::new_with_override("ops".into(), span.clone()),
|
||||||
],
|
],
|
||||||
suffix: Op {
|
suffix: Op {
|
||||||
op_variant: OpVariant::Equals,
|
op_variant: OpVariant::Equals,
|
||||||
|
@ -1526,10 +1526,10 @@ impl ty::TyExpression {
|
||||||
inner: MethodName::FromTrait {
|
inner: MethodName::FromTrait {
|
||||||
call_path: CallPath {
|
call_path: CallPath {
|
||||||
prefixes: vec![
|
prefixes: vec![
|
||||||
Ident::new_with_override("core", span.clone()),
|
Ident::new_with_override("core".into(), span.clone()),
|
||||||
Ident::new_with_override("ops", 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,
|
is_absolute: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
error::*,
|
error::*,
|
||||||
language::{parsed::*, ty, DepName},
|
language::{parsed::*, ty, ModName},
|
||||||
semantic_analysis::*,
|
semantic_analysis::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ impl ty::TyModule {
|
||||||
submodules,
|
submodules,
|
||||||
tree,
|
tree,
|
||||||
attributes,
|
attributes,
|
||||||
|
span,
|
||||||
} = parsed;
|
} = parsed;
|
||||||
|
|
||||||
// Type-check submodules first in order of declaration.
|
// Type-check submodules first in order of declaration.
|
||||||
|
@ -38,6 +39,7 @@ impl ty::TyModule {
|
||||||
|
|
||||||
submodules_res.flat_map(|submodules| {
|
submodules_res.flat_map(|submodules| {
|
||||||
typed_nodes_res.map(|all_nodes| Self {
|
typed_nodes_res.map(|all_nodes| Self {
|
||||||
|
span: span.clone(),
|
||||||
submodules,
|
submodules,
|
||||||
namespace: ctx.namespace.module().clone(),
|
namespace: ctx.namespace.module().clone(),
|
||||||
all_nodes,
|
all_nodes,
|
||||||
|
@ -64,20 +66,18 @@ impl ty::TyModule {
|
||||||
impl ty::TySubmodule {
|
impl ty::TySubmodule {
|
||||||
pub fn type_check(
|
pub fn type_check(
|
||||||
parent_ctx: TypeCheckContext,
|
parent_ctx: TypeCheckContext,
|
||||||
dep_name: DepName,
|
mod_name: ModName,
|
||||||
submodule: &ParseSubmodule,
|
submodule: &ParseSubmodule,
|
||||||
) -> CompileResult<Self> {
|
) -> CompileResult<Self> {
|
||||||
let ParseSubmodule {
|
let ParseSubmodule {
|
||||||
library_name,
|
|
||||||
module,
|
module,
|
||||||
dependency_path_span,
|
mod_name_span,
|
||||||
} = submodule;
|
} = 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);
|
let module_res = ty::TyModule::type_check(submod_ctx, module);
|
||||||
module_res.map(|module| ty::TySubmodule {
|
module_res.map(|module| ty::TySubmodule {
|
||||||
library_name: library_name.clone(),
|
|
||||||
module,
|
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 single `Module` within a Sway project.
|
||||||
///
|
///
|
||||||
/// A `Module` is most commonly associated with an individual file of Sway code, e.g. a top-level
|
/// 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.
|
/// `[dependencies]` table of a `forc` manifest.
|
||||||
///
|
///
|
||||||
/// A `Module` contains a set of all items that exist within the lexical scope via declaration or
|
/// 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
|
/// Submodules of the current module represented as an ordered map from each submodule's name
|
||||||
/// to the associated `Module`.
|
/// 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.
|
/// some library dependency that we include as a submodule.
|
||||||
///
|
///
|
||||||
/// Note that we *require* this map to be ordered to produce deterministic codegen results.
|
/// Note that we *require* this map to be ordered to produce deterministic codegen results.
|
||||||
pub(crate) submodules: im::OrdMap<ModuleName, Module>,
|
pub(crate) submodules: im::OrdMap<ModuleName, Module>,
|
||||||
/// The set of symbols, implementations, synonyms and aliases present within this module.
|
/// The set of symbols, implementations, synonyms and aliases present within this module.
|
||||||
items: Items,
|
items: Items,
|
||||||
/// Name of the module, package name for root module, library name for other modules.
|
/// Name of the module, package name for root module, module name for other modules.
|
||||||
/// Library name used is the same as declared in `library name;`.
|
/// Module name used is the same as declared in `mod name;`.
|
||||||
pub name: Option<Ident>,
|
pub name: Option<Ident>,
|
||||||
|
/// Empty span at the beginning of the file implementing the module
|
||||||
|
pub span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
|
|
|
@ -323,17 +323,22 @@ impl Namespace {
|
||||||
/// [SubmoduleNamespace] type. When dropped, the [SubmoduleNamespace] resets the `mod_path`
|
/// [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
|
/// back to the original path so that we can continue type-checking the current module after
|
||||||
/// finishing with the dependency.
|
/// 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();
|
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
|
let submod_path: Vec<_> = self
|
||||||
.mod_path
|
.mod_path
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain(Some(dep_name.clone()))
|
.chain(Some(mod_name.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
let parent_mod_path = std::mem::replace(&mut self.mod_path, submod_path);
|
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 {
|
SubmoduleNamespace {
|
||||||
namespace: self,
|
namespace: self,
|
||||||
parent_mod_path,
|
parent_mod_path,
|
||||||
|
|
|
@ -370,7 +370,7 @@ impl TraitMap {
|
||||||
///
|
///
|
||||||
/// `data.sw`:
|
/// `data.sw`:
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// library data;
|
/// library;
|
||||||
///
|
///
|
||||||
/// enum MyResult<T, E> {
|
/// enum MyResult<T, E> {
|
||||||
/// Ok: T,
|
/// Ok: T,
|
||||||
|
@ -403,7 +403,7 @@ impl TraitMap {
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// script;
|
/// script;
|
||||||
///
|
///
|
||||||
/// dep data;
|
/// mod data;
|
||||||
///
|
///
|
||||||
/// use data::Data;
|
/// use data::Data;
|
||||||
///
|
///
|
||||||
|
@ -490,7 +490,7 @@ impl TraitMap {
|
||||||
///
|
///
|
||||||
/// `my_double.sw`:
|
/// `my_double.sw`:
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// library my_double;
|
/// library;
|
||||||
///
|
///
|
||||||
/// pub trait MyDouble<T> {
|
/// pub trait MyDouble<T> {
|
||||||
/// fn my_double(self, input: T) -> T;
|
/// fn my_double(self, input: T) -> T;
|
||||||
|
@ -499,7 +499,7 @@ impl TraitMap {
|
||||||
///
|
///
|
||||||
/// `my_point.sw`:
|
/// `my_point.sw`:
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// library my_point;
|
/// library;
|
||||||
///
|
///
|
||||||
/// use ::my_double::MyDouble;
|
/// use ::my_double::MyDouble;
|
||||||
///
|
///
|
||||||
|
@ -519,8 +519,8 @@ impl TraitMap {
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// script;
|
/// script;
|
||||||
///
|
///
|
||||||
/// dep my_double;
|
/// mod my_double;
|
||||||
/// dep my_point;
|
/// mod my_point;
|
||||||
///
|
///
|
||||||
/// use my_point::MyPoint;
|
/// 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.
|
// These have the added complexity of converting CallPath and/or TypeInfo into a name.
|
||||||
Declaration::ImplSelf(decl) => {
|
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(
|
impl_sym(
|
||||||
trait_name,
|
trait_name,
|
||||||
&type_engine.get(decl.implementing_for.type_id),
|
&type_engine.get(decl.implementing_for.type_id),
|
||||||
|
|
|
@ -19,15 +19,15 @@ impl ty::TyProgram {
|
||||||
engines: Engines<'_>,
|
engines: Engines<'_>,
|
||||||
parsed: &ParseProgram,
|
parsed: &ParseProgram,
|
||||||
initial_namespace: namespace::Module,
|
initial_namespace: namespace::Module,
|
||||||
|
package_name: &str,
|
||||||
) -> CompileResult<Self> {
|
) -> CompileResult<Self> {
|
||||||
let mut namespace = Namespace::init_root(initial_namespace);
|
let mut namespace = Namespace::init_root(initial_namespace);
|
||||||
let ctx =
|
let ctx =
|
||||||
TypeCheckContext::from_root(&mut namespace, engines).with_kind(parsed.kind.clone());
|
TypeCheckContext::from_root(&mut namespace, engines).with_kind(parsed.kind.clone());
|
||||||
let ParseProgram { root, kind } = parsed;
|
let ParseProgram { root, kind } = parsed;
|
||||||
let mod_span = root.tree.span.clone();
|
|
||||||
let mod_res = ty::TyModule::type_check(ctx, root);
|
let mod_res = ty::TyModule::type_check(ctx, root);
|
||||||
mod_res.flat_map(|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 {
|
res.map(|(kind, declarations, configurables)| Self {
|
||||||
kind,
|
kind,
|
||||||
root,
|
root,
|
||||||
|
|
|
@ -139,14 +139,15 @@ impl<'a> TypeCheckContext<'a> {
|
||||||
/// Returns the result of the given `with_submod_ctx` function.
|
/// Returns the result of the given `with_submod_ctx` function.
|
||||||
pub fn enter_submodule<T>(
|
pub fn enter_submodule<T>(
|
||||||
self,
|
self,
|
||||||
dep_name: Ident,
|
mod_name: Ident,
|
||||||
|
module_span: Span,
|
||||||
with_submod_ctx: impl FnOnce(TypeCheckContext) -> T,
|
with_submod_ctx: impl FnOnce(TypeCheckContext) -> T,
|
||||||
) -> T {
|
) -> T {
|
||||||
// We're checking a submodule, so no need to pass through anything other than the
|
// 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
|
// namespace. However, we will likely want to pass through the type engine and declaration
|
||||||
// engine here once they're added.
|
// engine here once they're added.
|
||||||
let Self { namespace, .. } = self;
|
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(
|
let submod_ctx = TypeCheckContext::from_module_namespace(
|
||||||
&mut submod_ns,
|
&mut submod_ns,
|
||||||
Engines::new(self.type_engine, self.decl_engine),
|
Engines::new(self.type_engine, self.decl_engine),
|
||||||
|
|
|
@ -10,13 +10,13 @@ use sway_ast::{
|
||||||
expr::{ReassignmentOp, ReassignmentOpVariant},
|
expr::{ReassignmentOp, ReassignmentOpVariant},
|
||||||
ty::TyTupleDescriptor,
|
ty::TyTupleDescriptor,
|
||||||
AbiCastArgs, AngleBrackets, AsmBlock, Assignable, AttributeDecl, Braces, CodeBlockContents,
|
AbiCastArgs, AngleBrackets, AsmBlock, Assignable, AttributeDecl, Braces, CodeBlockContents,
|
||||||
CommaToken, Dependency, DoubleColonToken, Expr, ExprArrayDescriptor, ExprStructField,
|
CommaToken, DoubleColonToken, Expr, ExprArrayDescriptor, ExprStructField, ExprTupleDescriptor,
|
||||||
ExprTupleDescriptor, FnArg, FnArgs, FnSignature, GenericArgs, GenericParams, IfCondition,
|
FnArg, FnArgs, FnSignature, GenericArgs, GenericParams, IfCondition, IfExpr, Instruction,
|
||||||
IfExpr, Instruction, Intrinsic, Item, ItemAbi, ItemConfigurable, ItemConst, ItemEnum, ItemFn,
|
Intrinsic, Item, ItemAbi, ItemConfigurable, ItemConst, ItemEnum, ItemFn, ItemImpl, ItemKind,
|
||||||
ItemImpl, ItemKind, ItemStorage, ItemStruct, ItemTrait, ItemTraitItem, ItemUse, LitInt,
|
ItemStorage, ItemStruct, ItemTrait, ItemTraitItem, ItemUse, LitInt, LitIntType,
|
||||||
LitIntType, MatchBranchKind, Module, ModuleKind, Parens, PathExpr, PathExprSegment, PathType,
|
MatchBranchKind, Module, ModuleKind, Parens, PathExpr, PathExprSegment, PathType,
|
||||||
PathTypeSegment, Pattern, PatternStructField, PubToken, Punctuated, QualifiedPathRoot,
|
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::convert_parse_tree_error::ConvertParseTreeError;
|
||||||
use sway_error::handler::{ErrorEmitted, Handler};
|
use sway_error::handler::{ErrorEmitted, Handler};
|
||||||
|
@ -58,7 +58,7 @@ pub fn convert_module_kind(kind: &ModuleKind) -> TreeType {
|
||||||
ModuleKind::Script { .. } => TreeType::Script,
|
ModuleKind::Script { .. } => TreeType::Script,
|
||||||
ModuleKind::Contract { .. } => TreeType::Contract,
|
ModuleKind::Contract { .. } => TreeType::Contract,
|
||||||
ModuleKind::Predicate { .. } => TreeType::Predicate,
|
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 span = item.span();
|
||||||
let contents = match item.value {
|
let contents = match item.value {
|
||||||
ItemKind::Dependency(dependency) => {
|
ItemKind::Submodule(submodule) => {
|
||||||
// Check that Dependency is not annotated
|
// Check that Dependency is not annotated
|
||||||
if attributes.contains_key(&AttributeKind::DocComment) {
|
if attributes.contains_key(&AttributeKind::DocComment) {
|
||||||
let error = ConvertParseTreeError::CannotDocCommentDependency {
|
let error = ConvertParseTreeError::CannotDocCommentDependency {
|
||||||
|
@ -133,13 +133,13 @@ fn item_to_ast_nodes(
|
||||||
// Check that Dependency comes after only other Dependencies
|
// Check that Dependency comes after only other Dependencies
|
||||||
let emit_expected_dep_at_beginning = || {
|
let emit_expected_dep_at_beginning = || {
|
||||||
let error = ConvertParseTreeError::ExpectedDependencyAtBeginning {
|
let error = ConvertParseTreeError::ExpectedDependencyAtBeginning {
|
||||||
span: dependency.span(),
|
span: submodule.span(),
|
||||||
};
|
};
|
||||||
handler.emit_err(error.into());
|
handler.emit_err(error.into());
|
||||||
};
|
};
|
||||||
match prev_item {
|
match prev_item {
|
||||||
Some(Annotated {
|
Some(Annotated {
|
||||||
value: ItemKind::Dependency(_),
|
value: ItemKind::Submodule(_),
|
||||||
..
|
..
|
||||||
}) => (),
|
}) => (),
|
||||||
Some(_) => emit_expected_dep_at_beginning(),
|
Some(_) => emit_expected_dep_at_beginning(),
|
||||||
|
@ -148,7 +148,7 @@ fn item_to_ast_nodes(
|
||||||
if !is_root {
|
if !is_root {
|
||||||
emit_expected_dep_at_beginning();
|
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)]
|
vec![AstNodeContent::IncludeStatement(incl_stmt)]
|
||||||
}
|
}
|
||||||
ItemKind::Use(item_use) => item_use_to_use_statements(context, handler, item_use)?
|
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,
|
MATCH_RETURN_VAR_NAME_PREFIX,
|
||||||
context.next_match_expression_return_var_unique_suffix(),
|
context.next_match_expression_return_var_unique_suffix(),
|
||||||
);
|
);
|
||||||
let var_decl_name = Ident::new_with_override(
|
let var_decl_name =
|
||||||
Box::leak(match_return_var_name.into_boxed_str()),
|
Ident::new_with_override(match_return_var_name, var_decl_span.clone());
|
||||||
var_decl_span.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let var_decl_exp = Expression {
|
let var_decl_exp = Expression {
|
||||||
kind: ExpressionKind::Variable(var_decl_name.clone()),
|
kind: ExpressionKind::Variable(var_decl_name.clone()),
|
||||||
|
@ -2109,10 +2107,10 @@ fn op_call(
|
||||||
inner: MethodName::FromTrait {
|
inner: MethodName::FromTrait {
|
||||||
call_path: CallPath {
|
call_path: CallPath {
|
||||||
prefixes: vec![
|
prefixes: vec![
|
||||||
Ident::new_with_override("core", op_span.clone()),
|
Ident::new_with_override("core".into(), op_span.clone()),
|
||||||
Ident::new_with_override("ops", 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,
|
is_absolute: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2936,7 +2934,7 @@ fn statement_let_to_ast_nodes(
|
||||||
mutable,
|
mutable,
|
||||||
name,
|
name,
|
||||||
} => (reference, mutable, name),
|
} => (reference, mutable, name),
|
||||||
Pattern::Wildcard { .. } => (None, None, Ident::new_no_span("_")),
|
Pattern::Wildcard { .. } => (None, None, Ident::new_no_span("_".into())),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
if reference.is_some() {
|
if reference.is_some() {
|
||||||
|
@ -2989,10 +2987,8 @@ fn statement_let_to_ast_nodes(
|
||||||
DESTRUCTURE_PREFIX,
|
DESTRUCTURE_PREFIX,
|
||||||
context.next_destructured_struct_unique_suffix()
|
context.next_destructured_struct_unique_suffix()
|
||||||
);
|
);
|
||||||
let destructure_name = Ident::new_with_override(
|
let destructure_name =
|
||||||
Box::leak(destructured_name.into_boxed_str()),
|
Ident::new_with_override(destructured_name, path.prefix.name.span());
|
||||||
path.prefix.name.span(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Parse the type ascription and the type ascription span.
|
// Parse the type ascription and the type ascription span.
|
||||||
// In the event that the user did not provide a type ascription,
|
// 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,
|
TUPLE_NAME_PREFIX,
|
||||||
context.next_destructured_tuple_unique_suffix()
|
context.next_destructured_tuple_unique_suffix()
|
||||||
);
|
);
|
||||||
let tuple_name =
|
let tuple_name = Ident::new_with_override(tuple_name, span.clone());
|
||||||
Ident::new_with_override(Box::leak(tuple_name.into_boxed_str()), span.clone());
|
|
||||||
|
|
||||||
// Parse the type ascription and the type ascription span.
|
// Parse the type ascription and the type ascription span.
|
||||||
// In the event that the user did not provide a type ascription,
|
// 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 {
|
IncludeStatement {
|
||||||
_alias: None,
|
_span: dependency.span(),
|
||||||
span: dependency.span(),
|
_mod_name_span: dependency.name.span(),
|
||||||
_path_span: dependency.path.span(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,9 @@ fn generic_enum_resolution() {
|
||||||
let decl_engine = DeclEngine::default();
|
let decl_engine = DeclEngine::default();
|
||||||
|
|
||||||
let sp = Span::dummy();
|
let sp = Span::dummy();
|
||||||
let generic_name = Ident::new_with_override("T", sp.clone());
|
let generic_name = Ident::new_with_override("T".into(), sp.clone());
|
||||||
let a_name = Ident::new_with_override("a", sp.clone());
|
let a_name = Ident::new_with_override("a".into(), sp.clone());
|
||||||
let result_name = Ident::new_with_override("Result", sp.clone());
|
let result_name = Ident::new_with_override("Result".into(), sp.clone());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Result<_> {
|
Result<_> {
|
||||||
|
|
|
@ -328,7 +328,7 @@ impl<'a> Unifier<'a> {
|
||||||
NumericCastCompatResult::CastableWithWarning(warn) => {
|
NumericCastCompatResult::CastableWithWarning(warn) => {
|
||||||
vec![CompileWarning {
|
vec![CompileWarning {
|
||||||
span: span.clone(),
|
span: span.clone(),
|
||||||
warning_content: warn,
|
warning_content: *warn,
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
NumericCastCompatResult::Compatible => {
|
NumericCastCompatResult::Compatible => {
|
||||||
|
@ -502,10 +502,10 @@ fn numeric_cast_compat(
|
||||||
| (Sixteen, ThirtyTwo)
|
| (Sixteen, ThirtyTwo)
|
||||||
| (Sixteen, SixtyFour)
|
| (Sixteen, SixtyFour)
|
||||||
| (ThirtyTwo, SixtyFour) => {
|
| (ThirtyTwo, SixtyFour) => {
|
||||||
NumericCastCompatResult::CastableWithWarning(Warning::LossOfPrecision {
|
NumericCastCompatResult::CastableWithWarning(Box::new(Warning::LossOfPrecision {
|
||||||
initial_type: old_size,
|
initial_type: old_size,
|
||||||
cast_to: new_size,
|
cast_to: new_size,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
// Upcasting is ok, so everything else is ok.
|
// Upcasting is ok, so everything else is ok.
|
||||||
_ => NumericCastCompatResult::Compatible,
|
_ => NumericCastCompatResult::Compatible,
|
||||||
|
@ -514,5 +514,5 @@ fn numeric_cast_compat(
|
||||||
|
|
||||||
enum NumericCastCompatResult {
|
enum NumericCastCompatResult {
|
||||||
Compatible,
|
Compatible,
|
||||||
CastableWithWarning(Warning),
|
CastableWithWarning(Box<Warning>),
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,7 +320,7 @@ pub enum CompileError {
|
||||||
file_path: String,
|
file_path: String,
|
||||||
stringified_error: 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 },
|
ImportMustBeLibrary { span: Span },
|
||||||
#[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
|
#[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
|
||||||
MoreThanOneEnumInstantiator { span: Span, ty: String },
|
MoreThanOneEnumInstantiator { span: Span, ty: String },
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
library core;
|
library;
|
||||||
|
|
||||||
dep primitives;
|
mod primitives;
|
||||||
dep raw_ptr;
|
mod raw_ptr;
|
||||||
dep raw_slice;
|
mod raw_slice;
|
||||||
dep ops;
|
mod ops;
|
||||||
dep never;
|
mod never;
|
||||||
dep prelude;
|
mod prelude;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library never;
|
library;
|
||||||
|
|
||||||
use ::ops::{Eq, Not, Ord};
|
use ::ops::{Eq, Not, Ord};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library ops;
|
library;
|
||||||
|
|
||||||
use ::primitives::*;
|
use ::primitives::*;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ pub trait Mod {
|
||||||
impl Mod for u64 {
|
impl Mod for u64 {
|
||||||
fn modulo(self, other: Self) -> Self {
|
fn modulo(self, other: Self) -> Self {
|
||||||
asm(r1: self, r2: other, r3) {
|
asm(r1: self, r2: other, r3) {
|
||||||
mod r3 r1 r2;
|
r#mod r3 r1 r2;
|
||||||
r3: u64
|
r3: u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ impl Mod for u64 {
|
||||||
impl Mod for u32 {
|
impl Mod for u32 {
|
||||||
fn modulo(self, other: Self) -> Self {
|
fn modulo(self, other: Self) -> Self {
|
||||||
asm(r1: self, r2: other, r3) {
|
asm(r1: self, r2: other, r3) {
|
||||||
mod r3 r1 r2;
|
r#mod r3 r1 r2;
|
||||||
r3: u32
|
r3: u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ impl Mod for u32 {
|
||||||
impl Mod for u16 {
|
impl Mod for u16 {
|
||||||
fn modulo(self, other: Self) -> Self {
|
fn modulo(self, other: Self) -> Self {
|
||||||
asm(r1: self, r2: other, r3) {
|
asm(r1: self, r2: other, r3) {
|
||||||
mod r3 r1 r2;
|
r#mod r3 r1 r2;
|
||||||
r3: u16
|
r3: u16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ impl Mod for u16 {
|
||||||
impl Mod for u8 {
|
impl Mod for u8 {
|
||||||
fn modulo(self, other: Self) -> Self {
|
fn modulo(self, other: Self) -> Self {
|
||||||
asm(r1: self, r2: other, r3) {
|
asm(r1: self, r2: other, r3) {
|
||||||
mod r3 r1 r2;
|
r#mod r3 r1 r2;
|
||||||
r3: u8
|
r3: u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library prelude;
|
library;
|
||||||
|
|
||||||
//! Defines the Sway core library prelude.
|
//! Defines the Sway core library prelude.
|
||||||
//! The prelude consists of implicitly available items,
|
//! 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