[m-rev.] for review: update docs for foreign language interface

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Oct 30 03:50:30 AEDT 2002


I've probably screwed something up here, so I'd really appreciate it if
people -- especially Tyson and Peter Ross, but the more, the merrier --
could review this.

Branches: main
Estimated hours taken: 5

Clean up the documentation for the foreign language interface.

doc/reference_manual.texi:
	Document the C# and MC++ interfaces.
	Update the documentation for the foreign language interface
	chapter to remove much of the stuff about it not being supported,
	and to instead say that this interface is now the preferred one
	to use for new code.
	Also, fix a few Texinfo formatting errors.

Workspace: /mnt/ceres/home/ceres/fjh/mercury
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.259
diff -u -d -r1.259 reference_manual.texi
--- doc/reference_manual.texi	1 Oct 2002 08:13:26 -0000	1.259
+++ doc/reference_manual.texi	29 Oct 2002 16:20:06 -0000
@@ -1763,7 +1763,7 @@
 @end example
 
 A predicate or function can by declared to have a given higher-order
-type (@pxref{Higher-order}) by using `with_type` in the type declaration.
+type (@pxref{Higher-order}) by using @code{`with_type`} in the type declaration.
 This is useful where several predicates or functions need to have the
 same type signature, which often occurs for typeclass method implementations
 (@pxref{Type classes}), and for predicates to be passed as higher-order terms.
