Current section

Files

Jump to
orb lib orb global.ex
Raw

lib/orb/global.ex

defmodule Orb.Global do
@moduledoc false
defstruct [:name, :type, :initial_value, :mutability, :exported]
def new(type, name, mutability, exported, value)
when type in [:i32, :f32] and
is_atom(name) and
mutability in ~w[readonly mutable]a and
exported in ~w[internal exported]a do
%__MODULE__{
name: name,
type: type,
initial_value: value,
mutability: mutability,
exported: exported == :exported
}
end
def new32(name, mutability, exported, value)
when is_atom(name) and
mutability in ~w[readonly mutable]a and
exported in ~w[internal exported]a and is_integer(value) do
%__MODULE__{
name: name,
type: :i32,
initial_value: value,
mutability: mutability,
exported: exported == :exported
}
end
def new32(name, mutability, exported, value)
when is_atom(name) and
mutability in ~w[readonly mutable]a and
exported in ~w[internal exported]a and is_float(value) do
%__MODULE__{
name: name,
type: :f32,
initial_value: value,
mutability: mutability,
exported: exported == :exported
}
end
def new32(name, mutability, exported, value)
when is_atom(name) and
mutability in ~w[readonly mutable]a and
exported in ~w[internal exported]a and is_binary(value) do
require Orb
%__MODULE__{
name: name,
type: Orb.I32.String,
initial_value: value,
mutability: mutability,
exported: exported == :exported
}
end
defmacro register32(mutability, exported, list)
defmacro register32(mutability, exported, list) do
# when mutability in ~w{readonly mutable}a and
# exported in ~w[internal exported]a do
quote do
@wasm_globals (for {key, value} <- unquote(list) do
Orb.Global.new32(
key,
unquote(mutability),
unquote(exported),
value
)
end)
end
end
def expand!(%Orb.Global{type: Orb.I32.String, initial_value: ""} = global) do
%Orb.Global{
global
| type: Orb.I32.String,
initial_value: Orb.Constants.NulTerminatedString.empty()
}
end
def expand!(%Orb.Global{type: Orb.I32.String, initial_value: string} = global) do
%Orb.Global{
global
| type: Orb.I32.String,
initial_value: Orb.Constants.expand_if_needed(string)
}
end
def expand!(%Orb.Global{} = global), do: global
defimpl Orb.ToWat do
import Orb.ToWat.Helpers
def to_wat(
%Orb.Global{
name: name,
type: type,
initial_value: initial_value,
mutability: mutability,
exported: exported
},
indent
) do
[
indent,
"(global ",
case exported do
false -> [?$, to_string(name)]
true -> [?$, to_string(name), ~S{ (export "}, to_string(name), ~S{")}]
end,
" ",
case mutability do
:readonly -> do_type(type)
:mutable -> ["(mut ", do_type(type), ?)]
end,
" ",
cond do
is_number(initial_value) ->
["(", do_type(type), ".const ", to_string(initial_value), ")"]
true ->
Orb.ToWat.to_wat(initial_value, "")
end,
")\n"
]
end
end
defmodule Declare do
defmodule ReadonlyDSL do
import Kernel, except: [@: 1]
defmacro @{name, _meta, [arg]} do
quote do
with do
require Orb.Global
Orb.Global.register32(:readonly, :internal, [{unquote(name), unquote(arg)}])
end
end
end
end
defmodule MutableDSL do
import Kernel, except: [@: 1]
defmacro @{name, _meta, [arg]} do
quote do
with do
require Orb.Global
Orb.Global.register32(:mutable, :internal, [{unquote(name), unquote(arg)}])
end
end
end
end
defmodule ExportReadonlyDSL do
import Kernel, except: [@: 1]
defmacro @{name, _meta, [arg]} do
quote do
with do
require Orb.Global
Orb.Global.register32(:readonly, :exported, [{unquote(name), unquote(arg)}])
end
end
end
end
defmodule ExportMutableDSL do
import Kernel, except: [@: 1]
defmacro @{name, _meta, [arg]} do
quote do
with do
require Orb.Global
Orb.Global.register32(:mutable, :exported, [{unquote(name), unquote(arg)}])
end
end
end
end
defmodule DeclareDSL do
import Kernel, except: [@: 1]
defmacro register_global(name, value) do
quote do
with do
require Orb.Global
Orb.Global.register32(
Module.get_last_attribute(__MODULE__, :wasm_global_mutability),
Module.get_last_attribute(__MODULE__, :wasm_global_exported),
[
{unquote(name), unquote(value)}
]
)
end
end
end
defmacro @{name, _meta, [arg]} do
quote do
with do
require Orb.Global
Orb.Global.register32(
Module.get_last_attribute(__MODULE__, :wasm_global_mutability),
Module.get_last_attribute(__MODULE__, :wasm_global_exported),
[
{unquote(name), unquote(arg)}
]
)
end
end
end
end
# defmacro __import_dsl(:readonly, :internal), do: quote(do: import(ReadonlyDSL))
# defmacro __import_dsl(:mutable, :internal), do: quote(do: import(MutableDSL))
# defmacro __import_dsl(:readonly, :exported), do: quote(do: import(ExportReadonlyDSL))
# defmacro __import_dsl(:mutable, :exported), do: quote(do: import(ExportMutableDSL))
defmacro __import_dsl(mutability, exported) do
quote do
import DeclareDSL
Module.put_attribute(__MODULE__, :wasm_global_mutability, unquote(mutability))
Module.put_attribute(__MODULE__, :wasm_global_exported, unquote(exported))
# @wasm_global_mutability unquote(mutability)
# @wasm_global_exported unquote(exported)
end
end
end
defmodule DSL do
@moduledoc """
Adds @global_name support
"""
import Kernel, except: [@: 1]
defmacro @{:@, _meta, [arg]} do
quote do
Kernel.@(unquote(arg))
end
end
# defmacro @{name, meta, _args} do
# if Module.has_attribute?(__CALLER__.module, name) do
# quote do
# Kernel.@(unquote(Macro.var(name, nil)))
# end
# else
# {:global_get, meta, [name]}
# end
# end
defmacro @{name, _meta, _args} do
quote do
Orb.Instruction.global_get(Orb.__lookup_global_type!(unquote(name)), unquote(name))
end
end
end
end