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

Implementation of ISO throw/catch in the Warren abstract machine.

98 views
Skip to first unread message

Mark Thom

unread,
Aug 8, 2017, 6:08:32 PM8/8/17
to
Hi all,

I'm curious about the implementation of ISO-compliant throw/catch in the WAM, which I can't seem to find documented anywhere. I ask because I'm trying to add throw/catch to my own hobbyist WAM (which you can find at http://github.com/mthom/rusty-wam) and want to be reasonably efficient about it.

I have an idea of how it might be implemented, but it's very naive. Here it is in broad strokes:

1) ensure each catch instruction is bracketed by allocate / deallocate instructions in the WAM. The newly created environment frame will have written to it a catch_marker to flag the presence of a catch in the environment, just before catch calls its first argument.

2) create a choice point to store the contents of registers A2 and A3, which give the heap locations of the terms Ball and Handler in "catch(Pred, Ball, Handler)". this will also give needed info for unwinding the trail, truncating the heap, etc. in case an exception is thrown.

I have the sense that adding both a choice point and an environment frame is extraneous. Am I right about that?

Thanks.

Joachim Schimpf

unread,
Aug 8, 2017, 7:38:23 PM8/8/17
to
On 08/08/17 23:08, Mark Thom wrote:
> Hi all,
>
> I'm curious about the implementation of ISO-compliant throw/catch in the WAM, which I can't seem to find documented anywhere.


Bart Demoen, On the Implementation of Catch and Throw in WAM (1990)
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.57.4354


Cheers,
Joachim

Mark Thom

unread,
Aug 8, 2017, 8:35:42 PM8/8/17
to
Apparently I didn't search very hard! Thank you.

burs...@gmail.com

unread,
Aug 9, 2017, 4:07:36 AM8/9/17
to
The PDF behind the link is scrambled (5 minutes before).
Now if I look the PDF behind the link is even gone.

Am Mittwoch, 9. August 2017 01:38:23 UTC+2 schrieb Joachim Schimpf:
> Bart Demoen, On the Implementation of Catch and Throw in WAM (1990)
> http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.57.4354

But if I remember well the ISO core standard
also describes how catch/throw should work:

7.7 Executing a Prolog Goal
7.8.9 catch/3
7.8.10 throw/1

I guess some frame structure will be needed, not necesarely
a choice point, something along the call stack and
not along the backtracking list.

But the backtracking list needs to be removed as well.
The most interesting solution is in SWI-Prolog,
which also covers setup_call_cleanup/3 considerations,

which are not covered by the ISO core standard.

burs...@gmail.com

unread,
Aug 9, 2017, 4:10:16 AM8/9/17
to

Mark Thom

unread,
Aug 10, 2017, 11:39:27 PM8/10/17
to
I tried to look into how SWI Prolog implements exceptions and came up empty.

I did manage to find the Demoen paper, though. It looks like it should comply with the ISO standard. You just need to make a copy of the ball before passing it to the handler.

burs...@gmail.com

unread,
Aug 11, 2017, 5:54:36 AM8/11/17
to
There is also a way to cheat, in implementing
throw/catch. If your host language has exception
handling, for example if it has some try/catch and
can unwind the stack.

You might simply recursively call the interpreter
loop of the WAM and do some additional bookkeeping.
Disadvantage is that the host language call
stack is used.

An error term binding back and forth between the host
language can be also useful, for these scenarios:
- Calling foreign functions.
- The interpreter being called from the environment:
- For example GUI callbacks.
- Or simply entering the top-level

In my case the host language is Java, and I am for
example automaticall mapping a Java ArithmeticException
to a Prolog evaluation_error.

j4n bur53

unread,
Aug 11, 2017, 6:25:54 AM8/11/17
to
Hi,

Since non-deterministic solutions should permeate,
i.e. we have for example:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- catch((X=1;X=2;X=3),_,_).
X = 1 ;
X = 2 ;
X = 3

When using the host language trick, you need a full
fledged choice point. At least I didn't figure how
to get rid of the catch choice point in this aproach

yet. For other implementations I can imagine that not
really a full fledged choice point is needed. The choice
point and the extra call/1 can be a little annoying,

For example a predicate:

append([],X,X).
append([X|Y],Z,[X|T]) :-
append(Y,Z,T)

Works neatly with last call optimization. But this
code variant, not only crashes the host stack by an overflow,
when I use the trick, also last call is not anymore detected:

append([],X,X).
append([X|Y],Z,[X|T]) :-
catch(append(Y,Z,T),_,_).

So the host language trick also means to use catch only
sparingly, and I guess this advice also holds for
other implementations of catch/throw.

Bye

burs...@gmail.com schrieb:

ken...@gmail.com

unread,
Aug 12, 2017, 3:02:33 AM8/12/17
to
Hello