@@ -2257,7 +2257,7 @@
 
 As for type declarations, a predicate or function can be defined
 to have a given higher-order inst (@pxref{Higher-order modes} by using
-`with_inst` in the mode declaration.
+ at code{`with_inst`} in the mode declaration.
 
 For example,
 
@@ -4696,7 +4696,7 @@
 type, put it in a polymorphic data structure, or pass it to a
 polymorphic procedure whose argument type is universally quantified.
 (Note, however, that the standard library includes some quite powerful
-procedures such as `io__write' which can be useful in this context.)
+procedures such as @samp{io__write} which can be useful in this context.)
 
 A non-variable type (i.e.@: a type that is not a type variable)
 is considered @emph{more general} than an
@@ -5202,13 +5202,20 @@
 @end menu
 
 This chapter documents the new foreign language interface.
-This interface is not yet complete, and is not fully supported.
-It is documented here as an aid to the Mercury language developers.
-See the @pxref{C interface} chapter for the existing, supported C
-interface for Mercury.
+This is intended as a successor to the existing C interface for Mercury,
+which is documented in @xref{C interface}.
+However, the new foreign language interface is not yet complete
+(it does not yet include equivalents to
+ at samp{pragma import} and @samp{pragma export} in the C interface)
+and is not as well tested as the existing C interface.
+Furthermore, it is possible that incompatible changes will be needed in
+future versions of this interface.
 
-The syntax, documentation, behaviour and semantics of the constructs
-described in this chapter are subject to change without notice.
+In view of this, we currently support both the old C interface
+and the new foreign language interface.  We advise people writing new
+code to use the new foreign language interface, but existing code
+that uses the old C interface can continue to do so, and we do not
+recommended rewriting such code at this point in time.
 
 @node Calling foreign code from Mercury
 @section Calling foreign code from Mercury
@@ -5380,28 +5387,31 @@
 @node Data passing conventions
 @section Data passing conventions
 
-For each language,
+For each supported foreign language,
 we explain how to map a Mercury type to a type in that foreign language.
 We also map the Mercury parameter passing convention
-to the language parameter passing convention.
+to the foreign language's parameter passing convention.
 
 @menu
-* C language	:: Data passing convention for the C language.
-* IL language	:: Data passing convention for the IL language.
+* C data passing conventions ::
+* IL and C# data passing conventions ::
 @end menu
 
- at node C language
- at subsection C language
+ at node C data passing conventions
+ at subsection C data passing conventions
 
 This section is currently documented in @pxref{Passing data to and from C}.
 
- at node IL language
- at subsection IL language
+ at node IL and C# data passing conventions
+ at subsection IL and C# data passing conventions
 
 The Mercury types @code{int}, @code{float}, @code{char},
 and @code{string} are mapped to the Common Language Runtime types 
 @code{System.Int32}, @code{System.Double}, @code{System.Char} and
- at code{System.String} respectively.
+ at code{System.String} respectively, which correspond to the C# types
+ at code{int}, @code{double}, @code{char}, and @code{string},
+and to the IL assembler types
+ at samp{int}, @samp{float64}, @samp{char} and @samp{string}.
 
 Mercury variables whose type is a type variable will be passed as
 @code{System.Object}.
@@ -5415,9 +5425,9 @@
 an underscore and then the type arity,
 expressed as a decimal integer.
 Mercury module qualifiers are converted to CLR namespace qualifiers.
-For example the Mercury type `foo__bar__baz/1' will be passed as the CLR
-type `foo.bar.baz_1'.
-Note an extra namespace qualifier, `mercury', will be prepended to the
+For example the Mercury type @samp{foo__bar__baz/1} will be passed as the CLR
+type @samp{foo.bar.baz_1}.
+Note an extra namespace qualifier, @samp{mercury}, will be prepended to the
 beginning of names residing in the Mercury standard library.
 Mercury variables whose type is a Mercury equivalence type
 will be passed as the representation of the right hand side of the
@@ -5428,13 +5438,15 @@
 terms.
 
 Mercury arguments declared with input modes are passed by value to the
-IL function.
+IL or C# function.
 For output arguments,
-the Mercury implementation will pass to the IL function a reference to
-the location in which to store the result. 
+the Mercury implementation will pass to the IL or C# function a reference to
+the location in which to store the result; for example, a Mercury output
+argument of type @samp{int} would map to a C# function parameter with type
+ at samp{ref int}.
 If the Mercury procedure can fail,
-then its IL function should return a truth value of type
- at samp{System.Bool} indicating success or failure:
+then its IL or C# function should return a truth value of type
+ at samp{bool} (i.e.@: @samp{System.Bool}) indicating success or failure:
 @code{true} indicates success, and @code{false} indicates failure.
 If the Mercury procedure is a Mercury function that cannot fail,
 and the function result has an output mode,
@@ -5532,17 +5544,17 @@
 If @var{Lang} is @code{"C"} this is equivalent to
 
 @example
-:- pragma foreign_decl("C", "#include ""@var{ImportedModule.h}""").
+:- pragma foreign_decl("C", "#include ""@var{ImportedModule}.mh""").
 @end example
 
 @noindent
-where @file{@var{ImportedModule}.h} is the automatically generated
+where @file{@var{ImportedModule}.mh} is the automatically generated
 header file containing the C declarations for the predicates
 and functions exported to C.
 
 @samp{pragma foreign_import_module} should be used instead of the
 explicit @code{#include} because @samp{pragma foreign_import_module}
-tells the implementation that @file{@var{ImportedModule}.h} must be built
+tells the implementation that @file{@var{ImportedModule}.mh} must be built
 before the object file for the module containing the
 @samp{pragma foreign_import_module} declaration.
 
@@ -5600,9 +5612,13 @@
 
 @item @samp{IL}
 Use the string @code{"IL"} to set the foreign language to IL.
+IL (sometimes also known as CIL or MSIL) is the Intermediate Language
+for the .NET Common Language Runtime.
 
 @item @samp{Managed C++}
 Use the string @code{"MC++"} to set the foreign language to Managed C++.
+Managed C++ is C++ with Microsoft's extensions to support interfacing
+with and generating code for the .NET Common Language Runtime.
 
 @end table
 
@@ -5623,7 +5639,7 @@
 
 The input and output variables will have C types corresponding
 to their Mercury types, as determined by the rules specified in
- at ref{C language}.
+ at ref{C data passing conventions}.
 
 The C code fragment may declare local variables, but it should not
 declare any labels or static variables unless there is also a Mercury
@@ -5645,8 +5661,9 @@
 :- pred string__contains_char(string, character).
 :- mode string__contains_char(in, in) is semidet.
 
-:- pragma foreign_proc("C", string__contains_char(Str::in, Ch::in),
-        [will_not_call_mercury],
+:- pragma foreign_proc("C",
+	string__contains_char(Str::in, Ch::in),
+        [will_not_call_mercury, promise_pure],
         "SUCCESS_INDICATOR = (strchr(Str, Ch) != NULL);").
 @end example
 
@@ -5781,9 +5798,6 @@
 @node Interfacing with C#
 @subsection Interfacing with C#
 
- at c XXX
-Currently undocumented, sorry.
-
 @menu
 * Using pragma foreign_type for C#	:: Declaring C# types in Mercury
 * Using pragma foreign_proc for C# 	:: Calling C# code from Mercury
@@ -5794,8 +5808,8 @@
 @node Using pragma foreign_type for C#
 @subsubsection Using pragma foreign_type for C#
 
-There is no direct support for using C# types from Mercury; however, the
-types for IL are compatible with C#, and so the foreign_type
+There is currently no direct support for using C# types from Mercury;
+however, the types for IL are compatible with C#, and so the foreign_type
 support for IL can be used instead.
 See the section on using pragma foreign_type for IL
 (@pxref{Using pragma foreign_type for IL}).
@@ -5803,21 +5817,94 @@
 @node Using pragma foreign_proc for C#
 @subsubsection Using pragma foreign_proc for C#
 
-Not currently supported for C#.
- at c XXX
+The C# code from C# pragma foreign_proc declarations will be placed in
+the bodies of static member functions of an automatically-generated C# class.
+Since such C# code will become part of a static member function,
+it must not refer to the @samp{this} keyword.
+It may however refer to static member variables or static member
+functions declared with @samp{pragma foreign_code}.
+
+The input and output variables for a C# @samp{pragma foreign_proc} will
+have C# types corresponding to their Mercury types.  The exact rules
+for mapping Mercury types to C# types are described in
+ at xref{IL and C# data passing conventions}.
+
+C# code in a @code{pragma foreign_proc} declaration
+for any procedure whose determinism indicates that it could fail
+must assign a value of type bool to the variable @samp{succeeded}.
+For example:
+
+ at example
+:- pred string__contains_char(string, character).
+:- mode string__contains_char(in, in) is semidet.
+
+:- pragma foreign_proc("C#",
+	string__contains_char(Str::in, Ch::in),
+        [will_not_call_mercury, promise_pure],
+        "succeeded = (Str.IndexOf(Ch) != -1);").
+ at end example
+
+ at noindent
+C# code for procedures whose determinism indicates that that they cannot fail
+should not access @code{succeeded}.
+
+Arguments whose mode is input will have their values set by the
+Mercury implementation on entry to the C# code.  If the procedure
+succeeds, the C# code must set the values of all output arguments
+before returning.  If the procedure fails, the C# code need only
+set @code{succeeded} to false.
 
 @node Using pragma foreign_decl for C#
 @subsubsection Using pragma foreign_decl for C#
 
-Not currently supported for C#.
- at c XXX
+ at samp{pragma foreign_decl} declarations for C# can be used to provide
+any top-level C# declarations (e.g. @samp{using} declarations
+or auxiliary class definitions) which are needed by C# code in
+ at samp{pragma foreign_proc} declarations in that module.
+
+For example:
+
+ at example
+:- pragma foreign_decl("C#", "
+	using System;
+").
+:- pred hello(io__state::di, io__state::uo) is det.
+:- pragma foreign_decl("C#",
+	hello(_IO0::di, _IO::uo),
+	[will_not_call_mercury],
+"
+	// here we can refer directly to Console rather than System.Console
+	Console.WriteLine(""hello world"").
+").
+ at end example
 
 @node Using pragma foreign_code for C#
 @subsubsection Using pragma foreign_code for C#
 
-Not currently supported for C#.
- at c XXX
+The C# code from @samp{pragma foreign_proc} declarations for C# will be
+placed in the bodies of static member functions of an
+automatically-generated C# class.  @samp{pragma foreign_code}
+can be used to define additional members of this automatically-generated
+class, which can then be referenced by @samp{pragma foreign_proc}
+declarations for C# from that module.
 
+For example:
+
+ at example
+:- pragma foreign_code("C#", "
+	static int counter = 0;
+").
+
+:- impure pred incr_counter is det.
+:- pragma foreign_proc("C#", incr_counter,
+	[will_not_call_mercury], "counter++;").
+
+:- semipure func get_counter = int.
+:- pragma foreign_proc("C#",
+	get_counter = (Result::out),
+	[will_not_call_mercury, promise_semipure],
+	"Result = counter;").
+ at end example
 
 @c ----------------------------------------------------------------------------
 
@@ -5849,7 +5936,7 @@
 will use @var{DotNetForeignType} as the .NET CLR parameter type for
 parameters whose Mercury type is @var{MercuryTypeName}.
 
-The CIL assembler syntax is used to specify type names for all the .NET CLR
+The IL assembler syntax is used to specify type names for all the .NET CLR
 languages (IL, C# and Managed C++) supported by Mercury's
 @samp{foreign_proc} mechanism.  
 This syntax is documented in the ECMA specifications for .NET.
@@ -5886,7 +5973,7 @@
 :- pred loadxml(string::in, xmldoc::di, xmldoc::uo) is det.
 
 :- pragma foreign_proc("C#", load(String::in, XML0::di, XML::uo),
-        [will_not_call_mercury],
+        [will_not_call_mercury, promise_pure],
 "
     XML0.LoadXml(String);
     XML = XML0;
@@ -5941,23 +6028,18 @@
 @c set @code{success} to false (zero).
 
 Each of the head variables will be represented by the Common Language
-Runtime types as specified in @pxref{IL language}.
-Note that in IL assembler the types
- at samp{System.Int32}, @samp{System.Double}, @samp{System.Char}
-and @samp{System.String}
-are represented by 
- at samp{int}, @samp{float64}, @samp{char} and @samp{string}.
+Runtime types as specified in @pxref{IL and C# data passing conventions}.
 
 @node Using pragma foreign_decl for IL
 @subsubsection Using pragma foreign_decl for IL
 
-Not currently supported for IL.
+ at samp{pragma foreign_decl} is currently not supported for IL.
 @c XXX
 
 @node Using pragma foreign_code for IL
 @subsubsection Using pragma foreign_code for IL
 
-Not currently supported for IL.
+ at samp{pragma foreign_code} is currently not supported for IL.
 @c XXX
 
 @c ----------------------------------------------------------------------------
@@ -5965,9 +6047,6 @@
 @node Interfacing with Managed C++
 @subsection Interfacing with Managed C++
 
- at c XXX
-Currently undocumented, sorry.
-
 @menu
 * Using pragma foreign_type for MC++::  Declaring MC++ types in Mercury
 * Using pragma foreign_proc for MC++::  Calling MC++ code from Mercury
@@ -5987,20 +6066,87 @@
 @node Using pragma foreign_proc for MC++
 @subsubsection Using pragma foreign_proc for MC++
 
-Currently undocumented, sorry.
- at c XXX
+The MC++ code from MC++ pragma foreign_proc declarations will be copied into
+static member functions of an automatically-generated MC++ class.
+Since such MC++ code will become part of a static member function,
+it must not refer to the @samp{this} keyword.
+It may however refer to static member variables or static member
+functions declared with @samp{pragma foreign_code}.
+
+The input and output variables for an MC++ @samp{pragma foreign_proc} will
+have MC++ types corresponding to their Mercury types.  The exact rules
+for mapping Mercury types to MC++ types are determined by the rules
+for mapping Mercury types to IL (@pxref{IL and C# data passing conventions})
+and the rules relating IL types to MC++ types.
+
+MC++ code in a @code{pragma foreign_proc} declaration
+for any procedure whose determinism indicates that it could fail
+must assign a value of type bool to the variable @samp{succeeded}.
+For example:
+
+ at example
+:- pred string__contains_char(string, character).
+:- mode string__contains_char(in, in) is semidet.
+
+:- pragma foreign_proc("MC++", string__contains_char(Str::in, Ch::in),
+        [will_not_call_mercury, promise_pure],
+        "succeeded = (Str->IndexOf(Ch) != -1);").
+ at end example
+
+ at noindent
+MC++ code for procedures whose determinism indicates that that they cannot fail
+should not access @code{succeeded}.
+
+Arguments whose mode is input will have their values set by the
+Mercury implementation on entry to the MC++ code.  If the procedure
+succeeds, the MC++ code must set the values of all output arguments
+before returning.  If the procedure fails, the MC++ code need only
+set @code{succeeded} to false.
 
 @node Using pragma foreign_decl for MC++
 @subsubsection Using pragma foreign_decl for MC++
 
-Currently undocumented, sorry.
- at c XXX
+ at samp{pragma foreign_decl} declarations for MC++ can be used to provide
+any top-level MC++ declarations (e.g. @samp{#include} or @samp{#using})
+which are needed by code in @code{pragma foreign_proc} declarations for MC++.
+
+For example:
+
+ at example
+:- pragma foreign_decl("MC++", "
+	#include <stdio.h>
+	#using <mscorlib.dll>
+
+	#define MY_CONSTANT 42
+	// ...
+").
+ at end example
 
 @node Using pragma foreign_code for MC++
 @subsubsection Using pragma foreign_code for MC++
 
-Currently undocumented, sorry.
- at c XXX
+The MC++ code from @samp{pragma foreign_proc} declarations for MC++ will be
+placed in the bodies of static member functions of an
+automatically-generated C# class.  @samp{pragma foreign_code}
+can be used to define additional members of this automatically-generated
+class, which can then be referenced by @samp{pragma foreign_proc}
+declarations for MC++ from that module.
+
+For example:
+
+ at example
+:- pragma foreign_code("MC++", "
+	static int counter = 0;
+").
+
+:- impure pred incr_counter is det.
+:- pragma foreign_proc("MC++", incr_counter,
+	[will_not_call_mercury], "counter++;").
+
+:- semipure func get_counter = int.
+:- pragma foreign_proc("MC++", get_counter = (Result::out),
+	[will_not_call_mercury, promise_semipure], "Result = counter;").
+ at end example
 
 @c -----------------------------------------------------------------------
 
@@ -6026,6 +6172,11 @@
                                         allocated memory to or from C.
 * Trailing::                            Undoing side-effects on backtracking.
 @end menu
+
+This chapter documents the original C interface.
+In the long term we are planning to phase out support for this interface
+in favour of the new foreign language interface documented in
+ at xref{Foreign language interface}.
 
 The Mercury distribution includes a number of examples of the
 use of the C interface that show how to interface C++ with Mercury

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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