[m-rev.] for review: speed up .opt file reading and deps

Peter Wang novalazy at gmail.com
Tue Sep 2 11:50:08 AEST 2008


On 2008-09-01, Zoltan Somogyi <zs at csse.unimelb.edu.au> wrote:
> On 01-Sep-2008, Peter Wang <novalazy at gmail.com> wrote:
> > compiler/module_imports.m:
> > 	Change `module_imports' to hold items in a queue instead of a list.
> 
> Why a queue? I would have thought that the natural data structure to use
> in this case is a cord.

I simply forgot about it.  Here is a new diff.  Note that one of the
test case expected outputs was changed slightly.


Branches: main

Change some data representations to avoid repeatedly appending lists when
reading optimisation interface files and calculating dependencies.

compiler/module_imports.m:
	Change `module_imports' to hold items in a cord instead of a list.

	Add getter/setter for items that work with lists, as most code will
	continue to use lists.

	Make `get_dependencies' and `get_dependencies_int_imp' accumulate
	sets of modules instead of lists.

compiler/intermod.m:
	Conform to `module_imports' changes.

	Make `read_optimization_interfaces' accumulate cords of items
	so that appending a list of items doesn't rebuild as big a list.

compiler/make.module_dep_file.m:
compiler/mercury_compile.m:
compiler/modules.m:
compiler/trans_opt.m:
compiler/write_deps_file.m:
	Conform to `module_imports' changes.

tests/warnings/ambiguous_overloading.exp:
	Update expected output, which was changed due to the `get_dependencies'
	change.

diff --git a/compiler/intermod.m b/compiler/intermod.m
index 38a41c8..60009b0 100644
--- a/compiler/intermod.m
+++ b/compiler/intermod.m
@@ -122,6 +122,7 @@
 :- import_module transform_hlds.inlining.
 
 :- import_module assoc_list.
+:- import_module cord.
 :- import_module getopt_io.
 :- import_module int.
 :- import_module map.
