File: base_typeclass_info.m

package info (click to toggle)
mercury 0.10.1-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 21,984 kB
  • ctags: 11,923
  • sloc: objc: 187,634; ansic: 66,107; sh: 7,570; lisp: 1,568; cpp: 1,337; makefile: 614; perl: 511; awk: 274; asm: 252; exp: 32; xml: 12; fortran: 3; csh: 1
file content (183 lines) | stat: -rw-r--r-- 7,623 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
%---------------------------------------------------------------------------%
% Copyright (C) 1996-2000 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% This module generates the RTTI data for the global variables (or constants)
% that hold the base_typeclass_info structures of the typeclass instances
% defined by the current module.
%
% See notes/type_class_transformation.html for a description of the various 
% ways to represent type information, including a description of the
% base_typeclass_info structures.
%
% Author: dgj.
%
%---------------------------------------------------------------------------%

:- module base_typeclass_info.

:- interface.

:- import_module hlds_module, list, rtti, prog_data.

:- pred base_typeclass_info__generate_rtti(module_info, list(rtti_data)).
:- mode base_typeclass_info__generate_rtti(in, out) is det.

	% Given a list of types, mangle the names so into a string which
	% identifies them. The types must all have their top level functor
	% bound, with any arguments free variables.
:- pred base_typeclass_info__make_instance_string(list(type), string).
:- mode base_typeclass_info__make_instance_string(in, out) is det.

:- implementation.

:- import_module prog_io, prog_out.
:- import_module hlds_data, hlds_pred, hlds_out.
:- import_module code_util, globals, options, term.
:- import_module bool, string, map, std_util, require, assoc_list.
:- import_module type_util, int.

%---------------------------------------------------------------------------%

base_typeclass_info__generate_rtti(ModuleInfo, RttiDataList) :-
	module_info_name(ModuleInfo, ModuleName),
	module_info_instances(ModuleInfo, InstanceTable),
	map__to_assoc_list(InstanceTable, AllInstances),
	base_typeclass_info__gen_infos_for_classes(AllInstances, ModuleName,
		ModuleInfo, RttiDataList).

:- pred base_typeclass_info__gen_infos_for_classes(assoc_list(class_id,
	list(hlds_instance_defn)), module_name, module_info,
	list(rtti_data)).
:- mode base_typeclass_info__gen_infos_for_classes(in, in, in, out) is det.

base_typeclass_info__gen_infos_for_classes([], _ModuleName, _ModuleInfo, []).
base_typeclass_info__gen_infos_for_classes([C|Cs], ModuleName, ModuleInfo, 
		RttiDataList) :-
	base_typeclass_info__gen_infos_for_instance_list(C, ModuleName,
		ModuleInfo, RttiDataList1),
	base_typeclass_info__gen_infos_for_classes(Cs, ModuleName,
		ModuleInfo, RttiDataList2),
	% XXX make it use an accumulator
	list__append(RttiDataList1, RttiDataList2, RttiDataList).

	% XXX make it use an accumulator
:- pred base_typeclass_info__gen_infos_for_instance_list(
	pair(class_id, list(hlds_instance_defn)), module_name, module_info,
	list(rtti_data)).
:- mode base_typeclass_info__gen_infos_for_instance_list(in, in, in, out) 
	is det.

base_typeclass_info__gen_infos_for_instance_list(_ - [], _, _, []).
base_typeclass_info__gen_infos_for_instance_list(ClassId - [InstanceDefn|Is], 
		ModuleName, ModuleInfo, RttiDataList) :-
	base_typeclass_info__gen_infos_for_instance_list(ClassId - Is,
		ModuleName, ModuleInfo, RttiDataList1),
	InstanceDefn = hlds_instance_defn(InstanceModule, ImportStatus,
			_TermContext, InstanceConstraints, InstanceTypes, Body,
			PredProcIds, _Varset, _SuperClassProofs),
	(
		Body = concrete(_),
			% Only make the base_typeclass_info if the instance
			% declaration originally came from _this_ module.
		status_defined_in_this_module(ImportStatus, yes)
	->
		base_typeclass_info__make_instance_string(InstanceTypes, 
			InstanceString),
		base_typeclass_info__gen_body(PredProcIds,
			InstanceTypes, InstanceConstraints, ModuleInfo, 
			ClassId, BaseTypeClassInfo),
		RttiData = base_typeclass_info(InstanceModule,
			ClassId, InstanceString, BaseTypeClassInfo),
		RttiDataList = [RttiData | RttiDataList1]
	;
			% The instance decl is from another module,
			% or is abstract, so we don't bother including it.
		RttiDataList = RttiDataList1
	).

