Current section
Files
Jump to
Current section
Files
lib/pidge/compiler/compile_state.ex
defmodule Pidge.Compiler.CompileState do
use GenServer
# Client API
def start_link(initial_meta), do: GenServer.start_link(__MODULE__, initial_meta, name: __MODULE__)
def stop(pid), do: GenServer.stop(pid, :normal)
# meta
def set_meta(meta), do: GenServer.call(__MODULE__, {:set_meta, meta})
def set_meta_key(key, value), do: GenServer.call(__MODULE__, {:set_meta_key, key, value})
def push_meta_key(key, value), do: GenServer.call(__MODULE__, {:push_meta_key, key, value})
def delete_meta_key(key), do: GenServer.call(__MODULE__, {:delete_meta_key, key})
def get_meta(), do: GenServer.call(__MODULE__, :get_meta)
def get_meta_key(key, default \\ nil) do
case GenServer.call(__MODULE__, {:get_meta_key, key}) do
nil -> default
value -> value
end
end
def shift_meta_key(key), do: GenServer.call(__MODULE__, {:shift_meta_key, key})
# scope
def set_scope_key(key, value) do
keyname =
get_meta_key(:current_scope, [])
|> Enum.join("/")
set_meta_key("scope:#{keyname}", Map.put(get_meta_key("scope:#{keyname}", %{}), key, value))
end
def get_scope_key(key, default \\ nil) do
keyname =
get_meta_key(:current_scope, [])
|> Enum.join("/")
case get_meta_key("scope:#{keyname}", %{}) do
%{} = scope ->
case Map.has_key?(scope, key) do
true -> scope[key]
false -> default
end
nil -> default
end
end
##########################
### Server Callbacks
def init(%{} = initial_meta), do: {:ok, %{meta: initial_meta}}
# meta
def handle_call({:set_meta, %{} = meta}, _from, state), do: {:reply, meta, Map.put(state, :meta, meta)}
def handle_call({:set_meta_key, key, value}, _from, state), do: {:reply, :ok, Map.put(state, :meta, Map.put(state.meta, key, value))}
def handle_call({:push_meta_key, key, value}, _from, state) do
current_state =
case Map.has_key?(state.meta, key) do
true -> Map.get(state.meta, key)
false -> []
end
|> case do
[_|_] = s -> s
[] -> []
s -> raise "Tried to push a non-list meta key: #{inspect(key)} => #{inspect(s)}"
end
{:reply, :ok, Map.put(state, :meta, Map.put(state.meta, key, current_state ++ [value]))}
end
def handle_call({:delete_meta_key, key}, _from, state) do
case Map.has_key?(state.meta, key) do
true -> {:reply, :ok, state |> Map.put(:meta, Map.delete(state.meta, key))}
false -> {:reply, :ok, state}
end
end
def handle_call(:get_meta, _from, state), do: {:reply, state.meta, state}
def handle_call({:get_meta_key, key}, _from, state) do
case Map.has_key?(state.meta, key) do
true -> {:reply, Map.get(state.meta, key), state}
false -> {:reply, nil, state}
end
end
def handle_call({:shift_meta_key, key}, _from, state) do
case Map.has_key?(state.meta, key) do
true ->
case Map.get(state.meta, key) do
[head | tail] ->
{:reply, head, state |> Map.put(:meta, Map.put(state.meta, key, tail))}
[] -> {:reply, nil, state}
end
false -> {:reply, nil, state}
end
end
end