[m-dev.] question about exception.m and also mode-specific clauses
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Aug 17 21:29:12 AEST 2001
On 17-Aug-2001, Tyson Dowd <trd at miscrit.be> wrote:
> On 17-Aug-2001, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > On 17-Aug-2001, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > > One way to solve this is by writing each mode-specific clause so that
> > > it contains a disjunction, with the only difference between the clauses
> > > for different modes being that the disjuncts are in a different order.
> >
> > Forgot to mention that this will solve *both* the warning
> > *and* the problem that the semantics of different modes don't match.
>
> I'm not sure I fully understand what you are proposing.
>
> Something like:
>
> get_determinism(_Pred::(pred(out) is det), det::out(bound(det))).
> get_determinism(_Pred::(pred(out) is det), det::out(bound(semidet))).
> get_determinism(_Pred::(pred(out) is det), det::out(bound(nondet))).
> get_determinism(_Pred::(pred(out) is det), det::out(bound(cc_multi))).
> get_determinism(_Pred::(pred(out) is det), det::out(bound(multi))).
No. I was thinking of something like
get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
( Det = det
% these are unreachable
; Det = erroneous
; Det = multi
; Det = cc_multi
; Det = failure
; Det = semidet
; Det = nondet
; Det = cc_nondet
).
get_determinism(_Pred::(pred(out) is semidet),
Det::out(bound(semidet))) :-
( Det = semidet
% these are unreachable
; Det = erroneous
; Det = det
; Det = multi
; Det = cc_multi
; Det = failure
; Det = nondet
; Det = cc_nondet
).
... etc.
Or more simply, abstracting out the common code:
get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
( Det = det
; is_det(Det)
).
get_determinism(_Pred::(pred(out) is semidet),
Det::out(bound(semidet))) :-
( Det = semidet
; is_det(Det)
).
... etc. ...
is_det(erroneous).
is_det(det).
is_det(multi).
is_det(cc_multi).
is_det(failure).
is_det(semidet).
is_det(nondet).
is_det(cc_nondet).
Or even more simply:
get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
( Det = det
; true
).
get_determinism(_Pred::(pred(out) is semidet),
Det::out(bound(semidet))) :-
( Det = semidet
; true
).
... etc. ...
However, those don't actually work; you get a mode error because `Det' isn't
bound to the right subtype in the unreachable disjuncts.
To make it work, you need to put a call to error/1 instead of is_det/1 or
true/0.
So how about the following diff?
----------
Estimated hours taken: 1
Branches: main
library/exception.m:
Use mode-specific Mercury code rather than C code.
library/Mmakefile:
Compile the library with --strict-sequential.
This is needed by the new code in exception.m
and is a good idea anyway.
Workspace: /mnt/venus/home/venus/fjh/ws-venus4/mercury
Index: library/exception.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/exception.m,v
retrieving revision 1.49
diff -u -d -r1.49 exception.m
--- library/exception.m 2001/07/03 08:16:25 1.49
+++ library/exception.m 2001/08/17 11:18:44
@@ -196,9 +196,6 @@
:- mode try_all(in(bound(nondet)), pred(out) is nondet,
out(try_all_nondet)) is cc_multi.
-% The functors in this type must be in the same order as the
-% enumeration constants in the foreign language enums `ML_Determinism'
-% defined below.
:- type determinism
---> det
; semidet
@@ -224,160 +221,59 @@
is cc_multi.
:- mode get_determinism_2(pred(out, di, uo) is cc_multi, out(bound(cc_multi)))
is cc_multi.
-
-% Unfortunately the only way to implement get_determinism/2 is to use
-% the C interface, since Mercury doesn't allow different code for different
-% modes.
-
-:- pragma foreign_decl("C", "
-/* The `#ifndef ... #define ... #endif' guards against multiple inclusion */
-#ifndef ML_DETERMINISM_GUARD
-#define ML_DETERMINISM_GUARD
- /*
- ** The enumeration constants in this enum must be in the same
- ** order as the functors in the Mercury type `determinism'
- ** defined above.
- */
- typedef enum {
- ML_DET,
- ML_SEMIDET,
- ML_CC_MULTI,
- ML_CC_NONDET,
- ML_MULTI,
- ML_NONDET,
- ML_ERRONEOUS,
- ML_FAILURE
- } ML_Determinism;
-#endif
-").
-
-:- pragma foreign_proc("C",
- get_determinism(_Pred::pred(out) is det,
- Det::out(bound(det))),
- will_not_call_mercury,
- "Det = ML_DET"
-).
-:- pragma foreign_proc("C",
- get_determinism(_Pred::pred(out) is semidet,
- Det::out(bound(semidet))),
- will_not_call_mercury,
- "Det = ML_SEMIDET"
-).
-:- pragma foreign_proc("C",
- get_determinism(_Pred::pred(out) is cc_multi,
- Det::out(bound(cc_multi))),
- will_not_call_mercury,
- "Det = ML_CC_MULTI"
-).
-:- pragma foreign_proc("C",
- get_determinism(_Pred::pred(out) is cc_nondet,
- Det::out(bound(cc_nondet))),
- will_not_call_mercury,
- "Det = ML_CC_NONDET"
-).
-:- pragma foreign_proc("C",
- get_determinism(_Pred::pred(out) is multi,
- Det::out(bound(multi))),
- will_not_call_mercury,
- "Det = ML_MULTI"
-).
-:- pragma foreign_proc("C",
- get_determinism(_Pred::pred(out) is nondet,
- Det::out(bound(nondet))),
- will_not_call_mercury,
- "Det = ML_NONDET"
-).
-
-:- pragma foreign_proc("C",
- get_determinism_2(_Pred::pred(out, di, uo) is det,
- Det::out(bound(det))),
- will_not_call_mercury,
- "Det = ML_DET"
-).
-
-:- pragma foreign_proc("C",
- get_determinism_2(_Pred::pred(out, di, uo) is cc_multi,
- Det::out(bound(cc_multi))),
- will_not_call_mercury,
- "Det = ML_CC_MULTI"
-).
-
-:- pragma foreign_decl("MC++", "
-/* The `#ifndef ... #define ... #endif' guards against multiple inclusion */
-#ifndef ML_DETERMINISM_GUARD
-#define ML_DETERMINISM_GUARD
-
- /*
- ** The constants in these #defines must be in the same
- ** order as the functors in the Mercury type `determinism'
- ** defined above.
- ** XXX It would be nice to use an enum here, but at the moment
- ** I can't convince the MC++ compiler to accept the syntax for it.
- */
-
-#define ML_DET 0
-#define ML_SEMIDET 1
-#define ML_CC_MULTI 2
-#define ML_CC_NONDET 3
-#define ML_MULTI 4
-#define ML_NONDET 5
-#define ML_ERRONEOUS 6
-#define ML_FAILURE 7
-#endif
-").
-
-:- pragma foreign_proc("MC++",
- get_determinism(_Pred::pred(out) is det,
- Det::out(bound(det))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_DET);"
-).
-:- pragma foreign_proc("MC++",
- get_determinism(_Pred::pred(out) is semidet,
- Det::out(bound(semidet))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_SEMIDET);"
-).
-:- pragma foreign_proc("MC++",
- get_determinism(_Pred::pred(out) is cc_multi,
- Det::out(bound(cc_multi))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_CC_MULTI);"
-).
-:- pragma foreign_proc("MC++",
- get_determinism(_Pred::pred(out) is cc_nondet,
- Det::out(bound(cc_nondet))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_CC_NONDET);"
-).
-:- pragma foreign_proc("MC++",
- get_determinism(_Pred::pred(out) is multi,
- Det::out(bound(multi))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_MULTI);"
-).
-:- pragma foreign_proc("MC++",
- get_determinism(_Pred::pred(out) is nondet,
- Det::out(bound(nondet))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_NONDET);"
-).
-
-:- pragma foreign_proc("MC++",
- get_determinism_2(_Pred::pred(out, di, uo) is det,
- Det::out(bound(det))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_DET);"
-).
+% The calls to error/1 here are needed to ensure that the
+% declarative semantics of each clause is equivalent,
+% but operationally they are unreachable;
+% since each mode has determinism cc_multi,
+% it will pick the first disjunct and discard the call to error/1.
+% This relies on --no-reorder-disj.
-:- pragma foreign_proc("MC++",
- get_determinism_2(_Pred::pred(out, di, uo) is cc_multi,
- Det::out(bound(cc_multi))),
- will_not_call_mercury,
- "MR_newenum(Det, ML_CC_MULTI);"
-).
+get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
+ ( Det = det
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is semidet), Det::out(bound(semidet))) :-
+ ( Det = det
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is cc_multi), Det::out(bound(cc_multi))) :-
+ ( Det = cc_multi
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is cc_nondet), Det::out(bound(cc_nondet))) :-
+ ( Det = cc_nondet
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is multi), Det::out(bound(multi))) :-
+ ( Det = multi
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is nondet), Det::out(bound(nondet))) :-
+ ( Det = nondet
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is erroneous), Det::out(bound(erroneous))) :-
+ ( Det = erroneous
+ ; error("get_determinism")
+ ).
+get_determinism(_Pred::(pred(out) is failure), Det::out(bound(failure))) :-
+ ( Det = failure
+ ; error("get_determinism")
+ ).
+get_determinism_2(
+ _Pred::pred(out, di, uo) is det,
+ Det::out(bound(det))) :-
+ ( Det = det
+ ; error("get_determinism_2")
+ ).
+get_determinism_2(
+ _Pred::pred(out, di, uo) is det,
+ Det::out(bound(cc_multi))) :-
+ ( Det = cc_multi
+ ; error("get_determinism_2")
+ ).
% These are not worth inlining, since they will
% (presumably) not be called frequently, and so
Index: library/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/library/Mmakefile,v
retrieving revision 1.76
diff -u -d -r1.76 Mmakefile
--- library/Mmakefile 2001/08/03 12:30:50 1.76
+++ library/Mmakefile 2001/08/17 11:25:00
@@ -22,11 +22,18 @@
VPATH=.
#-----------------------------------------------------------------------------#
-#
+
+# We need to compile the library with --strict-sequential for two reasons:
+# (1) Otherwise Mercury code that is compiled with --strict-sequential
+# might do the wrong thing, because the standard library wasn't compiled
+# with --strict-sequential. (We could make it a separate grade, but
+# that's not worth it.)
+# (2) The code for get_determinism in library/exception.m relies on it
+# (in particular it relies on --no-reorder-disj).
+MCFLAGS = --strict-sequential
+
# XXX The following is needed only for bootstrapping
# the new modes of int__xor.
-#
-
MCFLAGS-int = --no-halt-at-warn
# Modules which use user-guided type specialization need to be
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list