[m-rev.] for review: ordering the items in interface files

Zoltan Somogyi zs at cs.mu.OZ.AU
Sun Mar 20 13:21:41 AEDT 2005


For review by Julien.

compiler/modules.m:
	Put lists of items into an approximation of a standard order
	when generating interface files. This should reduce the number
	of times modules are unnecessarily recompiled because of a change
	in a module that *reorders* its exported items without *changing*
	the set of exported items.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.319
diff -u -b -r1.319 modules.m
--- compiler/modules.m	10 Mar 2005 02:35:58 -0000	1.319
+++ compiler/modules.m	19 Mar 2005 15:40:12 -0000
@@ -7030,7 +7030,8 @@
     get_interface_and_implementation_2(IncludeImplTypes, Items0, no,
         [], RevItems, AddToImpl, unit, _),
     list__reverse(RevItems, Items1),
-    maybe_add_foreign_import_module(ModuleName, Items1, Items).
+    maybe_add_foreign_import_module(ModuleName, Items1, Items2),
+    order_items(Items2, Items).
 
 :- pred get_interface_and_implementation(module_name::in, bool::in,
     item_list::in, item_list::out, item_list::out) is det.
@@ -7161,7 +7162,8 @@
 get_short_interface(Items0, Kind, Items) :-
     get_short_interface_2(Items0, Kind, [], RevItems),
     list__reverse(RevItems, Items1),
-    maybe_strip_import_decls(Items1, Items).
+    maybe_strip_import_decls(Items1, Items2),
+    order_items(Items2, Items).
 
 :- pred get_short_interface_2(item_list::in, short_interface_kind::in,
     item_list::in, item_list::out) is det.
@@ -7364,6 +7366,158 @@
             (pred((ThisItem - _)::in) is semidet :-
                 ThisItem \= pragma(foreign_import_module(_, _))
             ), !Items)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+    % Put the given list of items into a sort of standard order. The idea is
