Current section
Files
Jump to
Current section
Files
lib/corsa/stack.ex
defmodule Corsa.Stack do
@moduledoc false
@typep id() :: {module(), atom(), non_neg_integer()}
@spec new(id()) :: :ok
defp new(function) do
id = to_id(function)
if :ets.info(id) == :undefined do
:ets.new(id, [:ordered_set, :private, :named_table])
:ets.insert(id, {"size", 0})
end
:ok
end
@spec push(id(), [any()]) :: :ok
def push(function, args) do
id = to_id(function)
if :ets.info(id) == :undefined do
new(function)
push(function, args)
else
[{_, size}] = :ets.lookup(id, "size")
:ets.insert(id, {size, args})
:ets.insert(id, {"size", size + 1})
:ok
end
end
@spec peek(id) :: :empty | [any()]
def peek(function) do
id = to_id(function)
info = :ets.info(id)
cond do
info == :undefined ->
new(function)
peek(function)
Keyword.get(info, :size) == 1 ->
:empty
true ->
[{_, size}] = :ets.lookup(id, "size")
[{_, args}] = :ets.lookup(id, size - 1)
args
end
end
@spec pop(id) :: :empty | [any()]
def pop(function) do
id = to_id(function)
info = :ets.info(id)
cond do
info == :undefined ->
new(function)
Keyword.get(info, :size) == 1 ->
:empty
true ->
[{_, size}] = :ets.lookup(id, "size")
[{_, args}] = :ets.lookup(id, size - 1)
:ets.delete(id, size - 1)
:ets.insert(id, {"size", size - 1})
args
end
end
@spec flush(id) :: :ok
def flush(function) do
id = to_id(function)
info = :ets.info(id)
if info == :undefined do
:ok
else
:ets.delete(id)
end
end
@spec empty?(id) :: boolean()
def empty?(function), do: peek(function) == :empty
@spec to_id(id) :: atom()
defp to_id({m, f, a}), do: :"#{m}.#{f}/#{a}"
end