defmodule Egglog.EGraph.Server do
@moduledoc false
use GenServer
alias Egglog.{Common, Native}
def start(opts) do
GenServer.start(__MODULE__, opts)
end
def call(pid, request) when is_pid(pid) do
GenServer.call(pid, request, :infinity)
catch
:exit, _reason -> {:error, {:closed, "egraph session is not available"}}
end
@impl true
def init(opts) do
source = Keyword.fetch!(opts, :source)
proofs? = Keyword.fetch!(opts, :proofs?)
case Native.new_egraph(source, proofs?) |> Common.from_native_load() do
{:ok, ref} -> {:ok, %{ref: ref}}
{:error, reason} -> {:stop, reason}
end
end
@impl true
def handle_call(_request, _from, %{ref: nil} = state) do
{:reply, {:error, {:closed, "egraph session is closed"}}, state}
end
def handle_call({:run, source, snapshot, output_limit}, _from, %{ref: ref} = state) do
result =
ref
|> Native.run_egraph(
source,
snapshot.format,
snapshot.max_functions,
snapshot.max_calls_per_function,
snapshot.inline_leaves,
snapshot.split_primitive_outputs?
)
|> Common.from_native_result(output_limit)
{:reply, result, state}
end
def handle_call({:run_parsed, commands_ref, snapshot, output_limit}, _from, %{ref: ref} = state) do
result =
ref
|> Native.run_parsed_egraph(
commands_ref,
snapshot.format,
snapshot.max_functions,
snapshot.max_calls_per_function,
snapshot.inline_leaves,
snapshot.split_primitive_outputs?
)
|> Common.from_native_result(output_limit)
{:reply, result, state}
end
def handle_call({:eval, expr}, _from, %{ref: ref} = state) do
result =
ref
|> Native.eval_egraph(expr)
|> Common.from_native_value()
{:reply, result, state}
end
def handle_call({:lookup, name, arg_exprs}, _from, %{ref: ref} = state) do
result =
ref
|> Native.lookup_egraph(name, arg_exprs)
|> Common.from_native_lookup()
{:reply, result, state}
end
def handle_call(:num_tuples, _from, %{ref: ref} = state) do
result = ref |> Native.egraph_num_tuples() |> Common.from_native_count()
{:reply, result, state}
end
def handle_call(:close, _from, %{ref: ref} = state) do
result = ref |> Native.close_egraph() |> Common.from_native_close()
{:reply, result, %{state | ref: nil}}
end
end