diff --git a/lib/orb/ops.ex b/lib/orb/ops.ex index 26100bd..a59d17d 100644 --- a/lib/orb/ops.ex +++ b/lib/orb/ops.ex @@ -58,6 +58,11 @@ defmodule Orb.Ops do Orb.CustomType.resolve!(mod) |> to_primitive_type() end + def type_stack_count(type) when is_primitive_type(type), do: 1 + def type_stack_count(type) when is_effect(type), do: 0 + def type_stack_count(type) when is_atom(type), do: 1 + def type_stack_count(type) when is_tuple(type), do: tuple_size(type) + def types_compatible?(Elixir.Integer, b), do: to_primitive_type(b) in @integer_types diff --git a/lib/orb/stack.ex b/lib/orb/stack.ex new file mode 100644 index 0000000..204cf6c --- /dev/null +++ b/lib/orb/stack.ex @@ -0,0 +1,42 @@ +defmodule Orb.Stack do + @moduledoc false + + defmodule Drop do + defstruct instruction: nil, count: 0 + + require alias Orb.Ops + + def new(%{type: type} = instruction) do + count = Ops.typeof(instruction) |> Ops.type_stack_count() + + %__MODULE__{ + instruction: instruction, + count: count + } + end + + def new(value) when is_number(value) do + %__MODULE__{ + instruction: value, + count: 1 + } + end + + defimpl Orb.ToWat do + def to_wat( + %Orb.Stack.Drop{instruction: instruction, count: count}, + indent + ) do + [ + Orb.ToWat.to_wat(instruction, indent), + "\n", + for _ <- 1..count do + [indent, "drop", "\n"] + end + ] + end + end + end + + def drop(instruction), do: Drop.new(instruction) +end