From 9c6b3998c26bffecf149c078523a2bb7047873fb Mon Sep 17 00:00:00 2001 From: Kacper Marzecki Date: Mon, 14 Jul 2025 23:04:45 +0200 Subject: [PATCH] fixed one test 3 to go --- lib/til.ex | 23 +++++++++++++++++++---- test/til_test.exs | 6 ------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lib/til.ex b/lib/til.ex index 25b90f9..590214d 100644 --- a/lib/til.ex +++ b/lib/til.ex @@ -946,6 +946,7 @@ defmodule Tdd.Store do @doc """ Updates a node's details directly. Used for knot-tying. + UNUSED RN """ @spec update_node_in_place( non_neg_integer(), @@ -1978,12 +1979,26 @@ defmodule Tdd.Compiler do raise "Tdd.Compiler: Unbound type variable: #{inspect(var_name)}" {:mu, var_name, body_spec} -> + # Create a placeholder ID to represent the recursive reference. placeholder_id = Store.create_placeholder({:mu_knot_tying_for, var_name, body_spec}) + + # Compile the body using the placeholder in the context. The resulting TDD + # will have `placeholder_id` at its recursive leaves. new_context = Map.put(context, var_name, placeholder_id) - body_id = compile_normalized_spec(body_spec, new_context) - {:ok, body_details} = Store.get_node(body_id) - Store.update_node_in_place(placeholder_id, {:ok, body_details}) - Algo.simplify(placeholder_id) + body_id_with_placeholder = compile_normalized_spec(body_spec, new_context) + + # "Tie the knot": substitute the placeholder with the ID of the body's root. + # This correctly forms the cyclic TDD graph using the standard algorithm. + # The `substitute` function is designed for this and does not corrupt the store. + final_id = + Algo.substitute( + body_id_with_placeholder, + placeholder_id, + body_id_with_placeholder + ) + + # The resulting graph may have new simplification opportunities after the knot is tied. + Algo.simplify(final_id) other_spec -> raw_id = do_structural_compile(other_spec, context) diff --git a/test/til_test.exs b/test/til_test.exs index 3244b9c..3f4608a 100644 --- a/test/til_test.exs +++ b/test/til_test.exs @@ -533,12 +533,6 @@ defmodule TddSystemTest do # list_of(integer & atom) is list_of(:none). # A list of :none can only be the empty list, as no element can ever exist. spec = {:list_of, {:intersect, [:integer, :atom]}} - Tdd.Store.init() - Debug.print_tdd_graph(Compiler.spec_to_id(spec)) - Debug.print_tdd_graph(Compiler.spec_to_id({:literal, []})) - - Process.get(:tdd_node_by_id) |> IO.inspect(label: ":tdd_node_by_id") - Process.get(:tdd_nodes) |> IO.inspect(label: ":tdd_nodes") assert_equivalent_specs(spec, {:literal, []}) end end