Abstract Types extension to WebAssembly's reference types proposal #4
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I don't expect this to be particularly useful to anyone, especially with the exciting work going on with the GC proposal and Type Imports proposal, but I wanted to share this abstract types language extension I implemented in case it is relevant to someone.
You can launch a Jupyter notebook with several examples and a modified Wasm interpreter implementing the following features by clicking .
Overview
I've implemented a small extension to the WebAssembly language that introduces abstract types (also known as "existential types" or "abstract data types" or "opaque references" or "nominal types"). I built this in the context of my undergraduate thesis which explored using WebAssembly as a multi-language platform (by enabling the various features needed for secure compilation).
This implementation of abstract types is based on OCaml's abstract types and loosely conforms with the ideas expressed by rossberg and RossTate in WebAssembly/proposal-type-imports#7:
These features allow WebAssembly to enforce higher-level abstractions such as:
a
inlet a = new Date(); a.getYear()
)Usage
To work with these new abstract types, I've introduced 4 operators to the language. The syntax is verbose in order to ensure clarity in the operations being performed. It's likely that a more ergonomic syntax would be adopted, such as merging the
abstype_new
andabstype_sealed
namespaces and referring to them with a single operator, as well as overloading the existingtype
instruction to support abstract types. For now, the syntax is as follows:abstype_new
abstype_new [IDENTIFIER] value_type
abstype_sealed_ref
)abstype_sealed
abstype_sealed [IDENTIFIER]
import
instruction, i.e.(import "mod" "id" (abstype_sealed [IDENTIFIER]))
abstype_new_ref
abstype_new_ref IDENTIFIER
abstype_new
)abstype_sealed_ref
abstype_sealed_ref IDENTIFIER
abstype_sealed
)Abstract types manifest in two ways:
abstype_new*
instructions are used within a given module. These abstract types are "unwrapped" within the module, and are treated as their underlying value_types. In this way, local abstract types are more like type aliases. This allows abstract types to be constructed, and only take on their abstract nature when used in a separate module.abstype_sealed*
instructions are being used. These abstract types are treated as opaque identifiers referencing the source module instance and the export statement. These abstract types are only treated as their underlying values upon program execution (i.e. after validation). Additionally, they do not have default values, so trying to immediately use alocal
with a sealed abstract type will fail, instead, thelocal
must be populated with a value provided by the sealed abstract type's source module.Examples
You can see simple syntax/usage examples in the test file for this feature at test/core/abstract-types.wast.
For something more interesting, I've configured my awendland/2020-thesis repository to be runnable via Binder so that you can jump right into a web-based Jupyter notebook with this
webassembly-spec-abstypes
interpreter already available and the code insamples/
all runnable. Try it out with:Implementation Details
I've created a PR (#4) showcasing the implementation on top of the reference interpreter's Reference Types Proposal branch.
The core changes for stack type checking were in interpreter/syntax/types.ml:
SealedAbsType of int32
tovalue_type
value_type
calledwrapped_value_types
that could be aNewAbsType of value_type * int32
in addition to a straightvalue_type
.In both of these instances, the
i32
value represents a unique identifier for the abstract type, since the types are "nominal", as in, even if they have the same underlying type they're unique if they are from different definitions (i.e. differentabstype_new
operations). See the test suite where this distinction is demonstrated.The core changes for type checking module linking were implemented in a new module called interpreter/runtime/extern_types.ml that:
All uses of
value_type
(should) have been expanded to support abstract types.Work in Progress
Several aspects of this implementation are unfinished (and likely to remain so given the exciting development going on with the GC Proposal and my interests moving elsewhere). I documented the issues I was aware of in the test suite; they are:
Additionally, I only implemented abstract types for the textual representation of WebAssembly, not the binary variant or the JS API. The binary variant should be a straightforward addition. The JS API will require various decisions to be made around how to enforce the abstraction across the JS boundary; hard problems that are getting compelling answers in the GC Proposal.
Related Discussions
This small language extension is related to much more exciting discussions going on elsewhere, such as:
It's also loosely related to much grander proposals that are in the works: GC, Type Imports, Interface Types.
Thanks for such great work on WebAssembly! I'm excited to see where the language goes.