Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates explanation of modules #369

Merged
merged 3 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions _books/ion-1-1/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
- [System macros](macros/system_macros.md)
- [Modules](modules.md)
- [Defining modules](modules/defining_modules.md)
- [The encoding module](modules/encoding_module.md)
- [Directives](modules/directives.md)
- [Shared modules](modules/shared_modules.md)
- [Inner modules](modules/inner_modules.md)
- [The system module](modules/system_module.md)
- [Local modules](modules/local_modules.md)
- [Encoding modules](modules/encoding_modules.md)
- [System module](modules/system_module.md)
- [Binary encoding](binary/encoding.md)
- [Encoding primitives](binary/primitives.md)
- [`FlexUInt`](binary/primitives/flex_uint.md)
Expand Down
49 changes: 24 additions & 25 deletions _books/ion-1-1/src/modules/defining_modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,27 @@ A module is defined by four kinds of subclauses which, if present, always appear
3. `symbol_table` - an exported list of text values
4. `macro_table` - an exported list of macro definitions

The lexical name given to a module definition must be an [identifier](../modules.md#identifiers).
However, it may not begin with a `$`--this is reserved for system-defined bindings like `$ion`.

### Internal environment

The body of a module tracks an internal environment by which macro references are resolved.
This environment is constructed incrementally by each clause in the definition and consists of:

* the _visible modules_, a map from identifier to module
* the _module bindings_, a map from identifier to module definition
* the _exported symbols_, an array containing symbol texts
* the _exported macros_, an array containing name/macro pairs

Before any clauses of the module definition are examined, the initial environment is as follows:

* The visible modules map binds `$ion` to the system module for the appropriate spec version.
Inside an encoding directive, the visible modules map also binds `$ion_encoding` to the active encoding module
(the encoding module that was active when the encoding directive was encountered).
For an inner module, it also includes the modules previously made available by the enclosing
module (via `import` or `module`).
* The macro table and symbol table are empty.
Before any clauses of the module definition are examined, each of these is empty.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The modules bindings does not contain $ion or _?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. The bindings for $ion and _ are at the stream level. Referencing them inside a module will result in recursive lookups through the parent scopes until it reaches the stream. (Optimizations are possible, of course, but this is the behavior that must be achieved.)


Each clause affects the environment as follows:

* An `import` declaration retrieves a shared module from the implementation’s catalog, assigns
it a name in the visible modules, and makes its macros available for use.
An error must be signaled if the name already appears in the visible modules.
* A `module` declaration defines a new module and assigns it a name in the visible modules.
An error must be signaled if the name already appears in the visible modules.
* An `import` declaration retrieves a shared module from the implementation’s catalog and binds a name to it,
making its macros available for use.
An error must be signaled if the name already appears in the module bindings.
* A `module` declaration defines a new module and binds a name to it.
An error must be signaled if the name already appears in the module bindings.
* A `symbol_table` declaration defines the exported symbols.
* A `macro_table` declaration defines the exported macros.

Expand All @@ -53,19 +48,22 @@ macro-addr ::= unannotated-uint

Macro references are resolved to a specific macro as follows:

* An unqualified _macro-name_ is looked up within the exported macros, and if not found, then the
active encoding module's macro table. If it maps to a macro, that’s the resolution of the reference.
Otherwise, an error is signaled due to an unbound reference.
* An anonymous local reference (_macro-addr_) is resolved by index in the exported macro array.
* An unqualified _macro-name_ is looked up in the following locations:
1. in the macros already exported in this module's `macro_table`
2. in the [default_module](encoding_modules.md#default-module)
3. in the [system module](system_module.md)

If it maps to a macro, that’s the resolution of the reference. Otherwise, an error is signaled due to an unbound reference.

* An anonymous local reference (_macro-addr_) is resolved by index in the exported macro array.
If the address exceeds the array boundary, an error is signaled due to an invalid reference.
* A qualified reference (_qualified-ref_) resolves solely against the referenced module.
If the module name does not exist in the visible modules, an error is signaled due to an unbound reference.
Otherwise, the name or address is resolved within that module’s exported macro array.
First, the module name must be resolved to a module definition.
* If the module name is in the module bindings, it resolves to the corresponding module definition.
* If the module name is not in the module bindings, resolution is attempted recursively upwards through the parent scopes.
* If the search reaches the top level without resolving to a module, an error is signaled due to an unbound reference.

> [!WARNING]
> An unqualified macro name can change meaning in the middle of an encoding module if you choose to shadow the
> name of a macro in the active encoding module. To unambiguously refer to the active encoding module,
> use the qualified reference syntax: `$ion_encoding::<macro-name>`.
Next, the name or address is resolved within that module definition’s exported macro table.


### `import`
Expand All @@ -82,7 +80,8 @@ catalog-name ::= string
catalog-version ::= int // positive, unannotated
```

An import binds a lexically scoped module name to a shared module that is identified by a catalog key—a `(name, version)` pair. The `version` of the catalog key is optional—when omitted, the version is implicitly 1.
An import binds a lexically scoped module name to a shared module that is identified by a catalog key—a `(name, version)` pair.
The `version` of the catalog key is optional—when omitted, the version is implicitly 1.

In Ion 1.0, imports may be substituted with a different version if an exact match is not found.
In Ion 1.1, however, all imports require an exact match to be found in the reader's catalog;
Expand Down
79 changes: 79 additions & 0 deletions _books/ion-1-1/src/modules/directives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Directives

_Directives_ are system values that modify the encoding context.

Syntactically, a directive is a top-level s-expression annotated with `$ion`.
Its first child value is an operation name.
The operation determines what changes will be made to the encoding context and which clauses may legally follow.

```ion
$ion::
(operation_name
(clause_1 /*...*/)
(clause_2 /*...*/)
/*...more clauses...*/
(clause_N /*...*/))
```

In Ion v1.1, there are three supported directive operations:
zslayton marked this conversation as resolved.
Show resolved Hide resolved
1. [`module`](#module-directives)
2. [`import`](#import-directives)
3. [`encoding`](#encoding-directives)

## Top-level bindings

The `module` and `import` directives each create a stream-level binding to a module definition.
Once created, module bindings at this level endure until the file ends or another Ion version marker is encountered.

Module bindings at the stream-level can be redefined.

> [!TIP]
> The [`add_macros`](../macros/system_macros.md#add_macros) and [`add_symbols`](../macros/system_macros.md#add_symbols)
> system macros work by redefining the default module (`_`) in terms of itself.

This behavior differs from module bindings created inside another module;
[attempting to redefine these will raise an error](defining_modules.md#internal-environment).

### `module` directives
The `module` directive binds a name to a [local module](local_modules.md) definition at the top level of the stream.

```ion
$ion::
(module foo
/*...imports, if any...*/
/*...submodules, if any...*/
(macro_table /*...*/)
(symbol_table /*...*/)
)
```

### `import` directives

The _import_ directive looks up the module corresponding to the given `(name, version)` pair in the catalog.
Upon success, it creates a new binding to that module at the top level of the stream.

```ion
$ion::
(import
bar // Binding
zslayton marked this conversation as resolved.
Show resolved Hide resolved
"com.example.bar" // Module name
2) // Module version
zslayton marked this conversation as resolved.
Show resolved Hide resolved
```
If the catalog does contain an exact match, this operation raises an error.

## `encoding` directives

An `encoding` directive accepts a sequence of module bindings to use as the following stream segment's
[encoding module sequence](encoding_modules.md).

```ion
$ion::
(encoding
mod_a
mod_b
mod_c)
```

The new encoding module sequence takes effect immediately after the directive and remains the same until the next `encoding` directive or Ion version marker.

Note that the [default module](encoding_modules.md#default-module) is always implicitly at the head of the encoding module sequence.
75 changes: 0 additions & 75 deletions _books/ion-1-1/src/modules/encoding_module.md

This file was deleted.

Loading
Loading