Skip to content

Commit 62a8539

Browse files
committed
FIXED: Code generation for unification moved to the head.
Minimal test case: `p(X, Y) :- X = f(Y), Y = a.`. Issue occurs if a variable is accessed (Y) before its unification must be moved to the head.
1 parent bd98d95 commit 62a8539

2 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/pl-comp.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ typedef struct _varDef
350350
#define VD_MAYBE_UNBALANCED 0x04
351351
#define VD_UNBALANCED 0x08
352352
#define VD_ARGUMENT 0x10 /* Unified against an argument */
353+
#define VD_ARGUMENT_DONE 0x20 /* Generated unification code */
353354

354355
typedef struct
355356
{ unsigned int isize;
@@ -1369,12 +1370,25 @@ isFirstVar(VarTable vt, int n)
13691370

13701371

13711372
#define argUnifiedTo(w) LDFUNC(argUnifiedTo, w)
1372-
static Word
1373+
static bool
13731374
argUnifiedTo(DECL_LD word w)
13741375
{ VarDef v = varInfo(w);
13751376

13761377
if ( ison(v, VD_ARGUMENT) )
1378+
return !!v->arg_value;
1379+
1380+
return false;
1381+
}
1382+
1383+
#define argMoveUnify(w) LDFUNC(argMoveUnify, w)
1384+
static Word
1385+
argMoveUnify(DECL_LD word w)
1386+
{ VarDef v = varInfo(w);
1387+
1388+
if ( ison(v, VD_ARGUMENT) && isoff(v, VD_ARGUMENT_DONE) )
1389+
{ set(v, VD_ARGUMENT_DONE);
13771390
return v->arg_value;
1391+
}
13781392

13791393
return NULL;
13801394
}
@@ -2704,13 +2718,15 @@ Non-void variables. There are many cases for this.
27042718
Output_0(ci, B_VAR);
27052719
}
27062720
} else /* head */
2707-
{ if ( !(where & A_ARG) && first )
2721+
{ if ( !(where & A_ARG) )
27082722
{ Word p;
27092723

2710-
if ( (p=argUnifiedTo(*arg)) )
2724+
if ( (p=argMoveUnify(*arg)) )
27112725
return compileArgument(p, where, ci);
2712-
Output_0(ci, H_VOID);
2713-
return true;
2726+
if ( first )
2727+
{ Output_0(ci, H_VOID);
2728+
return true;
2729+
}
27142730
}
27152731
if ( argUnifiedTo(*arg) )
27162732
set(ci->clause, CL_HEAD_TERMS);
@@ -3642,8 +3658,13 @@ skippedVar(DECL_LD Word arg, compileInfo *ci)
36423658
}
36433659

36443660

3661+
/**
3662+
* Test whether the unification already took place because it
3663+
* as moved to the head.
3664+
*/
3665+
36453666
#define isUnifiedArg(a1, a2) LDFUNC(isUnifiedArg, a1, a2)
3646-
static int
3667+
static bool
36473668
isUnifiedArg(DECL_LD Word a1, Word a2)
36483669
{ if ( isVarInfo(*a1) )
36493670
{ VarDef vd = varInfo(*a1);

tests/core/test_moved_ubody.pl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@
101101
D = since(_,_),
102102
C = D.
103103

104+
s9(X, Y) :-
105+
X = f(Y),
106+
Y = a.
107+
104108
test(decom1, (Head :- Body) =@= (nf_add([B|Bs], CLP, A, As, Cs) :-
105109
A = v(Ka,Pa),
106110
B = v(Kb,Pb),
@@ -143,5 +147,10 @@
143147
test(decomp9, (Head :- Body) =@= (s8(A,B) :- A=since(_,_),B=A)) :-
144148
Head = s8(_,_),
145149
clause(Head, Body).
150+
test(run9, X+Y == f(a)+a) :-
151+
s9(X,Y).
152+
test(decomp9, (Head :- Body) =@= (s9(f(Y),Y) :- Y = a)) :-
153+
Head = s9(_,_),
154+
clause(Head, Body).
146155

147156
:- end_tests(moved_decompile).

0 commit comments

Comments
 (0)