[m-rev.] for review: change behaviour of pragma foreign_import_module

Julien Fischer juliensf at csse.unimelb.edu.au
Wed Feb 28 19:03:45 AEDT 2007


For review by anyone - only the reference manual changes really require
reviewing, the code changes are all pretty trivial.

Estimated hours taken: 4
Branches: main

Fix an inconsistency between the compiler's handling of foreign_import_module
pragmas (which was itself inconsistent between backends) and what is documented
about that pragma in the reference manual.

According to the reference manual if foreign code (in either a foreign_proc or
foreign_code pragma) wants to refer to pragma foreign_exported procedures from
the same module then there needs to be a foreign_import_module in the module
for itself.

The high-level C backend ignores this entirely and modules always effectively
implicitly foreign import themselves.  The situation with the low-level C
backend varies depending on whether a module has any children or not; if it
does then it does not implicitly foreign import itself otherwise it does.

This diff changes the language to require that modules always implicitly
foreign import themselves and adds a workaround to the low-level C backend
to make sure this always happens.  (A better fix would be to modify
the frontend of the compiler to handle the implicit foreign imports
for both backends but the lack of structure in the parse tree makes this
quite awkward at the moment.)

Fix a bunch of comments that were out-of-date.

doc/reference_manual.texi:
 	Change the description of behaviour of
 	`:- pragma foreign_import_module' so that it matches what the
 	implementation actually does (well, at least what it actually
 	does most of the time.)  The new behaviour removes the requirement
 	that modules need to foreign_import themselves.  This is pretty much
 	what users (and implementors) have assumed anyway

compiler/mercury_compile.m:
 	Make sure that in LLDS grades modules always foreign import themselves
 	(this was the exception to "most of the time" above.)

 	Change an if-then-else into a switch.

tests/hard_coded/sub-modules/Makefile:
tests/hard_coded/sub-modules/sm_exp_bug.m:
tests/hard_coded/sub-modules/sm_exp_bug.child.m:
tests/hard_coded/sub-modules/sm_exp_bug.exp:
 	Test case for the above.

compiler/mlds.m:
 	Update a comment.  pragma foreign_export has been implemented
 	for other backends.

compiler/modules.m:
 	Fix the formatting of the module_imports structure.

 	Divide some of this module more visibly into sections.

compiler/process_util.m:
 	Replace a pragma_export with pragma foreign_export.

compiler/add_pragma.m:
compiler/det_analysis.m:
compiler/export.m:
compiler/hlds_module.m:
compiler/make.m:
compiler/make_hlds_passes.m:
compiler/ml_code_gen.m:
compiler/ml_elim_nested.m:
compiler/mlds_to_c.m:
compiler/prog_foreign.m:
 	s/pragma export/pragma foreign_export/

compiler/make_hlds.m:
compiler/prog_io_pragma.m:
compiler/prog_item.m:
 	Minor formatting fixes.

Julien.

Index: compiler/add_pragma.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_pragma.m,v
retrieving revision 1.61
diff -u -r1.61 add_pragma.m
--- compiler/add_pragma.m	7 Feb 2007 14:00:43 -0000	1.61
+++ compiler/add_pragma.m	28 Feb 2007 08:00:51 -0000
@@ -74,7 +74,7 @@
      % for that predicate containing an appropriate HLDS `foreign_proc' goal.
      %
      % NB. Any changes here might also require similar changes to the
-    % handling of `pragma export' declarations, in export.m.
+    % handling of `pragma foreign_export' declarations, in export.m.
      %
  :- pred module_add_pragma_import(sym_name::in, pred_or_func::in,
      list(mer_mode)::in, pragma_foreign_proc_attributes::in, string::in,
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.206
diff -u -r1.206 det_analysis.m
--- compiler/det_analysis.m	5 Feb 2007 03:12:51 -0000	1.206
+++ compiler/det_analysis.m	28 Feb 2007 08:00:51 -0000
@@ -346,7 +346,7 @@
                  PragmaContext)
          ->
              ExportPieces = [words("Error: "),
-                fixed("`:- pragma export' declaration"),
+                fixed("`:- pragma foreign_export' declaration"),
                  words("for a procedure that has a determinism of"),
                  fixed(hlds_out.determinism_to_string(NewDetism) ++ ".")],
              ExportSpec = error_spec(severity_error, phase_detism_check,
@@ -354,7 +354,7 @@
              !:Specs = [ExportSpec | !.Specs]
          ;
              unexpected(this_file,
-                "Cannot find proc in table of pragma exported procs")
+                "Cannot find proc in table of pragma foreign_exported procs")
          )
      ;
          true
