Packages

An experimental work-in-progress (WIP) WebAssembly runtime written in Gleam.

Current section

Files

Jump to
gwr src gwr@parser@binary_parser.erl
Raw

src/gwr@parser@binary_parser.erl

-module(gwr@parser@binary_parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([parse_locals_declaration/1, parse_function_code/1, parse_code/1, parse_section/1, parse_binary_module/1]).
-spec parse_locals_declaration(gwr@parser@binary_reader:binary_reader()) -> {ok,
{gwr@parser@binary_reader:binary_reader(),
gwr@binary:locals_declaration()}} |
{error, binary()}.
parse_locals_declaration(Reader) ->
gleam@result:'try'(
gwr@parser@value_parser:parse_unsigned_leb128_integer(Reader),
fun(_use0) ->
{Reader@1, Count} = _use0,
gleam@result:'try'(
gwr@parser@types_parser:parse_value_type(Reader@1),
fun(_use0@1) ->
{Reader@2, Value_type} = _use0@1,
{ok, {Reader@2, {locals_declaration, Count, Value_type}}}
end
)
end
).
-spec parse_function_code(gwr@parser@binary_reader:binary_reader()) -> {ok,
{gwr@parser@binary_reader:binary_reader(), gwr@binary:function_code()}} |
{error, binary()}.
parse_function_code(Reader) ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader,
fun parse_locals_declaration/1
),
fun(_use0) ->
{Reader@1, Locals_declaration} = _use0,
gleam@result:'try'(
gwr@parser@instruction_parser:parse_expression(Reader@1),
fun(_use0@1) ->
{Reader@2, Expression} = _use0@1,
{ok,
{Reader@2,
{function_code, Locals_declaration, Expression}}}
end
)
end
).
-spec parse_code(gwr@parser@binary_reader:binary_reader()) -> {ok,
{gwr@parser@binary_reader:binary_reader(), gwr@binary:code()}} |
{error, binary()}.
parse_code(Reader) ->
gleam@result:'try'(
gwr@parser@value_parser:parse_unsigned_leb128_integer(Reader),
fun(_use0) ->
{Reader@1, Size} = _use0,
gleam@result:'try'(
parse_function_code(Reader@1),
fun(_use0@1) ->
{Reader@2, Function_code} = _use0@1,
{ok, {Reader@2, {code, Size, Function_code}}}
end
)
end
).
-spec parse_section(gwr@parser@binary_reader:binary_reader()) -> {ok,
{gwr@parser@binary_reader:binary_reader(), gwr@binary:section()}} |
{error, binary()}.
parse_section(Reader) ->
gleam@result:'try'(case gwr@parser@binary_reader:read(Reader, 1) of
{ok, {Reader@1, <<Section_type_id>>}} ->
{ok, {Reader@1, Section_type_id}};
_ ->
{error,
<<"gwr/parser/binary_parser.parse_section: can't get section type id raw data"/utf8>>}
end, fun(_use0) ->
{Reader@2, Section_type_id@1} = _use0,
gleam@result:'try'(
gwr@parser@value_parser:parse_unsigned_leb128_integer(Reader@2),
fun(_use0@1) ->
{Reader@3, Section_length} = _use0@1,
gleam@result:'try'(
gwr@parser@binary_reader:get_remaining(Reader@3),
fun(Remaining_data) ->
Remaining_data_length = erlang:byte_size(
Remaining_data
),
gleam@bool:guard(
Section_length > Remaining_data_length,
{error,
<<<<<<<<"gwr/parser/binary_parser.parse_section: unexpected end of the section's content segment. Expected "/utf8,
(gleam@int:to_string(
Section_length
))/binary>>/binary,
" bytes but got "/utf8>>/binary,
(gleam@int:to_string(
Remaining_data_length
))/binary>>/binary,
" bytes"/utf8>>},
fun() ->
gleam@result:'try'(
case {gwr@parser@binary_reader:can_read(
Reader@3
),
Section_type_id@1} of
{true, Id} when Id =:= 16#00 ->
gleam@result:'try'(
gwr@parser@value_parser:parse_name(
Reader@3
),
fun(_use0@2) ->
{Reader@4,
Custom_section_name} = _use0@2,
gleam@result:'try'(
gwr@parser@binary_reader:read_remaining(
Reader@4
),
fun(_use0@3) ->
{Reader@5,
Custom_section_data} = _use0@3,
{ok,
{Reader@5,
{section,
16#00,
Section_length,
{some,
{custom_section,
Custom_section_name,
{some,
Custom_section_data}}}}}}
end
)
end
);
{true, Id@1} when Id@1 =:= 16#01 ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader@3,
fun gwr@parser@types_parser:parse_function_type/1
),
fun(_use0@4) ->
{Reader@6,
Function_types_vec} = _use0@4,
{ok,
{Reader@6,
{section,
16#01,
Section_length,
{some,
{type_section,
Function_types_vec}}}}}
end
);
{true, Id@2} when Id@2 =:= 16#03 ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader@3,
fun(Reader@7) ->
gleam@result:'try'(
gwr@parser@value_parser:parse_unsigned_leb128_integer(
Reader@7
),
fun(_use0@5) ->
{Reader@8,
Index} = _use0@5,
{ok,
{Reader@8,
Index}}
end
)
end
),
fun(_use0@6) ->
{Reader@9, Indices_vec} = _use0@6,
{ok,
{Reader@9,
{section,
16#03,
Section_length,
{some,
{function_section,
Indices_vec}}}}}
end
);
{true, Id@3} when Id@3 =:= 16#05 ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader@3,
fun gwr@parser@module_parser:parse_memory/1
),
fun(_use0@7) ->
{Reader@10, Mem_vec} = _use0@7,
{ok,
{Reader@10,
{section,
16#05,
Section_length,
{some,
{memory_section,
Mem_vec}}}}}
end
);
{true, Id@4} when Id@4 =:= 16#06 ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader@3,
fun gwr@parser@module_parser:parse_global/1
),
fun(_use0@8) ->
{Reader@11, Globals_vec} = _use0@8,
{ok,
{Reader@11,
{section,
16#06,
Section_length,
{some,
{global_section,
Globals_vec}}}}}
end
);
{true, Id@5} when Id@5 =:= 16#07 ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader@3,
fun gwr@parser@module_parser:parse_export/1
),
fun(_use0@9) ->
{Reader@12, Exports_vec} = _use0@9,
{ok,
{Reader@12,
{section,
16#07,
Section_length,
{some,
{export_section,
Exports_vec}}}}}
end
);
{true, Id@6} when Id@6 =:= 16#0a ->
gleam@result:'try'(
gwr@parser@convention_parser:parse_vector(
Reader@3,
fun parse_code/1
),
fun(_use0@10) ->
{Reader@13, Codes_vec} = _use0@10,
{ok,
{Reader@13,
{section,
16#0a,
Section_length,
{some,
{code_section,
Codes_vec}}}}}
end
);
{false, Id@7} when Id@7 =:= 16#00 ->
{ok,
{Reader@3,
{section,
16#00,
Section_length,
none}}};
{false, Id@8} when Id@8 =:= 16#01 ->
{ok,
{Reader@3,
{section,
16#01,
Section_length,
none}}};
{false, Id@9} when Id@9 =:= 16#03 ->
{ok,
{Reader@3,
{section,
16#03,
Section_length,
none}}};
{false, Id@10} when Id@10 =:= 16#05 ->
{ok,
{Reader@3,
{section,
16#05,
Section_length,
none}}};
{false, Id@11} when Id@11 =:= 16#07 ->
{ok,
{Reader@3,
{section,
16#07,
Section_length,
none}}};
{false, Id@12} when Id@12 =:= 16#0a ->
{ok,
{Reader@3,
{section,
16#0a,
Section_length,
none}}};
{_, _} ->
{error,
<<<<"gwr/parser/binary_parser.parse_section: unknown section type id \""/utf8,
(gleam@int:to_string(
Section_type_id@1
))/binary>>/binary,
"\""/utf8>>}
end,
fun(_use0@11) ->
{Reader@14, Decoded_dection} = _use0@11,
{ok, {Reader@14, Decoded_dection}}
end
)
end
)
end
)
end
)
end).
-spec parse_binary_module(gwr@parser@binary_reader:binary_reader()) -> {ok,
{gwr@parser@binary_reader:binary_reader(), gwr@binary:binary_()}} |
{error, binary()}.
parse_binary_module(Reader) ->
gleam@bool:guard(
gwr@parser@binary_reader:is_empty(Reader),
{error,
<<"gwr/parser/binary_parser.parse_binary_module: empty data"/utf8>>},
fun() ->
{Reader@3, Found_magic_number} = case gwr@parser@binary_reader:read(
Reader,
4
) of
{ok, {Reader@1, <<16#00, 16#61, 16#73, 16#6d>>}} ->
{Reader@1, true};
{ok, {Reader@2, _}} ->
{Reader@2, false};
{error, _} ->
{Reader, false}
end,
gleam@bool:guard(
not Found_magic_number,
{error,
<<"gwr/parser/binary_parser.parse_binary_module: couldn't find module's magic number"/utf8>>},
fun() ->
gleam@result:'try'(
case gwr@parser@binary_reader:read(Reader@3, 4) of
{ok, {Reader@4, <<Version:32/unsigned-little>>}} ->
{ok, {Reader@4, Version}};
_ ->
{error,
<<"gwr/parser/binary_parser.parse_binary_module: couldn't find module version"/utf8>>}
end,
fun(_use0) ->
{Reader@5, Module_wasm_version} = _use0,
Empty_module = {module,
[],
[],
[],
[],
[],
[],
[],
none,
[],
[]},
gleam@result:'try'(
gleam@iterator:fold(
gleam@iterator:range(16#00, 16#0c),
{ok, {Reader@5, Empty_module, []}},
fun(State, _) ->
gleam@result:'try'(
State,
fun(_use0@1) ->
{Reader@6,
Module,
Function_section_type_indices} = _use0@1,
gleam@bool:guard(
not gwr@parser@binary_reader:can_read(
Reader@6
),
State,
fun() ->
gleam@result:'try'(
parse_section(
Reader@6
),
fun(_use0@2) ->
{Reader@7,
Section} = _use0@2,
gleam@result:'try'(
case erlang:element(
4,
Section
) of
none ->
{ok,
{Module,
Function_section_type_indices}};
{some,
Content} ->
case Content of
{custom_section,
_,
_} ->
{ok,
{Module,
Function_section_type_indices}};
{type_section,
Function_types} ->
{ok,
{erlang:setelement(
2,
Module,
Function_types
),
Function_section_type_indices}};
import_section ->
{ok,
{Module,
Function_section_type_indices}};
{function_section,
Type_indices_list} ->
{ok,
{Module,
Type_indices_list}};
table_section ->
{ok,
{Module,
Function_section_type_indices}};
{memory_section,
Memories_list} ->
{ok,
{erlang:setelement(
5,
Module,
Memories_list
),
Function_section_type_indices}};
{global_section,
Globals_list} ->
{ok,
{erlang:setelement(
6,
Module,
Globals_list
),
Function_section_type_indices}};
{export_section,
Exports_list} ->
{ok,
{erlang:setelement(
11,
Module,
Exports_list
),
Function_section_type_indices}};
{start_section,
Start_function} ->
{ok,
{erlang:setelement(
9,
Module,
{some,
Start_function}
),
Function_section_type_indices}};
element_section ->
{ok,
{Module,
Function_section_type_indices}};
{code_section,
Code_entries} ->
gleam@result:'try'(
gleam@list:index_fold(
Code_entries,
{ok,
[]},
fun(
Function_list,
Entry,
Index
) ->
gleam@result:'try'(
Function_list,
fun(
Function_list@1
) ->
case begin
_pipe = Function_section_type_indices,
_pipe@1 = gleam@list:take(
_pipe,
Index
+ 1
),
gleam@list:last(
_pipe@1
)
end of
{ok,
Function_type_index} ->
Function = {function,
Function_type_index,
gleam@list:map(
erlang:element(
2,
erlang:element(
3,
Entry
)
),
fun(
Lc
) ->
erlang:element(
3,
Lc
)
end
),
erlang:element(
3,
erlang:element(
3,
Entry
)
)},
{ok,
lists:append(
Function_list@1,
[Function]
)};
{error,
_} ->
{error,
<<"gwr/parser/binary_parser.parse_binary_module: couldn't find type index "/utf8,
(gleam@int:to_string(
Index
))/binary>>}
end
end
)
end
),
fun(
Function_list@2
) ->
{ok,
{erlang:setelement(
3,
Module,
Function_list@2
),
Function_section_type_indices}}
end
);
data_section ->
{ok,
{Module,
Function_section_type_indices}};
data_count_section ->
{ok,
{Module,
Function_section_type_indices}}
end
end,
fun(_use0@3) ->
{Module@1,
Function_section_type_indices@1} = _use0@3,
{ok,
{Reader@7,
Module@1,
Function_section_type_indices@1}}
end
)
end
)
end
)
end
)
end
),
fun(_use0@4) ->
{Reader@8, Filled_module, _} = _use0@4,
{ok,
{Reader@8,
{binary,
Module_wasm_version,
gwr@parser@binary_reader:bytes_read(
Reader@8
),
Filled_module}}}
end
)
end
)
end
)
end
).