@@ -2289,13 +2290,15 @@ grab_opt_files(!Module, FoundError, !IO) :-
     ModulesProcessed = set.insert(set.sorted_list_to_set(OptFiles),
         ModuleName),
     read_optimization_interfaces(Transitive, ModuleName, OptFiles,
-        ModulesProcessed, [], OptItems, no, OptError, !IO),
+        ModulesProcessed, cord.empty, OptItemsCord, no, OptError, !IO),
+    OptItems = cord.list(OptItemsCord),
 
     % Append the items to the current item list, using a `opt_imported'
     % psuedo-declaration to let make_hlds know the opt_imported stuff
     % is coming.
     module_imports_get_items(!.Module, Items0),
-    Items1 = Items0 ++ [make_pseudo_decl(md_opt_imported) | OptItems],
+    Items1 = Items0 ++ cord.from_list([
+        make_pseudo_decl(md_opt_imported) | OptItems]),
     module_imports_set_items(Items1, !Module),
 
     % Get the :- pragma unused_args(...) declarations created when writing
@@ -2318,7 +2321,8 @@ grab_opt_files(!Module, FoundError, !IO) :-
         )
     ->
         read_optimization_interfaces(no, ModuleName, [ModuleName],
-            set.init, [], LocalItems, no, UA_SR_Error, !IO),
+            set.init, cord.empty, LocalItemsCord, no, UA_SR_Error, !IO),
+        LocalItems = cord.list(LocalItemsCord),
         KeepPragma = (pred(Item::in) is semidet :-
             Item = item_pragma(ItemPragma),
             ItemPragma = item_pragma_info(_, Pragma, _, _),
@@ -2333,7 +2337,7 @@ grab_opt_files(!Module, FoundError, !IO) :-
         list.filter(KeepPragma, LocalItems, PragmaItems),
 
         module_imports_get_items(!.Module, Items2),
-        list.append(Items2, PragmaItems, Items),
+        Items = Items2 ++ cord.from_list(PragmaItems),
         module_imports_set_items(Items, !Module)
     ;
         UA_SR_Error = no
@@ -2386,7 +2390,7 @@ grab_opt_files(!Module, FoundError, !IO) :-
 
 :- pred read_optimization_interfaces(bool::in, module_name::in,
     list(module_name)::in, set(module_name)::in,
-    list(item)::in, list(item)::out, bool::in, bool::out,
+    cord(item)::in, cord(item)::out, bool::in, bool::out,
     io::di, io::uo) is det.
 
 read_optimization_interfaces(_, _, [], _, !Items, !Error, !IO).
@@ -2406,7 +2410,7 @@ read_optimization_interfaces(Transitive, ModuleName,
     prog_io.read_opt_file(FileName, ModuleToRead, OptItems, Specs, ModuleError,
         !IO),
     update_error_status(opt_file, FileName, ModuleError, Specs, !Error, !IO),
-    !:Items = !.Items ++ OptItems,
+    !:Items = !.Items ++ cord.from_list(OptItems),
     maybe_write_string(VeryVerbose, "% done.\n", !IO),
 
     globals.io_get_globals(Globals, !IO),
diff --git a/compiler/make.module_dep_file.m b/compiler/make.module_dep_file.m
index 90806c3..d36f050 100644
--- a/compiler/make.module_dep_file.m
+++ b/compiler/make.module_dep_file.m
@@ -53,6 +53,7 @@
 :- import_module parse_tree.prog_out.
 
 :- import_module assoc_list.
+:- import_module cord.
 :- import_module dir.
 :- import_module getopt_io.
 :- import_module parser.
@@ -244,7 +245,8 @@ module_dependencies_version_number = 1.
 write_module_dep_file(Imports0, !IO) :-
     % Make sure all the required fields are filled in.
     globals.io_get_globals(Globals, !IO),
-    strip_imported_items(Imports0 ^ items, Items),
+    module_imports_get_items_list(Imports0, Items0),
+    strip_imported_items(Items0, Items),
     init_dependencies(Imports0 ^ source_file_name,
         Imports0 ^ source_file_module_name,
         Imports0 ^ nested_children, no_module_errors, Globals,
@@ -476,7 +478,7 @@ read_module_dependencies_2(RebuildModuleDeps, SearchDirs, ModuleName, !Info,
             Imports ^ has_foreign_code = ContainsForeignCode,
             Imports ^ foreign_import_modules = ForeignImports,
             Imports ^ contains_foreign_export = ContainsForeignExport,
-            Imports ^ items = [],       % not used.
+            Imports ^ items = cord.empty,       % not used.
             Imports ^ error = no_module_errors, % not used.
             Imports ^ maybe_timestamps = no,    % not used.
             Imports ^ has_main = HasMain,
diff --git a/compiler/mercury_compile.m b/compiler/mercury_compile.m
index 530e1ec..ab714a9 100644
--- a/compiler/mercury_compile.m
+++ b/compiler/mercury_compile.m
@@ -1864,7 +1864,7 @@ pre_hlds_pass(ModuleImports0, DontWriteDFile0, HLDS1, QualInfo,
         )
     ),
 
-    module_imports_get_items(ModuleImports1, Items1),
+    module_imports_get_items_list(ModuleImports1, Items1),
     MaybeTimestamps = ModuleImports1 ^ maybe_timestamps,
 
     invoke_module_qualify_items(Items1, Items2, EventSpecMap1, EventSpecMap2,
diff --git a/compiler/module_imports.m b/compiler/module_imports.m
index 7967fb1..5e779f0 100644
--- a/compiler/module_imports.m
+++ b/compiler/module_imports.m
@@ -25,11 +25,14 @@
 :- import_module parse_tree.prog_io.    % for module_error;
                                         % undesirable dependency
 
+:- import_module cord.
 :- import_module list.
 :- import_module map.
 :- import_module maybe.
 :- import_module pair.
 
+%-----------------------------------------------------------------------------%
+
     % When doing smart recompilation record for each module the suffix of
     % the file that was read and the modification time of the file.
     %
@@ -109,7 +112,7 @@
                 contains_foreign_export     :: contains_foreign_export,
 
                 % The contents of the module and its imports.
-                items                       :: list(item),
+                items                       :: cord(item),
 
                 % Whether an error has been encountered when reading in
                 % this module.
@@ -132,10 +135,14 @@
     is det.
 :- pred module_imports_get_impl_deps(module_imports::in,
     list(module_name)::out) is det.
-:- pred module_imports_get_items(module_imports::in, list(item)::out) is det.
+:- pred module_imports_get_items(module_imports::in, cord(item)::out) is det.
+:- pred module_imports_get_items_list(module_imports::in, list(item)::out)
+    is det.
 :- pred module_imports_get_error(module_imports::in, module_error::out) is det.
 
-:- pred module_imports_set_items(list(item)::in,
+:- pred module_imports_set_items(cord(item)::in,
+    module_imports::in, module_imports::out) is det.
+:- pred module_imports_set_items_list(list(item)::in,
     module_imports::in, module_imports::out) is det.
 :- pred module_imports_set_error(module_error::in,
     module_imports::in, module_imports::out) is det.
@@ -226,6 +233,7 @@
 :- pred get_fact_table_dependencies(list(item)::in, list(string)::out) is det.
 
 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
 
 :- implementation.
 
@@ -236,14 +244,20 @@
 :- import_module bool.
 :- import_module dir.
 :- import_module set.
+:- import_module svset.
 :- import_module term.
 
+%-----------------------------------------------------------------------------%
+
 module_imports_get_source_file_name(Module, Module ^ source_file_name).
 module_imports_get_module_name(Module, Module ^ module_name).
 module_imports_get_impl_deps(Module, Module ^ impl_deps).
 module_imports_get_items(Module, Module ^ items).
+module_imports_get_items_list(Module, cord.list(Module ^ items)).
 module_imports_get_error(Module, Module ^ error).
 module_imports_set_items(Items, Module, Module ^ items := Items).
+module_imports_set_items_list(Items, Module, Module ^ items := Cord) :-
+    Cord = cord.from_list(Items).
 module_imports_set_error(Error, Module, Module ^ error := Error).
 module_imports_set_int_deps(IntDeps, Module, Module ^ int_deps := IntDeps).
 module_imports_set_impl_deps(ImplDeps, Module,
@@ -332,26 +346,31 @@ init_dependencies(FileName, SourceFileModuleName, NestedModuleNames,
         ImplementationDeps, IndirectDeps, IncludeDeps,
         InterfaceIncludeDeps, NestedDeps, FactTableDeps,
         ContainsForeignCode, ForeignImports, ContainsPragmaExport,
-        [], Error, no, HasMain, dir.this_directory).
+        cord.empty, Error, no, HasMain, dir.this_directory).
 
 %-----------------------------------------------------------------------------%
 
 get_dependencies(Items, ImportDeps, UseDeps) :-
-    get_dependencies_implementation(Items,
-        [], IntImportDeps, [], IntUseDeps, [], ImpImportDeps, [], ImpUseDeps),
+    get_dependencies_int_imp(Items, IntImportDeps, IntUseDeps,
+        ImpImportDeps, ImpUseDeps),
     ImportDeps = IntImportDeps ++ ImpImportDeps,
     UseDeps = IntUseDeps ++ ImpUseDeps.
 
 get_dependencies_int_imp(Items, IntImportDeps, IntUseDeps,
         ImpImportDeps, ImpUseDeps) :-
     get_dependencies_implementation(Items,
-        [], IntImportDeps, [], IntUseDeps, [], ImpImportDeps, [], ImpUseDeps).
+        set.init, IntImportDepsSet, set.init, IntUseDepsSet,
+        set.init, ImpImportDepsSet, set.init, ImpUseDepsSet),
+    IntImportDeps = set.to_sorted_list(IntImportDepsSet),
+    ImpImportDeps = set.to_sorted_list(ImpImportDepsSet),
+    IntUseDeps = set.to_sorted_list(IntUseDepsSet),
+    ImpUseDeps = set.to_sorted_list(ImpUseDepsSet).
 
 :- pred get_dependencies_implementation(list(item)::in,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out) is det.
+    set(module_name)::in, set(module_name)::out,
+    set(module_name)::in, set(module_name)::out,
+    set(module_name)::in, set(module_name)::out,
+    set(module_name)::in, set(module_name)::out) is det.
 
 get_dependencies_implementation([],
         !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps).
@@ -364,9 +383,9 @@ get_dependencies_implementation([Item | Items],
                 !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
         ;
             ( ModuleDefn = md_import(Modules) ->
-                !:ImpImportDeps = !.ImpImportDeps ++ Modules
+                svset.insert_list(Modules, !ImpImportDeps)
             ; ModuleDefn = md_use(Modules) ->
-                !:ImpUseDeps = !.ImpUseDeps ++ Modules
+                svset.insert_list(Modules, !ImpUseDeps)
             ;
                 true
             ),
@@ -379,10 +398,10 @@ get_dependencies_implementation([Item | Items],
     ).
 
 :- pred get_dependencies_interface(list(item)::in,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out) is det.
+    set(module_name)::in, set(module_name)::out,
+    set(module_name)::in, set(module_name)::out,
+    set(module_name)::in, set(module_name)::out,
+    set(module_name)::in, set(module_name)::out) is det.
 
 get_dependencies_interface([],
         !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps).
@@ -395,9 +414,9 @@ get_dependencies_interface([Item | Items],
                 !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
         ;
             ( ModuleDefn = md_import(Modules) ->
-                !:IntImportDeps = !.IntImportDeps ++ Modules
+                svset.insert_list(Modules, !IntImportDeps)
             ; ModuleDefn = md_use(Modules) ->
-                !:IntUseDeps = !.IntUseDeps ++ Modules
+                svset.insert_list(Modules, !IntUseDeps)
             ;
                 true
             ),
diff --git a/compiler/modules.m b/compiler/modules.m
index d0903e8..662ff49 100644
--- a/compiler/modules.m
+++ b/compiler/modules.m
@@ -377,6 +377,7 @@
 :- import_module recompilation.version.
 
 :- import_module char.
+:- import_module cord.
 :- import_module dir.
 :- import_module getopt_io.
 :- import_module int.
@@ -417,7 +418,7 @@ make_private_interface(SourceFileName, SourceFileModuleName, ModuleName,
             "`", FileName, "' not written.\n"], !IO)
     ;
         % Module-qualify all items.
