I have an automatically generated program that calls some automatically generated auxiliary programs. I assert the lot into the dynamic database in their own module, and call the top-level program in the new module.
The dynamic database is evil so I typically do that in a setup_call_cleanup/3
call, like this:
S = (assert(Maps:M0,Ref)
% Top-level program:
,assert_program(program,Ss,Rs_S)
% Auxiliary programs:
,assert_program(program,As,Rs_A)
)
,G = (% The goal in E is s/2, the top-level program.
call(program:E)
)
,C = (erase_program_clauses([Ref|Rs_S])
,erase_program_clauses(Rs_A)
)
,setup_call_cleanup(S,G,C)
The goal call(program:E)
fails. This is difficult to understand because one of the auxiliary programsā clauses unifies with one of the body goals in the top-level program, s/2
.
Hereās a protocol-log of a tracing session where I show this; Iāve listed s/2
and the auxiliary, step_right/1
in the tracer and Iām also spying them so I can leap to their goals:
[debug] ?- spy(program:[s/2,step_right/2]).
% Spy point on program:s/2
% Spy point on program:step_right/2
true.
[debug] ?- program([s/2],experiment_file,_Ps), solver_executor(_Ps,id(tessera_1),print,_As,_M), print_map(tiles,_M).
* Call: (20) program:s([dyn1, 1/7, s, q0, [_125922, _125928|...], [_126022|...], [...|...]|...], [dyn1, 7/1, e, _124374, [], [], []|...]) ? bbreak
% Break level 1
[debug] [1] ?- listing(program:s/2).
:- dynamic s/2.
s(A, B) :-
step_down(A, B).
s(A, B) :-
step_left(A, B).
s(A, B) :-
step_right(A, B).
s(A, B) :-
step_up(A, B).
s(A, B) :-
step_down(A, C),
s(C, B).
s(A, B) :-
step_left(A, C),
s(C, B).
s(A, B) :-
step_right(A, C),
s(C, B).
s(A, B) :-
step_up(A, C),
s(C, B).
true.
[debug] [1] ?-
% Exit break level 1
* Call: (20) program:s([dyn1, 1/7, s, q0, [_125922, _125928|...], [_126022|...], [...|...]|...], [dyn1, 7/1, e, _124374, [], [], []|...]) ? lleap
* Call: (21) program:step_right([dyn1, 1/7, s, q0, [_125922, _125928|...], [_126022|...], [...|...]|...], [dyn1, 7/1, e, _124374, [], [], []|...]) ? lleap
* Fail: (21) program:step_right([dyn1, 1/7, s, q0, [_125922, _125928|...], [_126022|...], [...|...]|...], [dyn1, 7/1, e, _124374, [], [], []|...]) ? lleap
* Call: (21) program:step_right([dyn1, 1/7, s, q0, [_125922, _125928|...], [_126022|...], [...|...]|...], _135120) ? wwrite
* Call: (21) program:step_right([dyn1, 1/7, s, q0, [_125922, _125928, _125934, _125940, _125946, _125952, _125958, _125964, _125970, _125976, _125982, _125988, _125994, _126000, _126006, _126012], [_126022, _126028, _126034, _126040, _126046, _126052, _126058, _126064, _126070, _126076, _126082, _126088, _126094, _126100, _126106, _126112], [_126122, _126128, _126134, _126140, _126146, _126152, _126158, _126164, _126170, _126176, _126182, _126188, _126194, _126200, _126206, _126212], [_126222, _126228, _126234, _126240, _126246, _126252, _126258, _126264, _126270, _126276, _126282, _126288, _126294, _126300, _126306, _126312]], _135120) ? bbreak
% Break level 1
[debug] [1] ?- listing(program:step_right/2).
:- dynamic step_right/2.
step_right([dyn1, 1/1, f, Q0, [Q0|Qs], [ppuu|Os], [right|As], [q1|Qs_]], [dyn1, 2/1, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 1/7, s, Q0, [Q0|Qs], [upuu|Os], [right|As], [q1|Qs_]], [dyn1, 2/7, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 2/1, f, Q0, [Q0|Qs], [upup|Os], [right|As], [q1|Qs_]], [dyn1, 3/1, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 2/7, f, Q0, [Q0|Qs], [upup|Os], [right|As], [q1|Qs_]], [dyn1, 3/7, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 3/1, f, Q0, [Q0|Qs], [ppup|Os], [right|As], [q1|Qs_]], [dyn1, 4/1, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 4/1, f, Q0, [Q0|Qs], [upup|Os], [right|As], [q1|Qs_]], [dyn1, 5/1, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 5/3, f, Q0, [Q0|Qs], [uppu|Os], [right|As], [q1|Qs_]], [dyn1, 6/3, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 5/7, f, Q0, [Q0|Qs], [uppu|Os], [right|As], [q1|Qs_]], [dyn1, 6/7, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 6/3, f, Q0, [Q0|Qs], [upup|Os], [right|As], [q1|Qs_]], [dyn1, 7/3, f, q1, Qs, Os, As, Qs_]).
step_right([dyn1, 6/7, f, Q0, [Q0|Qs], [upup|Os], [right|As], [q1|Qs_]], [dyn1, 7/7, f, q1, Qs, Os, As, Qs_]).
true.
[debug] [1] ?- step_right([dyn1, 1/7, s, q0, [_125922, _125928, _125934, _125940, _125946, _125952, _125958, _125964, _125970, _125976, _125982, _125988, _125994, _126000, _126006, _126012], [_126022, _126028, _126034, _126040, _126046, _126052, _126058, _126064, _126070, _126076, _126082, _126088, _126094, _126100, _126106, _126112], [_126122, _126128, _126134, _126140, _126146, _126152, _126158, _126164, _126170, _126176, _126182, _126188, _126194, _126200, _126206, _126212], [_126222, _126228, _126234, _126240, _126246, _126252, _126258, _126264, _126270, _126276, _126282, _126288, _126294, _126300, _126306, _126312]], _135120) = step_right([dyn1, 1/7, s, Q0, [Q0|Qs], [upuu|Os], [right|As], [q1|Qs_]], [dyn1, 2/7, f, q1, Qs, Os, As, Qs_]).
_125922 = Q0, Q0 = q0,
_126022 = upuu,
_126122 = right,
_126222 = q1,
_135120 = [dyn1,2/7,f,q1,[_125928,_125934,_125940,_125946,_125952,_125958,_125964,_125970,_125976,_125982,_125988,_125994,_126000,_126006|...],[_126028,_126034,_126040,_126046,_126052,_126058,_126064,_126070,_126076,_126082,_126088,_126094,_126100|...],[_126128,_126134,_126140,_126146,_126152,_126158,_126164,_126170,_126176,_126182,_126188,_126194|...],[_126228,_126234,_126240,_126246,_126252,_126258,_126264,_126270,_126276,_126282,_126288|...]],
Qs = [_125928,_125934,_125940,_125946,_125952,_125958,_125964,_125970,_125976,_125982,_125988,_125994,_126000,_126006,_126012],
Os = [_126028,_126034,_126040,_126046,_126052,_126058,_126064,_126070,_126076,_126082,_126088,_126094,_126100,_126106,_126112],
As = [_126128,_126134,_126140,_126146,_126152,_126158,_126164,_126170,_126176,_126182,_126188,_126194,_126200,_126206,_126212],
Qs_ = [_126228,_126234,_126240,_126246,_126252,_126258,_126264,_126270,_126276,_126282,_126288,_126294,_126300,_126306,_126312].
[debug] [1] ?-
% Exit break level 1
* Call: (21) program:step_right([dyn1, 1/7, s, q0, [_125922, _125928, _125934, _125940, _125946, _125952, _125958, _125964, _125970, _125976, _125982, _125988, _125994, _126000, _126006, _126012], [_126022, _126028, _126034, _126040, _126046, _126052, _126058, _126064, _126070, _126076, _126082, _126088, _126094, _126100, _126106, _126112], [_126122, _126128, _126134, _126140, _126146, _126152, _126158, _126164, _126170, _126176, _126182, _126188, _126194, _126200, _126206, _126212], [_126222, _126228, _126234, _126240, _126246, _126252, _126258, _126264, _126270, _126276, _126282, _126288, _126294, _126300, _126306, _126312]], _135120) ?
creep
* Fail: (21) program:step_right([dyn1, 1/7, s, q0, [_125922, _125928, _125934, _125940, _125946, _125952, _125958, _125964, _125970, _125976, _125982, _125988, _125994, _126000, _126006, _126012], [_126022, _126028, _126034, _126040, _126046, _126052, _126058, _126064, _126070, _126076, _126082, _126088, _126094, _126100, _126106, _126112], [_126122, _126128, _126134, _126140, _126146, _126152, _126158, _126164, _126170, _126176, _126182, _126188, _126194, _126200, _126206, _126212], [_126222, _126228, _126234, _126240, _126246, _126252, _126258, _126264, _126270, _126276, _126282, _126288, _126294, _126300, _126306, _126312]], _135120) ? aabort
% Execution Aborted
[debug] ?- noprotocol.
Note that the first call to step_right/2
fails correctly. I donāt understand why the second call fails. The second call unifies with the second clause of step_right/2
in the dynamic database (the one that starts with step_right([dyn1, 1/7, s, Q0 ...
).
What is going on here? This is the first time this happens [edit: I mean that Iāve used this technique many times and itās the first time it fails like this]. If I load s/2, step_right/2
and the other auxiliaries from a file, call(program:E)
succeeds, so thereās nothing wrong with the query, as such.
My suspicion is that there is some sort of clash with further clauses of step_right/2
(and the other auxiliaries) that are loaded into the program database from a module file, before the above code is executed. However, that module has a different name than my on-the-fly populated, program
module. Do I have to use a multifile directive somewhere, nonetheless?
I tried running call(program:E)
inside a transaction just in case magick works but I guess it doesnāt.
Btw, Iām on Win 11 64 bits with SWI 9.3.7-1 (development version). I havenāt tried this on Linux yet. Will it make a difference?