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
164 lines
6.9 KiB
Elixir
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
|