+    % that just reordering the contents of e.g. an interface section without
+    % changing the set of exported entities should not cause a change in the
+    % interface files. The "sort of" is because we are not doing as good a job
+    % as we could. Unfortunately, doing significantly better is quite hard
+    % with the current representation of the module is just a list of items
+    % without further structure.
+    %
+:- pred order_items(item_list::in, item_list::out) is det.
+
+order_items(Items0, Items) :-
+    do_order_items(Items0, Items1),
+        % Delete any redundant :- interface and :- implementation markers
+        % at the end, to make Items as insensitive as we can to the number
+        % of interface sections in the source file. If some of the
+        % implementation sections are not empty, we won't be fully successful.
+    list__reverse(Items1, RevItems1),
+    list__takewhile(interface_or_import_marker, RevItems1, _, RevItems),
+    list__reverse(RevItems, Items).
+
+:- pred interface_or_import_marker(item_and_context::in) is semidet.
+
+interface_or_import_marker(module_defn(_, interface) - _).
+interface_or_import_marker(module_defn(_, implementation) - _).
+
+    % Find a chunk of items which should in most cases (but unfortunately
+    % not all cases) be all the exported items, and put them in a standard
+    % order, with import_module and use_module items first in lexical order,
+    % then type, inst and mode definitions, again in lexical order, then
+    % pred and predmode declarations, in lexical order by sym_name, and
+    % finally all other items in the chunk. The chunk consists of the initial
+    % prefix of items for which this reordering is safe. The chunk will then
+    % be followed by the ordered versions of later chunks, if any.
+    %
+:- pred do_order_items(item_list::in, item_list::out) is det.
+
+do_order_items([], []).
+do_order_items([Item0 | Items0], OrderedItems) :-
+    ( chunkable(Item0) ->
+        list__takewhile(chunkable, Items0, FrontItems, RemainItems),
+        list__filter(reorderable, [Item0 | FrontItems],
+            ReorderableItems, NonReorderableItems),
+        list__filter(import_or_use, ReorderableItems,
+            ImportReorderableItems, NonImportReorderableItems),
+        list__filter(symname_orderable, NonReorderableItems,
+            SymNameItems, NonSymNameItems),
+            % We rely on the sort being stable to keep the items
+            % with the same sym_names in their original order.
+        list__sort(compare_by_symname, SymNameItems, OrderedSymNameItems),
+        do_order_items(RemainItems, OrderedRemainItems),
+        OrderedItems = list__sort(ImportReorderableItems) ++
+            list__sort(NonImportReorderableItems) ++
+            OrderedSymNameItems ++ NonSymNameItems ++ OrderedRemainItems
+    ;
+        do_order_items(Items0, OrderedItemsTail),
+        OrderedItems = [Item0 | OrderedItemsTail]
+    ).
+
+:- pred import_or_use(item_and_context::in) is semidet.
+
+import_or_use(module_defn(_, import(_)) - _).
+import_or_use(module_defn(_, use(_)) - _).
+
+    % The kinds of items for which reorderable succeeds can be arbitrarily
+    % reordered with respect to each other and with respect to other chunkable
+    % items in all kinds of interface files (.int, .int2, .int3, .int0, .opt
+    % and .trans_opt).
+    %
+:- pred reorderable(item_and_context::in) is semidet.
+
+reorderable(module_defn(_, import(_)) - _).
+reorderable(module_defn(_, use(_)) - _).
+reorderable(pragma(export(_, _, _, _)) - _).
+reorderable(pragma(type_spec(_, _, _, _, _, _, _, _)) - _).
+reorderable(pragma(inline(_, _)) - _).
+reorderable(pragma(no_inline(_, _)) - _).
+reorderable(pragma(unused_args(_, _, _, _, _)) - _).
+reorderable(pragma(tabled(_, _, _, _, _)) - _).
+reorderable(pragma(reserve_tag(_, _)) - _).
+reorderable(pragma(promise_pure(_, _)) - _).
+reorderable(pragma(promise_semipure(_, _)) - _).
+reorderable(pragma(termination_info(_, _, _, _, _)) - _).
+reorderable(pragma(terminates(_, _)) - _).
+reorderable(pragma(does_not_terminate(_, _)) - _).
+reorderable(pragma(check_termination(_, _)) - _).
+reorderable(type_defn(_, _, _, _, _) - _).
+reorderable(inst_defn(_, _, _, _, _) - _).
+reorderable(mode_defn(_, _, _, _, _) - _).
+reorderable(promise(_, _, _, _) - _).
+reorderable(typeclass(_, _, _, _, _) - _).
+reorderable(instance(_, _, _, _, _, _) - _).
+
+    % Given a list of items for which chunkable succeeds, we need to keep
+    % the relative order of the non-reorderable items, but we can move the
+    % reorderable items around arbitrarily.
+    %
+:- pred chunkable(item_and_context::in) is semidet.
+
+chunkable(module_defn(_, import(_)) - _).
+chunkable(module_defn(_, use(_)) - _).
+chunkable(pragma(export(_, _, _, _)) - _).
+chunkable(pragma(type_spec(_, _, _, _, _, _, _, _)) - _).
+chunkable(pragma(inline(_, _)) - _).
+chunkable(pragma(no_inline(_, _)) - _).
+chunkable(pragma(unused_args(_, _, _, _, _)) - _).
+chunkable(pragma(tabled(_, _, _, _, _)) - _).
+chunkable(pragma(reserve_tag(_, _)) - _).
+chunkable(pragma(promise_pure(_, _)) - _).
+chunkable(pragma(promise_semipure(_, _)) - _).
+chunkable(pragma(termination_info(_, _, _, _, _)) - _).
+chunkable(pragma(terminates(_, _)) - _).
+chunkable(pragma(does_not_terminate(_, _)) - _).
+chunkable(pragma(check_termination(_, _)) - _).
+chunkable(type_defn(_, _, _, _, _) - _).
+chunkable(inst_defn(_, _, _, _, _) - _).
+chunkable(mode_defn(_, _, _, _, _) - _).
+chunkable(pred_or_func(_, _, _, _, _, _, _, _, _, _, _, _) - _).
+chunkable(pred_or_func_mode(_, _, _, _, _, _, _) - _).
+chunkable(promise(_, _, _, _) - _).
+chunkable(typeclass(_, _, _, _, _) - _).
+chunkable(instance(_, _, _, _, _, _) - _).
+
+    % Given a list of items for which symname_ordered succeeds, we need to keep
+    % the relative order of the items with the same sym_name as returned by
+    % symname_ordered, but the relative order of items with different sym_names
+    % doesn't matter.
+    %
+:- pred symname_ordered(item_and_context::in, sym_name::out) is semidet.
+
+symname_ordered(pred_or_func(_, _, _, _, Name, _, _, _, _, _, _, _) - _, Name).
+symname_ordered(pred_or_func_mode(_, _, Name, _, _, _, _) - _, Name).
+
+:- pred symname_orderable(item_and_context::in) is semidet.
+
+symname_orderable(ItemAndContext) :-
+    symname_ordered(ItemAndContext, _).
+
+:- pred compare_by_symname(item_and_context::in, item_and_context::in,
+    comparison_result::out) is det.
+
+compare_by_symname(ItemAndContextA, ItemAndContextB, Result) :-
+    (
+        symname_ordered(ItemAndContextA, SymNameA),
+        symname_ordered(ItemAndContextB, SymNameB)
+    ->
+        compare(Result, SymNameA, SymNameB)
+    ;
+        error("compare_by_symname: symname not found")
     ).
 
 %-----------------------------------------------------------------------------%
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
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