Index: compiler/export.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.108
diff -u -r1.108 export.m
--- compiler/export.m	19 Jan 2007 07:04:12 -0000	1.108
+++ compiler/export.m	28 Feb 2007 08:00:51 -0000
@@ -34,15 +34,15 @@

      % From the module_info, get a list of foreign_export_decls, each of which
      % holds information about the declaration of a foreign function named in a
-    % `pragma export' declaration, which is used to allow a call to be made to
-    % a Mercury procedure from the foreign language.
+    % `pragma foreign_export' declaration, which is used to allow a call to
+    % be made to a Mercury procedure from the foreign language.
      %
  :- pred get_foreign_export_decls(module_info::in, foreign_export_decls::out)
      is det.

      % From the module_info, get a list of foreign_export_defns, each of which
      % is a string containing the foreign code for defining a foreign function
-    % named in a `pragma export' decl.
+    % named in a `pragma foreign_export' decl.
      %
  :- pred get_foreign_export_defns(module_info::in, foreign_export_defns::out)
      is det.
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_module.m,v
retrieving revision 1.149
diff -u -r1.149 hlds_module.m
--- compiler/hlds_module.m	19 Jan 2007 07:04:14 -0000	1.149
+++ compiler/hlds_module.m	28 Feb 2007 08:00:51 -0000
@@ -20,7 +20,6 @@
  % There is a separate interface section for each of these.
  %
  %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%

  :- module hlds.hlds_module.
  :- interface.
@@ -688,8 +687,8 @@

                  num_errors                  :: int,

-                % List of the procs for which there is a pragma export(...)
-                % declaration.
+                % List of the procs for which there is a
+                % pragma foreign_export(...) declaration.
                  pragma_exported_procs       :: list(pragma_exported_proc),

                  type_ctor_gen_infos         :: list(type_ctor_gen_info),
Index: compiler/make.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.m,v
retrieving revision 1.45
diff -u -r1.45 make.m
--- compiler/make.m	28 Feb 2007 05:01:57 -0000	1.45
+++ compiler/make.m	28 Feb 2007 08:00:51 -0000
@@ -185,7 +185,7 @@
      ;       module_target_xml_doc.

  :- type c_header_type
-    --->    header_mh      % For `:- pragma export' declarations.
+    --->    header_mh      % For `:- pragma foreign_export' declarations.
      ;       header_mih.    % Declarations for hlc grades, for compiler use only.

  % :- type linked_target_type in compile_target_code.m.
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.527
diff -u -r1.527 make_hlds.m
--- compiler/make_hlds.m	25 Sep 2006 18:31:23 -0000	1.527
+++ compiler/make_hlds.m	28 Feb 2007 08:00:51 -0000
@@ -43,6 +43,8 @@
  :- import_module maybe.
  :- import_module term.

