diff: typeclasses bug fix
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Mar 18 07:16:55 AEDT 1999
Estimated hours taken: 2
Fix a bug with typeclasses where the compiler would sometimes
generate code that called the wrong method.
compiler/make_hlds.m:
Ensure that the list(pred_proc_id) in the hlds_class_defn
is sorted, to match the way that check_typeclass.m generates
the corresponding list(pred_proc_id) for the hlds_instance_defn.
tests/hard_coded/typeclasses/Mmakefile:
tests/hard_coded/typeclasses/func_default_mode_bug.m:
tests/hard_coded/typeclasses/func_default_mode_bug.exp:
tests/hard_coded/typeclasses/mode_decl_order_bug.m:
tests/hard_coded/typeclasses/mode_decl_order_bug.exp:
Add a couple of regression tests for problems fixed by
the above change.
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.289
diff -u -r1.289 make_hlds.m
--- make_hlds.m 1999/03/15 08:47:46 1.289
+++ make_hlds.m 1999/03/17 19:26:32
@@ -1626,7 +1626,16 @@
Maybe = yes(Pred - Proc),
PredProcId = hlds_class_proc(Pred, Proc)
)) },
- { list__filter_map(IsYes, PredProcIds0, PredProcIds) },
+ { list__filter_map(IsYes, PredProcIds0, PredProcIds1) },
+
+ %
+ % The list must be sorted on pred_id and then
+ % proc_id -- check_typeclass.m assumes this
+ % when it is generating the corresponding list
+ % of pred_proc_ids for instance definitions.
+ %
+ { list__sort(PredProcIds1, PredProcIds) },
+
{ Value = hlds_class_defn(Constraints, Vars, PredProcIds,
VarSet, Context) },
{ map__det_insert(Classes0, ClassId, Value, Classes) },
Index: tests/hard_coded/typeclasses/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/typeclasses/Mmakefile,v
retrieving revision 1.14
diff -u -r1.14 Mmakefile
--- Mmakefile 1999/02/12 04:19:22 1.14
+++ Mmakefile 1999/03/17 20:01:33
@@ -11,12 +11,14 @@
extract_typeinfo \
existential_type_classes \
extra_typeinfo \
+ func_default_mode_bug \
ho_map \
implied_instance \
implied_instance_poly \
inference_test \
inference_test_2 \
lambda_multi_constraint_same_tvar \
+ mode_decl_order_bug \
multi_constraint_diff_tvar \
multi_constraint_same_tvar \
multi_parameter \
Index: tests/hard_coded/typeclasses/func_default_mode_bug.exp
===================================================================
RCS file: func_default_mode_bug.exp
diff -N func_default_mode_bug.exp
--- /dev/null Thu Mar 18 07:11:41 1999
+++ func_default_mode_bug.exp Thu Mar 18 07:00:49 1999
@@ -0,0 +1 @@
+bidon(value(value(-1.00000000000000, -1.00000000000000)))
Index: tests/hard_coded/typeclasses/func_default_mode_bug.m
===================================================================
RCS file: func_default_mode_bug.m
diff -N func_default_mode_bug.m
--- /dev/null Thu Mar 18 07:11:41 1999
+++ func_default_mode_bug.m Thu Mar 18 07:11:33 1999
@@ -0,0 +1,162 @@
+:- module func_default_mode_bug.
+
+% +++++++++++
+:- interface.
+% +++++++++++
+
+:- import_module io.
+
+:- pred main(io__state, io__state).
+:- mode main(di, uo) is det.
+
+% ----------
+:- type term
+% ----------
+
+---> parameter(parameter)
+; value(value).
+
+
+% -----------
+:- type bidon
+% -----------
+
+---> bidon(term).
+
+
+% -----------
+:- type value
+% -----------
+
+---> value(float,float).
+
+% ---------------
+:- type parameter
+% ---------------
+
+---> parameter(string).
+
+
+% We declare a typeclass for the constants used in the expressions.
+% The user has to provide a null element for the mult operator
+% and a null element for the plus operator.
+% The user also has to provide a way to test whether term are null
+% or not.
+% Finally, the user has to provide a way of turning a minus operator
+% to a plus. Typically, this is done by doing :
+% A - B -> A + ( B * -1 )
+% where the constant -1 is up to the user to define...
+:- typeclass constant( C)
+where [
+ func null_for_mult = C,
+
+ pred is_null_for_mult( C),
+ mode is_null_for_mult( in) is semidet,
+
+ func null_for_plus = C,
+
+ pred is_null_for_plus( C),
+ mode is_null_for_plus( in) is semidet,
+
+ func minus_one = C
+ ].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Declares the predicates needed to handle the constants in
+% the expressions.
+
+:- instance constant( term)
+where [
+ func( null_for_mult/0) is my_null_for_mult,
+
+ pred( is_null_for_mult/1) is my_is_null_for_mult,
+
+ func( null_for_plus/0) is my_null_for_plus,
+
+ pred( is_null_for_plus/1) is my_is_null_for_plus,
+
+ func( minus_one/0) is my_minus_one
+ ].
+
+
+% ++++++++++++++++
+:- implementation.
+% ++++++++++++++++
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This function generates a null element for the multiplication.
+
+:- func my_null_for_mult = term.
+:- mode my_null_for_mult = out is det.
+
+my_null_for_mult = value( definition_value( 1.0)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This predicate succeeds if the argument is the 1.0 value.
+
+:- pred my_is_null_for_mult( term).
+:- mode my_is_null_for_mult( in) is semidet.
+
+my_is_null_for_mult( value( definition_value( 1.0))).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This function generates a null element for the addition.
+
+:- func my_null_for_plus = term.
+:- mode my_null_for_plus = out is det.
+
+my_null_for_plus = value( definition_value( 0.0)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This predicate succeeds if the argument is the 0.0 value.
+
+:- pred my_is_null_for_plus( term).
+:- mode my_is_null_for_plus( in) is semidet.
+
+my_is_null_for_plus( value( definition_value( 0.0))).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This function generates a null element for the addition.
+
+:- func my_minus_one = term.
+:- mode my_minus_one = out is det.
+
+my_minus_one = value( definition_value( -1.0)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This predicate is used to turn a float or a pair of floats
+% into the type value.
+:- func definition_value( float) = value.
+:- mode definition_value( in) = out is det.
+
+definition_value(X) = value( X, X).
+
+:- func definition_value( float, float) = value.
+:- mode definition_value( in, in) = out is det.
+
+definition_value( X, Y) = value( X, Y).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%:- pred main(io__state, io__state).
+%:- mode main(di, uo) is det.
+
+main( In, Out) :-
+ io__write( bidon( minus_one), In, Int3),
+ io__nl( Int3, Out).
Index: tests/hard_coded/typeclasses/mode_decl_order_bug.exp
===================================================================
RCS file: mode_decl_order_bug.exp
diff -N mode_decl_order_bug.exp
--- /dev/null Thu Mar 18 07:11:41 1999
+++ mode_decl_order_bug.exp Thu Mar 18 07:01:07 1999
@@ -0,0 +1 @@
+bidon(value(value(-1.00000000000000, -1.00000000000000)))
Index: tests/hard_coded/typeclasses/mode_decl_order_bug.m
===================================================================
RCS file: mode_decl_order_bug.m
diff -N mode_decl_order_bug.m
--- /dev/null Thu Mar 18 07:11:41 1999
+++ mode_decl_order_bug.m Thu Mar 18 07:11:33 1999
@@ -0,0 +1,166 @@
+:- module mode_decl_order_bug.
+
+% +++++++++++
+:- interface.
+% +++++++++++
+
+:- import_module io.
+
+:- pred main(io__state, io__state).
+:- mode main(di, uo) is det.
+
+% ----------
+:- type term
+% ----------
+
+---> parameter(parameter)
+; value(value).
+
+
+% -----------
+:- type bidon
+% -----------
+
+---> bidon(term).
+
+
+% -----------
+:- type value
+% -----------
+
+---> value(float,float).
+
+% ---------------
+:- type parameter
+% ---------------
+
+---> parameter(string).
+
+
+% We declare a typeclass for the constants used in the expressions.
+% The user has to provide a null element for the mult operator
+% and a null element for the plus operator.
+% The user also has to provide a way to test whether term are null
+% or not.
+% Finally, the user has to provide a way of turning a minus operator
+% to a plus. Typically, this is done by doing :
+% A - B -> A + ( B * -1 )
+% where the constant -1 is up to the user to define...
+:- typeclass constant( C)
+where [
+ func null_for_mult = C,
+
+ pred is_null_for_mult( C),
+ mode is_null_for_mult( in) is semidet,
+
+ func null_for_plus = C,
+ mode null_for_plus = out is det,
+
+ func minus_one = C,
+ mode minus_one = out is det,
+
+ mode null_for_mult = out is det,
+
+ pred is_null_for_plus( C),
+ mode is_null_for_plus( in) is semidet
+ ].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Declares the predicates needed to handle the constants in
+% the expressions.
+
+:- instance constant( term)
+where [
+ func( null_for_mult/0) is my_null_for_mult,
+
+ pred( is_null_for_mult/1) is my_is_null_for_mult,
+
+ func( null_for_plus/0) is my_null_for_plus,
+
+ pred( is_null_for_plus/1) is my_is_null_for_plus,
+
+ func( minus_one/0) is my_minus_one
+ ].
+
+
+% ++++++++++++++++
+:- implementation.
+% ++++++++++++++++
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This function generates a null element for the multiplication.
+
+:- func my_null_for_mult = term.
+:- mode my_null_for_mult = out is det.
+
+my_null_for_mult = value( definition_value( 1.0)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This predicate succeeds if the argument is the 1.0 value.
+
+:- pred my_is_null_for_mult( term).
+:- mode my_is_null_for_mult( in) is semidet.
+
+my_is_null_for_mult( value( definition_value( 1.0))).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This function generates a null element for the addition.
+
+:- func my_null_for_plus = term.
+:- mode my_null_for_plus = out is det.
+
+my_null_for_plus = value( definition_value( 0.0)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This predicate succeeds if the argument is the 0.0 value.
+
+:- pred my_is_null_for_plus( term).
+:- mode my_is_null_for_plus( in) is semidet.
+
+my_is_null_for_plus( value( definition_value( 0.0))).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This function generates a null element for the addition.
+
+:- func my_minus_one = term.
+:- mode my_minus_one = out is det.
+
+my_minus_one = value( definition_value( -1.0)).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This predicate is used to turn a float or a pair of floats
+% into the type value.
+:- func definition_value( float) = value.
+:- mode definition_value( in) = out is det.
+
+definition_value(X) = value( X, X).
+
+:- func definition_value( float, float) = value.
+:- mode definition_value( in, in) = out is det.
+
+definition_value( X, Y) = value( X, Y).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%:- pred main(io__state, io__state).
+%:- mode main(di, uo) is det.
+
+main( In, Out) :-
+ io__write( bidon( minus_one), In, Int3),
+ io__nl( Int3, Out).
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list