elipl/test/tilly/bdd_test.exs
Kacper Marzecki 748f87636a checkpoint
checkpoint

failing test

after fixing tests

checkpoint

checkpoint

checkpoint

re-work

asd

checkpoint

checkpoint

checkpoint

mix proj

checkpoint mix

first parser impl

checkpoint

fix tests

re-org parser

checkpoint strings

fix multiline strings

tuples

checkpoint maps

checkpoint

checkpoint

checkpoint

checkpoint

fix weird eof expression parse error

checkpoint before typing

checkpoint

checpoint

checkpoint

checkpoint

checkpoint ids in primitive types

checkpoint

checkpoint

fix tests

initial annotation

checkpoint

checkpoint

checkpoint

union subtyping

conventions

refactor - split typer

typing tuples

checkpoint test refactor

checkpoint test refactor

parsing atoms

checkpoint atoms

wip lists

checkpoint typing lists

checkopint

checkpoint

wip fixing

correct list typing

map discussion

checkpoint map basic typing

fix tests checkpoint

checkpoint

checkpoint

checkpoint

fix condition typing

fix literal keys in map types

checkpoint union types

checkpoint union type

checkpoint row types discussion & bidirectional typecheck

checkpoint

basic lambdas

checkpoint lambdas typing application

wip function application

checkpoint

checkpoint

checkpoint cduce

checkpoint

checkpoint

checkpoint

checkpoint

checkpoint

checkpoint

checkpoint
2025-06-13 23:48:07 +02:00

164 lines
6.9 KiB
Elixir