+%-----------------------------------------------------------------------------%
+
  :- type make_hlds_qual_info.

      % parse_tree_to_hlds(ParseTree, MQInfo, EqvMap, UsedModules,
Index: compiler/make_hlds_passes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds_passes.m,v
retrieving revision 1.65
diff -u -r1.65 make_hlds_passes.m
--- compiler/make_hlds_passes.m	19 Jan 2007 07:04:18 -0000	1.65
+++ compiler/make_hlds_passes.m	28 Feb 2007 08:00:51 -0000
@@ -282,8 +282,8 @@
      %
      % Check that predicates listed in `:- initialise' and `:- finalise'
      % declarations exist and have the correct signature, introduce
-    % pragma export declarations for them and record their exported name in
-    % the module_info so that we can tell the code generator to call it at
+    % pragma foreign_export declarations for them and record their exported
+    % name in the module_info so that we can generate code to call it at
      % initialisation/finalisation time.
      %
  :- pred add_item_list_clauses(item_list::in, import_status::in,
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.430
diff -u -r1.430 mercury_compile.m
--- compiler/mercury_compile.m	27 Feb 2007 20:36:28 -0000	1.430
+++ compiler/mercury_compile.m	28 Feb 2007 08:00:51 -0000
@@ -16,7 +16,6 @@
  % compiler/notes/compiler_design.html.
  %
  %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%

  :- module top_level.mercury_compile.
  :- interface.
@@ -1460,10 +1459,14 @@
      grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName,
          NestedSubModules, ReadModules, MaybeTimestamp, Items, Module, Error2,
          !IO),
-    ( Error2 \= fatal_module_errors ->
+    ( 
+        ( Error2 = no_module_errors
+        ; Error2 = some_module_errors
+        ),
          mercury_compile(Module, NestedSubModules, FindTimestampFiles,
              FactTableObjFiles, no_prev_dump, _, !IO)
      ;
+        Error2 = fatal_module_errors,
          FactTableObjFiles = []
      ).

@@ -4443,7 +4446,7 @@
      % This stuff mostly just gets passed directly to the LLDS unchanged, but
      % we do do a bit of code generation -- for example, we call
      % export.get_foreign_export_{decls,defns} here, which do the generation
-    % of C code for `pragma export' declarations.
+    % of C code for `pragma foreign_export' declarations.
      %
  :- pred get_c_interface_info(module_info::in, foreign_language::in,
      foreign_interface_info::out) is det.
@@ -4451,7 +4454,20 @@
  get_c_interface_info(HLDS, UseForeignLanguage, Foreign_InterfaceInfo) :-
      module_info_get_name(HLDS, ModuleName),
      module_info_get_foreign_decl(HLDS, ForeignDecls),
-    module_info_get_foreign_import_module(HLDS, ForeignImports),
+    module_info_get_foreign_import_module(HLDS, ForeignImports0),
+    %
+    % Always include the module we are compiling amongst the foreign import
+    % modules so that pragma foreign_exported procedures are visible to
+    % foreign code in this module.
+    %
+    % XXX The frontend should really handle this but it is quite
+    % inconsistent in its treatement of self-imports.  Both this backend
+    % (the LLDS) and the MLDS backend currently handle self foreign imports
+    % directly.
+    %
+    ForeignSelfImport = foreign_import_module_info(UseForeignLanguage, 
+        ModuleName, term.context_init),
+    ForeignImports = [ ForeignSelfImport | ForeignImports0 ],
      module_info_get_foreign_body_code(HLDS, ForeignBodyCode),
      foreign.filter_decls(UseForeignLanguage, ForeignDecls,
          WantedForeignDecls, _OtherDecls),
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.197
diff -u -r1.197 ml_code_gen.m
--- compiler/ml_code_gen.m	22 Feb 2007 03:50:35 -0000	1.197
+++ compiler/ml_code_gen.m	28 Feb 2007 08:00:51 -0000
@@ -914,8 +914,8 @@

  %-----------------------------------------------------------------------------%
  %
-% For each pragma export declaration we associate with it the information
-% used to generate the function prototype for the MLDS entity.
+% For each pragma foreign_export declaration we associate with it the
+% information used to generate the function prototype for the MLDS entity.

  :- pred ml_gen_pragma_export_proc(module_info::in, pragma_exported_proc::in,
      mlds_pragma_export::out) is det.
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.89
diff -u -r1.89 ml_elim_nested.m
--- compiler/ml_elim_nested.m	19 Jan 2007 07:04:20 -0000	1.89
+++ compiler/ml_elim_nested.m	28 Feb 2007 08:00:51 -0000
@@ -202,7 +202,7 @@
  %   all parameters and locals that point to the heap on the GC's shadow stack),
  %   and MR_deep_copy() needs to call MR_GC_check() before each heap allocation.
  %
-% - XXX We need to handle `pragma export'.
+% - XXX We need to handle `pragma foreign_export'.
  %
  %  The C interface in general is a bit problematic for GC. But for code which
  %   does not call back to Mercury, the way we currently handle it is fairly
@@ -216,14 +216,14 @@
  %   and the loop contains no intervening calls to Mercury code that allocates
  %   heap space (and hence calls MR_GC_check()).
  %
-%   But if Mercury code calls C code which calls back to Mercury code,
-%   and the C code uses pointers to the Mercury heap, then there could be
-%   serious problems (i.e. dangling pointers). Even if you just use
-%   `pragma export' to export a procedure and `pragma import' to import it back
-%   again, there may be trouble. The code generated for the exported functions
-%   can include calls to MR_MAYBE_BOX_FOREIGN_TYPE, which may allocate heap;
-%   we ought to register the frame and call MR_GC_check() before each call
-%   to MR_MAYBE_BOX_FOREIGN_TYPE, but currently we don't.
+%   But if Mercury code calls C code which calls back to Mercury code, and
+%   the C code uses pointers to the Mercury heap, then there could be
+%   serious problems (i.e. dangling pointers). Even if you just use `pragma
+%   foreign_export' to export a procedure and `pragma import' to import it
+%   back again, there may be trouble. The code generated for the exported
+%   functions can include calls to MR_MAYBE_BOX_FOREIGN_TYPE, which may
+%   allocate heap; we ought to register the frame and call MR_GC_check()
+%   before each call to MR_MAYBE_BOX_FOREIGN_TYPE, but currently we don't.
  %
  %   Even if that was solved, there is still the issue of what to do about
  %   any heap pointers held by user-written C code; we need to provide an API
Index: compiler/mlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds.m,v
retrieving revision 1.146
diff -u -r1.146 mlds.m
--- compiler/mlds.m	8 Jan 2007 03:03:13 -0000	1.146
+++ compiler/mlds.m	28 Feb 2007 08:00:51 -0000
@@ -378,8 +378,8 @@
                  defns               :: mlds_defns,

                  % The names of init and final preds.
-                % XXX These only work for the C backend, because
-                % pragma export doesn't work for the other backends.
+                % XXX These only work for the C backend because initialisers
+                % and finalisers do not (yet) work for the other backends.
                  init_preds          :: list(string),
                  final_preds         :: list(string)
              ).
@@ -389,7 +389,7 @@
  :- type mlds_imports == list(mlds_import).

      % For the C backend, we generate a `.mh' file containing the
-    % prototypes for C functions generated for `:- pragma export'
+    % prototypes for C functions generated for `:- pragma foreign_export'
      % declarations, and a `.mih' file containing the prototypes
      % for the C functions generated by the compiler which should
      % not be visible to the user.
@@ -542,7 +542,7 @@
                  ef_pred_id          :: pred_id
              )
      ;       entity_export(
-                % A pragma export name.
+                % A pragma foreign_export name.
                  string
              ).

Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.211
diff -u -r1.211 mlds_to_c.m
--- compiler/mlds_to_c.m	29 Jan 2007 04:52:38 -0000	1.211
+++ compiler/mlds_to_c.m	28 Feb 2007 08:00:51 -0000
@@ -893,7 +893,7 @@
      expect(unify(Lang, lang_c), this_file, "export to language other than C."),
      Name = qual(ModuleName, module_qual, entity_export(ExportName)),
      mlds_indent(Context, Indent, !IO),
