[m-rev.] for review: add `any_is_bound' pragma
David Overton
dmo at cs.mu.OZ.AU
Fri Jul 25 12:24:38 AEST 2003
On Thu, Jul 24, 2003 at 03:46:24PM +1000, Fergus Henderson wrote:
> On 24-Jul-2003, David Overton <dmo at cs.mu.OZ.AU> wrote:
> > Allow types to be declared as "solver" types using the syntax
> > `:- solver type ...'.
>
> extras/trailed_update/var.m and extras/clpr/cfloat.m
> should be modified to use the new syntax.
Done.
>
> There should be more test cases. In particular, there should be a
> test case to test that `any' matches `bound' for non-solver types.
> There should be some tests of whether `any' matches bound for polymorphic
> types (it should not) and for tuple types (where it should match unless
> one of the tuple elements is a solver type).
Done.
>
> > @@ -1070,19 +1082,37 @@
> > :- mode inst_matches_binding_3(in, in, in, in, out) is semidet.
> >
> > % Note that `any' is *not* considered to match `any' unless
> > -% Info ^ any_matches_any = yes.
> > +% Info ^ any_matches_any = yes or the type is a solver type.
>
> Shouldn't that be "or the type is not a solver type".
>
> Or, more correctly, "or the type is not a solver type (and does not
> contain any solver types)".
Yes, I've changed the comment.
>
> > +:- pred maybe_any_to_bound(maybe(type), module_info, uniqueness, inst).
> > +:- mode maybe_any_to_bound(in, in, in, out) is semidet.
>
> I suggest adding a comment for this predicate,
> e.g. (copied from your log message):
>
> % For a non-solver type t (i.e. any type declared without using
> % the `solver' keyword), the inst `any' should be considered
> % to be equivalent to a bound inst i where i contains all
> % the functors of the type t and each argument has inst `any'.
Done.
>
> > +maybe_any_to_bound(yes(Type), ModuleInfo, Uniq, Inst) :-
> > + \+ type_util__is_solver_type(ModuleInfo, Type),
> > + (
> > + type_constructors(Type, ModuleInfo, Constructors)
> > + ->
> > + constructors_to_bound_any_insts(Constructors, Uniq,
> > + ModuleInfo, BoundInsts0),
> > + list__sort_and_remove_dups(BoundInsts0, BoundInsts),
> > + Inst = bound(Uniq, BoundInsts)
> > + ;
> > + classify_type(Type, ModuleInfo, user_type)
> > + ->
> > + % XXX For a user-defined type for which constructors are not
> > + % available (e.g. an abstract type) we should return `nonvar',
> > + % but we don't have a `nonvar' inst (yet) so we fail, meaning
> > + % that we will use `any' for this type.
> > + fail
> > + ;
> > + Inst = ground(Uniq, none)
> > + ).
>
> I'm pretty sure it is not safe to use `ground' here in the cases where
> classify_type(Type, ModuleInfo, Category) returns Category = tuple_type
> or Category = polymorphic_type.
The code is correct (although not as robust as it could be). For
polymorphic_type, the call to type_util__is_solver_type will succeed so
maybe_any_to_bound will fail. For tuple types, the call to
type_constructors will succeed so we return the appropriate bound inst.
>
> The code should also be written so that it is robust against future
> changes to the builtin_type enum that classify_type returns, e.g.
> by having this code call a det function that covers all the different
> alternatives for builtin_type.
Done.
>
> Otherwise that looks fine.
Okay. I'll commit this now. Relative diff below.
--- CVSLOG.1 Fri Jul 25 12:15:36 2003
+++ CVSLOG Fri Jul 25 12:18:37 2003
@@ -81,4 +81,16 @@
tests/invalid/any_mode.m:
tests/invalid/any_mode.err_exp:
- Modify this test case to use a "solver" type instead of `int'.
+tests/hard_coded/any_free_unify.m:
+ Modify these test cases to use a "solver" type instead of `int'.
+
+tests/valid/any_matches_bound.m:
+tests/valid/Mmakefile:
+tests/invalid/Mmakefile:
+tests/invalid/any_should_not_match_bound.m:
+tests/invalid/any_should_not_match_bound.err_exp:
+ Add new test cases.
+
+extras/trailed_update/var.m:
+clpr/cfloat.m:
+ Modify to use the new `:- solver type' syntax.
diff -u compiler/inst_match.m compiler/inst_match.m
--- compiler/inst_match.m 22 Jul 2003 07:05:54 -0000
+++ compiler/inst_match.m 25 Jul 2003 01:41:04 -0000
@@ -1082,7 +1082,8 @@
:- mode inst_matches_binding_3(in, in, in, in, out) is semidet.
% Note that `any' is *not* considered to match `any' unless
-% Info ^ any_matches_any = yes or the type is a solver type.
+% Info ^ any_matches_any = yes or the type is not a solver type (and does not
+% contain any solver types).
inst_matches_binding_3(free, free, _, I, I).
inst_matches_binding_3(any(UniqA), any(UniqB), Type, Info0, Info) :-
( Info0 ^ any_matches_any = yes ->
@@ -1944,6 +1945,10 @@
%-----------------------------------------------------------------------------%
+ % For a non-solver type t (i.e. any type declared without using
+ % the `solver' keyword), the inst `any' should be considered
+ % to be equivalent to a bound inst i where i contains all
+ % the functors of the type t and each argument has inst `any'.
:- pred maybe_any_to_bound(maybe(type), module_info, uniqueness, inst).
:- mode maybe_any_to_bound(in, in, in, out) is semidet.
@@ -1957,16 +1962,34 @@
list__sort_and_remove_dups(BoundInsts0, BoundInsts),
Inst = bound(Uniq, BoundInsts)
;
- classify_type(Type, ModuleInfo, user_type)
+ type_may_contain_solver_type(Type, ModuleInfo)
->
- % XXX For a user-defined type for which constructors are not
- % available (e.g. an abstract type) we should return `nonvar',
- % but we don't have a `nonvar' inst (yet) so we fail, meaning
- % that we will use `any' for this type.
+ % For a type for which constructors are not available (e.g. an
+ % abstract type) and which may contain solver types, we fail,
+ % meaning that we will use `any' for this type.
fail
;
Inst = ground(Uniq, none)
).
+
+:- pred type_may_contain_solver_type((type), module_info).
+:- mode type_may_contain_solver_type(in, in) is semidet.
+
+type_may_contain_solver_type(Type, ModuleInfo) :-
+ classify_type(Type, ModuleInfo, Category),
+ type_may_contain_solver_type_2(Category) = yes.
+
+:- func type_may_contain_solver_type_2(builtin_type) = bool.
+
+type_may_contain_solver_type_2(int_type) = no.
+type_may_contain_solver_type_2(char_type) = no.
+type_may_contain_solver_type_2(str_type) = no.
+type_may_contain_solver_type_2(float_type) = no.
+type_may_contain_solver_type_2(pred_type) = no.
+type_may_contain_solver_type_2(tuple_type) = yes.
+type_may_contain_solver_type_2(enum_type) = no.
+type_may_contain_solver_type_2(polymorphic_type) = yes.
+type_may_contain_solver_type_2(user_type) = yes.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/valid/any_matches_bound.m 25 Jul 2003 01:42:48 -0000
@@ -0,0 +1,42 @@
+:- module any_matches_bound.
+
+:- interface.
+
+:- pred p(T::in, T::out(any)) is det.
+
+:- pred test_any_string(string::in(any), string::out) is det.
+:- pred test_any_int(int::in(any), int::out) is det.
+:- pred test_any_float(float::in(any), float::out) is det.
+:- pred test_any_char(character::in(any), character::out) is det.
+:- pred test_any_enum(enum::in(any), enum::out) is det.
+:- pred test_any_tuple({enum, int}::in(any), {enum, int}::out) is det.
+:- pred test_any_du(du(enum)::in(any), du(enum)::out) is det.
+
+:- type enum ---> foo ; bar ; baz.
+
+:- type du(T) ---> nil ; cons(T, du(T)).
+
+:- implementation.
+
+p(X, X).
+
+test_any_string(X, Y) :-
+ p(X, Y).
+
+test_any_int(X, Y) :-
+ p(X, Y).
+
+test_any_float(X, Y) :-
+ p(X, Y).
+
+test_any_char(X, Y) :-
+ p(X, Y).
+
+test_any_enum(X, Y) :-
+ p(X, Y).
+
+test_any_tuple(X, Y) :-
+ p(X, Y).
+
+test_any_du(X, Y) :-
+ p(X, Y).
only in patch2:
--- tests/valid/Mmakefile 17 May 2003 04:31:53 -0000 1.129
+++ tests/valid/Mmakefile 25 Jul 2003 01:44:09 -0000
@@ -52,6 +52,7 @@
OTHER_PROGS= \
any_inst_merge \
+ any_matches_bound \
common_struct_bug \
compl_unify_bug \
complicated_unify \
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/invalid/any_should_not_match_bound.m 25 Jul 2003 02:02:48 -0000
@@ -0,0 +1,30 @@
+:- module any_should_not_match_bound.
+
+:- interface.
+
+:- pred p(T::in, T::out(any)) is det.
+
+:- pred test_any_poly(T::in(any), T::out) is det.
+:- pred test_any_tuple({int, foo}::in(any), {int, foo}::out) is det.
+:- pred test_any_du(du(T)::in(any), du(T)::out) is det.
+:- pred test_any_solver(foo::in(any), foo::out) is det.
+
+:- solver type foo ---> bar ; baz.
+
+:- type du(T) ---> nil ; cons(T, du(T)).
+
+:- implementation.
+
+p(X, X).
+
+test_any_poly(X, Y) :-
+ p(X, Y).
+
+test_any_tuple(X, Y) :-
+ p(X, Y).
+
+test_any_du(X, Y) :-
+ p(X, Y).
+
+test_any_solver(X, Y) :-
+ p(X, Y).
only in patch2:
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/invalid/any_should_not_match_bound.err_exp 25 Jul 2003 02:03:46 -0000
@@ -0,0 +1,17 @@
+any_should_not_match_bound.m:021: In clause for `test_any_poly(in(any), out)':
+any_should_not_match_bound.m:021: in argument 1 of call to predicate `any_should_not_match_bound.p/2':
+any_should_not_match_bound.m:021: mode error: variable `X' has instantiatedness `any',
+any_should_not_match_bound.m:021: expected instantiatedness was `ground'.
+any_should_not_match_bound.m:024: In clause for `test_any_tuple(in(any), out)':
+any_should_not_match_bound.m:024: in argument 1 of call to predicate `any_should_not_match_bound.p/2':
+any_should_not_match_bound.m:024: mode error: variable `X' has instantiatedness `any',
+any_should_not_match_bound.m:024: expected instantiatedness was `ground'.
+any_should_not_match_bound.m:027: In clause for `test_any_du(in(any), out)':
+any_should_not_match_bound.m:027: in argument 1 of call to predicate `any_should_not_match_bound.p/2':
+any_should_not_match_bound.m:027: mode error: variable `X' has instantiatedness `any',
+any_should_not_match_bound.m:027: expected instantiatedness was `ground'.
+any_should_not_match_bound.m:030: In clause for `test_any_solver(in(any), out)':
+any_should_not_match_bound.m:030: in argument 1 of call to predicate `any_should_not_match_bound.p/2':
+any_should_not_match_bound.m:030: mode error: variable `X' has instantiatedness `any',
+any_should_not_match_bound.m:030: expected instantiatedness was `ground'.
+For more information, try recompiling with `-E'.
only in patch2:
--- tests/invalid/Mmakefile 2 Jun 2003 04:56:30 -0000 1.137
+++ tests/invalid/Mmakefile 25 Jul 2003 02:04:51 -0000
@@ -31,6 +31,7 @@
SINGLEMODULE_PROGS= \
any_mode \
+ any_should_not_match_bound \
assert_in_interface \
bigtest \
bind_in_negated \
only in patch2:
--- tests/hard_coded/any_free_unify.m 2 Jun 2003 04:56:30 -0000 1.1
+++ tests/hard_coded/any_free_unify.m 25 Jul 2003 01:11:04 -0000
@@ -14,7 +14,9 @@
{ test_any_free_unify([], Result1) },
io__print(Result1), io__nl.
-:- pred test_any_free_unify(list(int), bool).
+:- solver type foo ---> bar ; baz.
+
+:- pred test_any_free_unify(list(foo), bool).
:- mode test_any_free_unify(in(list_skel(any)), out) is det.
% In the unification in the condition of the if-then-else, the variable
only in patch2:
--- extras/trailed_update/var.m 7 Nov 2002 06:19:09 -0000 1.21
+++ extras/trailed_update/var.m 25 Jul 2003 00:02:15 -0000
@@ -1,5 +1,5 @@
%-----------------------------------------------------------------------------%
-% Copyright (C) 1998-2000, 2002 The University of Melbourne.
+% Copyright (C) 1998-2000, 2002-2003 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%-----------------------------------------------------------------------------%
@@ -34,7 +34,7 @@
:- import_module io, std_util.
% A `var(T)' is a Prolog-style variable that holds a value of type T.
-:- type var(T).
+:- solver type var(T).
% `init(Var)' can be used to initialize
% the inst of a variable to `any'.
@@ -166,7 +166,7 @@
% representations simply because that name is "traditional".
% (Note that the representation can be printed out, if you call
% io__write(Var), so this is not entirely hidden from the user.)
-:- type var(T) ---> '$VAR'(var_rep(T))
+:- solver type var(T) ---> '$VAR'(var_rep(T))
where equality is (==).
:- type var_rep(T)
only in patch2:
--- extras/clpr/cfloat.m 7 Nov 2002 05:38:38 -0000 1.35
+++ extras/clpr/cfloat.m 25 Jul 2003 00:01:48 -0000
@@ -1,5 +1,5 @@
%-----------------------------------------------------------------------------%
-% Copyright (C) 1996-1997, 1999-2000 The University of Melbourne.
+% Copyright (C) 1996-1997, 1999-2000, 2003 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%-----------------------------------------------------------------------------%
@@ -44,7 +44,7 @@
%-----------------------------------------------------------------------------%
-:- type cfloat.
+:- solver type cfloat.
% NOTE:
@@ -349,7 +349,7 @@
%----------------------------------------------------------------------------%
-:- type cfloat ---> cfloat(int)
+:- solver type cfloat ---> cfloat(int)
where equality is cfloat__eq.
% The cfloat is stored as an int (the CLP(R) solver_id for it).
--
David Overton Uni of Melbourne +61 3 8344 1354
dmo at cs.mu.oz.au Monash Uni (Clayton) +61 3 9905 5779
http://www.cs.mu.oz.au/~dmo Mobile Phone +61 4 0337 4393
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list