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:
IGI-111 2023-03-09 09:14:52 +01:00 committed by GitHub
parent 0848a887b7
commit 0eaa3a6da9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
430 changed files with 994 additions and 1171 deletions

View file

@ -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: (),

View file

@ -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;

View file

@ -1,4 +1,4 @@
library fizzbuzz; library;
// ANCHOR: state // ANCHOR: state
enum State { enum State {

View file

@ -1,4 +1,4 @@
library arrays; library;
// ANCHOR: syntax // ANCHOR: syntax
fn syntax() { fn syntax() {

View file

@ -1,4 +1,4 @@
library booleans; library;
// ANCHOR: syntax // ANCHOR: syntax
fn returns_true() -> bool { fn returns_true() -> bool {

View file

@ -1,4 +1,4 @@
library bytes; library;
fn syntax() { fn syntax() {
// ANCHOR: syntax // ANCHOR: syntax

View file

@ -1,4 +1,4 @@
library basic_enum; library;
// ANCHOR: definition // ANCHOR: definition
enum Color { enum Color {

View file

@ -1,4 +1,4 @@
library enum_of_enums; library;
// ANCHOR: content // ANCHOR: content
enum UserError { enum UserError {

View file

@ -1,4 +1,4 @@
library enum_of_structs; library;
// ANCHOR: content // ANCHOR: content
struct Item { struct Item {

View file

@ -1,4 +1,4 @@
library enums; library;
dep basic_enum; mod basic_enum;
dep enum_of_structs; mod enum_of_structs;

View file

@ -1,4 +1,4 @@
library numerics; library;
fn syntax() { fn syntax() {
// ANCHOR: syntax // ANCHOR: syntax

View file

@ -1,4 +1,4 @@
library strings; library;
fn explicit() { fn explicit() {
// ANCHOR: explicit // ANCHOR: explicit

View file

@ -1,4 +1,4 @@
library structs; library;
// ANCHOR: definition // ANCHOR: definition
struct Foo { struct Foo {

View file

@ -1,4 +1,4 @@
library tuples; library;
fn syntax() { fn syntax() {
// ANCHOR: declare // ANCHOR: declare

View file

@ -1,4 +1,4 @@
library comments; library;
fn comment() { fn comment() {
// ANCHOR: comment // ANCHOR: comment

View file

@ -1,4 +1,4 @@
library control_flow; library;
fn conditional() { fn conditional() {
// ANCHOR: conditional // ANCHOR: conditional

View file

@ -1,4 +1,4 @@
library explicit; library;
// ANCHOR: main // ANCHOR: main
fn main() -> bool { fn main() -> bool {

View file

@ -1,4 +1,4 @@
library implicit; library;
// ANCHOR: main // ANCHOR: main
fn main() -> bool { fn main() -> bool {

View file

@ -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 {

View file

@ -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

View file

@ -1,4 +1,4 @@
library my_library; library;
use my_other_library::quix; use my_other_library::quix;

View file

@ -1,3 +1,3 @@
library my_other_library; library;
pub fn quix() {} pub fn quix() {}

View file

@ -1,6 +1,6 @@
library lib; library;
dep my_library; mod my_library;
use my_library::bar; use my_library::bar;

View file

@ -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

View file

@ -1,4 +1,4 @@
library annotations; library;
// ANCHOR: type_annotation // ANCHOR: type_annotation
fn execute() { fn execute() {

View file

@ -1,4 +1,4 @@
library enums; library;
pub enum Error { pub enum Error {
StateError: StateError, StateError: StateError,

View file

@ -1,4 +1,4 @@
library getters; library;
// ANCHOR: avoid // ANCHOR: avoid
fn get_maximum_deposit() -> u64 { fn get_maximum_deposit() -> u64 {

View file

@ -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;

View file

@ -1,4 +1,4 @@
library struct_shorthand; library;
// ANCHOR: struct_shorthand_definition // ANCHOR: struct_shorthand_definition
struct Structure { struct Structure {

View file

@ -1,4 +1,4 @@
library variables; library;
fn mutable() { fn mutable() {
// ANCHOR: mutable // ANCHOR: mutable

View file

@ -1,4 +1,4 @@
library enums; library;
// ANCHOR: u64_example // ANCHOR: u64_example
pub enum T { pub enum T {

View file

@ -1,4 +1,4 @@
library arrays; library;
// ANCHOR: syntax // ANCHOR: syntax
fn syntax() { fn syntax() {

View file

@ -1,4 +1,4 @@
library strings; library;
fn single_quotes() { fn single_quotes() {
// ANCHOR: single_quotes // ANCHOR: single_quotes

View file

@ -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 {

View file

@ -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 {

View file

@ -1,4 +1,4 @@
library asset_operations; library;
// ANCHOR: mint_import // ANCHOR: mint_import
use std::token::mint; use std::token::mint;

View file

@ -1,4 +1,4 @@
library call_data; library;
// ANCHOR: import_sender // ANCHOR: import_sender
use std::auth::msg_sender; use std::auth::msg_sender;

View file

@ -1,4 +1,4 @@
library interface; library;
abi Vault { abi Vault {
fn deposit(); fn deposit();

View file

@ -1,4 +1,4 @@
library hashing; library;
// ANCHOR: import_sha256 // ANCHOR: import_sha256
use std::hash::sha256; use std::hash::sha256;

View file

@ -1,4 +1,4 @@
library logging; library;
// ANCHOR: logging // ANCHOR: logging
fn log_data(number: u64) { fn log_data(number: u64) {

View file

@ -1,4 +1,4 @@
library namespace; library;
// ANCHOR: address // ANCHOR: address
pub struct Address { pub struct Address {

View file

@ -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}}

View file

@ -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

View file

@ -1,6 +1,6 @@
contract; contract;
dep other_contract; mod other_contract;
use other_contract::*; use other_contract::*;

View file

@ -1,4 +1,4 @@
library other_contract; library;
abi OtherContract { abi OtherContract {
#[payable] #[payable]

View file

@ -1,4 +1,4 @@
library basic_enum; library;
// Declare the enum // Declare the enum
enum Color { enum Color {

View file

@ -1,4 +1,4 @@
library enum_of_enums; library;
pub enum Error { pub enum Error {
StateError: StateError, StateError: StateError,

View file

@ -1,4 +1,4 @@
library enum_of_structs; library;
struct Item { struct Item {
price: u64, price: u64,

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -1,4 +1,4 @@
library r#abi; library;
abi IdentityExample { abi IdentityExample {
#[storage(read)] #[storage(read)]

View file

@ -1,4 +1,4 @@
library errors; library;
pub enum MyError { pub enum MyError {
UnauthorizedUser: Identity, UnauthorizedUser: Identity,

View file

@ -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;

View file

@ -1,4 +1,4 @@
library data_structures; library;
// Declare a struct type // Declare a struct type
pub struct Foo { pub struct Foo {

View file

@ -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 {

View file

@ -1,4 +1,4 @@
library tuples; library;
fn tuple() { fn tuple() {
// You can declare the types youself // You can declare the types youself

View file

@ -1,5 +1,5 @@
// ANCHOR: abi_library // ANCHOR: abi_library
library wallet_abi; library;
// ANCHOR: abi // ANCHOR: abi
abi Wallet { abi Wallet {

View file

@ -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);
} }

View file

@ -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(

View file

@ -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)

View file

@ -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 {

View file

@ -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(),
}
}
}

View file

@ -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(),

View file

@ -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");

View file

@ -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},
}; };

View file

@ -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()),
} }
} }
} }

View file

@ -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
View 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())
}
}

View file

@ -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,
} }

View file

@ -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;

View file

@ -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())
} }
} }

View file

@ -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,
} }

View file

@ -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),
} }

View file

@ -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,
} }

View file

@ -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",
} }
) )
} }

View file

@ -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,

View file

@ -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() {

View file

@ -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,
} }

View file

@ -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(); ) {
if !matches!(kind, parsed::TreeType::Library) {
let span = span::Span::new(submod_str, 0, 0, Some(submod_path)).unwrap();
handler.emit_err(CompileError::ImportMustBeLibrary { span }); handler.emit_err(CompileError::ImportMustBeLibrary { span });
return; 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: &Path,
parent_module_name: Option<&str>,
submod: &sway_ast::Submodule,
) -> PathBuf {
if let Some(parent_name) = parent_module_name {
parent_module_dir parent_module_dir
.iter() .join(parent_name)
.chain(dep.path.span().as_str().split('/').map(AsRef::as_ref)) .join(submod.name.to_string())
.collect::<PathBuf>()
.with_extension(sway_types::constants::DEFAULT_FILE_EXTENSION) .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)
}) })

View file

@ -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

View file

@ -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(),

View file

@ -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,
}; };

View file

@ -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(),
}; };

View file

@ -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,
}, },
}, },

View file

@ -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(),
}) })
}) })
} }

View file

@ -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 {

View file

@ -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,

View file

@ -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;
/// ///

View file

@ -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),

View file

@ -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,

View file

@ -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),

View file

@ -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(),
} }
} }

View file

@ -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<_> {

View file

@ -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>),
} }

View file

@ -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 },

View file

@ -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;

View file

@ -1,4 +1,4 @@
library never; library;
use ::ops::{Eq, Not, Ord}; use ::ops::{Eq, Not, Ord};

View file

@ -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
} }
} }

View file

@ -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