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
Desugar type use abbreviation #16
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This is where type definitions actually originate from. I’m choosing to represent a type definition with its originating field verbatim (versus e.g. only the function type) so that we can use the same array to both look up existing type definitions and store any new ones which get generated as a result of desugaring the type use abbreviation.
We’ve filled in the type definitions returned by #process_type_definition, and we know that all other fields generate no immediate type definitions. (Notwithstanding the effect of desugaring the type use abbreviation, but we haven’t implemented that yet.)
The real type definition lists (sometimes legitimately empty!) have now been filled in everywhere, so we no longer need a dummy value.
When no `(type …)` is present we’ll need to automatically insert one [0], which is going to be more complicated than simply passing through the existing one verbatim and desugaring its parameters & results, so it needs a dedicated code path. [0] https://webassembly.github.io/spec/core/text/modules.html#abbreviations
This is the simplest case of the type use abbreviation [0]: if we can find an existing type definition whose type is exactly the same as the one being used, we insert a reference to that definition. We’re not yet accounting for (irrelevant) parameter identifier mismatches, nor for the case where no matching definition is found. This commit includes a lot of tests. Earlier commits have already plumbed the type definitions into every place where a type use can syntactically occur, but this is our first opportunity to check that it’s actually worked in all those cases. [0] https://webassembly.github.io/spec/core/text/modules.html#abbreviations
This allows us to extract the parameter and result declarations and compare them separately, rather than comparing the function type verbatim. This change is a prerequisite for ignoring parameter identifiers, which we’ll do next.
This ignores identifiers in type definitions and uses, allowing them to match even when the identifiers don’t.
Per the spec [0], “if no such index exists, then a new type definition […] is inserted at the end of the module”. We’re doing this by mutating the incoming array of type definitions, which isn’t particularly elegant but gets the job done without having to worry about threading another result value (i.e. a separate array of generated type definitions) through the field-processing methods. We can’t add tests for this commit’s behaviour in isolation because the resulting program is syntactically invalid: we’re inserting the index of a type definition which hasn’t yet been added to the module. In the next commit we’ll also insert the generated definitions at the end of the module and add some tests to check that both halves of the solution are working together correctly. [0] https://webassembly.github.io/spec/core/text/modules.html#abbreviations
We need a deep copy of the generated type definitions because they contain object references to parameters and results elsewhere in the source S-expression; since the AST parser consumes the S-expression destructively, any structural sharing will cause serious problems. The approach of “count the type definitions before and after processing the fields, and the difference between these two counts must be the newly-generated definitions” is a bit hacky, but it gives us the behaviour we need. In future we should consider a more elegant approach to this whole problem of modifying different parts of the S-expression during preprocessing.
Now that the preprocessor is desugaring all legitimate occurrences of the type use abbreviation, it’s safe for the parser to assume that a block type contains an optional value type [0] if the `type` keyword is missing. [0] https://webassembly.github.io/spec/core/text/instructions.html#text-blocktype
This is desugared by the preprocessor now.
This is desugared by the preprocessor now.
The preprocessor has already generated all necessary type definitions while desugaring the type use abbreviation.
The initial context is no longer mutated during parsing because the preprocessor has already done the work to insert whatever type definitions are needed, so we don’t need to worry about allowing methods to update it. We’re therefore switching to an explicit argument since it’s clearer and easier to understand. For now we have to be careful to use the modified context (i.e. `self.context`) inside #with_context blocks instead of the `context` local variable. In the next commit we’ll be able to undo this when we remove #with_context calls entirely.
The previous commit switched to an explicit `context:` argument, so we no longer need to update the current context.
…arser We now pass the context around explicitly.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
As an abbreviation, a type use can be replaced by inline parameter and result declarations: instead of writing e.g.
(func (type $t) …)
and defining$t
elsewhere in the module with(type $t (func (param i32) (result i64)))
, we can write the more concise and expressive(func (param i32) (result i64) …)
.To support this abbreviation, a WebAssembly implementation must automatically insert a type index referring either to a matching type definition in the current module (e.g.
$t
above) or a newly-inserted type definition if no matching one exists.This PR implements desugaring for this abbreviation in the preprocessor and removes support for it from the AST parser. It relies upon machinery introduced in #14 and #15 which allows type definitions to be collected while preprocessing a module’s fields and then provided to the deferred result to yield the final S-expressions.