-    % For functions exported using `pragma export',
+    % For functions exported using `pragma foreign_export',
      % we use the default C calling convention.
      CallingConvention = "",
      mlds_output_func_decl_ho(Indent, Name, Context,
@@ -970,7 +970,7 @@
  mlds_output_pragma_export_type(prefix, mlds_unknown_type, !IO) :-
      unexpected(this_file, "mlds_output_pragma_export_type: unknown_type").

-    % Output the definition body for a pragma export.
+    % Output the definition body for a pragma foreign_export.
      %
  :- pred mlds_output_pragma_export_defn_body(mlds_module_name::in,
      mlds_qualified_entity_name::in, mlds_func_params::in, io::di, io::uo)
@@ -1888,7 +1888,7 @@
              Name = entity_data(mlds_rtti(RttiId)),
              module_qualify_name_of_rtti_id(RttiId) = no
          ;
-            % We don't module qualify pragma export names.
+            % We don't module qualify pragma foreign_export names.
              Name = entity_export(_)
          )
      ->
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.420
diff -u -r1.420 modules.m
--- compiler/modules.m	19 Jan 2007 07:04:24 -0000	1.420
+++ compiler/modules.m	28 Feb 2007 08:00:51 -0000
@@ -237,90 +237,94 @@
      io::di, io::uo) is det.

  %-----------------------------------------------------------------------------%
+%
+% The `module_imports' structure
+%

      % The `module_imports' structure holds information about
      % a module and the modules that it imports.
-
+    %
      % Note that we build this structure up as we go along.
