Currently experimenting with this guard, might be more

complicated for modules. Where does this guard come from?

Derived from ISO body conversion algorithm:

```
sys_trans_allowed(V) :- var(V), !, fail.
sys_trans_allowed((A,B)) :- sys_trans_allowed(A), sys_trans_allowed(B).
sys_trans_allowed((A;B)) :- sys_trans_allowed(A), sys_trans_allowed(B).
sys_trans_allowed((A->B)) :- sys_trans_allowed(A), sys_trans_allowed(B).
sys_trans_allowed(A) :- callable(A).
```

The idea of sys_trans_allowed/1 is to check whether the given

goal is âtroublesomeâ or not. A similar check that leads Ciao Prolog

to display a warning, only we do not check for the presence of cut (!)/1.

Rather the check is for naked variables that would get the call/1

treatment. Now if `sys_trans_allowed(A)`

holds, you can perform

these transformations:

```
/* Basically Done in SWI-Prolog */
\+ A ~~> (A -> fail; true)
/* Not available in SWI-Prolog, unlike other Prolog Systems */
once(A) ~~> (A -> true; fail)
```

Transformations from outside to inside. I get these result in

SWI-Prolog, observe that for A = p(X) the predicate sys_trans_allowed/1

holds and obsever that SWI-Prolog does not inline once/1:

```
test(1, X) :- \+ p(X).
test(2, X) :- once(p(X)).
?- vm_list(test/2).
/* \+ p(X) */
3 c_not(2,'L1')
6 b_var1
7 i_call(user:p/1)
9 c_cut(2)
11 c_fail
L1: 12 i_exit
/* once(X) */
3 b_functor(p/1)
5 b_argvar(1)
7 b_pop
8 i_depart(system:once/1)
10 i_exit
```

The above is fine, now consider a case where sys_trans_allowed/1

does not hold. Use A = (X,Y,Z) again. I get these results, SWI-Prolog

insists to still inline `(\+)/2`

:

```
test2(1,X,Y,Z) :- \+ (X,Y,Z).
test2(2,X,Y,Z) :- once((X,Y,Z)).
?- vm_list(test2/4).
/* \+ (X,Y,Z) */
3 c_not(4,'L1')
6 b_var1
7 i_usercall0
8 b_var2
9 i_usercall0
10 b_var(3)
12 i_usercall0
13 c_cut(4)
15 c_fail
L1: 16 i_exi
/* once((X,Y,Z)) */
3 b_functor((',')/2)
5 b_argvar(1)
7 b_rfunctor((',')/2)
9 b_argvar(2)
11 b_argvar(3)
13 b_pop
14 i_depart(system:once/1)
16 i_exit
```

Now observe that once/1 doesnât show a discrepancy between

inside a clause and inside a query. I get this result, no bug for

once/1 but a bug for `(\+)/1`

:

```
p(a).
p(b).
q(b).
/* Bug in (\+)/1 */
?- \+ (p(X),!,q(X)).
true.
?- test2(1,p(X),!,q(X)).
false.
/* No Bug in once/1 */
?- once((p(X),!,q(X))).
false.
?- test2(2,p(X),!,q(X)).
false.
```

The consistent result is because `once/1`

isnât inlined. So you could

fix the bug by not always inlining `(\+)/1`

or then inline it through some

approach that preserves semantics.