%----------------------------------------------------------------------------%

:- pred base_typeclass_info__gen_body(maybe(list(hlds_class_proc)),
		list(type), list(class_constraint), module_info, class_id,
		base_typeclass_info).
:- mode base_typeclass_info__gen_body(in, in, in, in, in, out) is det.

base_typeclass_info__gen_body(no, _, _, _, _, _) :-
	error("pred_proc_ids should have been filled in by check_typeclass.m").
base_typeclass_info__gen_body(yes(PredProcIds0), Types, Constraints,
		ModuleInfo, ClassId, BaseTypeClassInfo) :-
	term__vars_list(Types, TypeVars),
	get_unconstrained_tvars(TypeVars, Constraints, Unconstrained),
	list__length(Constraints, NumConstraints),
	list__length(Unconstrained, NumUnconstrained),
	NumExtra = NumConstraints + NumUnconstrained,
	ExtractPredProcId = lambda([HldsPredProc::in, PredProc::out] is det,
		(
			HldsPredProc = hlds_class_proc(PredId, ProcId),
			PredProc = proc(PredId, ProcId)
		)),
	list__map(ExtractPredProcId, PredProcIds0, PredProcIds),
	base_typeclass_info__construct_proc_labels(PredProcIds, ModuleInfo,
		ProcLabels),
	base_typeclass_info__gen_superclass_count(ClassId, ModuleInfo,
			SuperClassCount, ClassArity),
	list__length(ProcLabels, NumMethods),
	BaseTypeClassInfo = base_typeclass_info(NumExtra, NumConstraints,
		SuperClassCount, ClassArity, NumMethods, ProcLabels).

:- pred base_typeclass_info__construct_proc_labels(list(pred_proc_id),
	module_info, list(rtti_proc_label)).
:- mode base_typeclass_info__construct_proc_labels(in, in, out) is det.

base_typeclass_info__construct_proc_labels([], _, []).
base_typeclass_info__construct_proc_labels([proc(PredId, ProcId) | Procs],
		ModuleInfo, [ProcLabel | ProcLabels]) :-
	ProcLabel = rtti__make_proc_label(ModuleInfo, PredId, ProcId),
	base_typeclass_info__construct_proc_labels(Procs, ModuleInfo,
		ProcLabels).

%----------------------------------------------------------------------------%

:- pred base_typeclass_info__gen_superclass_count(class_id, module_info, 
		int, int).
:- mode base_typeclass_info__gen_superclass_count(in, in, out, out) is det.

base_typeclass_info__gen_superclass_count(ClassId, ModuleInfo, 
		NumSuperClasses, ClassArity) :-
	module_info_classes(ModuleInfo, ClassTable),
	map__lookup(ClassTable, ClassId, ClassDefn),
	ClassDefn = hlds_class_defn(_, SuperClassConstraints, ClassVars,
			_, _, _, _),
	list__length(SuperClassConstraints, NumSuperClasses),
	list__length(ClassVars, ClassArity).

%----------------------------------------------------------------------------%

	% Note that for historical reasons, builtin types
	% are treated as being unqualified (`int') rather than
	% being qualified (`builtin:int') at this point.

base_typeclass_info__make_instance_string(InstanceTypes, InstanceString) :-
	list__map(base_typeclass_info__type_to_string, 
		InstanceTypes, InstanceStrings),
	string__append_list(InstanceStrings, InstanceString).

:- pred base_typeclass_info__type_to_string(type, string).
:- mode base_typeclass_info__type_to_string(in, out) is det.

base_typeclass_info__type_to_string(Type, String) :-
	( sym_name_and_args(Type, TypeName, TypeArgs) ->
		prog_out__sym_name_to_string(TypeName, "__", TypeNameString),
		list__length(TypeArgs, TypeArity),
		string__int_to_string(TypeArity, TypeArityString),
		string__append_list(
			[TypeNameString, "__arity", TypeArityString, "__"],
			String)
	;
		error("base_typeclass_info__type_to_string: invalid type")
	).
		
%----------------------------------------------------------------------------%