-    % When generating the dependencies (for `--generate-dependencies'),
-    % the two fields that hold the direct imports do not include
-    % the imports via ancestors when the module is first read in;
-    % the ancestor imports are added later, once all the modules
-    % have been read in.  Similarly the indirect imports field is
-    % initially set to the empty list and filled in later.
+    % When generating the dependencies (for `--generate-dependencies'), the
+    % two fields that hold the direct imports do not include the imports via
+    % ancestors when the module is first read in; the ancestor imports are
+    % added later, once all the modules have been read in.  Similarly the
+    % indirect imports field is initially set to the empty list and filled
+    % in later.
      %
-    % When compiling or when making interface files, the same
-    % sort of thing applies: initially all the list(module_name) fields
-    % except the public children field are set to empty lists,
-    % and then we add ancestor modules and imported modules
-    % to their respective lists as we process the interface files
-    % for those imported or ancestor modules.
-
-:- type module_imports --->
-        module_imports(
-            % The source file.
-            source_file_name            :: file_name,
+    % When compiling or when making interface files, the same sort of thing
+    % applies: initially all the list(module_name) fields except the public
+    % children field are set to empty lists, and then we add ancestor
+    % modules and imported modules to their respective lists as we process
+    % the interface files for those imported or ancestor modules.
+    %
+:- type module_imports
+    --->    module_imports(
+                % The source file.
+                source_file_name            :: file_name,

-            % The name of the top-level module in the source file
-            % containing the module that we are compiling.
-            source_file_module_name     :: module_name,
+                % The name of the top-level module in the source file
+                % containing the module that we are compiling.
+                source_file_module_name     :: module_name,

-            % The module (or sub-module) that we are compiling.
-            module_name                 :: module_name,
+                % The module (or sub-module) that we are compiling.
+                module_name                 :: module_name,

-            % The list of ancestor modules it inherits.
-            parent_deps                 :: list(module_name),
+                % The list of ancestor modules it inherits.
+                parent_deps                 :: list(module_name),

-            % The list of modules it directly imports in the interface
-            % (imports via ancestors count as direct).
-            int_deps                    :: list(module_name),
+                % The list of modules it directly imports in the interface
+                % (imports via ancestors count as direct).
+                int_deps                    :: list(module_name),

-            % The list of modules it directly imports in the implementation.
-            impl_deps                   :: list(module_name),
+                % The list of modules it directly imports in the
+                % implementation.
+                impl_deps                   :: list(module_name),

-            % The list of modules it indirectly imports.
-            indirect_deps               :: list(module_name),
+                % The list of modules it indirectly imports.
+                indirect_deps               :: list(module_name),

-            children                    :: list(module_name),
+                children                    :: list(module_name),

-            % The list of its public children, i.e. child modules that
-            % it includes in the interface section.
-            public_children             :: list(module_name),
+                % The list of its public children, i.e. child modules that
+                % it includes in the interface section.
+                public_children             :: list(module_name),

-            % The modules included in the same source file. This field
-            % is only set for the top-level module in each file.
-            nested_children             :: list(module_name),
+                % The modules included in the same source file. This field
+                % is only set for the top-level module in each file.
+                nested_children             :: list(module_name),

-            % The list of filenames for fact tables in this module.
-            fact_table_deps             :: list(string),
+                % The list of filenames for fact tables in this module.
+                fact_table_deps             :: list(string),

-            % Whether or not the module contains foreign code, and if yes,
-            % which languages they use.
-            has_foreign_code            :: contains_foreign_code,
+                % Whether or not the module contains foreign code, and if yes,
+                % which languages they use.
+                has_foreign_code            :: contains_foreign_code,

-            % The `:- pragma foreign_import_module' declarations.
-            foreign_import_modules      :: foreign_import_module_info_list,
+                % The `:- pragma foreign_import_module' declarations.
+                foreign_import_modules      :: foreign_import_module_info_list,

-            % Does the module contain any `:- pragma export' declarations?
-            contains_foreign_export     :: contains_foreign_export,
+                % Does the module contain any `:- pragma foreign_export'
+                % declarations?
+                contains_foreign_export     :: contains_foreign_export,

-            % The contents of the module and its imports.
-            items                       :: item_list,
+                % The contents of the module and its imports.
+                items                       :: item_list,

-            % Whether an error has been encountered when reading in
-            % this module.
-            error                       :: module_error,
+                % Whether an error has been encountered when reading in
+                % this module.
+                error                       :: module_error,

-            % If we are doing smart recompilation, we need to keep
-            % the timestamps of the modules read in.
-            maybe_timestamps            :: maybe(module_timestamps),
+                % If we are doing smart recompilation, we need to keep
+                % the timestamps of the modules read in.
+                maybe_timestamps            :: maybe(module_timestamps),

-            % Does this module contain main/2?
-            has_main                    :: has_main,
+                % Does this module contain main/2?
+                has_main                    :: has_main,

-            % The directory containing the module source.
-            module_dir                  :: dir_name
-        ).
+                % The directory containing the module source.
+                module_dir                  :: dir_name
+            ).

  :- type contains_foreign_code
      --->    contains_foreign_code(set(foreign_language))
@@ -335,9 +339,9 @@
      --->    has_main
      ;       no_main.

-    % When doing smart recompilation record for each module
-    % the suffix of the file that was read and the modification
-    % time of the file.
+    % When doing smart recompilation record for each module the suffix of
+    % the file that was read and the modification time of the file.
+    %
  :- type module_timestamps == map(module_name, module_timestamp).
  :- type module_timestamp
      --->    module_timestamp(
@@ -346,9 +350,9 @@
                  need_qualifier  :: need_qualifier
              ).

-    % recompilation_check.m records each file read to avoid
-    % reading it again. The string is the suffix of the file
-    % name.
+    % recompilation_check.m records each file read to avoid reading it
+    % again. The string is the suffix of the file name.
+    %
  :- type read_modules == map(pair(module_name, string), read_module).

  :- type read_module
@@ -368,7 +372,10 @@
      bool::in, item_list::out, maybe(timestamp)::out, module_error::out,
      file_name::out) is semidet.

