Exceptions from C

Consider, for example, a function returning the square root of its argument after checking that the argument is valid. If the argument is invalid, the function should raise an exception instead.

                               
/* math.c */
#include <math.h> #include <stdio.h> #include <sicstus/sicstus.h> extern double sqrt_check(double d); double sqrt_check(double d) { if (d < 0.0) { /* build a domain_error/4 exception term */ SP_term_ref culprit=SP_new_term_ref(); SP_term_ref argno=SP_new_term_ref(); SP_term_ref expdomain=SP_new_term_ref(); SP_term_ref t1=SP_new_term_ref(); SP_put_float(culprit, d); SP_put_integer(argno, 1); SP_put_string(expdomain, ">=0.0"); SP_cons_functor(t1, SP_atom_from_string("sqrt"), 1, culprit); SP_cons_functor(t1, SP_atom_from_string("domain_error"), 4, t1, argno, expdomain, culprit); SP_raise_exception(t1); /* raise the exception */ return 0.0; } return sqrt(d); }

The Prolog interface to this function is defined in a file math.pl. The function uses the sqrt() library function, and so the math library -lm has to be included:

                                  
% math.pl
foreign_resource(math, [sqrt_check]). foreign(sqrt_check, c, sqrt(+float, [-float])). :- load_foreign_resource(math).

A linked foreign resource is created:

     % splfr math.pl math.c -lm
     

A simple session using this function could be:

     % sicstus
     SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
     Licensed to SICS
     | ?- [math].
     % consulting /home/san/pl/math.pl...
     % /home/san/pl/math.pl consulted, 10 msec 816 bytes
     
     | ?- sqrt(5.0,X).
     
     X = 2.23606797749979
     
     | ?- sqrt(a,X).
     ! Type error in argument 1 of user:sqrt/2
     ! number expected, but a found
     ! goal:  sqrt(a,_143)
     
     | ?- sqrt(-5,X).
     ! Domain error in argument 1 of user:sqrt/1
     ! expected '>=0.0', found -5.0
     ! goal:  sqrt(-5.0)
     

The above example used the foreign language interface with dynamic linking. To statically link math.s.o with the Prolog emulator, the following steps would have been taken:

     % splfr -S math.pl math.c -lm
     SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
     Licensed to SICS
     % spXxQwsr.c generated, 0 msec
     
     % spld -D -o mathsp --resources=./math.s.o
     SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
     Licensed to SICS
     % spYdLTgi1.c generated, 0 msec
     
     Created "mathsp"
     % ./mathsp
     SICStus 3.9 (sparc-solaris-5.7): Thu Aug 19 16:25:28 MET DST 1999
     Licensed to SICS
     | ?- [math].
     % consulting /a/filur/export/labs/isl/sicstus/jojo/sicstus38p/math.pl...
     % consulted /a/filur/export/labs/isl/sicstus/jojo/sicstus38p/math.pl in module user, 0 msec 960 bytes
     
     | ?- sqrt(5.0,X).
     
     X = 2.23606797749979