diff: typeclasses (final) [4/6]
David Glen JEFFERY
dgj at cs.mu.oz.au
Fri Dec 19 14:01:35 AEDT 1997
+modecheck_goal_expr(class_method_call(_, _, _, _, _, _),
+ _GoalInfo0, _Goal) -->
+ { error("modecheck_goal_expr: class method exists at modecheck time") }.
+
modecheck_goal_expr(unify(A0, B0, _, UnifyInfo0, UnifyContext), GoalInfo0, Goal)
-->
mode_checkpoint(enter, "unify"),
Index: compiler/module_qual.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/module_qual.m,v
retrieving revision 1.25
diff -u -r1.25 module_qual.m
--- module_qual.m 1997/12/09 04:01:14 1.25
+++ module_qual.m 1997/12/15 06:19:44
@@ -97,12 +97,13 @@
type_id_set, % Sets of all types, modes and
inst_id_set, % insts visible in this module.
mode_id_set,
+ class_id_set,
set(module_name), % modules imported in the
% interface that are not definitely
% needed in the interface.
import_status, % import status of the current item.
int, % number of errors found.
- bool, % are there any undefined types.
+ bool, % are there any undefined types or typeclasses.
bool, % are there any undefined insts or modes.
bool, % do we want to report errors.
error_context, % context of the current item.
@@ -131,14 +132,18 @@
add_mode_defn(ModeDefn, Info0, Info).
collect_mq_info_2(module_defn(_, ModuleDefn), Info0, Info) :-
process_module_defn(ModuleDefn, Info0, Info).
-collect_mq_info_2(pred(_,_,_,_,_,_), Info, Info).
-collect_mq_info_2(func(_,_,_,_,_,_,_), Info, Info).
+collect_mq_info_2(pred(_,_,_,_,_,_,_), Info, Info).
+collect_mq_info_2(func(_,_,_,_,_,_,_,_), Info, Info).
collect_mq_info_2(pred_mode(_,_,_,_,_), Info, Info).
collect_mq_info_2(func_mode(_,_,_,_,_,_), Info, Info).
collect_mq_info_2(pragma(_), Info, Info).
collect_mq_info_2(nothing, Info, Info).
+collect_mq_info_2(typeclass(_, Name, Vars, _, _), Info0, Info) :-
+ add_typeclass_defn(Name, Vars, Info0, Info).
+collect_mq_info_2(instance(_,_,_,_,_), Info, Info).
-% Predicates to add the type, inst and mode ids visible
+
+% Predicates to add the type, inst, mode and typeclass ids visible
% in this module to the mq_info.
:- pred add_type_defn(type_defn::in, mq_info::in, mq_info::out) is det.
@@ -176,6 +181,16 @@
id_set_insert(NeedQualifier, SymName - Arity, Modes0, Modes),
mq_info_set_modes(Info0, Modes, Info).
+:- pred add_typeclass_defn(sym_name::in, list(var)::in,
+ mq_info::in, mq_info::out) is det.
+
+add_typeclass_defn(SymName, Params, Info0, Info) :-
+ list__length(Params, Arity),
+ mq_info_get_classes(Info0, Classes0),
+ mq_info_get_need_qual_flag(Info0, NeedQualifier),
+ id_set_insert(NeedQualifier, SymName - Arity, Classes0, Classes),
+ mq_info_set_classes(Info0, Classes, Info).
+
% Update import status.
% Add imported modules if in the interface.
:- pred process_module_defn(module_defn::in, mq_info::in, mq_info::out) is det.
@@ -258,23 +273,28 @@
module_defn(A, ModuleDefn) - Context, Info0, Info, Continue) -->
{ update_import_status(ModuleDefn, Info0, Info, Continue) }.
-module_qualify_item(pred(A, SymName, TypesAndModes0, D, E, F) - Context,
- pred(A, SymName, TypesAndModes, D, E, F) - Context,
+module_qualify_item(
+ pred(A, SymName, TypesAndModes0, D,E,F, Constraints0) - Context,
+ pred(A, SymName, TypesAndModes, D,E,F, Constraints) - Context,
Info0, Info, yes) -->
{ list__length(TypesAndModes0, Arity) },
{ mq_info_set_error_context(Info0, pred(SymName - Arity) - Context,
Info1) },
- qualify_types_and_modes(TypesAndModes0, TypesAndModes, Info1, Info).
+ qualify_types_and_modes(TypesAndModes0, TypesAndModes, Info1, Info2),
+ qualify_class_constraints(Constraints0, Constraints, Info2, Info).
module_qualify_item(
- func(A,SymName,TypesAndModes0,TypeAndMode0,D,E,F) - Context,
- func(A,SymName,TypesAndModes,TypeAndMode,D,E,F) - Context,
+ func(A,SymName, TypesAndModes0, TypeAndMode0, D, E, F
+ ,Constraints0) - Context,
+ func(A, SymName, TypesAndModes, TypeAndMode, D, E, F,
+ Constraints) - Context,
Info0, Info, yes) -->
{ list__length(TypesAndModes0, Arity) },
{ mq_info_set_error_context(Info0, func(SymName - Arity) - Context,
Info1) },
qualify_types_and_modes(TypesAndModes0, TypesAndModes, Info1, Info2),
- qualify_type_and_mode(TypeAndMode0, TypeAndMode, Info2, Info).
+ qualify_type_and_mode(TypeAndMode0, TypeAndMode, Info2, Info3),
+ qualify_class_constraints(Constraints0, Constraints, Info3, Info).
module_qualify_item(pred_mode(A, SymName, Modes0, C, D) - Context,
pred_mode(A, SymName, Modes, C, D) - Context,
@@ -299,6 +319,31 @@
qualify_pragma(Pragma0, Pragma, Info1, Info).
module_qualify_item(nothing - Context, nothing - Context,
Info, Info, yes) --> [].
+module_qualify_item(typeclass(Constraints0, Name, Vars, Interface0, VarSet) -
+ Context,
+ typeclass(Constraints, Name, Vars, Interface, VarSet) -
+ Context,
+ Info0, Info, yes) -->
+ { list__length(Vars, Arity) },
+ { Id = Name - Arity },
+ { mq_info_set_error_context(Info0, class(Id) - Context, Info1) },
+ qualify_class_constraints(Constraints0, Constraints, Info1, Info2),
+ qualify_class_interface(Interface0, Interface, Info2, Info).
+
+module_qualify_item(instance(Constraints0, Name0, Types0, Interface0, VarSet) -
+ Context,
+ instance(Constraints, Name, Types, Interface, VarSet) -
+ Context,
+ Info0, Info, yes) -->
+ { list__length(Types0, Arity) },
+ { Id = Name0 - Arity },
+ { mq_info_set_error_context(Info0, instance(Id) - Context, Info1) },
+ % We don't qualify the interface yet, since that requires
+ % us to resolve overloading.
+ qualify_class_constraints(Constraints0, Constraints, Info1, Info2),
+ qualify_class_name(Id, Name - _, Info2, Info3),
+ qualify_type_list(Types0, Types, Info3, Info),
+ { qualify_instance_interface(Name, Interface0, Interface) }.
:- pred update_import_status(module_defn::in, mq_info::in, mq_info::out,
bool::out) is det.
@@ -630,11 +675,116 @@
qualify_mode(Mode0, Mode, Info0, Info1),
qualify_pragma_vars(PragmaVars0, PragmaVars, Info1, Info).
+:- pred qualify_class_constraints(list(class_constraint)::in,
+ list(class_constraint)::out, mq_info::in, mq_info::out, io__state::di,
+ io__state::uo) is det.
+
+qualify_class_constraints([], [], MQInfo, MQInfo) --> [].
+qualify_class_constraints([C0|C0s], [C|Cs], MQInfo0, MQInfo) -->
+ qualify_class_constraint(C0, C, MQInfo0, MQInfo1),
+ qualify_class_constraints(C0s, Cs, MQInfo1, MQInfo).
+
+:- pred qualify_class_constraint(class_constraint::in, class_constraint::out,
+ mq_info::in, mq_info::out, io__state::di, io__state::uo) is det.
+
+qualify_class_constraint(constraint(ClassName0, Types0),
+ constraint(ClassName, Types), MQInfo0, MQInfo) -->
+ { list__length(Types0, Arity) },
+ qualify_class_name(ClassName0 - Arity, ClassName - _, MQInfo0, MQInfo1),
+ qualify_type_list(Types0, Types, MQInfo1, MQInfo).
+
+:- pred qualify_class_name(pair(class_name, arity)::in,
+ pair(class_name, arity)::out, mq_info::in, mq_info::out,
+ io__state::di, io__state::uo) is det.
+
+qualify_class_name(Class0, Class, MQInfo0, MQInfo) -->
+ { mq_info_get_classes(MQInfo0, ClassIdSet) },
+ find_unique_match(Class0, Class, ClassIdSet, class_id,
+ MQInfo0, MQInfo).
+
+:- pred qualify_class_interface(class_interface::in, class_interface::out,
+ mq_info::in, mq_info::out, io__state::di, io__state::uo) is det.
+
+qualify_class_interface([], [], MQInfo, MQInfo) --> [].
+qualify_class_interface([M0|M0s], [M|Ms], MQInfo0, MQInfo) -->
+ qualify_class_method(M0, M, MQInfo0, MQInfo1),
+ qualify_class_interface(M0s, Ms, MQInfo1, MQInfo).
+
+:- pred qualify_class_method(class_method::in, class_method::out,
+ mq_info::in, mq_info::out, io__state::di, io__state::uo) is det.
+
+ % There is no need to qualify the method name, since that is
+ % done when the item is parsed.
+qualify_class_method(
+ pred(Varset, Name, TypesAndModes0, MaybeDet, Cond,
+ ClassContext0, Context),
+ pred(Varset, Name, TypesAndModes, MaybeDet, Cond,
+ ClassContext, Context),
+ MQInfo0, MQInfo
+ ) -->
+ qualify_types_and_modes(TypesAndModes0, TypesAndModes,
+ MQInfo0, MQInfo1),
+ qualify_class_constraints(ClassContext0, ClassContext,
+ MQInfo1, MQInfo).
+qualify_class_method(
+ func(Varset, Name, TypesAndModes0, ReturnMode0, MaybeDet, Cond,
+ ClassContext0, Context),
+ func(Varset, Name, TypesAndModes, ReturnMode, MaybeDet, Cond,
+ ClassContext, Context),
+ MQInfo0, MQInfo
+ ) -->
+ qualify_types_and_modes(TypesAndModes0, TypesAndModes,
+ MQInfo0, MQInfo1),
+ qualify_type_and_mode(ReturnMode0, ReturnMode, MQInfo1, MQInfo2),
+ qualify_class_constraints(ClassContext0, ClassContext,
+ MQInfo2, MQInfo).
+qualify_class_method(
+ pred_mode(Varset, Name, Modes0, MaybeDet, Cond, Context),
+ pred_mode(Varset, Name, Modes, MaybeDet, Cond, Context),
+ MQInfo0, MQInfo
+ ) -->
+ qualify_mode_list(Modes0, Modes, MQInfo0, MQInfo).
+qualify_class_method(
+ func_mode(Varset, Name, Modes0, ReturnMode0, MaybeDet, Cond,
+ Context),
+ func_mode(Varset, Name, Modes, ReturnMode, MaybeDet, Cond,
+ Context),
+ MQInfo0, MQInfo
+ ) -->
+ qualify_mode_list(Modes0, Modes, MQInfo0, MQInfo1),
+ qualify_mode(ReturnMode0, ReturnMode, MQInfo1, MQInfo).
+
+:- pred qualify_instance_interface(sym_name::in, instance_interface::in,
+ instance_interface::out) is det.
+
+qualify_instance_interface(ClassName, M0s, Ms) :-
+ (
+ ClassName = qualified(Module, _)
+ ;
+ ClassName = unqualified( _),
+ Module = ""
+ ),
+ Qualify = lambda([M0::in, M::out] is det,
+ (
+ M0 = pred_instance(unqualified(Method), A, B),
+ M = pred_instance(qualified(Module, Method), A, B)
+ ;
+ M0 = pred_instance(qualified(_, _), _A, _B),
+ M = M0
+ ;
+ M0 = func_instance(unqualified(Method), A, B),
+ M = func_instance(qualified(Module, Method), A, B)
+ ;
+ M0 = func_instance(qualified(_, _), _A, _B),
+ M = M0
+ )),
+ list__map(Qualify, M0s, Ms).
+
% Find the unique match in the current name space for a given id
% from a list of ids. If none exists, either because no match was
% found or mulitiple matches were found, report an error.
- % This predicate assumes that type_ids, inst_ids and mode_ids
- % have the same representation.
+ % This predicate assumes that type_ids, inst_ids, mode_ids and
+ % class_ids have the same representation.
:- pred find_unique_match(id::in, id::out, id_set::in, id_type::in,
mq_info::in, mq_info::out, io__state::di, io__state::uo) is det.
@@ -703,7 +853,8 @@
:- type id_type --->
type_id
; mode_id
- ; inst_id.
+ ; inst_id
+ ; class_id.
:- type error_context == pair(error_context2, term__context).
@@ -719,7 +870,9 @@
; func_mode(id)
; (pragma)
; lambda_expr
- ; type_qual.
+ ; type_qual
+ ; class(id)
+ ; instance(id).
% Report an undefined type, inst or mode.
:- pred report_undefined(error_context, pair(sym_name, int),
@@ -803,12 +956,19 @@
io__write_string("pragma").
write_error_context2(type_qual) -->
io__write_string("explicit type qualification").
+write_error_context2(class(Id)) -->
+ io__write_string("declaration of typeclass "),
+ write_id(Id).
+write_error_context2(instance(Id)) -->
+ io__write_string("declaration of instance of typeclass "),
+ write_id(Id).
:- pred id_type_to_string(id_type::in, string::out) is det.
id_type_to_string(type_id, "type").
id_type_to_string(mode_id, "mode").
id_type_to_string(inst_id, "inst").
+id_type_to_string(class_id, "typeclass").
% Write sym_name/arity.
:- pred write_id(id::in, io__state::di, io__state::uo) is det.
@@ -920,12 +1080,13 @@
ErrorContext = type(unqualified("") - 0) - Context,
set__init(InterfaceModules0),
id_set_init(Empty),
- Info0 = mq_info(Empty, Empty, Empty, InterfaceModules0, local, 0,
+ Info0 = mq_info(Empty, Empty, Empty, Empty, InterfaceModules0, local, 0,
no, no, ReportErrors, ErrorContext, may_be_unqualified).
:- pred mq_info_get_types(mq_info::in, type_id_set::out) is det.
:- pred mq_info_get_insts(mq_info::in, inst_id_set::out) is det.
:- pred mq_info_get_modes(mq_info::in, mode_id_set::out) is det.
+:- pred mq_info_get_classes(mq_info::in, class_id_set::out) is det.
:- pred mq_info_get_interface_modules(mq_info::in,
set(module_name)::out) is det.
:- pred mq_info_get_import_status(mq_info::in, import_status::out) is det.
@@ -935,22 +1096,24 @@
:- pred mq_info_get_report_error_flag(mq_info::in, bool::out) is det.
:- pred mq_info_get_error_context(mq_info::in, error_context::out) is det.
-mq_info_get_types(mq_info(Types, _,_,_,_,_,_,_,_,_,_), Types).
-mq_info_get_insts(mq_info(_, Insts, _,_,_,_,_,_,_,_,_), Insts).
-mq_info_get_modes(mq_info(_,_, Modes, _,_,_,_,_,_,_,_), Modes).
-mq_info_get_interface_modules(mq_info(_,_,_, Modules, _,_,_,_,_,_,_), Modules).
-mq_info_get_import_status(mq_info(_,_,_,_, Status, _,_,_,_,_,_), Status).
-mq_info_get_num_errors(mq_info(_,_,_,_,_, NumErrors, _,_,_,_,_), NumErrors).
-mq_info_get_type_error_flag(mq_info(_,_,_,_,_,_, TypeErrs, _,_,_,_), TypeErrs).
-mq_info_get_mode_error_flag(mq_info(_,_,_,_,_,_,_, ModeError, _,_,_),
+mq_info_get_types(mq_info(Types, _, _,_,_,_,_,_,_,_,_,_), Types).
+mq_info_get_insts(mq_info(_, Insts, _,_,_,_,_,_,_,_,_,_), Insts).
+mq_info_get_modes(mq_info(_,_, Modes, _,_,_,_,_,_,_,_,_), Modes).
+mq_info_get_classes(mq_info(_,_,_, Classes, _,_,_,_,_,_,_,_), Classes).
+mq_info_get_interface_modules(mq_info(_,_,_,_, Modules,_,_,_,_,_,_,_), Modules).
+mq_info_get_import_status(mq_info(_,_,_,_,_, Status, _,_,_,_,_,_), Status).
+mq_info_get_num_errors(mq_info(_,_,_,_,_,_, NumErrors, _,_,_,_,_), NumErrors).
+mq_info_get_type_error_flag(mq_info(_,_,_,_,_,_,_, TypeErrs,_,_,_,_), TypeErrs).
+mq_info_get_mode_error_flag(mq_info(_,_,_,_,_,_,_,_, ModeError, _,_,_),
ModeError).
-mq_info_get_report_error_flag(mq_info(_,_,_,_,_,_,_,_, Report,_,_), Report).
-mq_info_get_error_context(mq_info(_,_,_,_,_,_,_,_,_, Context,_), Context).
-mq_info_get_need_qual_flag(mq_info(_,_,_,_,_,_,_,_,_,_,UseModule), UseModule).
+mq_info_get_report_error_flag(mq_info(_,_,_,_,_,_,_,_,_, Report,_,_), Report).
+mq_info_get_error_context(mq_info(_,_,_,_,_,_,_,_,_,_, Context,_), Context).
+mq_info_get_need_qual_flag(mq_info(_,_,_,_,_,_,_,_,_,_,_,UseModule), UseModule).
:- pred mq_info_set_types(mq_info::in, type_id_set::in, mq_info::out) is det.
:- pred mq_info_set_insts(mq_info::in, inst_id_set::in, mq_info::out) is det.
:- pred mq_info_set_modes(mq_info::in, mode_id_set::in, mq_info::out) is det.
+:- pred mq_info_set_classes(mq_info::in, class_id_set::in, mq_info::out) is det.
:- pred mq_info_set_interface_modules(mq_info::in, set(module_name)::in,
mq_info::out) is det.
:- pred mq_info_set_import_status(mq_info::in, import_status::in,
@@ -960,29 +1123,31 @@
:- pred mq_info_set_error_context(mq_info::in, error_context::in,
mq_info::out) is det.
-mq_info_set_types(mq_info(_, B,C,D,E,F,G,H,I,J,K), Types,
- mq_info(Types, B,C,D,E,F,G,H,I,J,K)).
-mq_info_set_insts(mq_info(A,_,C,D,E,F,G,H,I,J,K), Insts,
- mq_info(A, Insts, C,D,E,F,G,H,I,J,K)).
-mq_info_set_modes(mq_info(A,B,_,D,E,F,G,H,I,J,K), Modes,
- mq_info(A,B, Modes, D,E,F,G,H,I,J,K)).
-mq_info_set_interface_modules(mq_info(A,B,C,_,E,F,G,H,I,J,K), Modules,
- mq_info(A,B,C, Modules, E,F,G,H,I,J,K)).
-mq_info_set_import_status(mq_info(A,B,C,D,_,F,G,H,I,J,K), Status,
- mq_info(A,B,C,D, Status, F,G,H,I,J,K)).
-mq_info_set_type_error_flag(mq_info(A,B,C,D,E,F, _, H,I,J,K),
- mq_info(A,B,C,D,E,F, yes, H,I,J,K)).
-mq_info_set_mode_error_flag(mq_info(A,B,C,D,E,F,G,_,I,J,K),
- mq_info(A,B,C,D,E,F,G, yes, I,J,K)).
-mq_info_set_error_context(mq_info(A,B,C,D,E,F,G,H,I,_,K), Context,
- mq_info(A,B,C,D,E,F,G,H,I, Context,K)).
-mq_info_set_need_qual_flag(mq_info(A,B,C,D,E,F,G,H,I,J,_), Flag,
- mq_info(A,B,C,D,E,F,G,H,I,J, Flag)).
+mq_info_set_types(mq_info(_, B,C,D,E,F,G,H,I,J,K,L), Types,
+ mq_info(Types, B,C,D,E,F,G,H,I,J,K,L)).
+mq_info_set_insts(mq_info(A,_,C,D,E,F,G,H,I,J,K,L), Insts,
+ mq_info(A, Insts, C,D,E,F,G,H,I,J,K,L)).
+mq_info_set_modes(mq_info(A,B,_,D,E,F,G,H,I,J,K,L), Modes,
+ mq_info(A,B, Modes, D,E,F,G,H,I,J,K,L)).
+mq_info_set_classes(mq_info(A,B,C,_,E,F,G,H,I,J,K,L), Classes,
+ mq_info(A,B, C, Classes,E,F,G,H,I,J,K,L)).
+mq_info_set_interface_modules(mq_info(A,B,C,D,_,F,G,H,I,J,K,L), Modules,
+ mq_info(A,B,C,D, Modules, F,G,H,I,J,K,L)).
+mq_info_set_import_status(mq_info(A,B,C,D,E,_,G,H,I,J,K,L), Status,
+ mq_info(A,B,C,D,E, Status, G,H,I,J,K,L)).
+mq_info_set_type_error_flag(mq_info(A,B,C,D,E,F,G, _, I,J,K,L),
+ mq_info(A,B,C,D,E,F,G, yes, I,J,K,L)).
+mq_info_set_mode_error_flag(mq_info(A,B,C,D,E,F,G,H,_,J,K,L),
+ mq_info(A,B,C,D,E,F,G,H, yes, J,K,L)).
+mq_info_set_error_context(mq_info(A,B,C,D,E,F,G,H,I,J,_,L), Context,
+ mq_info(A,B,C,D,E,F,G,H,I,J, Context,L)).
+mq_info_set_need_qual_flag(mq_info(A,B,C,D,E,F,G,H,I,J,K,_), Flag,
+ mq_info(A,B,C,D,E,F,G,H,I,J,K, Flag)).
:- pred mq_info_incr_errors(mq_info::in, mq_info::out) is det.
-mq_info_incr_errors(mq_info(A,B,C,D,E, NumErrors0, G,H,I,J,K),
- mq_info(A,B,C,D,E, NumErrors, G,H,I,J,K)) :-
+mq_info_incr_errors(mq_info(A,B,C,D,E,F, NumErrors0, H,I,J,K,L),
+ mq_info(A,B,C,D,E,F, NumErrors,H,I,J,K,L)) :-
NumErrors is NumErrors0 + 1.
:- pred mq_info_set_error_flag(mq_info::in, id_type::in, mq_info::out) is det.
@@ -993,6 +1158,8 @@
mq_info_set_mode_error_flag(Info0, Info).
mq_info_set_error_flag(Info0, inst_id, Info) :-
mq_info_set_mode_error_flag(Info0, Info).
+mq_info_set_error_flag(Info0, class_id, Info) :-
+ mq_info_set_type_error_flag(Info0, Info).
% If the current item is in the interface, remove its module
% name from the list of modules not used in the interface.
@@ -1035,6 +1202,7 @@
:- type type_id_set == id_set.
:- type mode_id_set == id_set.
:- type inst_id_set == id_set.
+:- type class_id_set == id_set.
:- pred id_set_init(id_set::out) is det.
Index: compiler/modules.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/modules.m,v
retrieving revision 1.43
diff -u -r1.43 modules.m
--- modules.m 1997/11/21 08:08:23 1.43
+++ modules.m 1997/12/02 05:29:44
@@ -8,13 +8,13 @@
% main author: fjh
% This module contains all the code for handling module imports and exports,
-% for computing module dependencies, and for generate makefile fragments to
+% for computing module dependencies, and for generating makefile fragments to
% record those dependencies.
%
%
% The interface system works as follows:
%
-% 1. a .int3 file is written, which contains all the types, insts
+% 1. a .int3 file is written, which contains all the types, typeclasses, insts
% and modes defined in the interface. Equivalence types, insts and
% modes are written in full, others are written in abstract form.
% These are module qualified as far as possible given the information
@@ -1562,7 +1562,7 @@
% Given a module interface (well, a list of items), extract the
% short interface part of that module, i.e. the exported
- % type/inst/mode declarations, but not the exported pred or
+ % type/typeclass/inst/mode declarations, but not the exported pred or
% constructor declarations. If the module interface imports
% other modules, then the short interface only needs to include
% those import_module declarations only if the short interface
@@ -1626,6 +1626,7 @@
include_in_short_interface(inst_defn(_, _, _)).
include_in_short_interface(mode_defn(_, _, _)).
include_in_short_interface(module_defn(_, _)).
+include_in_short_interface(typeclass(_, _, _, _, _)).
:- pred make_abstract_type_defn(item, item).
:- mode make_abstract_type_defn(in, out) is semidet.
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/opt_debug.m,v
retrieving revision 1.75
diff -u -r1.75 opt_debug.m
--- opt_debug.m 1997/12/05 15:47:40 1.75
+++ opt_debug.m 1997/12/09 06:37:19
@@ -687,6 +687,8 @@
string__append("common", N_str, Str).
opt_debug__dump_data_name(base_type(BaseData, TypeName, TypeArity), Str) :-
llds_out__make_base_type_name(BaseData, TypeName, TypeArity, Str).
+opt_debug__dump_data_name(base_typeclass_info(ClassId, InstanceNum), Str) :-
+ llds_out__make_base_typeclass_info_name(ClassId, InstanceNum, Str).
opt_debug__dump_data_name(stack_layout(Label), Str) :-
opt_debug__dump_label(Label, LabelStr),
string__append_list(["stack_layout(", LabelStr, ")"], Str).
@@ -738,6 +740,9 @@
opt_debug__dump_code_addr(do_det_closure, "do_det_closure").
opt_debug__dump_code_addr(do_semidet_closure, "do_semidet_closure").
opt_debug__dump_code_addr(do_nondet_closure, "do_nondet_closure").
+opt_debug__dump_code_addr(do_det_class_method, "do_det_class_method").
+opt_debug__dump_code_addr(do_semidet_class_method, "do_semidet_class_method").
+opt_debug__dump_code_addr(do_nondet_class_method, "do_nondet_class_method").
opt_debug__dump_code_addr(do_not_reached, "do_not_reached").
opt_debug__dump_code_addrs([], "").
Index: compiler/opt_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/opt_util.m,v
retrieving revision 1.85
diff -u -r1.85 opt_util.m
--- opt_util.m 1997/12/05 15:47:42 1.85
+++ opt_util.m 1997/12/09 06:37:20
@@ -1199,6 +1199,9 @@
opt_util__livevals_addr(do_det_closure, yes).
opt_util__livevals_addr(do_semidet_closure, yes).
opt_util__livevals_addr(do_nondet_closure, yes).
+opt_util__livevals_addr(do_det_class_method, yes).
+opt_util__livevals_addr(do_semidet_class_method, yes).
+opt_util__livevals_addr(do_nondet_class_method, yes).
opt_util__livevals_addr(do_not_reached, no).
opt_util__count_temps_instr_list([], R, R, F, F).
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/polymorphism.m,v
retrieving revision 1.118
diff -u -r1.118 polymorphism.m
--- polymorphism.m 1997/10/14 09:27:53 1.118
+++ polymorphism.m 1997/12/15 06:15:47
@@ -8,9 +8,10 @@
% main author: fjh
% This module is a pass over the HLDS.
-% It does a syntactic transformation to implement polymorphism
-% using higher-order predicates, and also invokes `lambda__transform_lambda'
-% to handle lambda expressions by creating new predicates for them.
+% It does a syntactic transformation to implement polymorphism, including
+% typeclasses, using higher-order predicates, and also invokes
+% `lambda__transform_lambda' to handle lambda expressions by creating new
+% predicates for them.
%
%-----------------------------------------------------------------------------%
%
@@ -40,7 +41,7 @@
% word 3 <compare/3 predicate for type>
% word 4 <base_type_layout for type>
% word 5 <base_type_functors for type>
-% word 6 <string name of type>
+% word 6 <string name of type constructor>
% e.g. "int" for `int', "list" for `list(T)',
% "map" for `map(K,V)'
% word 7 <string name of module>
@@ -150,6 +151,137 @@
% single shared base_type_info.
%
%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+%
+% Tranformation of code using typeclasses:
+%
+% Every predicate which has a typeclass constraint is given an extra
+% argument for every constraint in the predicate's type declaration.
+% The argument is the "dictionary", or "typeclass_info" for the typeclass.
+% The dictionary contains pointers to each of the class methods.
+%
+%-----------------------------------------------------------------------------%
+%
+% Representation of a typeclass_info:
+% The typeclass_info is represented in two parts (the typeclass_info
+% itself, and a base_typeclass_info), in a similar fashion to the
+% type_info being represented in two parts (the type_info and the
+% base_type_info).
+%
+% The base_typeclass_info contains:
+% * the number of constraints on the instance decl.
+% * pointer to method #1
+% ...
+% * pointer to method #n
+%
+% The typeclass_info contains:
+% * a pointer to the base typeclass info
+% * typeclass info #1 for constraint on instance decl
+% * ...
+% * typeclass info #n for constraint on instance decl
+% * typeclass info for superclass #1
+% ...
+% * typeclass info for superclass #n
+% * type info #1
+% * ...
+% * type info #n
+%
+% The base_type_info is produced statically, and there is one for each instance
+% declaration. For each constraint on the instance declaration, the
+% corresponding typeclass info is stored in the second part.
+%
+% eg. for the following program:
+%
+% :- typeclass foo(T) where [...].
+% :- instance foo(int) where [...].
+% :- instance foo(list(T)) <= foo(T) where [...].
+%
+% The typeclass_info for foo(int) is:
+% The base_type_info:
+% * 0 (arity of the instance declaration)
+% * pointer to method #1
+% ...
+% * pointer to method #n
+%
+% The type_info:
+% * a pointer to the base typeclass info
+% * type info for int
+%
+% The typeclass_info for foo(list(T)) is:
+% The base_type_info:
+% * 1 (arity of the instance declaration)
+% * pointer to method #1
+% ...
+% * pointer to method #n
+%
+% The type_info contains:
+% * a pointer to the base typeclass info
+% * typeclass info for foo(T)
+% * type info for list(T)
+%
+% If the "T" for the list is known, the whole typeclass_info will be static
+% data. When we do not know until runtime, the typeclass_info is constructed
+% dynamically.
+%
+%-----------------------------------------------------------------------------%
+%
+% Example of transformation:
+%
+% Take the following code as an example (assuming the declarations above),
+% ignoring the requirement for super-homogeneous form for clarity:
+%
+% :- pred p(T1) <= foo(T1).
+% :- pred q(T2, T3) <= foo(T2), bar(T3).
+% :- pred r(T4, T5) <= foo(T4).
+%
+% p(X) :- q([X], 0), r(0, X).
+%
+% We add an extra argument for each typeclass constraint, and one argument for
+% each unconstrained type variable.
+%
+% :- pred p(typeclass_info(foo(T1)), T1).
+% :- pred q(typeclass_info(foo(T2)), typeclass_info(bar(T3)), T2, T3).
+% :- pred r(typeclass_info(foo(T4)), type_info(T5), T4, T5).
+%
+% We transform the body of p to this:
+%
+% p(TypeClassInfoT1, X) :-
+% BaseTypeClassInfoT2 = base_typeclass_info(
+% 1,
+% ...
+% ... (The methods for the foo class from the list
+% ... instance)
+% ...
+% ),
+% TypeClassInfoT2 = typeclass_info(
+% BaseClassTypeInfoT2,
+% TypeClassInfoT1,
+% <type_info for list(T1)>),
+% BaseTypeClassInfoT3 = base_typeclass_info(
+% 0,
+% ...
+% ... (The methods for the bar class from the int
+% ... instance)
+% ...
+% ),
+% TypeClassInfoT3 = typeclass_info(
+% BaseClassTypeInfoT3,
+% <type_info for int>),
+% q(TypeClassInfoT2, TypeClassInfoT3, [X], 0),
+% BaseTypeClassInfoT4 = baseclass_type_info(
+% 0,
+% ...
+% ... (The methods for the foo class from the int
+% ... instance)
+% ...
+% ),
+% TypeClassInfoT4 = typeclass_info(
+% BaseTypeClassInfoT4,
+% <type_info for int>),
+% r(TypeClassInfoT1, <type_info for int>, 0, X).
+%
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
:- module polymorphism.
:- interface.
@@ -166,10 +298,10 @@
:- import_module hlds_pred, hlds_goal, hlds_data, llds, (lambda), globals.
:- import_module prog_data, type_util, mode_util, quantification, instmap.
:- import_module code_util, unify_proc, special_pred, prog_util, make_hlds.
-:- import_module (inst), hlds_out.
+:- import_module (inst), hlds_out, base_typeclass_info.
:- import_module bool, int, string, list, set, map.
-:- import_module term, varset, std_util, require.
+:- import_module term, varset, std_util, require, assoc_list.
%-----------------------------------------------------------------------------%
@@ -187,7 +319,8 @@
polymorphism__process_preds(PredIds0, ModuleInfo0, ModuleInfo1),
module_info_preds(ModuleInfo1, Preds1),
map__keys(Preds1, PredIds1),
- polymorphism__fixup_preds(PredIds1, ModuleInfo1, ModuleInfo).
+ polymorphism__fixup_preds(PredIds1, ModuleInfo1, ModuleInfo2),
+ polymorphism__expand_class_method_bodies(ModuleInfo2, ModuleInfo).
:- pred polymorphism__process_preds(list(pred_id), module_info, module_info).
:- mode polymorphism__process_preds(in, in, out) is det.
@@ -284,9 +417,32 @@
varset, % from the proc_info
map(var, type), % from the proc_info
tvarset, % from the proc_info
- map(tvar, var), % specifies the type_info var
+ map(tvar, type_info_locn),
+ % specifies the location of
+ % the type_info var
% for each of the pred's type
% parameters
+
+ map(class_constraint, var),
+ % specifies the location of
+ % the typeclass_info var
+ % for each of the pred's class
+ % constraints
+ map(class_constraint, constraint_proof),
+ % specifies why each constraint
+ % that was eliminated from the
+ % pred was able to be eliminated
+ % (this allows us to efficiently
+ % construct the dictionary)
+
+ % Note that the two maps above
+ % are separate since the second
+ % is the information calculated
+ % by typecheck.m, while the
+ % first is the information
+ % calculated here in
+ % polymorphism.m
+
string, % pred name
module_info
).
@@ -300,34 +456,76 @@
% grab the appropriate fields from the pred_info and proc_info
pred_info_arg_types(PredInfo0, ArgTypeVarSet, ArgTypes),
pred_info_typevarset(PredInfo0, TypeVarSet0),
+ pred_info_get_class_context(PredInfo0, ClassContext),
+ pred_info_get_constraint_proofs(PredInfo0, Proofs),
pred_info_name(PredInfo0, PredName),
proc_info_headvars(ProcInfo0, HeadVars0),
proc_info_variables(ProcInfo0, VarSet0),
proc_info_vartypes(ProcInfo0, VarTypes0),
proc_info_goal(ProcInfo0, Goal0),
proc_info_argmodes(ProcInfo0, ArgModes0),
- % insert extra head variables to hold the address of the
- % equality predicate for each polymorphic type in the predicate's
- % type declaration
+
+
+ % Insert extra head variables to hold the address of the
+ % type_infos and typeclass_infos.
+ % We insert one variable for each unconstrained type variable
+ % (for the type_info) and one variable for each constraint (for
+ % the typeclass_info).
term__vars_list(ArgTypes, HeadTypeVars0),
- list__remove_dups(HeadTypeVars0, HeadTypeVars), % remove duplicates
- polymorphism__make_head_vars(HeadTypeVars, ArgTypeVarSet,
- VarSet0, VarTypes0, ExtraHeadVars, VarSet1, VarTypes1),
- list__append(ExtraHeadVars, HeadVars0, HeadVars),
- list__length(ExtraHeadVars, NumExtraVars),
+ % Make a fresh variable for each class constraint, returning
+ % a list of variables that appear in the constraints, along
+ % with the location of the type infos for them.
+ polymorphism__make_typeclass_info_head_vars(ClassContext, ModuleInfo0,
+ VarSet0, VarTypes0, ExtraHeadTypeclassInfoVars,
+ TypeClassInfoMap, ConstrainedTVars,
+ VarSet1, VarTypes1),
+
+ list__delete_elems(HeadTypeVars0, ConstrainedTVars,
+ UnconstrainedTVars0),
+ list__remove_dups(UnconstrainedTVars0, UnconstrainedTVars),
+
+ polymorphism__make_head_vars(UnconstrainedTVars, ArgTypeVarSet,
+ VarSet1, VarTypes1, ExtraHeadTypeInfoVars, VarSet2, VarTypes2),
+
+ % First the type_infos, then the typeclass_infos,
+ % but we have to do it in reverse because we're appending...
+ list__append(ExtraHeadTypeclassInfoVars, HeadVars0, HeadVars1),
+ list__append(ExtraHeadTypeInfoVars, HeadVars1, HeadVars),
+
+ % Work out the total number of new vars
+ list__length(ExtraHeadTypeInfoVars, NumExtraVars0),
+ list__length(ExtraHeadTypeclassInfoVars, NumExtraVars1),
+ NumExtraVars is NumExtraVars1 + NumExtraVars0,
+
list__duplicate(NumExtraVars, user_defined_mode(
qualified("mercury_builtin", "in"), []), ExtraModes),
list__append(ExtraModes, ArgModes0, ArgModes),
+ % Make a map of the locations of the unconstrained typeinfos
+ AddLocn = lambda([TVarAndVar::in, TIM0::in, TIM::out] is det,
+ (
+ TVarAndVar = TVar - TheVar,
+ map__det_insert(TIM0, TVar, type_info(TheVar), TIM)
+ )),
+ assoc_list__from_corresponding_lists(UnconstrainedTVars,
+ ExtraHeadTypeInfoVars, TVarsAndVars),
+ list__foldl(AddLocn, TVarsAndVars, TypeClassInfoMap, TypeInfoMap1),
+
+
+ % Make a map of the locations of the typeclass_infos
+ map__from_corresponding_lists(ClassContext, ExtraHeadTypeclassInfoVars,
+ TypeclassInfoLocations0),
+
+ Info0 = poly_info(VarSet2, VarTypes2, TypeVarSet0,
+ TypeInfoMap1, TypeclassInfoLocations0,
+ Proofs, PredName, ModuleInfo0),
+
% process any polymorphic calls inside the goal
- map__from_corresponding_lists(HeadTypeVars, ExtraHeadVars,
- TypeInfoMap0),
- Info0 = poly_info(VarSet1, VarTypes1, TypeVarSet0,
- TypeInfoMap0, PredName, ModuleInfo0),
polymorphism__process_goal(Goal0, Goal1, Info0, Info1),
polymorphism__fixup_quantification(Goal1, Goal, Info1, Info),
- Info = poly_info(VarSet, VarTypes, TypeVarSet, TypeInfoMap, _PredName,
- ModuleInfo),
+ Info = poly_info(VarSet, VarTypes, TypeVarSet,
+ TypeInfoMap, TypeclassInfoLocations,
+ _Proofs, _PredName, ModuleInfo),
% set the new values of the fields in proc_info and pred_info
proc_info_set_headvars(ProcInfo0, HeadVars, ProcInfo1),
@@ -335,7 +533,9 @@
proc_info_set_varset(ProcInfo2, VarSet, ProcInfo3),
proc_info_set_vartypes(ProcInfo3, VarTypes, ProcInfo4),
proc_info_set_argmodes(ProcInfo4, ArgModes, ProcInfo5),
- proc_info_set_typeinfo_varmap(ProcInfo5, TypeInfoMap, ProcInfo),
+ proc_info_set_typeinfo_varmap(ProcInfo5, TypeInfoMap, ProcInfo6),
+ proc_info_set_typeclass_info_varmap(ProcInfo6, TypeclassInfoLocations,
+ ProcInfo),
pred_info_set_typevarset(PredInfo0, TypeVarSet, PredInfo).
:- pred polymorphism__process_goal(hlds_goal, hlds_goal,
@@ -357,6 +557,11 @@
GoalInfo, higher_order_call(A, B, C, D, E, F) - GoalInfo)
--> [].
+ % The same goes for class method calls
+polymorphism__process_goal_expr(class_method_call(A, B, C, D, E, F),
+ GoalInfo, class_method_call(A, B, C, D, E, F) - GoalInfo)
+ --> [].
+
polymorphism__process_goal_expr(call(PredId0, ProcId0, ArgVars0,
Builtin, Context, Name0), GoalInfo, Goal) -->
% Check for a call to a special predicate like compare/3
@@ -368,7 +573,7 @@
{ list__length(ArgVars0, Arity) },
{ special_pred_name_arity(SpecialPredId, PredName0,
MangledPredName, Arity) },
- =(poly_info(_, VarTypes, _, _TypeInfoMap, _PN, ModuleInfo)),
+ =(poly_info(_, VarTypes, _, _, _, _, _, ModuleInfo)),
{ special_pred_get_type(MangledPredName, ArgVars0, MainVar) },
{ map__lookup(VarTypes, MainVar, Type) },
{ Type \= term__variable(_) },
@@ -404,7 +609,7 @@
{ Unification = complicated_unify(UniMode, CanFail) },
{ Y = var(YVar) }
->
- =(poly_info(_, VarTypes, _, TypeInfoMap, _PName, ModuleInfo)),
+ =(poly_info(_, VarTypes, _, TypeInfoMap, _, _, _, ModuleInfo)),
{ map__lookup(VarTypes, XVar, Type) },
( { Type = term__variable(TypeVar) } ->
% Convert polymorphic unifications into calls to
@@ -428,14 +633,38 @@
% polymorphically typed variables in partially
% instantiated mode") if it isn't
{ hlds_pred__in_in_unification_proc_id(ProcId) },
- { map__lookup(TypeInfoMap, TypeVar, TypeInfoVar) },
+ { map__lookup(TypeInfoMap, TypeVar, TypeInfoLocn) },
{ SymName = unqualified("unify") },
- { ArgVars = [TypeInfoVar, XVar, YVar] },
{ code_util__builtin_state(ModuleInfo, PredId, ProcId,
BuiltinState) },
{ CallContext = call_unify_context(XVar, Y, Context) },
- { Goal = call(PredId, ProcId, ArgVars, BuiltinState,
- yes(CallContext), SymName) - GoalInfo }
+ (
+ % If the typeinfo is available in a
+ % variable, just use it
+ { TypeInfoLocn = type_info(TypeInfoVar) },
+ { ArgVars = [TypeInfoVar, XVar, YVar] },
+ { Goal = call(PredId, ProcId, ArgVars,
+ BuiltinState, yes(CallContext), SymName)
+ - GoalInfo }
+ ;
+ % If the typeinfo is in a
+ % typeclass_info, first extract it,
+ % then use it
+ { TypeInfoLocn =
+ typeclass_info(TypeClassInfoVar,
+ Index) },
+ extract_type_info(Type, TypeVar,
+ TypeClassInfoVar, Index,
+ Goals, TypeInfoVar),
+
+ { ArgVars = [TypeInfoVar, XVar, YVar] },
+ { Call = call(PredId, ProcId, ArgVars,
+ BuiltinState, yes(CallContext), SymName)
+ - GoalInfo },
+
+ { list__append(Goals, [Call], TheGoals) },
+ { Goal = conj(TheGoals) - GoalInfo }
+ )
; { type_is_higher_order(Type, _, _) } ->
{ SymName = unqualified("builtin_unify_pred") },
@@ -537,7 +766,7 @@
% so that the c_code can refer to the type_info variable
% for type T as `TypeInfo_for_T'.
%
- =(poly_info(_, _, _, _, _, ModuleInfo)),
+ =(poly_info(_, _, _, _, _, _, _, ModuleInfo)),
{ module_info_pred_info(ModuleInfo, PredId, PredInfo) },
{ pred_info_arg_types(PredInfo, PredTypeVarSet, PredArgTypes) },
{ term__vars_list(PredArgTypes, PredTypeVars0) },
@@ -612,14 +841,17 @@
polymorphism__process_call(PredId, _ProcId, ArgVars0, ArgVars,
ExtraVars, ExtraGoals, Info0, Info) :-
- Info0 = poly_info(VarSet0, VarTypes0, TypeVarSet0,
- TypeInfoMap0, PredName, ModuleInfo),
+
+ Info0 = poly_info(A, VarTypes, TypeVarSet0, D, E, F, G, ModuleInfo),
+
module_info_pred_info(ModuleInfo, PredId, PredInfo),
pred_info_arg_types(PredInfo, PredTypeVarSet, PredArgTypes0),
+ pred_info_get_class_context(PredInfo, PredClassContext0),
% rename apart
% (this merge might be a performance bottleneck?)
- varset__merge(TypeVarSet0, PredTypeVarSet, PredArgTypes0,
- TypeVarSet, PredArgTypes),
+ varset__merge_subst(TypeVarSet0, PredTypeVarSet, TypeVarSet, Subst),
+ term__apply_substitution_to_list(PredArgTypes0, Subst,
+ PredArgTypes),
term__vars_list(PredArgTypes, PredTypeVars0),
( PredTypeVars0 = [] ->
% optimize for common case of non-polymorphic call
@@ -628,24 +860,47 @@
ExtraVars = [],
Info = Info0
;
- list__remove_dups(PredTypeVars0, PredTypeVars),
- map__apply_to_list(ArgVars0, VarTypes0, ActualArgTypes),
+ list__remove_dups(PredTypeVars0, PredTypeVars1),
+ map__apply_to_list(ArgVars0, VarTypes, ActualArgTypes),
( type_list_subsumes(PredArgTypes, ActualArgTypes,
TypeSubst1) ->
TypeSubst = TypeSubst1
;
error("polymorphism__process_goal_expr: type unification failed")
),
+
+
+ apply_subst_to_constraints(Subst, PredClassContext0,
+ PredClassContext),
+
+ Info1 = poly_info(A, VarTypes, TypeVarSet, D, E, F, G,
+ ModuleInfo),
+
+ % Make the typeclass_infos for the call, and return
+ % a list of which variables were constrained by the
+ % context
+ polymorphism__make_typeclass_info_vars(PredClassContext,
+ Subst, TypeSubst, ExtraTypeClassVars,
+ ExtraTypeClassGoals, ConstrainedVars, Info1, Info2),
+
+ % No need to make typeinfos for the constrained vars
+ list__delete_elems(PredTypeVars1, ConstrainedVars,
+ PredTypeVars),
+
term__var_list_to_term_list(PredTypeVars, PredTypes0),
term__apply_rec_substitution_to_list(PredTypes0, TypeSubst,
PredTypes),
- polymorphism__make_vars(PredTypes, ModuleInfo, TypeInfoMap0,
- VarSet0, VarTypes0,
- ExtraVars, TypeInfoMap, ExtraGoals, VarSet,
- VarTypes),
- list__append(ExtraVars, ArgVars0, ArgVars),
- Info = poly_info(VarSet, VarTypes, TypeVarSet,
- TypeInfoMap, PredName, ModuleInfo)
+
+ polymorphism__make_type_info_vars(PredTypes,
+ ExtraTypeInfoVars, ExtraTypeInfoGoals,
+ Info2, Info),
+ list__append(ExtraTypeClassVars, ArgVars0, ArgVars1),
+ list__append(ExtraTypeInfoVars, ArgVars1, ArgVars),
+ list__append(ExtraTypeClassGoals, ExtraTypeInfoGoals,
+ ExtraGoals),
+ list__append(ExtraTypeClassVars, ExtraTypeInfoVars,
+ ExtraVars)
+
).
:- pred polymorphism__fixup_quantification(hlds_goal, hlds_goal,
@@ -661,31 +916,39 @@
polymorphism__fixup_quantification(Goal0, Goal, Info0, Info) :-
Info0 = poly_info(VarSet0, VarTypes0, TypeVarSet, TypeVarMap,
- PredName, ModuleInfo),
+ TypeClassVarMap, Proofs, PredName, ModuleInfo),
( map__is_empty(TypeVarMap) ->
Info = Info0,
Goal = Goal0
;
%
- % A type-info variable may be non-local to a goal if any of
+ % A type-info variable may be non-local to a goal if any of
% the ordinary non-local variables for that goal are
% polymorphically typed with a type that depends on that
% type-info variable.
%
+ % In addition, a typeclass-info may be non-local to a goal if
+ % any of the non-local variables for that goal are
+ % polymorphically typed and are constrained by the typeclass
+ % constraints for that typeclass-info variable
+ %
Goal0 = _ - GoalInfo0,
goal_info_get_nonlocals(GoalInfo0, NonLocals),
set__to_sorted_list(NonLocals, NonLocalsList),
map__apply_to_list(NonLocalsList, VarTypes0, NonLocalsTypes),
term__vars_list(NonLocalsTypes, NonLocalTypeVars),
- solutions_set(lambda([TypeInfoVar::out] is nondet, (
- list__member(Var, NonLocalTypeVars),
- map__search(TypeVarMap, Var, TypeInfoVar)
+ % Find all the type-infos and typeclass-infos that are
+ % non-local
+ solutions_set(lambda([Var::out] is nondet, (
+ list__member(TheVar, NonLocalTypeVars),
+ map__search(TypeVarMap, TheVar, Location),
+ type_info_locn_var(Location, Var)
)), NewOutsideVars),
set__union(NewOutsideVars, NonLocals, OutsideVars),
implicitly_quantify_goal(Goal0, VarSet0, VarTypes0,
OutsideVars, Goal, VarSet, VarTypes, _Warnings),
Info = poly_info(VarSet, VarTypes, TypeVarSet, TypeVarMap,
- PredName, ModuleInfo)
+ TypeClassVarMap, Proofs, PredName, ModuleInfo)
).
:- pred polymorphism__process_lambda(pred_or_func, list(var),
@@ -697,50 +960,484 @@
polymorphism__process_lambda(PredOrFunc, Vars, Modes, Det, OrigNonLocals,
LambdaGoal, Unification0, Functor, Unification,
PolyInfo0, PolyInfo) :-
- PolyInfo0 = poly_info(VarSet, VarTypes, TVarSet, TVarMap, PredName,
- ModuleInfo0),
+ PolyInfo0 = poly_info(VarSet, VarTypes, TVarSet, TVarMap,
+ TCVarMap, Proofs, PredName, ModuleInfo0),
+
+ % Calculate the constraints which apply to this lambda
+ % expression.
+ map__keys(TCVarMap, AllConstraints),
+ map__apply_to_list(Vars, VarTypes, LambdaVarTypes),
+ list__map(type_util__vars, LambdaVarTypes, LambdaTypeVarsList),
+ list__condense(LambdaTypeVarsList, LambdaTypeVars),
+ list__filter(polymorphism__constraint_contains_vars(LambdaTypeVars),
+ AllConstraints, Constraints),
+
lambda__transform_lambda(PredOrFunc, PredName, Vars, Modes, Det,
OrigNonLocals, LambdaGoal, Unification0, VarSet, VarTypes,
- TVarSet, TVarMap, ModuleInfo0, Functor,
+ Constraints, TVarSet, TVarMap, TCVarMap, ModuleInfo0, Functor,
Unification, ModuleInfo),
- PolyInfo = poly_info(VarSet, VarTypes, TVarSet, TVarMap, PredName,
- ModuleInfo).
+ PolyInfo = poly_info(VarSet, VarTypes, TVarSet, TVarMap,
+ TCVarMap, Proofs, PredName, ModuleInfo).
+
+:- pred polymorphism__constraint_contains_vars(list(var), class_constraint).
+:- mode polymorphism__constraint_contains_vars(in, in) is semidet.
+
+polymorphism__constraint_contains_vars(LambdaVars, ClassConstraint) :-
+ ClassConstraint = constraint(_, ConstraintTypes),
+ list__map(type_util__vars, ConstraintTypes, ConstraintVarsList),
+ list__condense(ConstraintVarsList, ConstraintVars),
+ % Probably not the most efficient way of doing it, but I
+ % wouldn't think that it matters.
+ set__list_to_set(LambdaVars, LambdaVarsSet),
+ set__list_to_set(ConstraintVars, ConstraintVarsSet),
+ set__subset(ConstraintVarsSet, LambdaVarsSet).
+
+%---------------------------------------------------------------------------%
+
+% Given a list of constraints, create a list of variables to hold the
+% typeclass_info for those constraints, and create a list of goals to
+% initialize those typeclass_info variables to the appropriate
+% typeclass_info structures for the constraints.
+
+:- pred polymorphism__make_typeclass_info_vars(list(class_constraint),
+ substitution, tsubst, list(var), list(hlds_goal), list(var),
+ poly_info, poly_info).
+:- mode polymorphism__make_typeclass_info_vars(in, in, in, out, out, out,
+ in, out) is det.
+
+polymorphism__make_typeclass_info_vars(PredClassContext, Subst, TypeSubst,
+ ExtraVars, ExtraGoals, ConstrainedVars, Info0, Info) :-
+
+ % initialise the accumulators
+ ExtraVars0 = [],
+ ExtraGoals0 = [],
+ ConstrainedVars0 = [],
+
+ % do the work
+ polymorphism__make_typeclass_info_vars_2(PredClassContext,
+ Subst, TypeSubst,
+ ExtraVars0, ExtraVars1,
+ ExtraGoals0, ExtraGoals1,
+ ConstrainedVars0, ConstrainedVars,
+ Info0, Info),
+
+ % We build up the vars and goals in reverse order
+ list__reverse(ExtraVars1, ExtraVars),
+ list__reverse(ExtraGoals1, ExtraGoals).
+
+% Accumulator version of the above.
+:- pred polymorphism__make_typeclass_info_vars_2(list(class_constraint),
+ substitution, tsubst,
+ list(var), list(var),
+ list(hlds_goal), list(hlds_goal),
+ list(var), list(var),
+ poly_info, poly_info).
+:- mode polymorphism__make_typeclass_info_vars_2(in, in, in, in, out, in, out,
+ in, out, in, out) is det.
+
+polymorphism__make_typeclass_info_vars_2([], _Subst, _TypeSubst,
+ ExtraVars, ExtraVars,
+ ExtraGoals, ExtraGoals,
+ ConstrainedVars, ConstrainedVars,
+ Info, Info).
+polymorphism__make_typeclass_info_vars_2([C|Cs], Subst, TypeSubst,
+ ExtraVars0, ExtraVars,
+ ExtraGoals0, ExtraGoals,
+ ConstrainedVars0, ConstrainedVars,
+ Info0, Info) :-
+ polymorphism__make_typeclass_info_var(C, Subst, TypeSubst,
+ ExtraGoals0, ExtraGoals1,
+ ConstrainedVars0, ConstrainedVars1, Info0, Info1,
+ ExtraVar),
+ polymorphism__make_typeclass_info_vars_2(Cs, Subst, TypeSubst,
+ [ExtraVar|ExtraVars0], ExtraVars,
+ ExtraGoals1, ExtraGoals,
+ ConstrainedVars1, ConstrainedVars,
+ Info1, Info).
+
+:- pred polymorphism__make_typeclass_info_var(class_constraint,
+ substitution, tsubst,
+ list(hlds_goal), list(hlds_goal),
+ list(var), list(var),
+ poly_info, poly_info,
+ var).
+:- mode polymorphism__make_typeclass_info_var(in, in, in, in, out, in, out,
+ in, out, out) is det.
+
+polymorphism__make_typeclass_info_var(Constraint, Subst, TypeSubst,
+ ExtraGoals0, ExtraGoals,
+ ConstrainedVars0, ConstrainedVars,
+ Info0, Info, Var) :-
+ Constraint = constraint(ClassName, NewConstrainedTypes),
+ list__length(NewConstrainedTypes, ClassArity),
+ ClassId = class_id(ClassName, ClassArity),
+ term__vars_list(NewConstrainedTypes, NewConstrainedVars),
+ list__append(NewConstrainedVars, ConstrainedVars0, ConstrainedVars),
+ term__apply_rec_substitution_to_list(NewConstrainedTypes, TypeSubst,
+ ConstrainedTypes),
+ NewC = constraint(ClassName, ConstrainedTypes),
+
+ Info0 = poly_info(VarSet0, VarTypes0, TypeVarSet0, TypeInfoMap0,
+ TypeClassInfoMap0, Proofs, PredName, ModuleInfo),
+
+ (
+ map__search(TypeClassInfoMap0, NewC, Location)
+ ->
+ % We already have a typeclass_info for this constraint
+ ExtraGoals = ExtraGoals0,
+ Var = Location,
+ Info = Info0
+ ;
+ % We don't have the typeclass_info as a parameter to
+ % the pred, so we must be able to create it from
+ % somewhere else
+
+ % Work out how to make it
+ map__lookup(Proofs, NewC, Proof),
+ (
+ % We have to construct the typeclass_info
+ % using an instance declaration
+ Proof = apply_instance(InstanceDefn, InstanceNum),
+
+ % The subst has already been applied to these
+ % constraints in typecheck.m
+ InstanceDefn = hlds_instance_defn(_,
+ InstanceConstraints, _, _, _, _, _),
+
+ % Make the type_infos for the types that are
+ % constrained by this. These are packaged in
+ % the typeclass_info
+ polymorphism__make_type_info_vars(ConstrainedTypes,
+ InstanceExtraTypeInfoVars, TypeInfoGoals,
+ Info0, Info1),
+
+ % Make the typeclass_infos for the constraints
+ % from the context of the instance decl.
+ polymorphism__make_typeclass_info_vars_2(
+ InstanceConstraints,
+ Subst, TypeSubst,
+ [], InstanceExtraTypeClassInfoVars,
+ ExtraGoals0, ExtraGoals1,
+ [], _, Info1, Info2),
+
+ polymorphism__construct_typeclass_info(
+ InstanceExtraTypeInfoVars,
+ InstanceExtraTypeClassInfoVars,
+ ClassId, InstanceNum, Var, NewGoals,
+ Info2, Info),
+
+ % Oh, yuck. The type_info goals have already
+ % been reversed, so lets reverse them back.
+ list__reverse(TypeInfoGoals, RevTypeInfoGoals),
+
+ list__append(ExtraGoals1, RevTypeInfoGoals,
+ ExtraGoals2),
+ list__append(NewGoals, ExtraGoals2, ExtraGoals)
+ ;
+ % We have to extract the typeclass_info from
+ % another one
+ Proof = superclass(SubClassConstraint0),
+
+ % First create a variable to hold the new
+ % typeclass_info
+ unqualify_name(ClassName, ClassNameString),
+ polymorphism__new_typeclass_info_var(VarSet0, VarTypes0,
+ ClassNameString, Var, VarSet1, VarTypes1),
+
+ % Then work out where to extract it from
+ SubClassConstraint0 =
+ constraint(SubClassName, SubClassTypes0),
+ term__apply_substitution_to_list(SubClassTypes0, Subst,
+ SubClassTypes),
+ SubClassConstraint =
+ constraint(SubClassName, SubClassTypes),
+ list__length(SubClassTypes, SubClassArity),
+ SubClassId = class_id(SubClassName, SubClassArity),
+
+ Info1 = poly_info(VarSet1, VarTypes1, TypeVarSet0,
+ TypeInfoMap0, TypeClassInfoMap0, Proofs,
+ PredName, ModuleInfo),
+
+ % Make the typeclass_info for the subclass
+ polymorphism__make_typeclass_info_var(
+ SubClassConstraint,
+ Subst, TypeSubst,
+ ExtraGoals0, ExtraGoals1,
+ [], _,
+ Info1, Info2,
+ SubClassVar),
+
+ % Look up the definition of the subclass
+ module_info_classes(ModuleInfo, ClassTable),
+ map__lookup(ClassTable, SubClassId, SubClassDefn),
+ SubClassDefn = hlds_class_defn(SuperClasses0,
+ SubClassVars, _, _, _),
+
+ % Work out which superclass typeclass_info to
+ % take
+ ToTerm = lambda([TheVar::in, TheTerm::out] is det,
+ (
+ TheTerm = term__variable(TheVar)
+ )),
+ list__map(ToTerm, SubClassVars, SubClassVarTerms),
+ (
+ type_list_subsumes(SubClassVarTerms,
+ SubClassTypes, SubTypeSubst0)
+ ->
+ SubTypeSubst0 = SubTypeSubst
+ ;
+ error("polymorphism__make_typeclass_info_var")
+ ),
+ apply_rec_subst_to_constraints(SubTypeSubst,
+ SuperClasses0, SuperClasses),
+ (
+ list__nth_member_search(SuperClasses,
+ Constraint, SuperClassIndex0)
+ ->
+ SuperClassIndex0 = SuperClassIndex
+ ;
+ % We shouldn't have got this far if
+ % the constraints were not satifsied
+ error("polymorphism.m: constraint not in constraint list")
+ ),
+
+ Info2 = poly_info(VarSet2, VarTypes2, TypeVarSet2,
+ TypeInfoMap2, TypeClassInfoMap2, Proofs2,
+ PredName2, ModuleInfo2),
+
+ polymorphism__make_count_var(SuperClassIndex, VarSet2,
+ VarTypes2, IndexVar, IndexGoal, VarSet,
+ VarTypes),
+
+ Info = poly_info(VarSet, VarTypes, TypeVarSet2,
+ TypeInfoMap2, TypeClassInfoMap2, Proofs2,
+ PredName2, ModuleInfo2),
+
+ % We extract the superclass typeclass_info by
+ % inserting a call to
+ % superclass_from_typeclass_info in
+ % mercury_builtin.
+
+ % Make the goal for the call
+ varset__init(Empty),
+ term__context_init(EmptyContext),
+ ExtractSuperClass =
+ qualified("mercury_builtin",
+ "superclass_from_typeclass_info"),
+ TypeClassInfoTerm = term__functor(
+ term__atom("typeclass_info"), [],
+ EmptyContext),
+ IntTerm = term__functor(
+ term__atom("int"), [],
+ EmptyContext),
+ get_pred_id_and_proc_id(ExtractSuperClass, predicate,
+ Empty,
+ [TypeClassInfoTerm, IntTerm, TypeClassInfoTerm],
+ ModuleInfo, PredId, ProcId),
+ Call = call(PredId, ProcId,
+ [SubClassVar, IndexVar, Var],
+ not_builtin, no,
+ ExtractSuperClass
+ ),
+
+ % Make the goal info for the call
+ set__list_to_set([SubClassVar, IndexVar, Var],
+ NonLocals),
+ instmap_delta_from_assoc_list(
+ [Var - ground(shared, no)],
+ InstmapDelta),
+ goal_info_init(NonLocals, InstmapDelta, det, GoalInfo),
+
+ % Put them together
+ SuperClassGoal = Call - GoalInfo,
+
+ % Add it to the accumulator
+ ExtraGoals = [SuperClassGoal,IndexGoal|ExtraGoals1]
+ )
+ ).
+
+:- pred polymorphism__construct_typeclass_info(list(var), list(var), class_id,
+ int, var, list(hlds_goal), poly_info, poly_info).
+:- mode polymorphism__construct_typeclass_info(in, in, in, in, out, out,
+ in, out) is det.
+
+polymorphism__construct_typeclass_info(ArgTypeInfoVars, ArgTypeClassInfoVars,
+ ClassId, InstanceNum, NewVar, NewGoals, Info0, Info) :-
+
+ Info0 = poly_info(_, _, _, _, _, _, _, ModuleInfo),
+
+ module_info_instances(ModuleInfo, InstanceTable),
+ map__lookup(InstanceTable, ClassId, InstanceList),
+ list__index1_det(InstanceList, InstanceNum, InstanceDefn),
+ InstanceDefn = hlds_instance_defn(_, _, InstanceTypes, _, _, _,
+ SuperClassProofs),
+
+ module_info_classes(ModuleInfo, ClassTable),
+ map__lookup(ClassTable, ClassId, ClassDefn),
+
+ polymorphism__get_arg_superclass_vars(ClassDefn, InstanceTypes,
+ SuperClassProofs, ArgSuperClassVars, SuperClassGoals,
+ Info0, Info1),
+
+ Info1 = poly_info(VarSet0, VarTypes0, TVarSet, TVarMap, TCVarMap,
+ Proofs, PredName, _),
+
+ % lay out the argument variables as expected in the
+ % typeclass_info
+ list__append(ArgTypeClassInfoVars, ArgSuperClassVars, ArgVars0),
+ list__append(ArgVars0, ArgTypeInfoVars, ArgVars),
+
+ ClassId = class_id(ClassName, _Arity),
+
+ unqualify_name(ClassName, ClassNameString),
+ polymorphism__new_typeclass_info_var(VarSet0, VarTypes0,
+ ClassNameString, BaseVar, VarSet1, VarTypes1),
+
+ base_typeclass_info__make_instance_string(InstanceTypes,
+ InstanceString),
+
+ % XXX I don't think we actually need to carry this string
+ % around.
+ ModuleName = "some bogus string",
+ ConsId = base_typeclass_info_const(ModuleName, ClassId, InstanceString),
+ BaseTypeClassInfoTerm = functor(ConsId, []),
+
+ % create the construction unification to initialize the variable
+ BaseUnification = construct(BaseVar, ConsId, [], []),
+ BaseUnifyMode = (free -> ground(shared, no)) -
+ (ground(shared, no) -> ground(shared, no)),
+ BaseUnifyContext = unify_context(explicit, []),
+ % XXX the UnifyContext is wrong
+ BaseUnify = unify(BaseVar, BaseTypeClassInfoTerm, BaseUnifyMode,
+ BaseUnification, BaseUnifyContext),
+
+ % create a goal_info for the unification
+ set__list_to_set([BaseVar], NonLocals),
+ instmap_delta_from_assoc_list([BaseVar - ground(shared, no)],
+ InstmapDelta),
+ goal_info_init(NonLocals, InstmapDelta, det, BaseGoalInfo),
+
+ BaseGoal = BaseUnify - BaseGoalInfo,
+
+ % build a unification to add the argvars to the
+ % base_typeclass_info
+ NewConsId = cons(qualified("mercury_builtin", "typeclass_info"), 1),
+ NewArgVars = [BaseVar|ArgVars],
+ TypeClassInfoTerm = functor(NewConsId, NewArgVars),
+
+ % introduce a new variable
+ polymorphism__new_typeclass_info_var(VarSet1, VarTypes1,
+ ClassNameString, NewVar, VarSet, VarTypes),
+
+ % create the construction unification to initialize the
+ % variable
+ UniMode = (free - ground(shared, no) ->
+ ground(shared, no) - ground(shared, no)),
+ list__length(NewArgVars, NumArgVars),
+ list__duplicate(NumArgVars, UniMode, UniModes),
+ Unification = construct(NewVar, NewConsId, NewArgVars,
+ UniModes),
+ UnifyMode = (free -> ground(shared, no)) -
+ (ground(shared, no) -> ground(shared, no)),
+ UnifyContext = unify_context(explicit, []),
+ % XXX the UnifyContext is wrong
+ Unify = unify(NewVar, TypeClassInfoTerm, UnifyMode,
+ Unification, UnifyContext),
+
+ % create a goal_info for the unification
+ goal_info_init(GoalInfo0),
+ set__list_to_set([NewVar | NewArgVars], TheNonLocals),
+ goal_info_set_nonlocals(GoalInfo0, TheNonLocals, GoalInfo1),
+ list__duplicate(NumArgVars, ground(shared, no), ArgInsts),
+ % note that we could perhaps be more accurate than
+ % `ground(shared)', but it shouldn't make any
+ % difference.
+ InstConsId = cons( qualified("mercury_builtin", "typeclass_info"),
+ NumArgVars),
+ instmap_delta_from_assoc_list(
+ [NewVar -
+ bound(unique, [functor(InstConsId, ArgInsts)])],
+ InstMapDelta),
+ goal_info_set_instmap_delta(GoalInfo1, InstMapDelta, GoalInfo2),
+ goal_info_set_determinism(GoalInfo2, det, GoalInfo),
+
+ TypeClassInfoGoal = Unify - GoalInfo,
+ NewGoals0 = [TypeClassInfoGoal, BaseGoal],
+ list__append(SuperClassGoals, NewGoals0, NewGoals),
+ Info = poly_info(VarSet, VarTypes, TVarSet, TVarMap,
+ TCVarMap, Proofs, PredName, ModuleInfo).
+
+%---------------------------------------------------------------------------%
+
+:- pred polymorphism__get_arg_superclass_vars(hlds_class_defn, list(type),
+ map(class_constraint, constraint_proof), list(var), list(hlds_goal),
+ poly_info, poly_info).
+:- mode polymorphism__get_arg_superclass_vars(in, in, in, out, out,
+ in, out) is det.
+
+polymorphism__get_arg_superclass_vars(ClassDefn, InstanceTypes,
+ SuperClassProofs, NewVars, NewGoals, Info0, Info) :-
+
+ Info0 = poly_info(VarSet0, VarTypes0, TVarSet, TVarMap0, TCVarMap0,
+ Proofs, PredName, ModuleInfo),
+
+ ClassDefn = hlds_class_defn(SuperClasses, ClassVars, _, ClassVarSet, _),
+
+ map__from_corresponding_lists(ClassVars, InstanceTypes, TypeSubst),
+ varset__merge_subst(VarSet0, ClassVarSet, VarSet1, Subst),
+
+ Info1 = poly_info(VarSet1, VarTypes0, TVarSet, TVarMap0, TCVarMap0,
+ SuperClassProofs, PredName, ModuleInfo),
+
+ polymorphism__make_superclasses_from_proofs(SuperClasses, Subst,
+ TypeSubst, [], NewGoals, Info1, Info2, [], NewVars),
+
+ Info2 = poly_info(VarSet, VarTypes, _, TVarMap, TCVarMap, _, _, _),
+
+ Info = poly_info(VarSet, VarTypes, TVarSet, TVarMap, TCVarMap,
+ Proofs, PredName, ModuleInfo) .
+
+
+:- pred polymorphism__make_superclasses_from_proofs(list(class_constraint),
+ substitution, tsubst, list(hlds_goal), list(hlds_goal),
+ poly_info, poly_info, list(var), list(var)).
+:- mode polymorphism__make_superclasses_from_proofs(in, in, in, in, out,
+ in, out, in, out) is det.
+
+polymorphism__make_superclasses_from_proofs([], _, _,
+ Goals, Goals, Info, Info, Vars, Vars).
+polymorphism__make_superclasses_from_proofs([C|Cs], Subst, TypeSubst,
+ Goals0, Goals, Info0, Info, Vars0, [Var|Vars]) :-
+ polymorphism__make_superclasses_from_proofs(Cs, Subst, TypeSubst,
+ Goals0, Goals1, Info0, Info1, Vars0, Vars),
+ polymorphism__make_typeclass_info_var(C, Subst, TypeSubst,
+ Goals1, Goals, [], _, Info1, Info, Var).
%---------------------------------------------------------------------------%
% Given a list of types, create a list of variables to hold the type_info
% for those types, and create a list of goals to initialize those type_info
% variables to the appropriate type_info structures for the types.
-% Update the varset and vartypes accordingly.
-
-:- pred polymorphism__make_vars(list(type), module_info, map(tvar, var),
- varset, map(var, type), list(var), map(tvar, var), list(hlds_goal),
- varset, map(var, type)).
-:- mode polymorphism__make_vars(in, in, in, in, in, out, out, out, out,
- out) is det.
-polymorphism__make_vars([], _, TypeInfoMap, VarSet, VarTypes, [], TypeInfoMap,
- [], VarSet, VarTypes).
-polymorphism__make_vars([Type | Types], ModuleInfo, TypeInfoMap0,
- VarSet0, VarTypes0, ExtraVars, TypeInfoMap, ExtraGoals,
- VarSet, VarTypes) :-
- polymorphism__make_var(Type, ModuleInfo, TypeInfoMap0,
- VarSet0, VarTypes0, Var, TypeInfoMap1, ExtraGoals1, VarSet1,
- VarTypes1),
- polymorphism__make_vars(Types, ModuleInfo, TypeInfoMap1,
- VarSet1, VarTypes1, ExtraVars2, TypeInfoMap, ExtraGoals2,
- VarSet, VarTypes),
+:- pred polymorphism__make_type_info_vars(list(type),
+ list(var), list(hlds_goal), poly_info, poly_info).
+:- mode polymorphism__make_type_info_vars(in, out, out, in, out) is det.
+
+polymorphism__make_type_info_vars([], [], [], Info, Info).
+polymorphism__make_type_info_vars([Type | Types],
+ ExtraVars, ExtraGoals, Info0, Info) :-
+ polymorphism__make_type_info_var(Type,
+ Var, ExtraGoals1, Info0, Info1),
+ polymorphism__make_type_info_vars(Types,
+ ExtraVars2, ExtraGoals2, Info1, Info),
ExtraVars = [Var | ExtraVars2],
list__append(ExtraGoals1, ExtraGoals2, ExtraGoals).
-:- pred polymorphism__make_var(type, module_info, map(tvar, var),
- varset, map(var, type), var, map(tvar, var), list(hlds_goal),
- varset, map(var, type)).
-:- mode polymorphism__make_var(in, in, in, in, in, out, out, out, out, out)
- is det.
+:- pred polymorphism__make_type_info_var(type, var, list(hlds_goal),
+ poly_info, poly_info).
+:- mode polymorphism__make_type_info_var(in, out, out, in, out) is det.
-polymorphism__make_var(Type, ModuleInfo, TypeInfoMap0, VarSet0, VarTypes0,
- Var, TypeInfoMap, ExtraGoals, VarSet, VarTypes) :-
+polymorphism__make_type_info_var(Type, Var, ExtraGoals, Info0, Info) :-
(
type_is_higher_order(Type, PredOrFunc, TypeArgs)
->
@@ -757,8 +1454,7 @@
hlds_out__pred_or_func_to_str(PredOrFunc, PredOrFuncStr),
TypeId = unqualified(PredOrFuncStr) - 0,
polymorphism__construct_type_info(Type, TypeId, TypeArgs,
- yes, ModuleInfo, TypeInfoMap0, VarSet0, VarTypes0,
- Var, TypeInfoMap, ExtraGoals, VarSet, VarTypes)
+ yes, Var, ExtraGoals, Info0, Info)
;
type_to_type_id(Type, TypeId, TypeArgs)
->
@@ -768,11 +1464,11 @@
% at the top of the module.
polymorphism__construct_type_info(Type, TypeId, TypeArgs,
- no, ModuleInfo, TypeInfoMap0, VarSet0, VarTypes0,
- Var, TypeInfoMap, ExtraGoals, VarSet, VarTypes)
+ no, Var, ExtraGoals, Info0, Info)
;
Type = term__variable(TypeVar1),
- map__search(TypeInfoMap0, TypeVar1, TypeInfoVar)
+ Info0 = poly_info(_, _, _, TypeInfoMap0, _, _, _, _),
+ map__search(TypeInfoMap0, TypeVar1, TypeInfoLocn)
->
% This occurs for code where a predicate calls a polymorphic
% predicate with a bound but unknown value of the type variable.
@@ -790,11 +1486,20 @@
%
% p(TypeInfo, X) :- q(TypeInfo, X).
- Var = TypeInfoVar,
- ExtraGoals = [],
- VarSet = VarSet0,
- VarTypes = VarTypes0,
- TypeInfoMap = TypeInfoMap0
+ (
+ % If the typeinfo is available in a variable,
+ % just use it
+ TypeInfoLocn = type_info(TypeInfoVar),
+ Var = TypeInfoVar,
+ ExtraGoals = [],
+ Info = Info0
+ ;
+ % If the typeinfo is in a typeclass_info, first
+ % extract it, then use it
+ TypeInfoLocn = typeclass_info(TypeClassInfoVar, Index),
+ extract_type_info(Type, TypeVar1, TypeClassInfoVar,
+ Index, ExtraGoals, Var, Info0, Info)
+ )
;
Type = term__variable(TypeVar1)
->
@@ -829,27 +1534,28 @@
% variable to zero
TypeId = unqualified("void") - 0,
polymorphism__construct_type_info(Type, TypeId, [],
- no, ModuleInfo, TypeInfoMap0, VarSet0, VarTypes0,
- Var, TypeInfoMap1, ExtraGoals, VarSet, VarTypes),
- map__det_insert(TypeInfoMap1, TypeVar1, Var, TypeInfoMap)
+ no, Var, ExtraGoals, Info0, Info1),
+ Info1 = poly_info(A, B, C, TypeInfoMap1, E, F, G, H),
+ map__det_insert(TypeInfoMap1, TypeVar1, type_info(Var),
+ TypeInfoMap),
+ Info = poly_info(A, B, C, TypeInfoMap, E, F, G, H)
;
error("polymorphism__make_var: unknown type")
).
:- pred polymorphism__construct_type_info(type, type_id, list(type),
- bool, module_info, map(tvar, var), varset, map(var, type),
- var, map(tvar, var), list(hlds_goal), varset, map(var, type)).
-:- mode polymorphism__construct_type_info(in, in, in, in, in, in, in, in,
- out, out, out, out, out) is det.
+ bool, var, list(hlds_goal), poly_info, poly_info).
+:- mode polymorphism__construct_type_info(in, in, in, in, out, out,
+ in, out) is det.
polymorphism__construct_type_info(Type, TypeId, TypeArgs, IsHigherOrder,
- ModuleInfo, TypeInfoMap0, VarSet0, VarTypes0,
- Var, TypeInfoMap, ExtraGoals, VarSet, VarTypes) :-
+ Var, ExtraGoals, Info0, Info) :-
% Create the typeinfo vars for the arguments
- polymorphism__make_vars(TypeArgs, ModuleInfo, TypeInfoMap0,
- VarSet0, VarTypes0, ArgTypeInfoVars, TypeInfoMap,
- ArgTypeInfoGoals, VarSet1, VarTypes1),
+ polymorphism__make_type_info_vars(TypeArgs, ArgTypeInfoVars,
+ ArgTypeInfoGoals, Info0, Info1),
+
+ Info1 = poly_info(VarSet1, VarTypes1, C, D, E, F, G, ModuleInfo),
module_info_globals(ModuleInfo, Globals),
globals__get_type_info_method(Globals, TypeInfoMethod),
@@ -863,7 +1569,9 @@
ArgTypeInfoGoals, Type, IsHigherOrder,
BaseVar, VarSet2, VarTypes2, [BaseGoal],
Var, VarSet, VarTypes, ExtraGoals)
- ).
+ ),
+
+ Info = poly_info(VarSet, VarTypes, C, D, E, F, G, ModuleInfo).
% Create a unification for the two-cell type_info
% variable for this type if the type arity is not zero:
@@ -1201,6 +1909,8 @@
BaseTypeInfoGoal = Unify - GoalInfo.
+%---------------------------------------------------------------------------%
+
:- pred polymorphism__make_head_vars(list(tvar), tvarset,
varset, map(var, type),
list(var), varset, map(var, type)).
@@ -1240,18 +1950,346 @@
[Type], UnifyPredType),
map__set(VarTypes0, Var, UnifyPredType, VarTypes).
+%---------------------------------------------------------------------------%
+
+:- pred extract_type_info(type, tvar, var, int, list(hlds_goal),
+ var, poly_info, poly_info).
+:- mode extract_type_info(in, in, in, in, out, out, in, out) is det.
+
+extract_type_info(Type, TypeVar, TypeClassInfoVar, Index, Goals,
+ TypeInfoVar, PolyInfo0, PolyInfo) :-
+ PolyInfo0 = poly_info(VarSet0, VarTypes0, C, TypeInfoLocns0,
+ E, F, G, ModuleInfo),
+ extract_type_info_2(Type, TypeVar, TypeClassInfoVar, Index, ModuleInfo,
+ Goals, TypeInfoVar, VarSet0, VarTypes0, TypeInfoLocns0,
+ VarSet, VarTypes, TypeInfoLocns),
+ PolyInfo = poly_info(VarSet, VarTypes, C, TypeInfoLocns, E, F, G,
+ ModuleInfo).
+
+:- pred extract_type_info_2(type, tvar, var, int, module_info, list(hlds_goal),
+ var, varset, map(var, type), map(tvar, type_info_locn),
+ varset, map(var, type), map(tvar, type_info_locn)).
+:- mode extract_type_info_2(in, in, in, in, in, out, out, in, in, in, out, out,
+ out) is det.
+
+extract_type_info_2(Type, _TypeVar, TypeClassInfoVar, Index, ModuleInfo, Goals,
+ TypeInfoVar, VarSet0, VarTypes0, TypeInfoLocns0,
+ VarSet, VarTypes, TypeInfoLocns) :-
+
+ % We need a tvarset to pass to get_pred_id_and_proc_id
+ varset__init(TVarSet0),
+ varset__new_var(TVarSet0, TVar, TVarSet),
+
+ term__context_init(EmptyContext),
+ ExtractTypeInfo = qualified("mercury_builtin",
+ "type_info_from_typeclass_info"),
+ TypeClassInfoTerm = term__functor(term__atom("typeclass_info"), [],
+ EmptyContext),
+ IntTerm = term__functor(term__atom("int"), [], EmptyContext),
+ TypeInfoTerm = term__functor(term__atom("type_info"),
+ [term__variable(TVar)], EmptyContext),
+
+ get_pred_id_and_proc_id(ExtractTypeInfo, predicate, TVarSet,
+ [TypeClassInfoTerm, IntTerm, TypeInfoTerm],
+ ModuleInfo, PredId, ProcId),
+ polymorphism__make_count_var(Index, VarSet0, VarTypes0, IndexVar,
+ IndexGoal, VarSet1, VarTypes1),
+
+ polymorphism__new_type_info_var(Type, "type_info", VarSet1, VarTypes1,
+ TypeInfoVar, VarSet2, VarTypes2),
+
+ % We have to put an extra type_info at the front of the call to
+ % type_info_from_typeclass_info, and pass it a bogus value
+ % because the pred has a type parameter... even though we are
+ % actually _extracting_ the type_info. Existential typing of
+ % type_info_from_typeclass_info would fix this.
+ polymorphism__new_type_info_var(Type, "type_info", VarSet2, VarTypes2,
+ DummyTypeInfoVar, VarSet, VarTypes),
+
+ % Now we put a dummy value in the dummy type-info variable.
+ polymorphism__init_with_int_constant(DummyTypeInfoVar, 0,
+ DummyTypeInfoGoal),
+
+ % Make the goal info for the call
+ set__list_to_set([DummyTypeInfoVar, TypeClassInfoVar, IndexVar,
+ TypeInfoVar], NonLocals),
+ instmap_delta_from_assoc_list([TypeInfoVar - ground(shared, no)],
+ InstmapDelta),
+ goal_info_init(NonLocals, InstmapDelta, det, GoalInfo),
+
+ Call = call(PredId, ProcId,
+ [DummyTypeInfoVar, TypeClassInfoVar, IndexVar, TypeInfoVar],
+ not_builtin, no, ExtractTypeInfo) - GoalInfo,
+
+ Goals = [IndexGoal, DummyTypeInfoGoal, Call],
+
+ /* We should do this, except that makes us incorrectly compute the
+ * non-locals for the goal, since it appears to fixup_quantification
+ * that the type-info is non-local, but the typeclass-info is not.
+ % Update the location of the type_info so that we don't go to
+ % the bother of re-extracting it.
+ map__det_update(TypeInfoLocns0, TypeVar, type_info(TypeInfoVar),
+ TypeInfoLocns).
+ */
+ TypeInfoLocns = TypeInfoLocns0.
+
+%---------------------------------------------------------------------------%
+
+ % Add a head var for each class constraint, and make an entry in the
+ % typeinfo locations map for each constrained type var.
+:- pred polymorphism__make_typeclass_info_head_vars(list(class_constraint),
+ module_info, varset, map(var, type), list(var),
+ map(var, type_info_locn), list(var), varset, map(var, type)).
+:- mode polymorphism__make_typeclass_info_head_vars(in, in, in, in,
+ out, out, out, out, out) is det.
+
+polymorphism__make_typeclass_info_head_vars(ClassContext, ModuleInfo, VarSet0,
+ VarTypes0, ExtraHeadVars, TypeClassInfoMap, ConstrainedTVars,
+ VarSet, VarTypes) :-
+
+ % initialise the new accumulators
+ ExtraHeadVars0 = [],
+ map__init(TypeClassInfoMap0),
+
+ % do the work
+ polymorphism__make_typeclass_info_head_vars_2(ClassContext, ModuleInfo,
+ VarSet0, VarSet,
+ VarTypes0, VarTypes,
+ ExtraHeadVars0, ExtraHeadVars1,
+ TypeClassInfoMap0, TypeClassInfoMap),
+
+ % A type var has a location in a typeclass info iff it is
+ % constrained
+ map__keys(TypeClassInfoMap, ConstrainedTVars),
+
+ % The ExtraHeadVars are built up in reverse
+ list__reverse(ExtraHeadVars1, ExtraHeadVars).
+
+:- pred polymorphism__make_typeclass_info_head_vars_2(list(class_constraint),
+ module_info, varset, varset,
+ map(var, type), map(var, type),
+ list(var), list(var),
+ map(var, type_info_locn), map(var, type_info_locn)).
+:- mode polymorphism__make_typeclass_info_head_vars_2(in, in, in, out, in, out,
+ in, out, in, out) is det.
+
+polymorphism__make_typeclass_info_head_vars_2([], _,
+ VarSet, VarSet,
+ VarTypes, VarTypes,
+ ExtraHeadVars, ExtraHeadVars,
+ TypeInfoLocations, TypeInfoLocations).
+polymorphism__make_typeclass_info_head_vars_2([C|Cs], ModuleInfo,
+ VarSet0, VarSet,
+ VarTypes0, VarTypes,
+ ExtraHeadVars0, ExtraHeadVars,
+ TypeClassInfoMap0, TypeClassInfoMap) :-
+
+ C = constraint(ClassName0, ClassTypes),
+
+ % Work out how many superclass the class has
+ list__length(ClassTypes, ClassArity),
+ ClassId = class_id(ClassName0, ClassArity),
+ module_info_classes(ModuleInfo, ClassTable),
+ map__lookup(ClassTable, ClassId, ClassDefn),
+ ClassDefn = hlds_class_defn(SuperClasses, _, _, _, _),
+ list__length(SuperClasses, NumSuperClasses),
+
+ unqualify_name(ClassName0, ClassName),
+
+ % Make a new variable to contain the dictionary for this
+ % typeclass constraint
+ polymorphism__new_typeclass_info_var(VarSet0, VarTypes0, ClassName,
+ Var, VarSet1, VarTypes1),
+ ExtraHeadVars1 = [Var | ExtraHeadVars0],
+
+ % Find all the type variables in the constraint, and remember
+ % what index they appear in in the typeclass info.
+
+ % The first type_info will be just after the superclass infos
+ First is NumSuperClasses + 1,
+ term__vars_list(ClassTypes, ClassTypeVars0),
+ MakeIndex = lambda([Elem0::in, Elem::out,
+ Index0::in, Index::out] is det,
+ (
+ Elem = Elem0 - Index0,
+ Index is Index0 + 1
+ )),
+ list__map_foldl(MakeIndex, ClassTypeVars0, ClassTypeVars, First, _),
+
+
+ % Work out which ones haven't been seen before
+ IsNew = lambda([TypeVar0::in] is semidet,
+ (
+ TypeVar0 = TypeVar - _Index,
+ \+ map__search(TypeClassInfoMap0, TypeVar, _)
+ )),
+ list__filter(IsNew, ClassTypeVars, NewClassTypeVars),
+
+ % Make an entry in the TypeInfo locations map for each new
+ % type variable. The type variable can be found at the
+ % previously calculated offset with the new typeclass_info
+ MakeEntry = lambda([IndexedTypeVar::in,
+ LocnMap0::in, LocnMap::out] is det,
+ (
+ IndexedTypeVar = TheTypeVar - Location,
+ map__det_insert(LocnMap0, TheTypeVar,
+ typeclass_info(Var, Location), LocnMap)
+ )),
+ list__foldl(MakeEntry, NewClassTypeVars,
+ TypeClassInfoMap0, TypeClassInfoMap1),
+
+ % Handle the rest of the constraints
+ polymorphism__make_typeclass_info_head_vars_2(Cs, ModuleInfo,
+ VarSet1, VarSet,
+ VarTypes1, VarTypes,
+ ExtraHeadVars1, ExtraHeadVars,
+ TypeClassInfoMap1, TypeClassInfoMap).
+
+:- pred polymorphism__new_typeclass_info_var(varset, map(var, type),
+ string, var,
+ varset, map(var, type)).
+:- mode polymorphism__new_typeclass_info_var(in, in, in, out, out, out) is det.
+
+polymorphism__new_typeclass_info_var(VarSet0, VarTypes0, ClassName,
+ Var, VarSet, VarTypes) :-
+ % introduce new variable
+ varset__new_var(VarSet0, Var, VarSet1),
+ string__append("TypeClassInfo_for_", ClassName, Name),
+ varset__name_var(VarSet1, Var, Name, VarSet),
+
+ construct_type(qualified("mercury_builtin", "typeclass_info") - 0,
+ [], DictionaryType),
+ map__set(VarTypes0, Var, DictionaryType, VarTypes).
+
+%---------------------------------------------------------------------------%
+
+ % Expand the bodies of all class methods for typeclasses which
+ % were defined in this module. The expansion involves inserting a
+ % class_method_call with the appropriate arguments, which is
+ % responsible for extracting the appropriate part of the dictionary.
+:- pred polymorphism__expand_class_method_bodies(module_info, module_info).
+:- mode polymorphism__expand_class_method_bodies(in, out) is det.
+
+polymorphism__expand_class_method_bodies(ModuleInfo0, ModuleInfo) :-
+ module_info_classes(ModuleInfo0, Classes),
+ module_info_name(ModuleInfo0, ModuleName),
+ map__keys(Classes, ClassIds0),
+
+ % Don't expand classes from other modules
+ FromThisModule = lambda([ClassId::in] is semidet,
+ (
+ ClassId = class_id(qualified(ModuleName, _), _)
+ )),
+ list__filter(FromThisModule, ClassIds0, ClassIds),
+
+ map__apply_to_list(ClassIds, Classes, ClassDefns),
+ list__foldl(expand_bodies, ClassDefns, ModuleInfo0, ModuleInfo).
+
+:- pred expand_bodies(hlds_class_defn, module_info, module_info).
+:- mode expand_bodies(in, in, out) is det.
+
+expand_bodies(hlds_class_defn(_, _, Interface, _, _),
+ ModuleInfo0, ModuleInfo) :-
+ list__foldl2(expand_one_body, Interface, 1, _, ModuleInfo0, ModuleInfo).
+
+:- pred expand_one_body(hlds_class_proc, int, int, module_info, module_info).
+:- mode expand_one_body(in, in, out, in, out) is det.
+
+expand_one_body(hlds_class_proc(PredId, ProcId), ProcNum0, ProcNum,
+ ModuleInfo0, ModuleInfo) :-
+ module_info_preds(ModuleInfo0, PredTable0),
+ map__lookup(PredTable0, PredId, PredInfo0),
+ pred_info_procedures(PredInfo0, ProcTable0),
+ map__lookup(ProcTable0, ProcId, ProcInfo0),
+
+ % Find which of the constraints on the pred is the one
+ % introduced because it is a class method.
+ pred_info_get_class_context(PredInfo0, ClassContext),
+ (
+ ClassContext = [Head|_]
+ ->
+ InstanceConstraint = Head
+ ;
+ error("expand_one_body: class method is not constrained")
+ ),
+
+ proc_info_typeclass_info_varmap(ProcInfo0, VarMap),
+ map__lookup(VarMap, InstanceConstraint, TypeClassInfoVar),
+
+ proc_info_headvars(ProcInfo0, HeadVars0),
+ proc_info_vartypes(ProcInfo0, Types0),
+ proc_info_argmodes(ProcInfo0, Modes0),
+ proc_info_declared_determinism(ProcInfo0, Detism0),
+ (
+ Detism0 = yes(Detism1)
+ ->
+ Detism = Detism1
+ ;
+ error("missing determinism decl. How did we get this far?")
+ ),
+
+ % Work out which argument corresponds to the constraint which
+ % is introduced because this is a class method, then delete it
+ % from the list of args to the class_method_call. That variable
+ % becomes the "dictionary" variable for the class_method_call.
+ % (cf. the closure for a higher order call).
+ (
+ list__nth_member_search(HeadVars0, TypeClassInfoVar, N),
+ delete_nth(HeadVars0, N, HeadVars1),
+ delete_nth(Modes0, N, Modes1)
+ ->
+ HeadVars = HeadVars1,
+ map__apply_to_list(HeadVars1, Types0, Types),
+ Modes = Modes1
+ ;
+ error("expand_one_body: typeclass_info var not found")
+ ),
+
+ BodyGoalExpr = class_method_call(TypeClassInfoVar, ProcNum0,
+ HeadVars, Types, Modes, Detism),
+
+ % Make the goal info for the call.
+ set__list_to_set(HeadVars0, NonLocals),
+ instmap_delta_from_mode_list(HeadVars0, Modes0, ModuleInfo0,
+ InstmapDelta),
+ goal_info_init(NonLocals, InstmapDelta, Detism, GoalInfo),
+ BodyGoal = BodyGoalExpr - GoalInfo,
+
+ proc_info_set_goal(ProcInfo0, BodyGoal, ProcInfo),
+ map__det_update(ProcTable0, ProcId, ProcInfo, ProcTable),
+ pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
+ map__det_update(PredTable0, PredId, PredInfo, PredTable),
+ module_info_set_preds(ModuleInfo0, PredTable, ModuleInfo),
+
+ ProcNum is ProcNum0 + 1.
+
+:- pred delete_nth(list(T)::in, int::in, list(T)::out) is semidet.
+
+delete_nth([X|Xs], N0, Result) :-
+ (
+ N0 > 1
+ ->
+ N is N0 - 1,
+ delete_nth(Xs, N, TheRest),
+ Result = [X|TheRest]
+ ;
+ Result = Xs
+ ).
+
+%---------------------------------------------------------------------------%
+
:- pred polymorphism__get_module_info(module_info, poly_info, poly_info).
:- mode polymorphism__get_module_info(out, in, out) is det.
polymorphism__get_module_info(ModuleInfo, PolyInfo, PolyInfo) :-
- PolyInfo = poly_info(_, _, _, _, _, ModuleInfo).
+ PolyInfo = poly_info(_, _, _, _, _, _, _, ModuleInfo).
:- pred polymorphism__set_module_info(module_info, poly_info, poly_info).
:- mode polymorphism__set_module_info(in, in, out) is det.
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