Packages
orb
0.0.5
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,
imports: [],
memory: nil,
globals: [],
body: []
def new(options) do
{body, options} = Keyword.pop(options, :body)
{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
fields = Keyword.put(options, :body, body)
struct!(__MODULE__, fields)
end
defp resolve_func_ref({:mod_func_ref, visiblity, {mod, name}}) do
fetch_func!(mod.__wasm_module__(), visiblity, mod, name)
end
defp resolve_func_ref({:mod_func_ref, visiblity, mod}) when is_atom(mod) do
fetch_func!(mod.__wasm_module__(), visiblity, mod)
end
defmodule FetchFuncError do
defexception [:func_name, :module_definition]
@impl true
def message(%{func_name: func_name, module_definition: module_definition}) do
"funcp #{func_name} not found in #{module_definition.name} #{inspect(module_definition.body)}"
end
end
def fetch_func!(%__MODULE__{body: body} = module_definition, visibility, source_module) do
body = List.flatten(body)
exported? = visibility == :exported
funcs =
Enum.flat_map(body, fn
%Orb.Func{} = func ->
[%{func | exported?: exported?, source_module: func.source_module || source_module}]
_ ->
[]
end)
funcs
end
def fetch_func!(%__MODULE__{body: body} = module_definition, visibility, source_module, name) 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?: exported?, source_module: func.source_module || source_module}
_ ->
false
end)
func || raise FetchFuncError, func_name: name, module_definition: module_definition
end
def func_ref!(mod, name) when is_atom(mod) do
{: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,
imports: imports,
globals: globals,
memory: memory,
body: body
},
indent
) do
[
[indent, "(module $#{name}", "\n"],
[for(import_def <- imports, do: [Instructions.do_wat(import_def, " " <> indent), "\n"])],
case memory do
nil ->
[]
%Orb.Memory{} ->
Orb.ToWat.to_wat(memory, " " <> indent)
end,
for global = %Orb.Global{} <- globals do
Orb.ToWat.to_wat(global, " " <> indent)
end,
case body do
[] ->
""
body ->
[indent, Instructions.do_wat(body, " " <> indent), "\n"]
end,
[indent, ")", "\n"]
]
end
end
end