diff: "superclass search"
David Glen JEFFERY
dgj at cs.mu.OZ.AU
Tue May 5 14:44:17 AEST 1998
Hi,
Could you please review this, Fergus?
--
Estimated hours taken: 15
Re-implement the part of context reduction which seeks to eliminate a
typeclass constraint by using the fact that one class is a superclass of
another. This achieves two things:
- Fixes a bug, in that the new algorithm (correctly) searches the whole
superclass relation to find a path from one constraint to
another.
- It makes the algorithm the same as what we put in the type class
paper. :-)
compiler/check_typeclass.m:
Pass the super class table to the context reduction predicate
compiler/hlds_data.m:
Declare the types which (explicitly) hold the superclass information
compiler/hlds_module.m:
Store the superclass information explicitly in the module_info, rather
than just implicitly in the class_table
compiler/make_hlds.m:
Explicitly construct the superclass information as classes are added.
This saves re-computing it for each constraint in typecheck.m
compiler/typecheck.m:
Use the explicit superclass information for context reduction, rather
than just the class table.
When reducing the context using superclasses, recursively search the
whole superclass relation until a match is found. (This is very
inefficient at this stage, but fixing it won't be hard. I'll leave
that for another commit, though).
tests/valid/superclass_search.m:
A test case for this bug fix.
Index: compiler/check_typeclass.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/check_typeclass.m,v
retrieving revision 1.5
diff -u -r1.5 check_typeclass.m
--- check_typeclass.m 1998/04/08 15:23:21 1.5
+++ check_typeclass.m 1998/05/05 01:07:02
@@ -446,14 +446,14 @@
map__from_corresponding_lists(ClassVars, InstanceTypes, TypeSubst),
module_info_instances(ModuleInfo, InstanceTable),
- module_info_classes(ModuleInfo, ClassTable),
+ module_info_superclasses(ModuleInfo, SuperClassTable),
(
% Try to reduce the superclass constraints,
% using the declared instance constraints
% and the usual context reduction rules.
typecheck__reduce_context_by_rule_application(InstanceTable,
- ClassTable, InstanceConstraints, TypeSubst,
+ SuperClassTable, InstanceConstraints, TypeSubst,
InstanceVarSet1, InstanceVarSet2,
Proofs0, Proofs1, SuperClasses,
[])
Index: compiler/hlds_data.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_data.m,v
retrieving revision 1.22
diff -u -r1.22 hlds_data.m
--- hlds_data.m 1998/03/03 17:34:27 1.22
+++ hlds_data.m 1998/05/05 01:07:02
@@ -756,3 +756,21 @@
; superclass(class_constraint).
%-----------------------------------------------------------------------------%
+
+:- interface.
+
+:- type subclass_details
+ ---> subclass_details(
+ list(var), % variables of the superclass
+ class_id, % name of the subclass
+ list(var), % variables of the subclass
+ tvarset % the names of these vars
+ ).
+
+:- import_module multi_map.
+
+ % I'm sure there's a very clever way of
+ % doing this with graphs or relations...
+:- type superclass_table == multi_map(class_id, subclass_details).
+
+%-----------------------------------------------------------------------------%
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_module.m,v
retrieving revision 1.33
diff -u -r1.33 hlds_module.m
--- hlds_module.m 1998/04/27 04:01:07 1.33
+++ hlds_module.m 1998/05/05 01:07:02
@@ -155,6 +155,13 @@
:- pred module_info_set_instances(module_info, instance_table, module_info).
:- mode module_info_set_instances(in, in, out) is det.
+:- pred module_info_superclasses(module_info, superclass_table).
+:- mode module_info_superclasses(in, out) is det.
+
+:- pred module_info_set_superclasses(module_info, superclass_table,
+ module_info).
+:- mode module_info_set_superclasses(in, in, out) is det.
+
% The cell count is used as a unique label number for
% constants in the generated C code.
:- pred module_info_get_cell_count(module_info, int).
@@ -449,6 +456,7 @@
cons_table,
class_table,
instance_table,
+ superclass_table,
int % cell count, passed into code_info
% and used to generate unique label
% numbers for constant terms in the
@@ -497,11 +505,12 @@
map__init(UnusedArgInfo),
map__init(ClassTable),
map__init(InstanceTable),
+ map__init(SuperClassTable),
ModuleSubInfo = module_sub(Name, Globals, [], [], no, 0, 0, [],
[], [], StratPreds, UnusedArgInfo, 0),
ModuleInfo = module(ModuleSubInfo, PredicateTable, Requests,
UnifyPredMap, ContinuationInfo, Types, Insts, Modes, Ctors,
- ClassTable, InstanceTable, 0).
+ ClassTable, SuperClassTable, InstanceTable, 0).
%-----------------------------------------------------------------------------%
@@ -638,7 +647,8 @@
% I cons_table,
% J class_table,
% K instance_table,
-% L int % cell count, passed into code_info
+% L superclass_table,
+% M int % cell count, passed into code_info
% % and used to generate unique label
% % numbers for constant terms in the
% % generated C code
@@ -649,92 +659,99 @@
% Various predicates which access the module_info data structure.
module_info_get_sub_info(MI0, A) :-
- MI0 = module(A, _, _, _, _, _, _, _, _, _, _, _).
+ MI0 = module(A, _, _, _, _, _, _, _, _, _, _, _, _).
module_info_get_predicate_table(MI0, B) :-
- MI0 = module(_, B, _, _, _, _, _, _, _, _, _, _).
+ MI0 = module(_, B, _, _, _, _, _, _, _, _, _, _, _).
module_info_get_proc_requests(MI0, C) :-
- MI0 = module(_, _, C, _, _, _, _, _, _, _, _, _).
+ MI0 = module(_, _, C, _, _, _, _, _, _, _, _, _, _).
module_info_get_special_pred_map(MI0, D) :-
- MI0 = module(_, _, _, D, _, _, _, _, _, _, _, _).
+ MI0 = module(_, _, _, D, _, _, _, _, _, _, _, _, _).
module_info_get_continuation_info(MI0, E) :-
- MI0 = module(_, _, _, _, E, _, _, _, _, _, _, _).
+ MI0 = module(_, _, _, _, E, _, _, _, _, _, _, _, _).
module_info_types(MI0, F) :-
- MI0 = module(_, _, _, _, _, F, _, _, _, _, _, _).
+ MI0 = module(_, _, _, _, _, F, _, _, _, _, _, _, _).
module_info_insts(MI0, G) :-
- MI0 = module(_, _, _, _, _, _, G, _, _, _, _, _).
+ MI0 = module(_, _, _, _, _, _, G, _, _, _, _, _, _).
module_info_modes(MI0, H) :-
- MI0 = module(_, _, _, _, _, _, _, H, _, _, _, _).
+ MI0 = module(_, _, _, _, _, _, _, H, _, _, _, _, _).
module_info_ctors(MI0, I) :-
- MI0 = module(_, _, _, _, _, _, _, _, I, _, _, _).
+ MI0 = module(_, _, _, _, _, _, _, _, I, _, _, _, _).
module_info_classes(MI0, J) :-
- MI0 = module(_, _, _, _, _, _, _, _, _, J, _, _).
+ MI0 = module(_, _, _, _, _, _, _, _, _, J, _, _, _).
module_info_instances(MI0, K) :-
- MI0 = module(_, _, _, _, _, _, _, _, _, _, K, _).
+ MI0 = module(_, _, _, _, _, _, _, _, _, _, K, _, _).
+
+module_info_superclasses(MI0, L) :-
+ MI0 = module(_, _, _, _, _, _, _, _, _, _, _, L, _).
-module_info_get_cell_count(MI0, L) :-
- MI0 = module(_, _, _, _, _, _, _, _, _, _, _, L).
+module_info_get_cell_count(MI0, M) :-
+ MI0 = module(_, _, _, _, _, _, _, _, _, _, _, _, M).
%-----------------------------------------------------------------------------%
% Various predicates which modify the module_info data structure.
module_info_set_sub_info(MI0, A, MI) :-
- MI0 = module(_, B, C, D, E, F, G, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(_, B, C, D, E, F, G, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_predicate_table(MI0, B, MI) :-
- MI0 = module(A, _, C, D, E, F, G, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, _, C, D, E, F, G, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_proc_requests(MI0, C, MI) :-
- MI0 = module(A, B, _, D, E, F, G, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, _, D, E, F, G, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_special_pred_map(MI0, D, MI) :-
- MI0 = module(A, B, C, _, E, F, G, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, _, E, F, G, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_continuation_info(MI0, E, MI) :-
- MI0 = module(A, B, C, D, _, F, G, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, _, F, G, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_types(MI0, F, MI) :-
- MI0 = module(A, B, C, D, E, _, G, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, E, _, G, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_insts(MI0, G, MI) :-
- MI0 = module(A, B, C, D, E, F, _, H, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, E, F, _, H, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_modes(MI0, H, MI) :-
- MI0 = module(A, B, C, D, E, F, G, _, I, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, E, F, G, _, I, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_ctors(MI0, I, MI) :-
- MI0 = module(A, B, C, D, E, F, G, H, _, J, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, E, F, G, H, _, J, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_classes(MI0, J, MI) :-
- MI0 = module(A, B, C, D, E, F, G, H, I, _, K, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, E, F, G, H, I, _, K, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
module_info_set_instances(MI0, K, MI) :-
- MI0 = module(A, B, C, D, E, F, G, H, I, J, _, L),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+ MI0 = module(A, B, C, D, E, F, G, H, I, J, _, L, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
-module_info_set_cell_count(MI0, L, MI) :-
- MI0 = module(A, B, C, D, E, F, G, H, I, J, K, _),
- MI = module(A, B, C, D, E, F, G, H, I, J, K, L).
+module_info_set_superclasses(MI0, L, MI) :-
+ MI0 = module(A, B, C, D, E, F, G, H, I, J, K, _, M),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
+
+module_info_set_cell_count(MI0, M, MI) :-
+ MI0 = module(A, B, C, D, E, F, G, H, I, J, K, L, _),
+ MI = module(A, B, C, D, E, F, G, H, I, J, K, L, M).
%-----------------------------------------------------------------------------%
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/make_hlds.m,v
retrieving revision 1.263
diff -u -r1.263 make_hlds.m
--- make_hlds.m 1998/03/04 19:47:34 1.263
+++ make_hlds.m 1998/05/05 01:07:02
@@ -1289,10 +1289,11 @@
module_add_class_defn(Module0, Constraints, Name, Vars, Interface, VarSet,
Context, Status, Module) -->
{ module_info_classes(Module0, Classes0) },
+ { module_info_superclasses(Module0, SuperClasses0) },
{ list__length(Vars, ClassArity) },
- { Key = class_id(Name, ClassArity) },
+ { ClassId = class_id(Name, ClassArity) },
(
- { map__search(Classes0, Key, OldValue) }
+ { map__search(Classes0, ClassId, OldValue) }
->
{ OldValue = hlds_class_defn(_, _, _, _, OldContext) },
multiple_def_error(Name, ClassArity, "typeclass",
@@ -1311,13 +1312,33 @@
{ list__filter_map(IsYes, PredProcIds0, PredProcIds) },
{ Value = hlds_class_defn(Constraints, Vars, PredProcIds,
VarSet, Context) },
- { map__det_insert(Classes0, Key, Value, Classes) },
+ { map__det_insert(Classes0, ClassId, Value, Classes) },
{ module_info_set_classes(Module1, Classes, Module2) },
+
+ % insert an entry into the super class table for each
+ % super class of this class
+ { AddSuper = lambda([Super::in, Ss0::in, Ss::out] is det,
+ (
+ Super = constraint(SuperName, SuperTypes),
+ list__length(SuperTypes, SuperClassArity),
+ term__vars_list(SuperTypes, SuperVars),
+ SuperClassId = class_id(SuperName,
+ SuperClassArity),
+ SubClassDetails = subclass_details(SuperVars,
+ ClassId, Vars, VarSet),
+ multi_map__set(Ss0, SuperClassId,
+ SubClassDetails, Ss)
+ )) },
+ { list__foldl(AddSuper, Constraints,
+ SuperClasses0, SuperClasses) },
+ { module_info_set_superclasses(Module2,
+ SuperClasses, Module3) },
+
% When we find the class declaration, make an
% entry for the instances.
- { module_info_instances(Module2, Instances0) },
- { map__det_insert(Instances0, Key, [], Instances) },
- { module_info_set_instances(Module2, Instances, Module) }
+ { module_info_instances(Module3, Instances0) },
+ { map__det_insert(Instances0, ClassId, [], Instances) },
+ { module_info_set_instances(Module3, Instances, Module) }
).
:- pred module_add_class_interface(module_info, sym_name, list(var),
Index: compiler/typecheck.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/typecheck.m,v
retrieving revision 1.236
diff -u -r1.236 typecheck.m
--- typecheck.m 1998/04/09 18:31:40 1.236
+++ typecheck.m 1998/05/05 04:27:32
@@ -159,7 +159,7 @@
% the instance rules or superclass rules, building up proofs for
% redundant constraints
:- pred typecheck__reduce_context_by_rule_application(instance_table,
- class_table, list(class_constraint), tsubst, tvarset, tvarset,
+ superclass_table, list(class_constraint), tsubst, tvarset, tvarset,
map(class_constraint, constraint_proof),
map(class_constraint, constraint_proof),
list(class_constraint), list(class_constraint)).
@@ -176,7 +176,7 @@
:- import_module mercury_to_mercury, mode_util, options, getopt, globals.
:- import_module passes_aux, clause_to_proc, special_pred, inst_match.
-:- import_module int, set, string, require, std_util, tree234.
+:- import_module int, set, string, require, std_util, tree234, multi_map.
:- import_module assoc_list, varset, term_io.
%-----------------------------------------------------------------------------%
@@ -3043,11 +3043,11 @@
perform_context_reduction(OrigTypeAssignSet, TypeCheckInfo0, TypeCheckInfo) :-
typecheck_info_get_module_info(TypeCheckInfo0, ModuleInfo),
typecheck_info_get_constraints(TypeCheckInfo0, DeclaredConstraints),
- module_info_classes(ModuleInfo, ClassTable),
+ module_info_superclasses(ModuleInfo, SuperClassTable),
module_info_instances(ModuleInfo, InstanceTable),
typecheck_info_get_type_assign_set(TypeCheckInfo0, TypeAssignSet0),
- list__filter_map(reduce_type_assign_context(ClassTable, InstanceTable,
- DeclaredConstraints),
+ list__filter_map(reduce_type_assign_context(SuperClassTable,
+ InstanceTable, DeclaredConstraints),
TypeAssignSet0, TypeAssignSet),
(
% Check that this context reduction hasn't eliminated
@@ -3069,11 +3069,11 @@
TypeAssignSet, TypeCheckInfo)
).
-:- pred reduce_type_assign_context(class_table, instance_table,
+:- pred reduce_type_assign_context(superclass_table, instance_table,
list(class_constraint), type_assign, type_assign).
:- mode reduce_type_assign_context(in, in, in, in, out) is semidet.
-reduce_type_assign_context(ClassTable, InstanceTable, DeclaredConstraints,
+reduce_type_assign_context(SuperClassTable, InstanceTable, DeclaredConstraints,
TypeAssign0, TypeAssign) :-
type_assign_get_typeclass_constraints(TypeAssign0, Constraints0),
type_assign_get_type_bindings(TypeAssign0, Bindings),
@@ -3081,7 +3081,7 @@
type_assign_get_constraint_proofs(TypeAssign0, Proofs0),
typecheck__reduce_context_by_rule_application(InstanceTable,
- ClassTable, DeclaredConstraints,
+ SuperClassTable, DeclaredConstraints,
Bindings, Tvarset0, Tvarset, Proofs0, Proofs,
Constraints0, Constraints),
@@ -3091,16 +3091,16 @@
type_assign_set_constraint_proofs(TypeAssign2, Proofs, TypeAssign).
-typecheck__reduce_context_by_rule_application(InstanceTable, ClassTable,
+typecheck__reduce_context_by_rule_application(InstanceTable, SuperClassTable,
DeclaredConstraints, Bindings, Tvarset0, Tvarset,
Proofs0, Proofs, Constraints0, Constraints) :-
apply_rec_subst_to_constraints(Bindings, Constraints0, Constraints1),
eliminate_declared_constraints(Constraints1, DeclaredConstraints,
Constraints2, Changed1),
- apply_class_rules(Constraints2, DeclaredConstraints, ClassTable,
- Tvarset0, Proofs0, Proofs1, Constraints3, Changed2),
- apply_instance_rules(Constraints3, InstanceTable,
- Tvarset0, Tvarset1, Proofs1, Proofs2, Constraints4, Changed3),
+ apply_instance_rules(Constraints2, InstanceTable,
+ Tvarset0, Tvarset1, Proofs0, Proofs1, Constraints3, Changed2),
+ apply_class_rules(Constraints3, DeclaredConstraints, SuperClassTable,
+ Tvarset0, Proofs1, Proofs2, Constraints4, Changed3),
(
Changed1 = no, Changed2 = no, Changed3 = no
->
@@ -3110,8 +3110,9 @@
Proofs = Proofs2
;
typecheck__reduce_context_by_rule_application(InstanceTable,
- ClassTable, DeclaredConstraints, Bindings, Tvarset1,
- Tvarset, Proofs2, Proofs, Constraints4, Constraints)
+ SuperClassTable, DeclaredConstraints, Bindings,
+ Tvarset1, Tvarset, Proofs2, Proofs,
+ Constraints4, Constraints)
).
:- pred eliminate_declared_constraints(list(class_constraint),
@@ -3240,82 +3241,100 @@
Proofs, NewConstraints)
).
- % To reduce the context using class declarations, we scan the
- % declared contexts plus the current inferred context one
- % constraint at a time. For each such class constraint, we
- % check to see if any of its superclasses is also a constraint,
- % and if so, delete the superclass from the current constraint
- % list as it is redundant.
+ % To reduce a constraint using class declarations, we search the
+ % superclass relation to find a path from the inferred constraint to
+ % another (declared or inferred) constraint.
:- pred apply_class_rules(list(class_constraint), list(class_constraint),
- class_table, tvarset, map(class_constraint, constraint_proof),
+ superclass_table, tvarset, map(class_constraint, constraint_proof),
map(class_constraint, constraint_proof), list(class_constraint), bool).
:- mode apply_class_rules(in, in, in, in, in, out, out, out) is det.
-apply_class_rules(Constraints0, DeclaredConstraints, ClassTable, TVarSet,
- Proofs0, Proofs, Constraints, Changed) :-
- list__append(DeclaredConstraints, Constraints0, AllConstraints),
- apply_class_rules_2(AllConstraints, Constraints0, ClassTable,
- TVarSet, Proofs0, Proofs, Constraints, Changed).
-
-:- pred apply_class_rules_2(list(class_constraint), list(class_constraint),
- class_table, tvarset, map(class_constraint, constraint_proof),
- map(class_constraint, constraint_proof), list(class_constraint), bool).
-:- mode apply_class_rules_2(in, in, in, in, in, out, out, out) is det.
+apply_class_rules([], _, _, _, Proofs, Proofs, [], no).
+apply_class_rules([C|Constraints0], DeclaredConstraints, SuperClassTable,
+ TVarSet, Proofs0, Proofs, Constraints, Changed) :-
+ (
+ eliminate_constraint_by_class_rules(C, DeclaredConstraints,
+ SuperClassTable, TVarSet, Proofs0, Proofs1)
+ ->
+ apply_class_rules(Constraints0, DeclaredConstraints,
+ SuperClassTable, TVarSet, Proofs1, Proofs,
+ Constraints, _),
+ Changed = yes
+ ;
+ apply_class_rules(Constraints0, DeclaredConstraints,
+ SuperClassTable, TVarSet, Proofs0, Proofs,
+ Constraints1, Changed),
+ Constraints = [C|Constraints1]
+ ).
- % The first argument is the list of declared or inferred constraints
- % left to be checked.
- % The second argument is the list of currently inferred constraints
- % that have not been rejected. If a redundant constraint is found,
- % it is deleted from both (if it is still in the first list).
-apply_class_rules_2([], Constraints, _, _, Proofs, Proofs, Constraints, no).
-apply_class_rules_2([C|Cs], Constraints0, ClassTable, TVarSet,
- Proofs0, Proofs, Constraints, Changed) :-
- C = constraint(ClassName, Types),
- list__length(Types, Arity),
- ClassId = class_id(ClassName, Arity),
- map__lookup(ClassTable, ClassId, ClassDefn),
- ClassDefn = hlds_class_defn(ParentClassConstraints0, ClassVars,
- _ClassInterface, ClassVarset, _TermContext),
- term__var_list_to_term_list(ClassVars, ClassTypes),
- varset__merge_subst(TVarSet, ClassVarset, NewTVarSet, RenameSubst),
- term__apply_rec_substitution_to_list(ClassTypes, RenameSubst,
- NewClassTypes),
- apply_rec_subst_to_constraints(RenameSubst, ParentClassConstraints0,
- ParentClassConstraints),
- IsRedundant = lambda(
- [ThisConstraint::in, RenamedConstraint::out] is semidet,
- (
- type_list_subsumes(NewClassTypes, Types, Subst),
- apply_rec_subst_to_constraint(Subst, ThisConstraint,
- RenamedConstraint),
- list__member(RenamedConstraint, Constraints0)
- )),
- list__filter_map(IsRedundant, ParentClassConstraints,
- RedundantConstraints),
+:- pred eliminate_constraint_by_class_rules(class_constraint,
+ list(class_constraint), superclass_table, tvarset,
+ map(class_constraint, constraint_proof),
+ map(class_constraint, constraint_proof)).
+:- mode eliminate_constraint_by_class_rules(in, in, in, in, in, out) is semidet.
- % Delete the redundant constraints
- list__delete_elems(Constraints0, RedundantConstraints, Constraints1),
- list__delete_elems(Cs, RedundantConstraints, NewCs),
-
- % Remember why the constraints were redundant
- RecordRedundancy = lambda([ConstraintName::in, TheProofs0::in,
- TheProofs::out] is det,
- (
- map__set(TheProofs0, ConstraintName, superclass(C),
- TheProofs)
+eliminate_constraint_by_class_rules(C, DeclaredConstraints, SuperClassTable,
+ TVarSet, Proofs0, Proofs) :-
+ C = constraint(SuperClassName, SuperClassTypes),
+ list__length(SuperClassTypes, SuperClassArity),
+ SuperClassId = class_id(SuperClassName, SuperClassArity),
+ multi_map__search(SuperClassTable, SuperClassId, SubClasses),
+
+ % Convert all the subclass_details into class_constraints by
+ % doing the appropriate variable renaming and applying the
+ % type variable bindings.
+ SubDetailsToConstraint = lambda([SubClassDetails::in, SubC::out]
+ is semidet, (
+ SubClassDetails = subclass_details(SuperVars0, SubID,
+ SubVars0, SuperVarset),
+
+ % Rename the variables from the typeclass
+ % declaration into those of the current pred
+ varset__merge_subst(TVarSet, SuperVarset, _NewTVarSet,
+ RenameSubst),
+ term__var_list_to_term_list(SubVars0, SubVars1),
+ term__apply_substitution_to_list(SubVars1,
+ RenameSubst, SubVars),
+ term__var_list_to_term_list(SuperVars0, SuperVars1),
+ term__apply_substitution_to_list(SuperVars1,
+ RenameSubst, SuperVars),
+
+ % Work out what the (renamed) vars from the
+ % typeclass declaration are bound to here
+ map__init(Empty),
+ type_unify_list(SuperVars, SuperClassTypes, [],
+ Empty, Bindings),
+ SubID = class_id(SubName, _SubArity),
+ term__apply_substitution_to_list(SubVars, Bindings,
+ SubClassTypes),
+ SubC = constraint(SubName, SubClassTypes)
+ )),
+ list__map(SubDetailsToConstraint, SubClasses, SubClassConstraints),
+
+ (
+ % Do the first level of search
+ FindSub = lambda([TheConstraint::in] is semidet,(
+ list__member(TheConstraint, DeclaredConstraints)
)),
- list__foldl(RecordRedundancy, RedundantConstraints, Proofs0, Proofs1),
- (
- RedundantConstraints = [],
- Changed1 = no
+ list__filter(FindSub, SubClassConstraints, [Sub|_])
+ ->
+ map__set(Proofs0, C, superclass(Sub), Proofs)
;
- RedundantConstraints = [_|_],
- Changed1 = yes
- ),
-
- apply_class_rules_2(NewCs, Constraints1, ClassTable,
- NewTVarSet, Proofs1, Proofs, Constraints, Changed2),
- bool__or(Changed1, Changed2, Changed).
+ % Recursively search the rest of the superclass
+ % relation.
+ SubClassSearch = lambda([Constraint::in, CnstrtAndProof::out]
+ is semidet, (
+ eliminate_constraint_by_class_rules(Constraint,
+ DeclaredConstraints, SuperClassTable,
+ TVarSet, Proofs0, SubProofs),
+ CnstrtAndProof = Constraint - SubProofs
+ )),
+ % XXX this could (and should) be more efficient.
+ % (ie. by manually doing a "cut").
+ list__filter_map(SubClassSearch, SubClassConstraints,
+ [NewSub - NewProofs|_]),
+ map__set(NewProofs, C, superclass(NewSub), Proofs)
+ ).
%-----------------------------------------------------------------------------%
New file: superclass_search.m:
--------------------------------------------------------
:- module superclass_search.
:- interface.
:- typeclass c1(T) where [
pred p(T::in) is semidet
].
:- typeclass c2(T) <= c1(T) where [
].
:- typeclass c3(T) <= c2(T) where [
].
:- pred test(T) <= c2(T).
:- mode test(in) is semidet.
:- implementation.
test(X) :- p(X).
--
love and cuddles,
dgj
--
David Jeffery (dgj at cs.mu.oz.au) | Marge: Did you just call everyone "chicken"?
MEngSc student, | Homer: Noooo. I swear on this Bible!
Department of Computer Science | Marge: That's not a Bible; that's a book of
University of Melbourne | carpet samples!
Australia | Homer: Ooooh... Fuzzy.
More information about the developers
mailing list