-    % Some access predicates for the module_imports structure.
+%-----------------------------------------------------------------------------%
+%
+% Access predicates for the module_imports structure
+%

  :- pred module_imports_get_source_file_name(module_imports::in, file_name::out)
      is det.
@@ -399,6 +406,8 @@
  :- pred module_imports_set_indirect_deps(list(module_name)::in,
      module_imports::in, module_imports::out) is det.

+%-----------------------------------------------------------------------------%
+
      % Make an item_and_context for a module declaration or pseudo-declaration
      % such as `:- imported' (which is inserted by the compiler, but can't be
      % used in user code).
@@ -6265,7 +6274,7 @@
          ContainsForeignCode = contains_foreign_code(LangSet)
      ),

-    % If this module contains `:- pragma export' or
+    % If this module contains `:- pragma foreign_export' or
      % `:- pragma foreign_type' declarations, importing modules
      % may need to import its `.mh' file.
      get_foreign_self_imports(ItemAndContexts, SelfImportLangs),
Index: compiler/process_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/process_util.m,v
retrieving revision 1.23
diff -u -r1.23 process_util.m
--- compiler/process_util.m	1 Dec 2006 15:04:15 -0000	1.23
+++ compiler/process_util.m	28 Feb 2007 08:00:51 -0000
@@ -406,7 +406,8 @@
  :- pred call_child_process_io_pred(io_pred::in(io_pred), int::out,
      io::di, io::uo) is det.

-:- pragma export(call_child_process_io_pred(in(io_pred), out, di, uo),
+:- pragma foreign_export("C",
+    call_child_process_io_pred(in(io_pred), out, di, uo),
      "MC_call_child_process_io_pred").

  call_child_process_io_pred(P, Status, !IO) :-
Index: compiler/prog_foreign.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_foreign.m,v
retrieving revision 1.11
diff -u -r1.11 prog_foreign.m
--- compiler/prog_foreign.m	8 Jan 2007 03:03:15 -0000	1.11
+++ compiler/prog_foreign.m	28 Feb 2007 08:00:51 -0000
@@ -89,7 +89,7 @@
                  term.context        % source code location
              ).

-    % The code for `pragma export' is generated directly as strings
+    % The code for `pragma foreign_export' is generated directly as strings
      % by export.m.
      %
  :- type foreign_export  ==  string.
Index: compiler/prog_io_pragma.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.122
diff -u -r1.122 prog_io_pragma.m
--- compiler/prog_io_pragma.m	19 Jan 2007 07:04:27 -0000	1.122
+++ compiler/prog_io_pragma.m	28 Feb 2007 08:00:51 -0000
@@ -12,7 +12,6 @@
  % This module handles the parsing of pragma directives.
  %
  %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%

  :- module parse_tree.prog_io_pragma.
  :- interface.
Index: compiler/prog_item.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_item.m,v
retrieving revision 1.25
diff -u -r1.25 prog_item.m
--- compiler/prog_item.m	12 Jan 2007 05:00:29 -0000	1.25
+++ compiler/prog_item.m	28 Feb 2007 08:00:51 -0000
@@ -19,7 +19,6 @@
  % are needed by the backends are contained in prog_data.m.
  %
  %-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%

  :- module parse_tree.prog_item.
  :- interface.
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.385
diff -u -r1.385 reference_manual.texi
--- doc/reference_manual.texi	22 Feb 2007 06:08:20 -0000	1.385
+++ doc/reference_manual.texi	28 Feb 2007 08:00:51 -0000
@@ -6892,10 +6892,14 @@
  Note: currently only the C backends support this variant
  of the @samp{pragma foreign_decl} declaration.

-To make the declarations for Mercury predicates or functions
-exported to a foreign language using a @samp{pragma export}
-declaration visible to foreign code in a @samp{pragma foreign_code}
-or @samp{pragma foreign_proc} declaration, use a declaration of the form
+The declarations for Mercury predicates or functions exported to a 
+foreign language using a @samp{pragma foreign_export} declaration
+are visible to foreign code in a @samp{pragma foreign_code} or
+ at samp{pragma foreign_proc} declaration of the same module and also in those
+of any sub-modules.
+They are not visible to the foreign code in @samp{pragma foreign_code} or
+ at samp{pragma foreign_proc} declarations in any other module.
+They can be made visible using a declaration of the form:

  @example
  :- pragma foreign_import_module("@var{Lang}", @var{ImportedModule}).
@@ -6903,7 +6907,7 @@

  @noindent
  where @var{ImportedModule} is the name of the module containing
-the @samp{pragma export} declarations.
+the @samp{pragma foreign_export} declarations.

  If @var{Lang} is @code{"C"} this is equivalent to

Index: tests/hard_coded/sub-modules/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/sub-modules/Mmakefile,v
retrieving revision 1.14
diff -u -r1.14 Mmakefile
--- tests/hard_coded/sub-modules/Mmakefile	24 Feb 2006 01:42:15 -0000	1.14
+++ tests/hard_coded/sub-modules/Mmakefile	28 Feb 2007 08:00:51 -0000
@@ -29,6 +29,7 @@
  	non_word_mutable \
  	parent \
  	parent2 \
+	sm_exp_bug \
  	ts \
  	use_submodule

Index: tests/hard_coded/sub-modules/sm_exp_bug.child.m
===================================================================
RCS file: tests/hard_coded/sub-modules/sm_exp_bug.child.m
diff -N tests/hard_coded/sub-modules/sm_exp_bug.child.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/sm_exp_bug.child.m	28 Feb 2007 08:00:51 -0000
@@ -0,0 +1,4 @@
+:- module sm_exp_bug.child.
+:- interface.
+
+:- type foo ---> foo.
Index: tests/hard_coded/sub-modules/sm_exp_bug.exp
===================================================================
RCS file: tests/hard_coded/sub-modules/sm_exp_bug.exp
diff -N tests/hard_coded/sub-modules/sm_exp_bug.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/sm_exp_bug.exp	28 Feb 2007 08:00:51 -0000
@@ -0,0 +1 @@
+Hello World!
Index: tests/hard_coded/sub-modules/sm_exp_bug.m
===================================================================
RCS file: tests/hard_coded/sub-modules/sm_exp_bug.m
diff -N tests/hard_coded/sub-modules/sm_exp_bug.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/sub-modules/sm_exp_bug.m	28 Feb 2007 08:00:51 -0000
@@ -0,0 +1,35 @@
+% Modules compiled by rotd-2007-02-27 and before sometimes did not
+% implicitly foreign_import themselves.  This meant that procedures
+% exported via a pragma foreign_export were not visible to foreign
+% code in the same module.  (This only showed up with the LLDS backend
+% since the MLDS->C code generator always inserted the necessary foreign
+% import regardless of whether it was present in the HLDS or not.)
+:- module sm_exp_bug.
+:- interface.
+
+:- include_module sm_exp_bug.child.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+main(!IO) :-
+	call_foreign(!IO).
+
+:- pred call_foreign(io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+	call_foreign(IO0::di, IO::uo),
+	[may_call_mercury, promise_pure],
+"
+	WRITE_HELLO();
+	IO = IO0;
+").
+
+:- pragma foreign_export("C", write_hello(di, uo), "WRITE_HELLO").
+:- pred write_hello(io::di, io::uo) is det.
+write_hello(!IO) :-
+	io.write_string("Hello World!\n", !IO).
+

--------------------------------------------------------------------------
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