Packages
orb
0.0.24
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
0.0.51
0.0.49
0.0.48
0.0.47
0.0.46
0.0.45
0.0.44
0.0.43
0.0.42
0.0.41
0.0.40
0.0.39
0.0.38
0.0.37
0.0.36
0.0.35
0.0.34
0.0.33
0.0.32
0.0.31
0.0.30
0.0.28
0.0.27
0.0.26
0.0.25
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
retired
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
DSL for WebAssembly
Current section
Files
Jump to
Current section
Files
lib/orb/module_definition.ex
defmodule Orb.ModuleDefinition do
@moduledoc false
defstruct name: nil,
types: [],
table_size: 0,
imports: [],
globals: [],
memory: nil,
constants: %Orb.Constants{},
body: []
@doc false
def expand_body_func_refs(body) do
{func_refs, other} = Enum.split_with(body, &match?({:mod_func_ref, _, _}, &1))
func_refs =
func_refs
|> Enum.uniq()
|> Enum.map(&resolve_func_ref/1)
|> List.flatten()
|> Enum.uniq_by(fn func -> {func.source_module, func.name} end)
body = func_refs ++ other
body
end
def expand_body_func_constants(body) do
body
|> Enum.map(fn
%Orb.Func{} = f ->
Orb.Func.expand(f)
other ->
other
end)
end
def new(options) do
struct!(__MODULE__, options)
end
defp resolve_func_ref({:mod_func_ref, visiblity, {mod, name}}) do
fetch_func!(Orb.Compiler.get_body_of(mod), visiblity, mod, name)
end
defp resolve_func_ref({:mod_func_ref, visiblity, mod}) when is_atom(mod) do
fetch_func!(Orb.Compiler.get_body_of(mod), visiblity, mod)
end
defmodule FetchFuncError do
defexception [:func_name, :source_module]
@impl true
def message(%{func_name: func_name, source_module: source_module}) do
"funcp #{func_name} not found in #{source_module}"
end
end
def fetch_func!(body, visibility, source_module) when is_list(body) do
body = List.flatten(body)
exported? = visibility == :exported
funcs =
Enum.flat_map(body, fn
%Orb.Func{} = func ->
[
%{
func
| exported_names: if(exported?, do: [func.name], else: []),
source_module: func.source_module || source_module
}
]
_ ->
[]
end)
funcs
end
def fetch_func!(body, visibility, source_module, name) when is_list(body) do
body = List.flatten(body)
exported? = visibility == :exported
# func = Enum.find(body, &match?(%Orb.Func{name: ^name}, &1))
func =
Enum.find_value(body, fn
%Orb.Func{name: ^name} = func ->
%{
func
| exported_names: if(exported?, do: [func.name], else: []),
source_module: func.source_module || source_module
}
_ ->
false
end)
func || raise FetchFuncError, func_name: name, source_module: source_module
end
def func_ref!(mod, name) when is_atom(mod) do
# TODO: convert to struct
{:mod_func_ref, :exported, {mod, name}}
end
def func_ref_all!(mod) when is_atom(mod) do
{:mod_func_ref, :exported, mod}
end
def funcp_ref!(mod, name) when is_atom(mod) do
{:mod_func_ref, :internal, {mod, name}}
end
def funcp_ref_all!(mod) when is_atom(mod) do
{:mod_func_ref, :internal, mod}
end
defimpl Orb.ToWat do
alias Orb.ToWat.Instructions
def to_wat(
%Orb.ModuleDefinition{
name: name,
types: types,
table_size: table_size,
imports: imports,
globals: globals,
memory: memory,
constants: constants,
body: body
},
indent
) do
next_indent = " " <> indent
[
[indent, "(module $#{name}", "\n"],
[for(type <- types, do: [Orb.ToWat.to_wat(type, next_indent), "\n"])],
[for(import_def <- imports, do: [Instructions.do_wat(import_def, next_indent), "\n"])],
case table_size do
0 -> []
n -> [next_indent, "(table ", to_string(n), " funcref)\n"]
end,
case memory do
nil ->
[]
%Orb.Memory{} ->
Orb.ToWat.to_wat(memory, next_indent)
end,
for global = %Orb.Global{} <- globals do
Orb.ToWat.to_wat(global, next_indent)
end,
Orb.ToWat.to_wat(constants, next_indent),
for statement <- List.flatten(body) do
Orb.ToWat.to_wat(statement, next_indent)
end,
[indent, ")", "\n"]
]
end
end
end