mirror of
https://github.com/enso-org/enso.git
synced 2024-10-26 13:14:43 +03:00
Imports, Exports, and Modules documentation (#1086)
Co-authored-by: Ara Adkins <iamrecursion@users.noreply.github.com>
This commit is contained in:
parent
5fcd80d4d0
commit
3b96b9c4cc
@ -8,23 +8,106 @@ order: 6
|
||||
|
||||
# Modules
|
||||
|
||||
Enso has a rudimentary module system in order to aid code modularity.
|
||||
Modules are the basic way to organize code into smaller, semantically-relevant
|
||||
parts. The following is the description of the semantics of Enso modules.
|
||||
|
||||
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
||||
|
||||
- [Enso Modules](#enso-modules)
|
||||
- [Future Directions](#future-directions)
|
||||
- [Introduction](#introduction)
|
||||
- [Referring to Modules](#referring-to-modules)
|
||||
- [Module-Level Methods](#module-level-methods)
|
||||
- [Types](#types)
|
||||
- [Referent Name Resolution](#referent-name-resolution)
|
||||
- [Referent Names in Method Calls](#referent-names-in-method-calls)
|
||||
- [Importing & Exporting Methods](#importing--exporting-methods)
|
||||
- [Export Statement Semantics](#export-statement-semantics)
|
||||
- [Project Main Module](#project-main-module)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Enso Modules
|
||||
## Introduction
|
||||
|
||||
> The actionables for this section are:
|
||||
>
|
||||
> - Specify the current state of the Enso module system.
|
||||
There's a one-to-one correspondence between source files and modules. Moreover,
|
||||
a module's name is the same as that of the corresponding source file. That also
|
||||
implies, that an Enso source file name must be a valid referent name. Modules
|
||||
are first-class objects, meaning they can be assigned to variables and passed as
|
||||
function parameters.
|
||||
|
||||
## Future Directions
|
||||
## Referring to Modules
|
||||
|
||||
> The actionables for this section are:
|
||||
>
|
||||
> - Specify what we'd like to do with modules in the future.
|
||||
Modules can be imported into the current scope by using the `import` statement.
|
||||
To import a module, one must provide it's full qualified path. A qualified path
|
||||
of a module is a number of `.`-separated segments, where:
|
||||
|
||||
1. The first segment is the name of the project in which the module is located.
|
||||
2. The following segments are the names of directories between `src` and the
|
||||
source file being imported.
|
||||
3. The last segment is the name of the source file, with the `.enso` extension
|
||||
stripped.
|
||||
|
||||
For example, a qualified name of a module corresponding to the file
|
||||
`src/Foo/Bar/Baz.enso` in project `Project` is `Project.Foo.Bar.Baz`.
|
||||
|
||||
Whenever a module is imported, its name (either the last segment of the
|
||||
qualified name or the name it was renamed to), becomes available in the
|
||||
importing scope as a value.
|
||||
|
||||
Moreover, the current module is always visible in the scope under its file-based
|
||||
name, and as the special variable `here`.
|
||||
|
||||
## Module-Level Methods
|
||||
|
||||
A method defined without an explicit `this` reference, or with `this` explicitly
|
||||
set to the current module, becomes a module-level method. Such a method can be
|
||||
called by passing the module as the `this` parameter. Such methods can also be
|
||||
called by importing modules and using the imported module in place of `this`.
|
||||
|
||||
## Types
|
||||
|
||||
From the perspective of accessing them through imports, there is no difference
|
||||
between a `type` constructor definition and a module-level method. Both can be
|
||||
accessed in exactly the same ways both from inside the module and from the
|
||||
importing modules.
|
||||
|
||||
## Referent Name Resolution
|
||||
|
||||
Referent names are resolved in a special way, by finding the relevant name among
|
||||
imported modules and items explicitely imported from them. Imported items may be
|
||||
one of the following: modules, types, module-level methods and polyglot symbols.
|
||||
|
||||
The order of resolving names is as follows:
|
||||
|
||||
1. Symbols defined in local (function or block) scopes.
|
||||
2. Symbols defined in the current module.
|
||||
3. Names of imported modules.
|
||||
4. Names explicitly imported from modules.
|
||||
|
||||
If there's an ambiguity at any level, an error is reported.
|
||||
|
||||
## Referent Names in Method Calls
|
||||
|
||||
If a referent name is used as the method name in method call syntax, it is not
|
||||
subject to referent name resolution and is instead treated as though it was not
|
||||
referent in this position.
|
||||
|
||||
## Importing & Exporting Methods
|
||||
|
||||
Methods defined both on the module and on other types are always imported and
|
||||
exported automatically whenever the module is imported or exported. There is
|
||||
currently no plan to allow hiding methods from imported / re-exported modules,
|
||||
but this decision will be revised after a sufficiently large corpus of Enso code
|
||||
exists.
|
||||
|
||||
## Export Statement Semantics
|
||||
|
||||
An export statement always exports the name of the exported module (possibly
|
||||
renamed). Additionally, any items explicitly mentioned in a `from` export,
|
||||
become available as though they were defined in the exporting module.
|
||||
|
||||
## Project Main Module
|
||||
|
||||
The module `Main` in any project is treated specially, as the main entry-point
|
||||
to the library. Therefore, using the bare project name in an import statement
|
||||
(e.g. `import My_Project`) is equivalent to importing the `Main` module with the
|
||||
proper rename (e.g. `import My_Project.Main as My_Project`). This syntax sugar
|
||||
works with any kind of import or export statement.
|
||||
|
@ -15,108 +15,105 @@ code from modules.
|
||||
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
||||
|
||||
- [Import Syntax](#import-syntax)
|
||||
- [Visibility of Imported Bindings](#visibility-of-imported-bindings)
|
||||
- [Qualified Imports](#qualified-imports)
|
||||
- [Unqualified Imports](#unqualified-imports)
|
||||
- [Export Syntax](#export-syntax)
|
||||
- [Qualified Exports](#qualified-exports)
|
||||
- [Unqualified Exports](#unqualified-exports)
|
||||
- [Visibility of Export Bindings](#visibility-of-export-bindings)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Import Syntax
|
||||
|
||||
Importing a module is a way to bring its contents into scope in the current
|
||||
module. Imports in Enso appear as follows:
|
||||
There are two main ways of importing a module into the current scope.
|
||||
|
||||
- They start with the `import` keyword.
|
||||
- The `import` keyword is followed by a module path (e.g. `Base.Vector.Unsafe`).
|
||||
### Qualified Imports
|
||||
|
||||
From there, Enso imports are broken up into four main categories:
|
||||
These imports consist of the word `import` followed by a qualified name of a
|
||||
module. This can by optionally followed by the `as` word, and a referent name of
|
||||
the module as it should be visible in the importing scope.
|
||||
|
||||
1. **Unqualified Imports:** These import all symbols from the module into the
|
||||
current scope, and consist only of the `import` keyword and a module path.
|
||||
Imported items are imported accessible without qualification.
|
||||
2. **Qualified Imports:** These import all symbols from the module into the
|
||||
current scope with symbols qualified under a name _different_ from the
|
||||
module name. It consists of the `import` keyword followed by a module path
|
||||
followed by the `as` keyword, followed by a referent name.
|
||||
3. **Restricted Imports:** These import only the specific symbols from the
|
||||
module into the current scope. They consist of the `import` keyword,
|
||||
followed by a module path, followed by the `only` keyword, followed by a
|
||||
space-separated list of symbols.
|
||||
4. **Hiding Imports:** These are the inverse of restricted imports, and import
|
||||
_all_ symbols other than the named ones into the current scope. They consist
|
||||
of the `import` keyword, followed by a module path, followed by the keyword
|
||||
`only`, followed by a space-separated list of symbols.
|
||||
The only name brought into scope by such an import is the name of the module (or
|
||||
the name provided after the `as` keyword, if provided).
|
||||
|
||||
The qualified import syntax can be combined with the restricted and hiding
|
||||
import syntaxes.
|
||||
### Unqualified Imports
|
||||
|
||||
By way of example, the following code uses a variety of import types:
|
||||
Unqualified imports are broken up into three main categories:
|
||||
|
||||
```ruby
|
||||
import A # unqualified
|
||||
import B as T # qualified
|
||||
import C only symbol_1 symbol_2 # restricted
|
||||
import D hiding symbol_1 symbol_2 # hiding
|
||||
import E as U only symbol_3 # qualified + restricted
|
||||
import F as V hiding symbol_4 # qualified + hiding
|
||||
```
|
||||
1. **Unrestricted Imports:** These import all symbols from the module into the
|
||||
current scope. They consist of the keyword `from`, followed by a qualified
|
||||
module name, followed by an optional rename part (using the `as` keyword),
|
||||
then the keywords `import all`. For example:
|
||||
```
|
||||
from Base.List as Builtin_List import all
|
||||
```
|
||||
2. **Restricted Imports:** These import a specified set of names for use as
|
||||
automatically resolved referent names. They consist of the keyword `from`,
|
||||
followed by a qualified module name (with optional `as`-rename), then the
|
||||
word `import` followed by a coma-separated list of referent names to be
|
||||
imported. For example:
|
||||
```
|
||||
from Base.List import Cons, Nil
|
||||
```
|
||||
3. **Hiding Imports:** These are the inverse of restricted imports, and import
|
||||
_all_ symbosl other than the named ones. They consist of the `from` keyword,
|
||||
followed by a qualified module name (with optional `as`-rename), then the
|
||||
words `import all hiding`, followed by a coma-separated list of referent
|
||||
names to be excluded from the import. For example:
|
||||
```
|
||||
from Base.List import all hiding Cons, Nil
|
||||
```
|
||||
|
||||
Imports in Enso _may_ introduce ambiguous symbols, but this is not an error
|
||||
until one of the ambiguous symbols is _used_ in Enso code.
|
||||
|
||||
### Visibility of Imported Bindings
|
||||
|
||||
When importing a module `X` into the current module `Y`, the bindings from `X`
|
||||
made available by the import (see above) become available in `Y`. However, Enso
|
||||
does not re-export imported bindings from a module by default, so the imported
|
||||
bindings from `X` are not visible in a module _importing_ `Y`.
|
||||
|
||||
## Export Syntax
|
||||
|
||||
In order to allow for easy composition and aggregation of code, Enso provides
|
||||
its users with a mechanism to _export_ imported elements from modules. They
|
||||
appear in Enso as follows:
|
||||
|
||||
- They start with the `export` keyword.
|
||||
- The `export` keyword is followed by a module name (e.g. `My_Module`) that is
|
||||
available in the current scope.
|
||||
- The _current_ module is implicitly exported unqualified.
|
||||
### Qualified Exports
|
||||
|
||||
From there, Enso exports are broken up into four main categories:
|
||||
These exports consist of the word `export` followed by a qualified name of a
|
||||
module. This can by optionally followed by the `as` word, and a referent name of
|
||||
the module as it should be visible in the exporting scope.
|
||||
|
||||
1. **Unqualified Exports:** These export all symbols from the named module as
|
||||
if they were defined in the exporting module. They consist of the `export`
|
||||
keyword, followed by a visible module name.
|
||||
2. **Qualified Exports:** These export all symbols from the module as if they
|
||||
were defined in a module nested within the exporting module. It consists of
|
||||
the `export` keyword, followed by a module name, followed by the `as`
|
||||
keyword, followed by another module name.
|
||||
3. **Restricted Exports:** These export only the specified symbols from the
|
||||
exporting module, as if they were defined in the exporting module. It
|
||||
consists of the `export` keyword, followed by a module name, followed by the
|
||||
`only` keyword, and then a space-separated list of symbols.
|
||||
4. **Hiding Exports:** These export all symbols from the module _except_ those
|
||||
explicitly specified. It consists of the `export` keyword, followed by a
|
||||
module name, followed by the `hiding` keyword, and then a space-separated
|
||||
list of symbols.
|
||||
The only name brought into scope by such an export is the name of the module (or
|
||||
the name provided after the `as` keyword, if provided).
|
||||
|
||||
The qualified export syntax can be combined with the restricted and hiding
|
||||
export syntaxes.
|
||||
### Unqualified Exports
|
||||
|
||||
By way of example, the following code uses a variety of export types:
|
||||
Unqualified exports are broken up into three main categories:
|
||||
|
||||
```ruby
|
||||
export A
|
||||
export B as X
|
||||
export C only symbol_1
|
||||
export D hiding symbol_1
|
||||
export E as Y only symbol_1
|
||||
export F as Y hiding symbol_1
|
||||
```
|
||||
1. **Unrestricted Exports:** These export all symbols from the module into the
|
||||
current scope. They consist of the keyword `from`, followed by a qualified
|
||||
module name, followed by an optional rename part (using the `as` keyword),
|
||||
then the keywords `export all`. For example:
|
||||
```
|
||||
from Base.List as Builtin_List export all
|
||||
```
|
||||
2. **Restricted Exports:** These export a specified set of names, behaving as
|
||||
though they were redefined in the current scope. They consist of the keyword
|
||||
`from`, followed by a qualified module name (with optional `as`-rename), then
|
||||
the word `export` followed by a coma-separated list of names to be exported.
|
||||
For example:
|
||||
```
|
||||
from Base.List export Cons, Nil, from_vector
|
||||
```
|
||||
3. **Hiding Exports:** These are the inverse of restricted exports, and export
|
||||
_all_ symbols other than the named ones. They consist of the `from` keyword,
|
||||
followed by a qualified module name (with optional `as`-rename), then the
|
||||
words `export all hiding`, followed by a coma-separated list of names to be
|
||||
excluded from the export. For example:
|
||||
```
|
||||
from Base.List export all hiding from_vector, Nil
|
||||
```
|
||||
|
||||
In essence, an export allows the user to `paste` the contents of the module
|
||||
In essence, an export allows the user to "paste" the contents of the module
|
||||
being exported into the module declaring the export. This means that exports
|
||||
that create name clashes need to be resolved at the _export_ site.
|
||||
that create name clashes must be resolved at the _export_ site.
|
||||
|
||||
### Visibility of Export Bindings
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user