[m-rev.] for review: clean up code for computing norms
Julien Fischer
juliensf at students.cs.mu.OZ.AU
Thu Oct 30 15:36:12 AEDT 2003
Estimated hours taken: 1
Branches: main
Shift some code related to setting up functor norms from termination.m
to term_norm.m. This avoids having to duplicate the same code in the
new termination analyser.
Clean up the code in term_norm.m.
compiler/termination.m:
Move predicate set_functor_info/3 from here to term_norm.m as this
removes the need to duplicate this predicate in the new termination
analyser.
compiler/term_norm.m:
Make the functor_info type abstract since the rest of the compiler
shouldn't need to modify it.
Do not export the types weight_info and weight_table.
Use ho list preds from the library where appropriate.
Use predmode declarations and state variables where appropriate.
Add an XXX comment about which norms the compiler currently supports.
Fix a comment relating to the norms and the module_info.
Index: compiler/term_norm.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/term_norm.m,v
retrieving revision 1.1
diff -u -r1.1 term_norm.m
--- compiler/term_norm.m 22 Oct 2003 07:05:17 -0000 1.1
+++ compiler/term_norm.m 29 Oct 2003 05:41:23 -0000
@@ -18,42 +18,23 @@
:- import_module hlds__hlds_data.
:- import_module hlds__hlds_goal.
:- import_module hlds__hlds_module.
+:- import_module libs__globals.
:- import_module parse_tree__prog_data.
-:- import_module std_util, bool, int, list, map.
+:- import_module int, list.
%-----------------------------------------------------------------------------%
-% We use semilinear norms (denoted by ||) to compute the sizes of terms.
-% These have the form
-%
-% | f(t1, ... tn) | = weight(f) + sum of | ti |
-% where i is an element of a set I, and I is a subset of {1, ... n}
-%
-% We currently support four kinds of semilinear norms.
-
-:- type functor_info
- ---> simple % All non-constant functors have weight 1,
- % while constants have weight 0.
- % Use the size of all subterms (I = {1, ..., n}.
-
- ; total % All functors have weight = arity of the functor.
- % Use the size of all subterms (I = {1, ..., n}.
-
- ; use_map(weight_table)
- % The weight of each functor is given by the table.
- % Use the size of all subterms (I = {1, ..., n}.
+% The functor_info type contains information about how the weight of a term
+% is calculated.
- ; use_map_and_args(weight_table).
- % The weight of each functor is given by the table,
- % and so is the set of arguments of the functor whose
- % size should be counted (I is given by the table
- % entry of the functor).
+:- type functor_info.
-:- type weight_info ---> weight(int, list(bool)).
-:- type weight_table == map(pair(type_ctor, cons_id), weight_info).
+% This predicate sets the functor_info depending on the value of the
+% termination_norm option.
-:- pred find_weights(module_info::in, weight_table::out) is det.
+:- pred set_functor_info(globals__termination_norm::in, module_info::in,
+ functor_info::out) is det.
% This predicate computes the weight of a functor and the set of arguments
% of that functor whose sizes should be counted towards the size of the whole
@@ -63,11 +44,9 @@
module_info::in, int::out, list(prog_var)::in, list(prog_var)::out,
list(uni_mode)::in, list(uni_mode)::out) is det.
-
% Succeeds if all values of the given type are zero size (for all norms).
-:- pred zero_size_type(type, module_info).
-:- mode zero_size_type(in, in) is semidet.
+:- pred zero_size_type((type)::in, module_info::in) is semidet.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -77,13 +56,40 @@
:- import_module check_hlds__inst_match.
:- import_module check_hlds__mode_util.
:- import_module check_hlds__type_util.
-:- import_module libs__globals.
:- import_module libs__options.
:- import_module parse_tree__prog_out.
-:- import_module assoc_list, require.
+:- import_module assoc_list, bool, map, require, std_util.
%-----------------------------------------------------------------------------%
+
+% We use semilinear norms (denoted by ||) to compute the sizes of terms.
+% These have the form
+%
+% | f(t1, ... tn) | = weight(f) + sum of | ti |
+% where i is an element of a set I, and I is a subset of {1, ... n}
+%
+% We currently support four kinds of semilinear norms.
+% XXX Actually we currently only use three of them. `use_map/1' is unused.
+
+:- type functor_info
+ ---> simple % All non-constant functors have weight 1,
+ % while constants have weight 0.
+ % Use the size of all subterms (I = {1, ..., n}.
+
+ ; total % All functors have weight = arity of the functor.
+ % Use the size of all subterms (I = {1, ..., n}.
+
+ ; use_map(weight_table)
+ % The weight of each functor is given by the table.
+ % Use the size of all subterms (I = {1, ..., n}.
+
+ ; use_map_and_args(weight_table).
+ % The weight of each functor is given by the table,
+ % and so is the set of arguments of the functor whose
+ % size should be counted (I is given by the table
+ % entry of the functor).
+
%-----------------------------------------------------------------------------%
% Calculate the weight to be assigned to each function symbol for the
@@ -103,68 +109,49 @@
% arguments, except that we assign a weight of at least 1 to all functors
% which are not constants.
+:- type weight_table == map(pair(type_ctor, cons_id), weight_info).
+
+:- type weight_info ---> weight(int, list(bool)).
+
+:- pred find_weights(module_info::in, weight_table::out) is det.
+
find_weights(ModuleInfo, Weights) :-
module_info_types(ModuleInfo, TypeTable),
map__to_assoc_list(TypeTable, TypeList),
map__init(Weights0),
- find_weights_for_type_list(TypeList, Weights0, Weights).
+ list__foldl(find_weights_for_type, TypeList, Weights0, Weights).
-:- pred find_weights_for_type_list(assoc_list(type_ctor, hlds_type_defn)::in,
+:- pred find_weights_for_type(pair(type_ctor, hlds_type_defn)::in,
weight_table::in, weight_table::out) is det.
-find_weights_for_type_list([], Weights, Weights).
-find_weights_for_type_list([TypeCtor - TypeDefn | TypeList],
- Weights0, Weights) :-
- find_weights_for_type(TypeCtor, TypeDefn, Weights0, Weights1),
- find_weights_for_type_list(TypeList, Weights1, Weights).
-
-:- pred find_weights_for_type(type_ctor::in, hlds_type_defn::in,
- weight_table::in, weight_table::out) is det.
-
-find_weights_for_type(TypeCtor, TypeDefn, Weights0, Weights) :-
+find_weights_for_type(TypeCtor - TypeDefn, !Weights) :-
hlds_data__get_type_defn_body(TypeDefn, TypeBody),
(
Constructors = TypeBody ^ du_type_ctors,
hlds_data__get_type_defn_tparams(TypeDefn, TypeParams),
- find_weights_for_cons_list(Constructors, TypeCtor, TypeParams,
- Weights0, Weights)
+ list__foldl(find_weights_for_cons(TypeCtor, TypeParams),
+ Constructors, !Weights)
;
% This type does not introduce any functors
- TypeBody = eqv_type(_),
- Weights = Weights0
+ TypeBody = eqv_type(_)
;
% This type may introduce some functors,
% but we will never see them in this analysis
- TypeBody = abstract_type(_),
- Weights = Weights0
+ TypeBody = abstract_type(_)
;
% This type does not introduce any functors
- TypeBody = foreign_type(_, _),
- Weights = Weights0
+ TypeBody = foreign_type(_, _)
).
-:- pred find_weights_for_cons_list(list(constructor)::in,
- type_ctor::in, list(type_param)::in,
- weight_table::in, weight_table::out) is det.
-
-find_weights_for_cons_list([], _, _, Weights, Weights).
-find_weights_for_cons_list([Constructor | Constructors], TypeCtor, Params,
- Weights0, Weights) :-
- find_weights_for_cons(Constructor, TypeCtor, Params,
- Weights0, Weights1),
- find_weights_for_cons_list(Constructors, TypeCtor, Params,
- Weights1, Weights).
-
-:- pred find_weights_for_cons(constructor::in,
- type_ctor::in, list(type_param)::in,
- weight_table::in, weight_table::out) is det.
+:- pred find_weights_for_cons(type_ctor::in, list(type_param)::in,
+ constructor::in, weight_table::in, weight_table::out) is det.
% XXX Currently, the weight of a functor is not affected by the presence
% of any arguments that are type_info related. However, the set of
% arguments whose sizes should be counted towards the total size of
% the term will include any type-info related arguments.
-find_weights_for_cons(Ctor, TypeCtor, Params, Weights0, Weights) :-
+find_weights_for_cons(TypeCtor, Params, Ctor, !Weights) :-
Ctor = ctor(ExistQVars, _Constraints, SymName, Args),
list__length(ExistQVars, NumExistQVars),
list__length(Args, Arity),
@@ -184,7 +171,7 @@
WeightInfo = weight(0, [])
),
ConsId = cons(SymName, Arity),
- map__det_insert(Weights0, TypeCtor - ConsId, WeightInfo, Weights).
+ map__det_insert(!.Weights, TypeCtor - ConsId, WeightInfo, !:Weights).
:- pred find_weights_for_tuple(arity::in, weight_info::out) is det.
@@ -208,8 +195,8 @@
ArgInfo = [no | ArgInfo0]
).
-:- pred is_arg_recursive(constructor_arg::in,
- type_ctor::in, list(type_param)::in) is semidet.
+:- pred is_arg_recursive(constructor_arg::in, type_ctor::in,
+ list(type_param)::in) is semidet.
is_arg_recursive(Arg, TypeCtor, Params) :-
Arg = _Name - ArgType,
@@ -218,7 +205,7 @@
list__perm(Params, ArgTypeParams).
:- pred search_weight_table(weight_table::in, type_ctor::in, cons_id::in,
- weight_info::out) is semidet.
+ weight_info::out) is semidet.
search_weight_table(WeightMap, TypeCtor, ConsId, WeightInfo) :-
( map__search(WeightMap, TypeCtor - ConsId, WeightInfo0) ->
@@ -232,10 +219,19 @@
%-----------------------------------------------------------------------------%
-% Although the module info is not used in either of these norms, it could
+set_functor_info(total, _Module, total).
+set_functor_info(simple, _Module, simple).
+set_functor_info(num_data_elems, Module, use_map_and_args(WeightMap)) :-
+ find_weights(Module, WeightMap).
+set_functor_info(size_data_elems, Module, use_map(WeightMap)) :-
+ find_weights(Module, WeightMap).
+
+%-----------------------------------------------------------------------------%
+
+% Although the module info is not used in any of these norms, it could
% be needed for other norms, so it should not be removed.
-functor_norm(simple, _, ConsId, _, Int, Args, Args, Modes, Modes) :-
+functor_norm(simple, _, ConsId, _, Int, !Args, !Modes) :-
(
ConsId = cons(_, Arity),
Arity \= 0
@@ -244,43 +240,38 @@
;
Int = 0
).
-functor_norm(total, _, ConsId, _Module, Int, Args, Args, Modes, Modes) :-
+functor_norm(total, _, ConsId, _, Int, !Args, !Modes) :-
( ConsId = cons(_, Arity) ->
Int = Arity
;
Int = 0
).
-functor_norm(use_map(WeightMap), TypeCtor, ConsId, _Module, Int,
- Args, Args, Modes, Modes) :-
+functor_norm(use_map(WeightMap), TypeCtor, ConsId, _, Int, !Args, !Modes) :-
( search_weight_table(WeightMap, TypeCtor, ConsId, WeightInfo) ->
WeightInfo = weight(Int, _)
;
Int = 0
).
-functor_norm(use_map_and_args(WeightMap), TypeCtor, ConsId, _Module, Int,
- Args0, Args, Modes0, Modes) :-
+functor_norm(use_map_and_args(WeightMap), TypeCtor, ConsId, _, Int, !Args,
+ !Modes) :-
( search_weight_table(WeightMap, TypeCtor, ConsId, WeightInfo) ->
WeightInfo = weight(Int, UseArgList),
(
- functor_norm_filter_args(UseArgList, Args0, Args1,
- Modes0, Modes1)
+ functor_norm_filter_args(UseArgList, !Args, !Modes)
->
- Modes = Modes1,
- Args = Args1
+ true
;
error("Unmatched lists in functor_norm_filter_args.")
)
;
- Int = 0,
- Modes = Modes0,
- Args = Args0
+ Int = 0
).
% This predicate will fail if the length of the input lists are not matched.
-:- pred functor_norm_filter_args(list(bool), list(prog_var), list(prog_var),
- list(uni_mode), list(uni_mode)).
-:- mode functor_norm_filter_args(in, in, out, in, out) is semidet.
+:- pred functor_norm_filter_args(list(bool)::in, list(prog_var)::in,
+ list(prog_var)::out, list(uni_mode)::in, list(uni_mode)::out)
+ is semidet.
functor_norm_filter_args([], [], [], [], []).
functor_norm_filter_args([yes | Bools], [Arg0 | Args0], [Arg0 | Args],
@@ -296,8 +287,7 @@
classify_type(Module, Type) = TypeCategory,
zero_size_type_category(TypeCategory, yes).
-:- pred zero_size_type_category(type_category, bool).
-:- mode zero_size_type_category(in, out) is det.
+:- pred zero_size_type_category(type_category::in, bool::out) is det.
zero_size_type_category(int_type, yes).
zero_size_type_category(char_type, yes).
Index: compiler/termination.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/termination.m,v
retrieving revision 1.32
diff -u -r1.32 termination.m
--- compiler/termination.m 24 Oct 2003 06:17:49 -0000 1.32
+++ compiler/termination.m 24 Oct 2003 07:01:52 -0000
@@ -148,21 +148,6 @@
[]
).
-% This predicate sets the functor info depending on the value of the
-% termination_norm option. The functor info field stores the weight which
-% is associated with each functor, and may contain information about which
-% subterms contribute to the size of that functor.
-
-:- pred set_functor_info(globals__termination_norm, module_info, functor_info).
-:- mode set_functor_info(in, in, out) is det.
-
-set_functor_info(total, _Module, total).
-set_functor_info(simple, _Module, simple).
-set_functor_info(num_data_elems, Module, use_map_and_args(WeightMap)) :-
- find_weights(Module, WeightMap).
-set_functor_info(size_data_elems, Module, use_map(WeightMap)) :-
- find_weights(Module, WeightMap).
-
%----------------------------------------------------------------------------%
% Check that any user-supplied termination information (from pragma
% terminates/does_not_terminate) is consistent for each SCC in the program.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list