-        module_imports_get_items(Module, Items1),
+        module_imports_get_items_list(Module, Items1),
         globals.io_get_globals(Globals, !IO),
         module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
             FileName, !IO),
@@ -531,7 +532,7 @@ make_interface(SourceFileName, SourceFileModuleName, ModuleName,
             ModuleName, !.InterfaceItems, Module0, Error, !IO),
 
         % Check whether we succeeded.
-        module_imports_get_items(Module0, !:InterfaceItems),
+        module_imports_get_items_list(Module0, !:InterfaceItems),
         % XXX zs: why does this code not check for fatal_module_errors?
         ( Error = some_module_errors ->
             module_name_to_file_name(ModuleName, ".int", do_not_create_dirs,
@@ -1741,7 +1742,7 @@ grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName,
                 [[make_pseudo_decl(md_interface) | InterfaceItems],
                 [make_pseudo_decl(md_private_interface) | ImplDecls],
                 [make_pseudo_decl(md_implementation) | Clauses]], Items1),
-            module_imports_set_items(Items1, !Module)
+            module_imports_set_items_list(Items1, !Module)
         ),
 
         % Add `builtin' and `private_builtin' to the list of imported modules.
@@ -1830,7 +1831,7 @@ grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName,
             make_pseudo_decl(md_abstract_imported),
             !Module, !IO),
 
