[m-rev.] Re: [m-dev.] question about exception.m and also mode-specific clauses

Fergus Henderson fjh at cs.mu.OZ.AU
Sun Aug 19 02:31:34 AEST 2001


On 17-Aug-2001, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> The diff is a good idea.  I have but one comment:
> 
> > +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")
> > +	).
> 
> This isn't right, Det = semidet should be here.
> 
> Did the compiler accept this?

No.  I made the mistake of not compiling before I posted the diff.
(I knew that I'd need a compiler with Simon's changes in it to get
the diff to compile, and being in a bit of a hurry... well never mind,
obviously not compiling it *was* a mistake.  Clearly I need a holiday! ;-)

As well as that one, there were a couple of other errors that the compiler
picked up (I had omitted the `pragma promise_pure' declarations for
get_determinism/2 and get_determinism_2/2; also I had clauses for `erroneous'
and `failure' in get_determinism/2.  but there weren't declared modes for them).

Unfortunately after all these errors are corrected, the compiler still
issues the same warnings about "declared `cc_multi', inferred `det'"
for all of these clauses.  I had thought that determinism inference
would infer these disjunctions as `cc_multi', but in fact it notices
that error/1 has determinism `erroneous', i.e. cannot succeed, and hence
infers that the disjunction has at most one solution...

The solution is to go back to the usual workaround for determinism
warnings, use semidet_succeed/semidet_fail/cc_multi_equal,
in this case cc_multi_equal:

	get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
		( cc_multi_equal(det, Det)
		; error("get_determinism")
		).

There was also a problem in my change to library/Mmakefile:
it should use `MCFLAGS +=' rather than `MCFLAGS =',
since MCFLAGS is set earlier by Mmake.common.

I am going to compound my earlier mistake and post another diff without having
run a full bootcheck yet.  Hopefully I will get away with it this time ;-)
I've attached a relative diff and a new full diff.

-- 
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.
-------------- next part --------------
diff -u library/exception.m library/exception.m
--- library/exception.m
+++ library/exception.m
@@ -229,49 +229,45 @@
 % it will pick the first disjunct and discard the call to error/1.
 % This relies on --no-reorder-disj.
 
+:- pragma promise_pure(get_determinism/2).
+
 get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
-	( Det = det
+	( cc_multi_equal(det, Det)
 	; error("get_determinism")
 	).
 get_determinism(_Pred::(pred(out) is semidet), Det::out(bound(semidet))) :-
-	( Det = det
+	( cc_multi_equal(semidet, Det)
 	; error("get_determinism")
 	).
 get_determinism(_Pred::(pred(out) is cc_multi), Det::out(bound(cc_multi))) :-
-	( Det = cc_multi
+	( cc_multi_equal(cc_multi, Det)
 	; error("get_determinism")
 	).
 get_determinism(_Pred::(pred(out) is cc_nondet), Det::out(bound(cc_nondet))) :-
-	( Det = cc_nondet
+	( cc_multi_equal(cc_nondet, Det)
 	; error("get_determinism")
 	).
 get_determinism(_Pred::(pred(out) is multi), Det::out(bound(multi))) :-
-	( Det = multi
+	( cc_multi_equal(multi, Det)
 	; 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
+	( cc_multi_equal(nondet, Det)
 	; error("get_determinism")
 	).
 
+:- pragma promise_pure(get_determinism_2/2).
+
 get_determinism_2(
 	_Pred::pred(out, di, uo) is det,
 			Det::out(bound(det))) :-
-	( Det = det
+	( cc_multi_equal(det, Det)
 	; error("get_determinism_2")
 	).
 get_determinism_2(
-	_Pred::pred(out, di, uo) is det,
+	_Pred::pred(out, di, uo) is cc_multi,
 			Det::out(bound(cc_multi))) :-
-	( Det = cc_multi
+	( cc_multi_equal(cc_multi, Det)
 	; error("get_determinism_2")
 	).
 
diff -u library/Mmakefile library/Mmakefile
--- library/Mmakefile
+++ library/Mmakefile
@@ -30,7 +30,7 @@
 #     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
+MCFLAGS += --strict-sequential
 
 # XXX The following is needed only for bootstrapping
 # the new modes of int__xor.
-------------- next part --------------
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: /home/venus/fjh/ws-venus4/mercury
Index: library/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/library/Mmakefile,v
retrieving revision 1.76
diff -u -d -r1.76 Mmakefile
--- library/Mmakefile	3 Aug 2001 12:30:50 -0000	1.76
+++ library/Mmakefile	18 Aug 2001 16:23:55 -0000
@@ -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
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	3 Jul 2001 08:16:25 -0000	1.49
+++ library/exception.m	18 Aug 2001 16:21:34 -0000
@@ -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
@@ -225,159 +222,54 @@
 :- 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
-").
+% 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(_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 promise_pure(get_determinism/2).
 
-:- 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);"
-).
+get_determinism(_Pred::(pred(out) is det), Det::out(bound(det))) :-
+	( cc_multi_equal(det, Det)
+	; error("get_determinism")
+	).
+get_determinism(_Pred::(pred(out) is semidet), Det::out(bound(semidet))) :-
+	( cc_multi_equal(semidet, Det)
+	; error("get_determinism")
+	).
+get_determinism(_Pred::(pred(out) is cc_multi), Det::out(bound(cc_multi))) :-
+	( cc_multi_equal(cc_multi, Det)
+	; error("get_determinism")
+	).
+get_determinism(_Pred::(pred(out) is cc_nondet), Det::out(bound(cc_nondet))) :-
+	( cc_multi_equal(cc_nondet, Det)
+	; error("get_determinism")
+	).
+get_determinism(_Pred::(pred(out) is multi), Det::out(bound(multi))) :-
+	( cc_multi_equal(multi, Det)
+	; error("get_determinism")
+	).
+get_determinism(_Pred::(pred(out) is nondet), Det::out(bound(nondet))) :-
+	( cc_multi_equal(nondet, Det)
+	; error("get_determinism")
+	).
 
-:- 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);"
-).
+:- pragma promise_pure(get_determinism_2/2).
 
+get_determinism_2(
+	_Pred::pred(out, di, uo) is det,
+			Det::out(bound(det))) :-
+	( cc_multi_equal(det, Det)
+	; error("get_determinism_2")
+	).
+get_determinism_2(
+	_Pred::pred(out, di, uo) is cc_multi,
+			Det::out(bound(cc_multi))) :-
+	( cc_multi_equal(cc_multi, Det)
+	; error("get_determinism_2")
+	).
 
 % These are not worth inlining, since they will
 % (presumably) not be called frequently, and so


More information about the reviews mailing list