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,133 @@
|
||||
defmodule CljElixir.Phase5Test do
|
||||
use ExUnit.Case, async: false
|
||||
|
||||
# Helper to compile and evaluate CljElixir code
|
||||
defp eval!(source) do
|
||||
case CljElixir.Compiler.eval_string(source) do
|
||||
{:ok, result, _bindings} -> result
|
||||
{:error, errors} -> raise "CljElixir eval error: #{inspect(errors)}"
|
||||
end
|
||||
end
|
||||
|
||||
# ==========================================================================
|
||||
# GenServer integration
|
||||
# ==========================================================================
|
||||
|
||||
describe "GenServer - simple counter" do
|
||||
test "define and use a counter GenServer" do
|
||||
eval!("""
|
||||
(defmodule TestCounter
|
||||
(use GenServer)
|
||||
|
||||
(defn init [initial]
|
||||
#el[:ok initial])
|
||||
|
||||
(defn handle-call
|
||||
([:get _from state]
|
||||
#el[:reply state state])
|
||||
([:increment _from state]
|
||||
#el[:reply :ok (+ state 1)])))
|
||||
""")
|
||||
|
||||
{:ok, pid} = GenServer.start_link(TestCounter, 0)
|
||||
assert GenServer.call(pid, :get) == 0
|
||||
assert GenServer.call(pid, :increment) == :ok
|
||||
assert GenServer.call(pid, :get) == 1
|
||||
GenServer.stop(pid)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GenServer - handle_cast" do
|
||||
test "cast resets state" do
|
||||
eval!("""
|
||||
(defmodule TestCaster
|
||||
(use GenServer)
|
||||
|
||||
(defn init [initial]
|
||||
#el[:ok initial])
|
||||
|
||||
(defn handle-call
|
||||
([:get _from state]
|
||||
#el[:reply state state]))
|
||||
|
||||
(defn handle-cast
|
||||
([:reset _state]
|
||||
#el[:noreply 0])))
|
||||
""")
|
||||
|
||||
{:ok, pid} = GenServer.start_link(TestCaster, 42)
|
||||
assert GenServer.call(pid, :get) == 42
|
||||
GenServer.cast(pid, :reset)
|
||||
Process.sleep(50)
|
||||
assert GenServer.call(pid, :get) == 0
|
||||
GenServer.stop(pid)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GenServer - handle_info" do
|
||||
test "handle-info receives plain messages" do
|
||||
eval!("""
|
||||
(defmodule TestInfoHandler
|
||||
(use GenServer)
|
||||
|
||||
(defn init [initial]
|
||||
#el[:ok initial])
|
||||
|
||||
(defn handle-call
|
||||
([:get _from state]
|
||||
#el[:reply state state]))
|
||||
|
||||
(defn handle-info
|
||||
([:bump state]
|
||||
#el[:noreply (+ state 1)])))
|
||||
""")
|
||||
|
||||
{:ok, pid} = GenServer.start_link(TestInfoHandler, 0)
|
||||
send(pid, :bump)
|
||||
Process.sleep(50)
|
||||
assert GenServer.call(pid, :get) == 1
|
||||
GenServer.stop(pid)
|
||||
end
|
||||
end
|
||||
|
||||
# ==========================================================================
|
||||
# ChatRoom pattern: spawn + send + receive loop
|
||||
# ==========================================================================
|
||||
|
||||
describe "ChatRoom pattern" do
|
||||
test "spawn + send + receive loop" do
|
||||
eval!("""
|
||||
(defmodule TestChatLoop
|
||||
(defn loop [state]
|
||||
(receive
|
||||
[:ping pid]
|
||||
(do
|
||||
(send pid #el[:pong state])
|
||||
(TestChatLoop/loop (+ state 1)))
|
||||
[:get pid]
|
||||
(do
|
||||
(send pid #el[:count state])
|
||||
(TestChatLoop/loop state))
|
||||
:stop
|
||||
:stopped
|
||||
:after 5000
|
||||
:timeout)))
|
||||
""")
|
||||
|
||||
pid = spawn(fn -> TestChatLoop.loop(0) end)
|
||||
|
||||
send(pid, {:ping, self()})
|
||||
assert_receive {:pong, 0}, 1000
|
||||
|
||||
send(pid, {:ping, self()})
|
||||
assert_receive {:pong, 1}, 1000
|
||||
|
||||
send(pid, {:get, self()})
|
||||
assert_receive {:count, 2}, 1000
|
||||
|
||||
send(pid, :stop)
|
||||
Process.sleep(50)
|
||||
refute Process.alive?(pid)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user