Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ANN: Jekejeke Prolog 1.5.0 (Dynamic Freshness)

140 views
Skip to first unread message

Mostowski Collapse

unread,
Mar 22, 2021, 6:24:05 AM3/22/21
to
Dear All,

We just uploaded a new release of Jekejeke Prolog. The
following major improvements are provided:

- Dynamic Freshness:
We rolled back the static compilation of unify_linear
instructions to optimize away the occurs check. Instead the
Prolog interpreter now uses a dynamic runtime heuristic, so
that it can decide whether a variable is fresh. Slightly
faster and little bit more versatile.

- var/1 Indexing:
We noticed that var/1 indexing was also applied to dynamic
predicates and could result in omitted clauses. var/1 Indexing
is now only applied to static predicates and as before, ISO
core standard compliant, we do not allow clause/2 for
static predicates.

- Rule Listing:
There are new predicates sys_rule/3 and sys_rule_ref/4
which allow access to the internal getList() which can
retrieve the clauses of a static predicate. Thanks to these
predicates listing/[0,1] and friends are now written in
Prolog itself.

Happy coding! #StaySafe

Jan Burse, 22.03.2021
http://www.jekejeke.ch/

Mostowski Collapse

unread,
Mar 24, 2021, 6:10:47 PM3/24/21
to
The var/1 indexing fix was done for reasons. SWI-Prolog
8.3.21 has now introduced body indexing as well. I don't
know whether it has var/1 indexing, but it has already

some body indexing:

p(X) :- X = f(_), g(X).

Now watch how clause/2 is broken:

/* SWI-Prolog 8.3.21 */
?- clause(p(g(A)), B).
false.

?- clause(p(C), B), C = g(A).
B = (g(A)=f(_26314), g(g(A))).

In release 1.5.0 of Jekejeke Prolog we avoid this mishap.
This mishap can lead to meta-interpreters that don't work as
before. So we invested some brains to avoid this mishap.

Mostowski Collapse

unread,
Mar 24, 2021, 6:20:21 PM3/24/21
to
A solution didn't seem simple at the beginning. But
then we recalled the ISO core standard which doesn't
allow clause/2 for static predicates. So whats

going on in release 1.5.0 of Jekejeke Prolog? Well
the following decisions were made:

- dynamic, thread_local and group_local predicates
are not body indexed. Thats new, that we automatically
switch off body indexing for these types of predicates.

- static predicates have body indexing as before. And
static predicates cannot be accessed as before, we
still refuse access of static predicates via clause/2.

- in case really static predicates need to be accessed,
there are the new sys_rule/3 and sys_rule_ref/4. These
bypass body indexing, even for static predicates.

So meta programming has now two options. Declare the
predicate dynamic and use clause/2, get the head indexing
only. Or do something with sys_rule/3 respectively sys_rule_ref/4

in case indexing isn't important.

Mostowski Collapse

unread,
Mar 25, 2021, 4:16:55 AM3/25/21
to
Ok its seems SWI-Prolog has also implemented the first policy.
The optimization is switched off for dynamic:

:- dynamic p/1.
p(X) :- X = f(_), g(X).

?- clause(p(g(A)), B).
B = (g(A)=f(_23292), g(g(A))).

Oki Doki. The release notes didn’t say so. Are there more differences
between dynamic and static now? What about thread local?

Mostowski Collapse

unread,
Mar 25, 2021, 4:26:22 AM3/25/21
to
It seems there is a new manual section for the thingy:

/* SWI-Prolog */
2.18.3 Indexing for body code
This transformation is only performed on static code.
https://www.swi-prolog.org/pldoc/man?section=indexbody

I got also a section for body indexing, which is already there for some years:

/* Jekejeke Prolog */
Body Indexing
Body indexing is only applied to clauses belonging to a static predicate.
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/05_run/10_docu/02_reference/07_theories/01_kernel/06_sharing.html

Mostowski Collapse

unread,
Mar 26, 2021, 5:08:17 AM3/26/21
to
With body indexing one can simplify DCG translation. Currently I get in
SWI-Prolog 8.3.21, the head movement is done by the DCG translation:

?- [user].
a --> [b], c.
a --> []

?- listing(a/2).
a([b|A], B) :-
c(A, B).
a(A, A).

?- expand_term((a --> [b], c), X).
X = (a([b|_1826], _1848):-c(_1826, _1848)).

?- expand_term((a --> []), X).
X = (a(_3086, _3086):-true).

But with body indexing the head movement is redundant,
one could also more simply translate:

?- listing(a/2).
a(A, B) :-
A = [b|C],
c(C, B).
a(A, B) :-
A = B.

But I dont know whether the compiler can do the corresponding movement.
The compiler also preferably recognizes that the first arguments ‘A’ are
unused in the body.

Mostowski Collapse

unread,
Apr 1, 2021, 5:11:10 AM4/1/21
to
Now I am happy that my Prolog system implements body indexing
without any movement. This allows me to observe others struggling
with body indexing that is based on movement. SWI-Prolog announced:

> Note that in the current (git) HEAD, a unification against a head
argument used as a guard is moved into the head. Also note that
this changes the semantics of =.

This would be Picat incompatible. Release 8.3.20 and 8.3.21 were
Picat compatible in this respect. So 8.2.22 might be the next release
that breaks compatibility.

Mostowski Collapse

unread,
Apr 1, 2021, 5:13:48 AM4/1/21
to
I hope the SWI-Prolog announcement is not an Aprils Fools day
joke. But one can try the following test cases. They show that
Picat doesn't move and old SWI didn't move.

Open source:

No unify movement in Picat
https://gist.github.com/jburse/7c71a2ae9ad7651b912f3920693438ad#file-swi-pi

No unify movement in SWI 8.3.20 and 8.3.21
SWI 8.3.22 not yet tested.
https://gist.github.com/jburse/7c71a2ae9ad7651b912f3920693438ad#file-swi-pl

Picat for Testing
https://github.com/mingodad/picat/actions/runs/682626585#artifacts

Thats why I am more a late adopter of head movements in my Prolog
system, since head movement poses a lot of semantic consistency
challenges. On the other hand indexing of nonvar/1 plus or (=)/2 or

indexing of (=)/2 only works, also for the pattern matcher (?-)/2.
Still holding back some changes. Head movement is easiest for
commutative operations, but subsumes_term/2 and (=)/2 do

not commute. Also nonvar/1 and (=)/2 do not commute.

Mostowski Collapse

unread,
Apr 1, 2021, 7:04:34 AM4/1/21
to
Woa! I finally got my head around what the Picat (?=>)/2 means.
The Picat documentation says:

The compiler converts Cond to once Cond if would otherwise
be possible for Cond to succeed more than once.

So Head, Cond ?=> Body could be translated as Head ?- once(Cond),
Body. All the compiler can do is omit once/1 when it sees for
example (=)/2. But it cannot change the semantic of (=)/2.

Same for (=>)/2. But dropping once/1 is also not that easy, since
(=)/2 might wake up attributed variables. I don’t know what Picat
means by “possible for Cond to succeed more than once”.

In (=>)/2 you don’t need to drop the once/1, since Head ?- once(Cond),
!, Body is the same as Head ?- Cond, !, Body. But again this
simplification only works if Cond doesn’t have cuts.
0 new messages