Skip to content

Commit

Permalink
Allow type definitions to be generated while preprocessing a module (#15
Browse files Browse the repository at this point in the history
)

The #process_module method is ready to provide type definitions to the
deferred results produced by preprocessing the module’s fields so that
the type use abbreviation [0] can be desugared, but we don’t currently
have any way to communicate those type definitions to #process_module.
Although the processed fields do include type definition fields, they’re
all deferred until we’re ready to provide the type definitions — another
chicken-and-egg situation.

This commit adds a “list of type definitions” return value
to #process_type_definition and refactors other preprocessor methods to
allow that value to propagate up to #process_module. The next (and
final!) step will be to populate it with real type definitions and use
those to desugar the type use abbreviation.

This concludes the preparatory work begun in #12, #13 and #14, and
therefore still doesn’t introduce any externally visible changes to the
preprocessor’s behaviour.

[0] https://webassembly.github.io/spec/core/text/modules.html#abbreviations
  • Loading branch information
tomstuart committed Jul 20, 2023
2 parents 046ad84 + a03d4f6 commit 370c28a
Showing 1 changed file with 83 additions and 53 deletions.
136 changes: 83 additions & 53 deletions lib/wasminna/preprocessor.rb
Expand Up @@ -62,18 +62,21 @@ def process_module
strings = repeatedly { read }
['module', *id, 'binary', *strings]
else
fields = process_fields.call(DUMMY_TYPE_DEFINITIONS)
['module', *id, *fields]
fields, type_definitions = process_fields
['module', *id, *fields.call(type_definitions)]
end
end

def process_fields
repeatedly do
read_list { process_field }
end.then do |fields|
after_all_fields do |type_definitions|
fields.flat_map { |field| field.call(type_definitions) }
end
end.transpose.then do |fields = [], type_definitions = []|
[
after_all_fields do |type_definitions|
fields.flat_map { |field| field.call(type_definitions) }
end,
type_definitions.flatten(1)
]
end
end

Expand Down Expand Up @@ -111,11 +114,14 @@ def process_function_definition
locals = process_locals
body = process_instructions

after_all_fields do |type_definitions|
[
['func', *id, *typeuse.call(type_definitions), *locals, *body.call(type_definitions)]
]
end
[
after_all_fields do |type_definitions|
[
['func', *id, *typeuse.call(type_definitions), *locals, *body.call(type_definitions)]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end
end

Expand All @@ -130,11 +136,14 @@ def process_table_definition
else
rest = repeatedly { read }

after_all_fields do
[
['table', *id, *rest]
]
end
[
after_all_fields do
[
['table', *id, *rest]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end
end

Expand Down Expand Up @@ -180,11 +189,14 @@ def process_memory_definition
else
rest = repeatedly { read }

after_all_fields do
[
['memory', *id, *rest]
]
end
[
after_all_fields do
[
['memory', *id, *rest]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end
end

Expand Down Expand Up @@ -219,11 +231,14 @@ def process_global_definition
read => type
instructions = process_instructions

after_all_fields do |type_definitions|
[
['global', *id, type, *instructions.call(type_definitions)]
]
end
[
after_all_fields do |type_definitions|
[
['global', *id, type, *instructions.call(type_definitions)]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end
end

Expand Down Expand Up @@ -386,11 +401,14 @@ def process_type_definition
read_optional_id => id
functype = read_list { process_functype }

after_all_fields do
[
['type', *id, functype]
]
end
[
after_all_fields do
[
['type', *id, functype]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end

def process_functype
Expand All @@ -407,11 +425,14 @@ def process_import
read => name
descriptor = read_list { process_import_descriptor }

after_all_fields do |type_definitions|
[
['import', module_name, name, descriptor.call(type_definitions)]
]
end
[
after_all_fields do |type_definitions|
[
['import', module_name, name, descriptor.call(type_definitions)]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end

def process_import_descriptor
Expand All @@ -437,13 +458,16 @@ def process_element_segment
read => 'elem'
read_optional_id => id

if can_read_list?
process_active_element_segment(id:)
elsif peek in 'declare'
process_declarative_element_segment(id:)
else
process_passive_element_segment(id:)
end
[
if can_read_list?
process_active_element_segment(id:)
elsif peek in 'declare'
process_declarative_element_segment(id:)
else
process_passive_element_segment(id:)
end,
DUMMY_TYPE_DEFINITIONS
]
end

def process_active_element_segment(id:)
Expand Down Expand Up @@ -557,11 +581,14 @@ def process_data_segment
read => 'data'
read_optional_id => id

if can_read_list?
process_active_data_segment(id:)
else
process_passive_data_segment(id:)
end
[
if can_read_list?
process_active_data_segment(id:)
else
process_passive_data_segment(id:)
end,
DUMMY_TYPE_DEFINITIONS
]
end

def process_active_data_segment(id:)
Expand Down Expand Up @@ -595,11 +622,14 @@ def process_unabbreviated_field
read => 'export' | 'start' => kind
rest = repeatedly { read }

after_all_fields do
[
[kind, *rest]
]
end
[
after_all_fields do
[
[kind, *rest]
]
end,
DUMMY_TYPE_DEFINITIONS
]
end

def process_assert_trap
Expand Down

0 comments on commit 370c28a

Please sign in to comment.