chceckpoint
This commit is contained in:
parent
bb08fbe078
commit
6a91950d02
386
test.exs
386
test.exs
@ -89,6 +89,10 @@ defmodule Tdd do
|
||||
_otherwise, acc_set -> acc_set
|
||||
end)
|
||||
|
||||
IO.inspect({assumptions_map, primary_true_predicates, MapSet.size(primary_true_predicates)},
|
||||
label: "CheckConsistency"
|
||||
)
|
||||
|
||||
if MapSet.size(primary_true_predicates) > 1 do
|
||||
:contradiction
|
||||
else
|
||||
@ -114,6 +118,8 @@ defmodule Tdd do
|
||||
|
||||
check_assumptions_consistency(assumptions_map) == :contradiction ->
|
||||
# Path is semantically impossible
|
||||
# Important
|
||||
IO.inspect({tdd_id, assumptions_map}, label: "SimplifyContradiction")
|
||||
update_state(%{op_cache: Map.put(state.op_cache, cache_key, @false_node_id)})
|
||||
@false_node_id
|
||||
|
||||
@ -144,6 +150,7 @@ defmodule Tdd do
|
||||
make_node_raw(var, simplified_y, simplified_n, simplified_d)
|
||||
end
|
||||
|
||||
IO.inspect({tdd_id, assumptions_map, result_id}, label: "SimplifyExit")
|
||||
update_state(%{op_cache: Map.put(state.op_cache, cache_key, result_id)})
|
||||
result_id
|
||||
end
|
||||
@ -402,31 +409,6 @@ tdd_empty_tuple = Tdd.type_empty_tuple()
|
||||
tdd_any = Tdd.type_any()
|
||||
tdd_none = Tdd.type_none()
|
||||
|
||||
IO.puts("\n--- TDD for :foo ---")
|
||||
Tdd.print_tdd(tdd_foo)
|
||||
|
||||
IO.puts("\n--- TDD for not :foo ---")
|
||||
Tdd.print_tdd(Tdd.negate(tdd_foo))
|
||||
|
||||
IO.puts("\n--- TDD for atom ---")
|
||||
Tdd.print_tdd(tdd_atom)
|
||||
|
||||
IO.puts("\n--- TDD for not atom ---")
|
||||
# Expected: make_node(@v_is_atom, @false_node_id, @true_node_id, @true_node_id)
|
||||
# This represents "anything that is not an atom". The DC branch becomes true because if
|
||||
# "is_atom" test is irrelevant for "not atom", it means it's part of "not atom".
|
||||
Tdd.print_tdd(Tdd.negate(tdd_atom))
|
||||
|
||||
IO.puts("\n--- TDD for :foo and :bar (should be none) ---")
|
||||
tdd_foo_and_bar = Tdd.intersect(tdd_foo, tdd_bar)
|
||||
# Expected ID 0: :false_terminal
|
||||
Tdd.print_tdd(tdd_foo_and_bar)
|
||||
|
||||
IO.puts("\n--- TDD for :foo and atom (should be :foo) ---")
|
||||
tdd_foo_and_atom = Tdd.intersect(tdd_foo, tdd_atom)
|
||||
# Expected to be structurally identical to tdd_foo
|
||||
Tdd.print_tdd(tdd_foo_and_atom)
|
||||
|
||||
test = fn name, expected, result ->
|
||||
current_failures = Process.get(:test_failures, [])
|
||||
|
||||
@ -450,176 +432,210 @@ tdd_tuple_s2 = Tdd.type_tuple_sized_any(2)
|
||||
tdd_any = Tdd.type_any()
|
||||
tdd_none = Tdd.type_none()
|
||||
|
||||
IO.puts("\n--- Basic Subtyping Tests ---")
|
||||
test.(":foo <: atom", true, Tdd.is_subtype(tdd_foo, tdd_atom))
|
||||
test.("atom <: :foo", false, Tdd.is_subtype(tdd_atom, tdd_foo))
|
||||
test.(":foo <: :bar", false, Tdd.is_subtype(tdd_foo, tdd_bar))
|
||||
test.(":foo <: :foo", true, Tdd.is_subtype(tdd_foo, tdd_foo))
|
||||
test.("{} <: tuple", true, Tdd.is_subtype(tdd_empty_tuple, tdd_tuple))
|
||||
test.("tuple <: {}", false, Tdd.is_subtype(tdd_tuple, tdd_empty_tuple))
|
||||
test.(":foo <: {}", false, Tdd.is_subtype(tdd_foo, tdd_empty_tuple))
|
||||
test.("tuple_size_2 <: tuple", true, Tdd.is_subtype(tdd_tuple_s2, tdd_tuple))
|
||||
test.("tuple <: tuple_size_2", false, Tdd.is_subtype(tdd_tuple, tdd_tuple_s2))
|
||||
test.("tuple_size_2 <: {}", false, Tdd.is_subtype(tdd_tuple_s2, tdd_empty_tuple))
|
||||
test_all = fn ->
|
||||
IO.puts("\n--- TDD for :foo ---")
|
||||
Tdd.print_tdd(tdd_foo)
|
||||
|
||||
IO.puts("\n--- Any/None Subtyping Tests ---")
|
||||
test.("any <: :foo", false, Tdd.is_subtype(tdd_any, tdd_foo))
|
||||
test.(":foo <: any", true, Tdd.is_subtype(tdd_foo, tdd_any))
|
||||
test.("none <: :foo", true, Tdd.is_subtype(tdd_none, tdd_foo))
|
||||
test.(":foo <: none", false, Tdd.is_subtype(tdd_foo, tdd_none))
|
||||
test.("none <: any", true, Tdd.is_subtype(tdd_none, tdd_any))
|
||||
test.("any <: none", false, Tdd.is_subtype(tdd_any, tdd_none))
|
||||
test.("any <: any", true, Tdd.is_subtype(tdd_any, tdd_any))
|
||||
test.("none <: none", true, Tdd.is_subtype(tdd_none, tdd_none))
|
||||
IO.puts("\n--- TDD for not :foo ---")
|
||||
Tdd.print_tdd(Tdd.negate(tdd_foo))
|
||||
|
||||
IO.puts("\n--- Union related Subtyping ---")
|
||||
tdd_foo_or_bar = Tdd.sum(tdd_foo, tdd_bar)
|
||||
tdd_foo_or_bar_or_baz = Tdd.sum(tdd_foo_or_bar, tdd_baz)
|
||||
IO.puts("\n--- TDD for atom ---")
|
||||
Tdd.print_tdd(tdd_atom)
|
||||
|
||||
test.(":foo <: (:foo | :bar)", true, Tdd.is_subtype(tdd_foo, tdd_foo_or_bar))
|
||||
test.(":baz <: (:foo | :bar)", false, Tdd.is_subtype(tdd_baz, tdd_foo_or_bar))
|
||||
test.("(:foo | :bar) <: atom", true, Tdd.is_subtype(tdd_foo_or_bar, tdd_atom))
|
||||
test.("atom <: (:foo | :bar)", false, Tdd.is_subtype(tdd_atom, tdd_foo_or_bar))
|
||||
IO.puts("\n--- TDD for not atom ---")
|
||||
# Expected: make_node(@v_is_atom, @false_node_id, @true_node_id, @true_node_id)
|
||||
# This represents "anything that is not an atom". The DC branch becomes true because if
|
||||
# "is_atom" test is irrelevant for "not atom", it means it's part of "not atom".
|
||||
Tdd.print_tdd(Tdd.negate(tdd_atom))
|
||||
|
||||
test.(
|
||||
"(:foo | :bar) <: (:foo | :bar | :baz)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_bar, tdd_foo_or_bar_or_baz)
|
||||
)
|
||||
IO.puts("\n--- TDD for :foo and :bar (should be none) ---")
|
||||
tdd_foo_and_bar = Tdd.intersect(tdd_foo, tdd_bar)
|
||||
# Expected ID 0: :false_terminal
|
||||
Tdd.print_tdd(tdd_foo_and_bar)
|
||||
|
||||
test.(
|
||||
"(:foo | :bar | :baz) <: (:foo | :bar)",
|
||||
false,
|
||||
Tdd.is_subtype(tdd_foo_or_bar_or_baz, tdd_foo_or_bar)
|
||||
)
|
||||
IO.puts("\n--- TDD for :foo and atom (should be :foo) ---")
|
||||
tdd_foo_and_atom = Tdd.intersect(tdd_foo, tdd_atom)
|
||||
# Expected to be structurally identical to tdd_foo
|
||||
Tdd.print_tdd(tdd_foo_and_atom)
|
||||
IO.puts("\n--- Basic Subtyping Tests ---")
|
||||
test.(":foo <: atom", true, Tdd.is_subtype(tdd_foo, tdd_atom))
|
||||
test.("atom <: :foo", false, Tdd.is_subtype(tdd_atom, tdd_foo))
|
||||
test.(":foo <: :bar", false, Tdd.is_subtype(tdd_foo, tdd_bar))
|
||||
test.(":foo <: :foo", true, Tdd.is_subtype(tdd_foo, tdd_foo))
|
||||
test.("{} <: tuple", true, Tdd.is_subtype(tdd_empty_tuple, tdd_tuple))
|
||||
test.("tuple <: {}", false, Tdd.is_subtype(tdd_tuple, tdd_empty_tuple))
|
||||
test.(":foo <: {}", false, Tdd.is_subtype(tdd_foo, tdd_empty_tuple))
|
||||
test.("tuple_size_2 <: tuple", true, Tdd.is_subtype(tdd_tuple_s2, tdd_tuple))
|
||||
test.("tuple <: tuple_size_2", false, Tdd.is_subtype(tdd_tuple, tdd_tuple_s2))
|
||||
test.("tuple_size_2 <: {}", false, Tdd.is_subtype(tdd_tuple_s2, tdd_empty_tuple))
|
||||
|
||||
# Test against a non-member of the union
|
||||
test.("(:foo | :bar) <: :baz", false, Tdd.is_subtype(tdd_foo_or_bar, tdd_baz))
|
||||
IO.puts("\n--- Any/None Subtyping Tests ---")
|
||||
test.("any <: :foo", false, Tdd.is_subtype(tdd_any, tdd_foo))
|
||||
test.(":foo <: any", true, Tdd.is_subtype(tdd_foo, tdd_any))
|
||||
test.("none <: :foo", true, Tdd.is_subtype(tdd_none, tdd_foo))
|
||||
test.(":foo <: none", false, Tdd.is_subtype(tdd_foo, tdd_none))
|
||||
test.("none <: any", true, Tdd.is_subtype(tdd_none, tdd_any))
|
||||
test.("any <: none", false, Tdd.is_subtype(tdd_any, tdd_none))
|
||||
test.("any <: any", true, Tdd.is_subtype(tdd_any, tdd_any))
|
||||
test.("none <: none", true, Tdd.is_subtype(tdd_none, tdd_none))
|
||||
|
||||
IO.puts("\n--- Union related Subtyping ---")
|
||||
tdd_foo_or_bar = Tdd.sum(tdd_foo, tdd_bar)
|
||||
tdd_foo_or_bar_or_baz = Tdd.sum(tdd_foo_or_bar, tdd_baz)
|
||||
|
||||
test.(":foo <: (:foo | :bar)", true, Tdd.is_subtype(tdd_foo, tdd_foo_or_bar))
|
||||
test.(":baz <: (:foo | :bar)", false, Tdd.is_subtype(tdd_baz, tdd_foo_or_bar))
|
||||
test.("(:foo | :bar) <: atom", true, Tdd.is_subtype(tdd_foo_or_bar, tdd_atom))
|
||||
test.("atom <: (:foo | :bar)", false, Tdd.is_subtype(tdd_atom, tdd_foo_or_bar))
|
||||
|
||||
test.(
|
||||
"(:foo | :bar) <: (:foo | :bar | :baz)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_bar, tdd_foo_or_bar_or_baz)
|
||||
)
|
||||
|
||||
test.(
|
||||
"(:foo | :bar | :baz) <: (:foo | :bar)",
|
||||
false,
|
||||
Tdd.is_subtype(tdd_foo_or_bar_or_baz, tdd_foo_or_bar)
|
||||
)
|
||||
|
||||
# Test against a non-member of the union
|
||||
test.("(:foo | :bar) <: :baz", false, Tdd.is_subtype(tdd_foo_or_bar, tdd_baz))
|
||||
|
||||
IO.puts("\n--- Intersection related Subtyping ---")
|
||||
# Should be equivalent to tdd_foo
|
||||
tdd_atom_and_foo = Tdd.intersect(tdd_atom, tdd_foo)
|
||||
# Should be tdd_none
|
||||
tdd_atom_and_tuple = Tdd.intersect(tdd_atom, tdd_tuple)
|
||||
|
||||
test.("(atom & :foo) <: :foo", true, Tdd.is_subtype(tdd_atom_and_foo, tdd_foo))
|
||||
test.(":foo <: (atom & :foo)", true, Tdd.is_subtype(tdd_foo, tdd_atom_and_foo))
|
||||
test.("(atom & tuple) <: none", true, Tdd.is_subtype(tdd_atom_and_tuple, tdd_none))
|
||||
test.("none <: (atom & tuple)", true, Tdd.is_subtype(tdd_none, tdd_atom_and_tuple))
|
||||
test.("(atom & :foo) <: :bar", false, Tdd.is_subtype(tdd_atom_and_foo, tdd_bar))
|
||||
# An intersection is a subtype of its components
|
||||
test.("(atom & :foo) <: atom", true, Tdd.is_subtype(tdd_atom_and_foo, tdd_atom))
|
||||
# (none <: atom)
|
||||
test.("(atom & tuple) <: atom", true, Tdd.is_subtype(tdd_atom_and_tuple, tdd_atom))
|
||||
# (none <: tuple)
|
||||
test.("(atom & tuple) <: tuple", true, Tdd.is_subtype(tdd_atom_and_tuple, tdd_tuple))
|
||||
|
||||
IO.puts("\n--- Negation related Subtyping (Contrapositives) ---")
|
||||
# Reminder: ¬A <: ¬B is equivalent to B <: A (contrapositive)
|
||||
|
||||
# Test 1: ¬atom <: ¬:foo (Equivalent to :foo <: atom, which is true)
|
||||
test.("¬atom <: ¬:foo", true, Tdd.is_subtype(Tdd.negate(tdd_atom), Tdd.negate(tdd_foo)))
|
||||
|
||||
# Test 2: ¬:foo <: ¬atom (Equivalent to atom <: :foo, which is false)
|
||||
test.("¬:foo <: ¬atom", false, Tdd.is_subtype(Tdd.negate(tdd_foo), Tdd.negate(tdd_atom)))
|
||||
|
||||
# Double negation
|
||||
test.("¬(¬:foo) <: :foo", true, Tdd.is_subtype(Tdd.negate(Tdd.negate(tdd_foo)), tdd_foo))
|
||||
test.(":foo <: ¬(¬:foo)", true, Tdd.is_subtype(tdd_foo, Tdd.negate(Tdd.negate(tdd_foo))))
|
||||
|
||||
# Disjoint types
|
||||
test.("atom <: ¬tuple", true, Tdd.is_subtype(tdd_atom, Tdd.negate(tdd_tuple)))
|
||||
test.("tuple <: ¬atom", true, Tdd.is_subtype(tdd_tuple, Tdd.negate(tdd_atom)))
|
||||
test.(":foo <: ¬{}", true, Tdd.is_subtype(tdd_foo, Tdd.negate(tdd_empty_tuple)))
|
||||
|
||||
IO.puts("\n--- Mixed Types & Complex Subtyping ---")
|
||||
tdd_atom_or_tuple = Tdd.sum(tdd_atom, tdd_tuple)
|
||||
tdd_foo_or_empty_tuple = Tdd.sum(tdd_foo, tdd_empty_tuple)
|
||||
|
||||
test.(
|
||||
"(:foo | {}) <: (atom | tuple)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_empty_tuple, tdd_atom_or_tuple)
|
||||
)
|
||||
|
||||
test.(
|
||||
"(atom | tuple) <: (:foo | {})",
|
||||
false,
|
||||
Tdd.is_subtype(tdd_atom_or_tuple, tdd_foo_or_empty_tuple)
|
||||
)
|
||||
|
||||
test.(":foo <: (atom | tuple)", true, Tdd.is_subtype(tdd_foo, tdd_atom_or_tuple))
|
||||
test.("{} <: (atom | tuple)", true, Tdd.is_subtype(tdd_empty_tuple, tdd_atom_or_tuple))
|
||||
|
||||
# De Morgan's Law illustration (A | B = ¬(¬A & ¬B))
|
||||
# (:foo | :bar) <: ¬(¬:foo & ¬:bar)
|
||||
tdd_not_foo_and_not_bar = Tdd.intersect(Tdd.negate(tdd_foo), Tdd.negate(tdd_bar))
|
||||
|
||||
test.(
|
||||
"(:foo | :bar) <: ¬(¬:foo & ¬:bar)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_bar, Tdd.negate(tdd_not_foo_and_not_bar))
|
||||
)
|
||||
|
||||
test.(
|
||||
"¬(¬:foo & ¬:bar) <: (:foo | :bar)",
|
||||
true,
|
||||
Tdd.is_subtype(Tdd.negate(tdd_not_foo_and_not_bar), tdd_foo_or_bar)
|
||||
)
|
||||
|
||||
# Type difference: atom - :foo (represented as atom & ¬:foo)
|
||||
tdd_atom_minus_foo = Tdd.intersect(tdd_atom, Tdd.negate(tdd_foo))
|
||||
test.("(atom - :foo) <: atom", true, Tdd.is_subtype(tdd_atom_minus_foo, tdd_atom))
|
||||
test.("(atom - :foo) <: :foo", false, Tdd.is_subtype(tdd_atom_minus_foo, tdd_foo))
|
||||
# True if :bar is in (atom - :foo)
|
||||
test.("(atom - :foo) <: :bar", true, Tdd.is_subtype(tdd_atom_minus_foo, tdd_bar))
|
||||
test.(":bar <: (atom - :foo)", true, Tdd.is_subtype(tdd_bar, tdd_atom_minus_foo))
|
||||
|
||||
# (atom - :foo) | :foo should be atom
|
||||
tdd_recombined_atom = Tdd.sum(tdd_atom_minus_foo, tdd_foo)
|
||||
test.("((atom - :foo) | :foo) <: atom", true, Tdd.is_subtype(tdd_recombined_atom, tdd_atom))
|
||||
test.("atom <: ((atom - :foo) | :foo)", true, Tdd.is_subtype(tdd_atom, tdd_recombined_atom))
|
||||
|
||||
# (atom | {}) & (tuple | :foo) must be (:foo | {})
|
||||
# Represents `atom() | {}`
|
||||
tdd_atom_or_empty = Tdd.sum(tdd_atom, tdd_empty_tuple)
|
||||
# Represents `tuple() | :foo`
|
||||
tdd_tuple_or_foo = Tdd.sum(tdd_tuple, tdd_foo)
|
||||
intersected_complex = Tdd.intersect(tdd_atom_or_empty, tdd_tuple_or_foo)
|
||||
# Expected result for intersected_complex is tdd_foo_or_empty_tuple
|
||||
|
||||
test.(
|
||||
"(atom | {}) & (tuple | :foo) <: (:foo | {})",
|
||||
true,
|
||||
Tdd.is_subtype(intersected_complex, tdd_foo_or_empty_tuple)
|
||||
)
|
||||
|
||||
test.(
|
||||
"(:foo | {}) <: (atom | {}) & (tuple | :foo)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_empty_tuple, intersected_complex)
|
||||
)
|
||||
|
||||
# {} | tuple_size_2 should be a subtype of tuple
|
||||
tdd_empty_or_s2 = Tdd.sum(tdd_empty_tuple, tdd_tuple_s2)
|
||||
test.("({} | tuple_size_2) <: tuple", true, Tdd.is_subtype(tdd_empty_or_s2, tdd_tuple))
|
||||
|
||||
test.(
|
||||
"({} | tuple_size_2) <: ({} | tuple_size_2)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_empty_or_s2, tdd_empty_or_s2)
|
||||
)
|
||||
|
||||
test.(
|
||||
"({} | tuple_size_2) <: tuple_size_2",
|
||||
false,
|
||||
Tdd.is_subtype(tdd_empty_or_s2, tdd_tuple_s2)
|
||||
)
|
||||
|
||||
IO.puts("\n--- TDD structure for (atom - :foo) ---")
|
||||
Tdd.print_tdd(tdd_atom_minus_foo)
|
||||
IO.puts("\n--- TDD structure for ((atom - :foo) | :foo) which should be 'atom' ---")
|
||||
Tdd.print_tdd(tdd_recombined_atom)
|
||||
IO.puts("\n--- TDD structure for 'atom' for comparison ---")
|
||||
Tdd.print_tdd(tdd_atom)
|
||||
|
||||
IO.inspect(Process.get(:test_failures, []))
|
||||
end
|
||||
|
||||
IO.puts("\n--- Intersection related Subtyping ---")
|
||||
# Should be equivalent to tdd_foo
|
||||
tdd_atom_and_foo = Tdd.intersect(tdd_atom, tdd_foo)
|
||||
# Should be tdd_none
|
||||
tdd_atom_and_tuple = Tdd.intersect(tdd_atom, tdd_tuple)
|
||||
|
||||
test.("(atom & :foo) <: :foo", true, Tdd.is_subtype(tdd_atom_and_foo, tdd_foo))
|
||||
test.(":foo <: (atom & :foo)", true, Tdd.is_subtype(tdd_foo, tdd_atom_and_foo))
|
||||
test.("(atom & tuple) <: none", true, Tdd.is_subtype(tdd_atom_and_tuple, tdd_none))
|
||||
test.("none <: (atom & tuple)", true, Tdd.is_subtype(tdd_none, tdd_atom_and_tuple))
|
||||
test.("(atom & :foo) <: :bar", false, Tdd.is_subtype(tdd_atom_and_foo, tdd_bar))
|
||||
# An intersection is a subtype of its components
|
||||
test.("(atom & :foo) <: atom", true, Tdd.is_subtype(tdd_atom_and_foo, tdd_atom))
|
||||
# (none <: atom)
|
||||
test.("(atom & tuple) <: atom", true, Tdd.is_subtype(tdd_atom_and_tuple, tdd_atom))
|
||||
# (none <: tuple)
|
||||
test.("(atom & tuple) <: tuple", true, Tdd.is_subtype(tdd_atom_and_tuple, tdd_tuple))
|
||||
|
||||
IO.puts("\n--- Negation related Subtyping (Contrapositives) ---")
|
||||
# Reminder: ¬A <: ¬B is equivalent to B <: A (contrapositive)
|
||||
|
||||
# Test 1: ¬atom <: ¬:foo (Equivalent to :foo <: atom, which is true)
|
||||
test.("¬atom <: ¬:foo", true, Tdd.is_subtype(Tdd.negate(tdd_atom), Tdd.negate(tdd_foo)))
|
||||
|
||||
# Test 2: ¬:foo <: ¬atom (Equivalent to atom <: :foo, which is false)
|
||||
test.("¬:foo <: ¬atom", false, Tdd.is_subtype(Tdd.negate(tdd_foo), Tdd.negate(tdd_atom)))
|
||||
|
||||
# Double negation
|
||||
test.("¬(¬:foo) <: :foo", true, Tdd.is_subtype(Tdd.negate(Tdd.negate(tdd_foo)), tdd_foo))
|
||||
test.(":foo <: ¬(¬:foo)", true, Tdd.is_subtype(tdd_foo, Tdd.negate(Tdd.negate(tdd_foo))))
|
||||
|
||||
# Disjoint types
|
||||
test.("atom <: ¬tuple", true, Tdd.is_subtype(tdd_atom, Tdd.negate(tdd_tuple)))
|
||||
test.("tuple <: ¬atom", true, Tdd.is_subtype(tdd_tuple, Tdd.negate(tdd_atom)))
|
||||
test.(":foo <: ¬{}", true, Tdd.is_subtype(tdd_foo, Tdd.negate(tdd_empty_tuple)))
|
||||
|
||||
IO.puts("\n--- Mixed Types & Complex Subtyping ---")
|
||||
tdd_atom_or_tuple = Tdd.sum(tdd_atom, tdd_tuple)
|
||||
tdd_foo_or_empty_tuple = Tdd.sum(tdd_foo, tdd_empty_tuple)
|
||||
|
||||
test.(
|
||||
"(:foo | {}) <: (atom | tuple)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_empty_tuple, tdd_atom_or_tuple)
|
||||
)
|
||||
|
||||
test.(
|
||||
"(atom | tuple) <: (:foo | {})",
|
||||
false,
|
||||
Tdd.is_subtype(tdd_atom_or_tuple, tdd_foo_or_empty_tuple)
|
||||
)
|
||||
|
||||
test.(":foo <: (atom | tuple)", true, Tdd.is_subtype(tdd_foo, tdd_atom_or_tuple))
|
||||
test.("{} <: (atom | tuple)", true, Tdd.is_subtype(tdd_empty_tuple, tdd_atom_or_tuple))
|
||||
|
||||
# De Morgan's Law illustration (A | B = ¬(¬A & ¬B))
|
||||
# (:foo | :bar) <: ¬(¬:foo & ¬:bar)
|
||||
tdd_not_foo_and_not_bar = Tdd.intersect(Tdd.negate(tdd_foo), Tdd.negate(tdd_bar))
|
||||
|
||||
test.(
|
||||
"(:foo | :bar) <: ¬(¬:foo & ¬:bar)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_bar, Tdd.negate(tdd_not_foo_and_not_bar))
|
||||
)
|
||||
|
||||
test.(
|
||||
"¬(¬:foo & ¬:bar) <: (:foo | :bar)",
|
||||
true,
|
||||
Tdd.is_subtype(Tdd.negate(tdd_not_foo_and_not_bar), tdd_foo_or_bar)
|
||||
)
|
||||
|
||||
# Type difference: atom - :foo (represented as atom & ¬:foo)
|
||||
tdd_atom_minus_foo = Tdd.intersect(tdd_atom, Tdd.negate(tdd_foo))
|
||||
test.("(atom - :foo) <: atom", true, Tdd.is_subtype(tdd_atom_minus_foo, tdd_atom))
|
||||
test.("(atom - :foo) <: :foo", false, Tdd.is_subtype(tdd_atom_minus_foo, tdd_foo))
|
||||
# True if :bar is in (atom - :foo)
|
||||
test.("(atom - :foo) <: :bar", true, Tdd.is_subtype(tdd_atom_minus_foo, tdd_bar))
|
||||
test.(":bar <: (atom - :foo)", true, Tdd.is_subtype(tdd_bar, tdd_atom_minus_foo))
|
||||
|
||||
# (atom - :foo) | :foo should be atom
|
||||
tdd_recombined_atom = Tdd.sum(tdd_atom_minus_foo, tdd_foo)
|
||||
test.("((atom - :foo) | :foo) <: atom", true, Tdd.is_subtype(tdd_recombined_atom, tdd_atom))
|
||||
test.("atom <: ((atom - :foo) | :foo)", true, Tdd.is_subtype(tdd_atom, tdd_recombined_atom))
|
||||
|
||||
# (atom | {}) & (tuple | :foo) must be (:foo | {})
|
||||
# Represents `atom() | {}`
|
||||
tdd_atom_or_empty = Tdd.sum(tdd_atom, tdd_empty_tuple)
|
||||
# Represents `tuple() | :foo`
|
||||
tdd_tuple_or_foo = Tdd.sum(tdd_tuple, tdd_foo)
|
||||
intersected_complex = Tdd.intersect(tdd_atom_or_empty, tdd_tuple_or_foo)
|
||||
# Expected result for intersected_complex is tdd_foo_or_empty_tuple
|
||||
|
||||
test.(
|
||||
"(atom | {}) & (tuple | :foo) <: (:foo | {})",
|
||||
true,
|
||||
Tdd.is_subtype(intersected_complex, tdd_foo_or_empty_tuple)
|
||||
)
|
||||
|
||||
test.(
|
||||
"(:foo | {}) <: (atom | {}) & (tuple | :foo)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_foo_or_empty_tuple, intersected_complex)
|
||||
)
|
||||
|
||||
# {} | tuple_size_2 should be a subtype of tuple
|
||||
tdd_empty_or_s2 = Tdd.sum(tdd_empty_tuple, tdd_tuple_s2)
|
||||
test.("({} | tuple_size_2) <: tuple", true, Tdd.is_subtype(tdd_empty_or_s2, tdd_tuple))
|
||||
|
||||
test.(
|
||||
"({} | tuple_size_2) <: ({} | tuple_size_2)",
|
||||
true,
|
||||
Tdd.is_subtype(tdd_empty_or_s2, tdd_empty_or_s2)
|
||||
)
|
||||
|
||||
test.("({} | tuple_size_2) <: tuple_size_2", false, Tdd.is_subtype(tdd_empty_or_s2, tdd_tuple_s2))
|
||||
|
||||
IO.puts("\n--- TDD structure for (atom - :foo) ---")
|
||||
Tdd.print_tdd(tdd_atom_minus_foo)
|
||||
IO.puts("\n--- TDD structure for ((atom - :foo) | :foo) which should be 'atom' ---")
|
||||
Tdd.print_tdd(tdd_recombined_atom)
|
||||
IO.puts("\n--- TDD structure for 'atom' for comparison ---")
|
||||
Tdd.print_tdd(tdd_atom)
|
||||
|
||||
IO.inspect(Process.get(:test_failures, []))
|
||||
IO.inspect("tdd_atom_and_tuple")
|
||||
Tdd.print_tdd(tdd_atom_and_tuple)
|
||||
IO.inspect("tdd_none")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user