Phases 1-7: Complete CljElixir compiler through Malli schema adapter
Bootstrap compiler (reader, analyzer, transformer, compiler, Mix plugin), core protocols (16 protocols for Map/List/Tuple/BitString), PersistentVector (bit-partitioned trie), domain tools (clojurify/elixirify), BEAM concurrency (receive, spawn, GenServer), control flow & macros (threading, try/catch, destructuring, defmacro with quasiquote/auto-gensym), and Malli schema adapter (m/=> specs, auto @type, recursive schemas, cross-references). 537 compiler tests + 55 Malli unit tests + 15 integration tests = 607 total. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
defmodule CljElixir.Equality do
|
||||
@moduledoc """
|
||||
Cross-type equality for CljElixir.
|
||||
|
||||
Handles the case where `(= [1 2 3] '(1 2 3))` should return true —
|
||||
PersistentVector and list are both sequential types with the same elements.
|
||||
"""
|
||||
|
||||
def equiv(a, b) when a === b, do: true
|
||||
|
||||
def equiv(%CljElixir.PersistentVector{} = a, %CljElixir.PersistentVector{} = b) do
|
||||
a.cnt == b.cnt and CljElixir.PersistentVector.to_list(a) == CljElixir.PersistentVector.to_list(b)
|
||||
end
|
||||
|
||||
def equiv(%CljElixir.PersistentVector{} = a, b) when is_list(b) do
|
||||
CljElixir.PersistentVector.to_list(a) == b
|
||||
end
|
||||
|
||||
def equiv(a, %CljElixir.PersistentVector{} = b) when is_list(a) do
|
||||
a == CljElixir.PersistentVector.to_list(b)
|
||||
end
|
||||
|
||||
def equiv(%CljElixir.SubVector{} = a, b) do
|
||||
CljElixir.SubVector.sv_to_list(a) |> equiv_list(b)
|
||||
end
|
||||
|
||||
def equiv(a, %CljElixir.SubVector{} = b) do
|
||||
equiv_list(CljElixir.SubVector.sv_to_list(b), a)
|
||||
end
|
||||
|
||||
def equiv(a, b), do: a == b
|
||||
|
||||
defp equiv_list(list, other) when is_list(other), do: list == other
|
||||
|
||||
defp equiv_list(list, %CljElixir.PersistentVector{} = pv) do
|
||||
list == CljElixir.PersistentVector.to_list(pv)
|
||||
end
|
||||
|
||||
defp equiv_list(_, _), do: false
|
||||
end
|
||||
|
||||
defimpl Enumerable, for: CljElixir.PersistentVector do
|
||||
def count(pv), do: {:ok, pv.cnt}
|
||||
|
||||
def member?(_pv, _value), do: {:error, __MODULE__}
|
||||
|
||||
def reduce(_pv, {:halt, acc}, _fun), do: {:halted, acc}
|
||||
def reduce(pv, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(pv, &1, fun)}
|
||||
|
||||
def reduce(pv, {:cont, acc}, fun) do
|
||||
list = CljElixir.PersistentVector.to_list(pv)
|
||||
Enumerable.List.reduce(list, {:cont, acc}, fun)
|
||||
end
|
||||
|
||||
def slice(pv) do
|
||||
size = pv.cnt
|
||||
{:ok, size, &slice_fun(pv, &1, &2, &3)}
|
||||
end
|
||||
|
||||
defp slice_fun(pv, start, length, step) do
|
||||
start..(start + (length - 1) * step)//step
|
||||
|> Enum.map(fn i -> CljElixir.PersistentVector.pv_nth(pv, i) end)
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Collectable, for: CljElixir.PersistentVector do
|
||||
def into(pv) do
|
||||
collector_fun = fn
|
||||
acc, {:cont, elem} -> CljElixir.PersistentVector.pv_conj(acc, elem)
|
||||
acc, :done -> acc
|
||||
_acc, :halt -> :ok
|
||||
end
|
||||
|
||||
{pv, collector_fun}
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Enumerable, for: Tuple do
|
||||
def count(t), do: {:ok, tuple_size(t)}
|
||||
|
||||
def member?(_t, _value), do: {:error, __MODULE__}
|
||||
|
||||
def reduce(_t, {:halt, acc}, _fun), do: {:halted, acc}
|
||||
def reduce(t, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(t, &1, fun)}
|
||||
|
||||
def reduce(t, {:cont, acc}, fun) do
|
||||
list = Tuple.to_list(t)
|
||||
Enumerable.List.reduce(list, {:cont, acc}, fun)
|
||||
end
|
||||
|
||||
def slice(t) do
|
||||
size = tuple_size(t)
|
||||
{:ok, size, &slice_fun(t, &1, &2, &3)}
|
||||
end
|
||||
|
||||
defp slice_fun(t, start, length, step) do
|
||||
start..(start + (length - 1) * step)//step
|
||||
|> Enum.map(fn i -> elem(t, i) end)
|
||||
end
|
||||
end
|
||||
|
||||
defimpl Collectable, for: Tuple do
|
||||
def into(t) do
|
||||
collector_fun = fn
|
||||
acc, {:cont, elem} -> :erlang.append_element(acc, elem)
|
||||
acc, :done -> acc
|
||||
_acc, :halt -> :ok
|
||||
end
|
||||
|
||||
{t, collector_fun}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user