I've implemented catch/throw to my interpreter.
I wonder about compatibility with ISO-Prolog.
Please show me some test codes for catch/throw.

O-Prolog Ver0.57
| ?-catch(write(1),tag(E),(write(E),write(end))),throw(tag(2)).
12endyes
|

Kenichi Sasagawa

burs...@gmail.com

unread,
Aug 12, 2017, 5:27:17 AM8/12/17
to
This is wrong, this is not catch/3. catch/3 is not
able to catch events in the continuation. It can
only catch exceptions occuring in G, but not in H:

catch(G, _, _), H

The catch "block", is the goals in G, and every
subgoal that is created during solving G. And throw
statement or thread interruption in G is catched.

The goals in H cannot be catched by the above
catch/3 control construct. Since any throw in
H is outside of the scope of the catch "block".

So the behaviour is:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- catch(write(1),tag(E),(write(E),write(end))), throw(tag(2)).
1
ERROR: Unhandled exception: tag(2)

Means the throw(tag(2)) permeates to the toplevel, and
is not catched by the catch/3 control construct in the
query. This is seen by the "Unhandled..." message.

What is this term "events in the continuation" I am using
for when something happens in H and not G. Well this
is terminology from setup_call_clean/3.
You find the following classification of events:

== event in the catch block ==
exception(Exception)
Goal raised the given exception.

== event in the continuation ==
external_exception(Exception)
Goal succeeded and it is now discarded due to an exception.

The ISO catch/3 is supposed to only catch events in the
catch block but not events in the continuation. On the other
hand the setup_call_cleanup/3 would execute the cleanup also

for when there is an event in the continuation. There is
no ISO definition for setup_call_cleanup/3 , but a
relatively good draft for it:
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/cleanup

ken...@gmail.com

unread,
Aug 12, 2017, 6:10:22 AM8/12/17
to
I see.
Thank you for detailed explanation.

Kenichi Sasagawa

burs...@gmail.com

unread,
Aug 12, 2017, 8:02:29 AM8/12/17
to
I guess you are very close in implementing both
setup_call_cleanup/3 and catch/3, and you might
consider also implementing setup_call_cleanup/3
and not only catch/3.

setup_call_cleanup/3 is very useful for dealing
with resources such as files, database, web
services, locks, etc.. etc... it is used in many
places for example in SWI-Prolog:

74 code results in SWI-Prolog/swipl-devel
https://github.com/SWI-Prolog/swipl-devel/search?utf8=%E2%9C%93&q=setup_call_cleanup&type=

ken...@gmail.com

unread,
Aug 12, 2017, 3:46:19 PM8/12/17
to
I guess that setup_call_cleanup/3 is similar to unwind-protect of Lisp.
Thank you.

Kenichi sasagawa

ken...@gmail.com

unread,
Aug 13, 2017, 7:41:39 AM8/13/17
to
I've updated my Prolog implementation.
I would like to effort to be compatible with ISO-Prolog.
At first, I gave my implementation catch/throw predicate and debugger.
http://eisl.kan-be.com/library/oprolog1.html

Kenichi Sasagawa


Markus Triska

unread,
Aug 13, 2017, 4:02:56 PM8/13/17
to
ken...@gmail.com writes:

> I guess that setup_call_cleanup/3 is similar to unwind-protect of Lisp.

Yes, it is similar, but setup_call_cleanup/3 is more powerful because
the setup goal is protected from asynchronous interrupts!

This would be extremely useful in Lisp too. Consider for example the
following feature suggestion for Emacs Lisp to reliably prevent a bug:

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=23963

Without such a feature, there are cases where interrupting the form
prevents reliable cleanup. setup_call_cleanup/3 helps to ensure it!

All the best,
Markus

--
comp.lang.prolog FAQ: http://www.logic.at/prolog/faq/
The Power of Prolog: https://www.metalevel.at/prolog

ken...@gmail.com

unread,
Aug 13, 2017, 7:22:57 PM8/13/17
to
I'm interested in setup_call_cleanup/3.
I will implement it to my interpreter.
Thank you.

Kenichi Sasagawa

Ulrich Neumerkel

unread,
Aug 15, 2017, 8:53:25 AM8/15/17
to
ken...@gmail.com writes:
>I'm interested in setup_call_cleanup/3.
>I will implement it to my interpreter.

Please refer to

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/cleanup

This is currently document post-N215. There are a couple of
test cases you might want to use.

(Any comment & question welcome, but please use a new subject
or even better, use SO)

ken...@gmail.com

unread,
Aug 16, 2017, 3:46:57 AM8/16/17
to
> http://www.complang.tuwien.ac.at/ulrich/iso-prolog/cleanup
>
> This is currently document post-N215. There are a couple of
> test cases you might want to use.

Thank you so much.

Kenichi Sasagawa
0 new messages