defmodule Tilly.BDDTest do
use ExUnit.Case, async: true
alias Tilly.BDD.Node
describe "init_bdd_store/1" do
test "initializes bdd_store in typing_ctx with predefined false and true nodes" do
typing_ctx = %{}
new_ctx = Tilly.BDD.init_bdd_store(typing_ctx)
assert %{bdd_store: bdd_store} = new_ctx
assert is_map(bdd_store.nodes_by_structure)
assert is_map(bdd_store.structures_by_id)
assert bdd_store.next_node_id == 2 # 0 for false, 1 for true
assert bdd_store.ops_cache == %{}
# Check false node
false_id = Tilly.BDD.false_node_id()
false_ops_module = Tilly.BDD.universal_ops_module()
assert bdd_store.nodes_by_structure[{Node.mk_false(), false_ops_module}] == false_id
assert bdd_store.structures_by_id[false_id] == %{structure: Node.mk_false(), ops_module: false_ops_module}
# Check true node
true_id = Tilly.BDD.true_node_id()
true_ops_module = Tilly.BDD.universal_ops_module()
assert bdd_store.nodes_by_structure[{Node.mk_true(), true_ops_module}] == true_id
assert bdd_store.structures_by_id[true_id] == %{structure: Node.mk_true(), ops_module: true_ops_module}
end
end
describe "get_or_intern_node/3" do
setup do
typing_ctx = Tilly.BDD.init_bdd_store(%{})
%{initial_ctx: typing_ctx}
end
test "interning Node.mk_false() returns predefined false_id and doesn't change store", %{initial_ctx: ctx} do
false_ops_module = Tilly.BDD.universal_ops_module()
{new_ctx, node_id} = Tilly.BDD.get_or_intern_node(ctx, Node.mk_false(), false_ops_module)
assert node_id == Tilly.BDD.false_node_id()
assert new_ctx.bdd_store == ctx.bdd_store
end
test "interning Node.mk_true() returns predefined true_id and doesn't change store", %{initial_ctx: ctx} do
true_ops_module = Tilly.BDD.universal_ops_module()
{new_ctx, node_id} = Tilly.BDD.get_or_intern_node(ctx, Node.mk_true(), true_ops_module)
assert node_id == Tilly.BDD.true_node_id()
assert new_ctx.bdd_store == ctx.bdd_store
end
test "interning a new leaf node returns a new ID and updates the store", %{initial_ctx: ctx} do
leaf_structure = Node.mk_leaf("test_leaf")
ops_mod = :my_ops
{ctx_after_intern, node_id} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod)
assert node_id == 2 # Initial next_node_id
assert ctx_after_intern.bdd_store.next_node_id == 3
assert ctx_after_intern.bdd_store.nodes_by_structure[{leaf_structure, ops_mod}] == node_id
assert ctx_after_intern.bdd_store.structures_by_id[node_id] == %{structure: leaf_structure, ops_module: ops_mod}
end
test "interning the same leaf node again returns the same ID and doesn't change store", %{initial_ctx: ctx} do
leaf_structure = Node.mk_leaf("test_leaf")
ops_mod = :my_ops
{ctx_after_first_intern, first_node_id} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod)
{ctx_after_second_intern, second_node_id} = Tilly.BDD.get_or_intern_node(ctx_after_first_intern, leaf_structure, ops_mod)
assert first_node_id == second_node_id
assert ctx_after_first_intern.bdd_store == ctx_after_second_intern.bdd_store
end
test "interning a new split node returns a new ID and updates the store", %{initial_ctx: ctx} do
split_structure = Node.mk_split(:el, Tilly.BDD.true_node_id(), Tilly.BDD.false_node_id(), Tilly.BDD.true_node_id())
ops_mod = :split_ops
{ctx_after_intern, node_id} = Tilly.BDD.get_or_intern_node(ctx, split_structure, ops_mod)
assert node_id == 2 # Initial next_node_id
assert ctx_after_intern.bdd_store.next_node_id == 3
assert ctx_after_intern.bdd_store.nodes_by_structure[{split_structure, ops_mod}] == node_id
assert ctx_after_intern.bdd_store.structures_by_id[node_id] == %{structure: split_structure, ops_module: ops_mod}
end
test "interning structurally identical nodes with different ops_modules results in different IDs", %{initial_ctx: ctx} do
leaf_structure = Node.mk_leaf("shared_leaf")
ops_mod1 = :ops1
ops_mod2 = :ops2
{ctx1, id1} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod1)
{_ctx2, id2} = Tilly.BDD.get_or_intern_node(ctx1, leaf_structure, ops_mod2)
assert id1 != id2
assert id1 == 2
assert id2 == 3
end
test "raises ArgumentError if bdd_store is not initialized" do
assert_raise ArgumentError, ~r/BDD store not initialized/, fn ->
Tilly.BDD.get_or_intern_node(%{}, Node.mk_leaf("foo"), :ops)
end
end
end
describe "get_node_data/2" do
setup do
ctx = Tilly.BDD.init_bdd_store(%{})
leaf_structure = Node.mk_leaf("data")
ops_mod = :leaf_ops
{new_ctx, leaf_id_val} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod)
%{ctx: new_ctx, leaf_structure: leaf_structure, ops_mod: ops_mod, leaf_id: leaf_id_val}
end
test "returns correct data for false node", %{ctx: ctx} do
false_id = Tilly.BDD.false_node_id()
false_ops_module = Tilly.BDD.universal_ops_module()
assert Tilly.BDD.get_node_data(ctx, false_id) == %{structure: Node.mk_false(), ops_module: false_ops_module}
end
test "returns correct data for true node", %{ctx: ctx} do
true_id = Tilly.BDD.true_node_id()
true_ops_module = Tilly.BDD.universal_ops_module()
assert Tilly.BDD.get_node_data(ctx, true_id) == %{structure: Node.mk_true(), ops_module: true_ops_module}
end
test "returns correct data for a custom interned leaf node", %{ctx: ctx, leaf_structure: ls, ops_mod: om, leaf_id: id} do
assert Tilly.BDD.get_node_data(ctx, id) == %{structure: ls, ops_module: om}
end
test "returns nil for an unknown node ID", %{ctx: ctx} do
assert Tilly.BDD.get_node_data(ctx, 999) == nil
end
test "returns nil if bdd_store not in ctx" do
assert Tilly.BDD.get_node_data(%{}, 0) == nil
end
end
describe "is_false_node?/2 and is_true_node?/2" do
setup do
ctx = Tilly.BDD.init_bdd_store(%{})
leaf_structure = Node.mk_leaf("data")
ops_mod = :leaf_ops
{new_ctx, leaf_id_val} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod)
%{ctx: new_ctx, leaf_id: leaf_id_val}
end
test "is_false_node?/2", %{ctx: ctx, leaf_id: id} do
assert Tilly.BDD.is_false_node?(ctx, Tilly.BDD.false_node_id()) == true
assert Tilly.BDD.is_false_node?(ctx, Tilly.BDD.true_node_id()) == false
assert Tilly.BDD.is_false_node?(ctx, id) == false
assert Tilly.BDD.is_false_node?(ctx, 999) == false # Unknown ID
end
test "is_true_node?/2", %{ctx: ctx, leaf_id: id} do
assert Tilly.BDD.is_true_node?(ctx, Tilly.BDD.true_node_id()) == true
assert Tilly.BDD.is_true_node?(ctx, Tilly.BDD.false_node_id()) == false
assert Tilly.BDD.is_true_node?(ctx, id) == false
assert Tilly.BDD.is_true_node?(ctx, 999) == false # Unknown ID
end
end
end