-        module_imports_get_items(!.Module, Items),
+        module_imports_get_items_list(!.Module, Items),
         check_imports_accessibility(ModuleName,
             IntImportedModules ++ IntUsedModules ++
             ImpImportedModules ++ ImpUsedModules, Items, !Specs),
@@ -1928,7 +1929,7 @@ grab_unqual_imported_modules(SourceFileName, SourceFileModuleName, ModuleName,
     some [!Specs] (
         !:Specs = [],
 
-        module_imports_get_items(!.Module, Items),
+        module_imports_get_items_list(!.Module, Items),
         check_imports_accessibility(ModuleName,
             IntImportDeps ++ IntUseDeps ++ ImpImportDeps ++ ImpUseDeps,
             Items, !Specs),
@@ -1943,7 +1944,7 @@ grab_unqual_imported_modules(SourceFileName, SourceFileModuleName, ModuleName,
 
 append_pseudo_decl(PseudoDecl, Module0, Module) :-
     Items0 = Module0 ^ items,
-    list.append(Items0, [make_pseudo_decl(PseudoDecl)], Items),
+    Items = cord.snoc(Items0, make_pseudo_decl(PseudoDecl)),
     Module = Module0 ^ items := Items.
 
 make_pseudo_decl(PseudoDecl) = Item :-
@@ -2787,7 +2788,7 @@ process_module_private_interfaces(ReadModules, [Ancestor | Ancestors],
         get_dependencies(Items, AncDirectImports, AncDirectUses),
         !:DirectImports = !.DirectImports ++ AncDirectImports,
         !:DirectUses = !.DirectUses ++ AncDirectUses,
-        ModItems = ModItems0 ++ Items,
+        ModItems = ModItems0 ++ cord.from_list(Items),
         !:Module = !.Module ^ items := ModItems,
         !:Module = !.Module ^ parent_deps := ModAncestors,
         !:Module = !.Module ^ error := ModError,
@@ -2846,7 +2847,7 @@ process_module_long_interfaces(ReadModules, NeedQualifier, [Import | Imports],
             ++ IndirectUses1,
         !:ImplIndirectImports = !.ImplIndirectImports
             ++ ImplIndirectImports1 ++ ImplIndirectUses1,
-        ModItems = ModItems0 ++ Items,
+        ModItems = ModItems0 ++ cord.from_list(Items),
         !:Module = !.Module ^ impl_deps := ModImplementationImports,
         !:Module = !.Module ^ items := ModItems,
         !:Module = !.Module ^ error := ModError,
@@ -3021,7 +3022,7 @@ process_module_short_interfaces(ReadModules, [Import | Imports], Ext,
         ModIndirectImports = [Import | ModIndirectImports0],
         !:IndirectImports = !.IndirectImports ++ IntImports1 ++ IntUses1,
         !:ImpIndirectImports = !.ImpIndirectImports ++ ImpImports1 ++ ImpUses1,
-        ModItems = ModItems0 ++ Items,
+        ModItems = ModItems0 ++ cord.from_list(Items),
         !:Module = !.Module ^ indirect_deps := ModIndirectImports,
         !:Module = !.Module ^ items := ModItems,
         !:Module = !.Module ^ error := ModError,
@@ -3411,10 +3412,11 @@ init_module_imports(SourceFileName, SourceFileModuleName, ModuleName,
     % module_imports.m is this call. This should be fixed, preferably
     % by changing the module_imports structure.
     maybe_add_foreign_import_module(ModuleName, Items0, Items),
+    ItemsCord = cord.from_list(Items),
     Module = module_imports(SourceFileName, SourceFileModuleName,
         ModuleName, [], [], [], [], [], PublicChildren,
         NestedChildren, FactDeps, contains_foreign_code_unknown, [],
-        contains_no_foreign_export, Items, no_module_errors,
+        contains_no_foreign_export, ItemsCord, no_module_errors,
         MaybeTimestamps, no_main, dir.this_directory).
 
 :- pred maybe_add_foreign_import_module(module_name::in,
diff --git a/compiler/trans_opt.m b/compiler/trans_opt.m
index cf5bbb8..097d992 100644
--- a/compiler/trans_opt.m
+++ b/compiler/trans_opt.m
@@ -107,6 +107,7 @@
 :- import_module transform_hlds.trailing_analysis.
 
 :- import_module assoc_list.
+:- import_module cord.
 :- import_module list.
 :- import_module map.
 :- import_module pair.
@@ -197,18 +198,19 @@ grab_trans_opt_files(TransOptDeps, !Module, FoundError, !IO) :-
     maybe_write_string(Verbose, "% Reading .trans_opt files..\n", !IO),
     maybe_flush_output(Verbose, !IO),
 
-    read_trans_opt_files(TransOptDeps, [], OptItems, no, FoundError, !IO),
+    read_trans_opt_files(TransOptDeps, cord.empty, OptItems, no, FoundError,
+        !IO),
 
     append_pseudo_decl(md_opt_imported, !Module),
     module_imports_get_items(!.Module, Items0),
-    list.append(Items0, OptItems, Items),
+    Items = Items0 ++ OptItems,
     module_imports_set_items(Items, !Module),
     module_imports_set_error(no_module_errors, !Module),
 
     maybe_write_string(Verbose, "% Done.\n", !IO).
 
-:- pred read_trans_opt_files(list(module_name)::in, list(item)::in,
-    list(item)::out, bool::in, bool::out, io::di, io::uo) is det.
+:- pred read_trans_opt_files(list(module_name)::in, cord(item)::in,
+    cord(item)::out, bool::in, bool::out, io::di, io::uo) is det.
 
 read_trans_opt_files([], !Items, !Error, !IO).
 read_trans_opt_files([Import | Imports], !Items, !Error, !IO) :-
@@ -229,7 +231,7 @@ read_trans_opt_files([Import | Imports], !Items, !Error, !IO) :-
 
     intermod.update_error_status(trans_opt_file, FileName, ModuleError,
         Specs, !Error, !IO),
-    list.append(!.Items, NewItems, !:Items),
+    !:Items = !.Items ++ cord.from_list(NewItems),
     read_trans_opt_files(Imports, !Items, !Error, !IO).
 
 %-----------------------------------------------------------------------------%
diff --git a/compiler/write_deps_file.m b/compiler/write_deps_file.m
index dee2a1b..904a9f0 100644
--- a/compiler/write_deps_file.m
+++ b/compiler/write_deps_file.m
@@ -75,6 +75,7 @@
     string::in, list(module_name)::out, io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
 
 :- implementation.
 
@@ -91,12 +92,15 @@
 :- import_module parse_tree.source_file_map.
 
 :- import_module assoc_list.
+:- import_module cord.
 :- import_module dir.
 :- import_module library.
 :- import_module map.
 :- import_module string.
 :- import_module pair.
 
+%-----------------------------------------------------------------------------%
+
 write_dependency_file(Module, AllDepsSet, MaybeTransOptDeps, !IO) :-
     Module = module_imports(SourceFileName, SourceFileModuleName,
         ModuleName, ParentDeps, IntDeps, ImplDeps, IndirectDeps,
@@ -513,7 +517,7 @@ write_dependency_file(Module, AllDepsSet, MaybeTransOptDeps, !IO) :-
             ForeignImports = ForeignImports0
         ;
             ContainsForeignCode = contains_foreign_code_unknown,
-            get_item_list_foreign_code(Globals, Items, LangSet,
+            get_item_list_foreign_code(Globals, cord.list(Items), LangSet,
                 ForeignImports1, _),
             % If we're generating the `.dep' file, ForeignImports0 will contain
             % a conservative approximation to the set of foreign imports
diff --git a/tests/warnings/ambiguous_overloading.exp b/tests/warnings/ambiguous_overloading.exp
index 328bca1..3bd2a56 100644
--- a/tests/warnings/ambiguous_overloading.exp
+++ b/tests/warnings/ambiguous_overloading.exp
@@ -31,8 +31,8 @@ ambiguous_overloading.m:056:   The following symbol was overloaded in the
 ambiguous_overloading.m:056:   following contexts.
 ambiguous_overloading.m:050:   The predicate symbol predicate `<'/2.
 ambiguous_overloading.m:050:   The possible matches are:
-ambiguous_overloading.m:050:     predicate `float.<'/2,
-ambiguous_overloading.m:050:     predicate `int.<'/2.
+ambiguous_overloading.m:050:     predicate `int.<'/2,
+ambiguous_overloading.m:050:     predicate `float.<'/2.
 ambiguous_overloading.m:051:   The predicate symbol predicate `<'/2 is also
 ambiguous_overloading.m:051:   overloaded here.
 ambiguous_overloading.m:052:   The predicate symbol predicate `<'/2 is also

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list