From: lhe@sics.se (Lars-Henrik Eriksson)
Subject: Re: SICStus prolog problem
Reply-To: lhe@sics.se (Lars-Henrik Eriksson)
Organization: SICS, Kista (Stockholm), Sweden
Date: Wed, 26 Aug 1992 14:53:53 GMT

In article <714823911.21006@minster.york.ac.uk> cjhs@minster.york.ac.uk writes:
>: I have a program in SICStus prolog that makes extensive use of the wait
>: declaration. Program (137 lines) supplied to anyone who is curious.
>: 
>: The problem is that it runs ok interpreted, but fails when compiled.
>: Insertion of a diagnostic in a critical place makes the compiled
>: version behave like the interpreted version.

I suspect that the problem you have run into is the same one that I
once encountered and that caused me much grief before I got an
explanation and a workaround.

If you have a clause body that looks like this:

	.... baz(...), !, ....

and the call to baz causes blocked goals to run, the compiler executes
the cut *before* running the blocked goals. This may cause the program
to fail even if it works correctly under the interpreter.

The following program illustrates the point:

	:- block bar(-). /* :- wait bar/1 before SICStus 2.0 /*
	foo :- bar(X), baz(X), !.
	bar(2).
	baz(X) :- X=1.
	baz(X) :- X=2.

The reason baz/1 is written in a slightly odd way is to prevent
indexing. It is essential that a choicepoint is created.

Calling foo/0 as a goal succeeds under the interpreter, but fails
under the compiler.

The compiled code calls baz(X), which succeeds, binding X to 1. The
call to bar/1 is now unblocked, but *not* run.  First Sicstus cuts
away the choice point in baz/1, *then* calls the unblocked goal. Of
course bar(1) will fail, and since the choicepoint in baz/1 has been
cut away, the call to foo/0 will also fail.

The interpreter will do the cut only *after* calling bar/1, so in that
case foo/0 will succeed.

Running the program gives the following result:

	SICStus 2.1 #5: Fri Apr 24 17:00:24 MET DST 1992
	| ?- [foo].
	{consulting /home1/lhe/foo.pl...}
	{/home1/lhe/foo.pl consulted, 20 msec 1104 bytes}

	yes
	| ?- foo.

	yes
	| ?- compile(foo).
	{compiling /home1/lhe/foo.pl...}
	{/home1/lhe/foo.pl compiled, 100 msec 512 bytes}

	yes
	| ?- foo.

	no

The solution is to insert a dummy goal (likely the diagnostic in your
case!) before the cut, e.g.

	foo :- bar(X), baz(X), true, !.

Now the compiled code runs as expected.

>: SICStus 0.6 #17: Mon Apr 9 09:37:54 BST 1990
>: Copyright (C) 1987, Swedish Institute of Computer Science.
>: All rights reserved.
>: 
>: Am I out of date? Who can I contact to fix the problem?

As you can see, I run the latest version of Sicstus, and the problem
is still there. According to Mats Carlsson, the Sicstus implementor,
there is no good way of changing the implementation to avoid the
problem.

The manual should really state clearly that this can happen. Not
everyone is as fortunate as I to work in the same place as the
Sicstus implementor.
-- 
Lars-Henrik Eriksson                            Internet: lhe@sics.se
Swedish Institute of Computer Science           Phone (intn'l): +46 8 752 15 09
Box 1263                                        Telefon (nat'l): 08 - 752 15 09
S-164 28  KISTA, SWEDEN                         Fax: +46 8 751 72 30