Packages
orb
0.2.0
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/str.ex
defmodule Orb.Str do
@moduledoc """
A string slice. Represented under the hood as a `{:i32, :i32}` tuple, the first element being the base address, and the second element the string length.
"""
defstruct push_type: __MODULE__, memory_offset: nil, string: nil
with @behaviour Orb.CustomType do
@impl Orb.CustomType
def wasm_type, do: {:i32, :i32}
end
@doc """
An empty string, represented by a string slice from offset zero and of zero length.
The ol’ billion-dollar mistake: null.
"""
def empty() do
%__MODULE__{
memory_offset: 0x0,
string: ""
}
end
def to_slice(%__MODULE__{} = str) do
len = byte_size(str.string)
if is_integer(str.memory_offset) do
Orb.Memory.Slice.from(str.memory_offset, len)
else
Orb.Memory.Slice.from(str.memory_offset, Orb.Instruction.Const.new(:i32, len))
end
end
def to_slice(string) when is_binary(string) do
string |> Orb.Constants.expand_if_needed() |> to_slice()
end
def get_base_address(string) when is_binary(string) do
str = string |> Orb.Constants.expand_if_needed()
str.memory_offset
end
# with @behaviour Access do
# @impl Access
# def fetch(%VariableReference{} = var_ref, :ptr) do
# ast = %Orb.VariableReference.Local{
# identifier:
# }
# {:ok, ast}
# end
#
# @impl Access
# def get_and_update(_data, _key, _function) do
# raise UndefinedFunctionError, module: __MODULE__, function: :get_and_update, arity: 3
# end
#
# @impl Access
# def pop(_data, _key) do
# raise UndefinedFunctionError, module: __MODULE__, function: :pop, arity: 2
# end
# end
defimpl Orb.ToWat do
def to_wat(
%Orb.Str{memory_offset: memory_offset, string: string},
indent
) do
[
indent,
Orb.Instruction.Const.new(:i32, memory_offset)
|> Orb.ToWat.to_wat(""),
" ",
Orb.Instruction.Const.new(:i32, byte_size(string))
|> Orb.ToWat.to_wat("")
]
end
end
defimpl Orb.ToWasm do
def to_wasm(
%Orb.Str{memory_offset: memory_offset, string: string},
context
) do
[
Orb.Instruction.Const.new(:i32, memory_offset)
|> Orb.ToWasm.to_wasm(context),
Orb.Instruction.Const.new(:i32, byte_size(string))
|> Orb.ToWasm.to_wasm(context)
]
end
end
defmodule Slice do
@moduledoc """
A string slice represented as a i64, a compromise for when storing strings as globals (Globals cannot be `(i32 i32)`, only single primitives like `i32` or `i64`).
"""
defstruct push_type: __MODULE__, slice64: nil
def to_str(str_slice) do
{
Orb.I32.wrap_i64(str_slice),
str_slice |> Orb.I64.shr_u(32) |> Orb.I32.wrap_i64()
}
end
with @behaviour Orb.CustomType do
@impl Orb.CustomType
def wasm_type, do: :i64
end
defimpl Orb.ToWat do
def to_wat(%Orb.Str.Slice{slice64: slice64}, indent) do
Orb.Instruction.Const.new(:i64, slice64)
|> Orb.ToWat.to_wat(indent)
end
end
end
end