[m-rev.] for review: new foreign_type syntax

Tyson Dowd trd at cs.mu.OZ.AU
Thu Dec 6 13:19:19 AEDT 2001


Hi,

Here's a relative diff of the documentation, and a full diff of the
whole change, so let's try another iteration.


diff -u doc/reference_manual.texi doc/reference_manual.texi
--- doc/reference_manual.texi
+++ doc/reference_manual.texi
@@ -5010,25 +5010,32 @@
 @node Using foreign types from Mercury
 @section Using foreign types from Mercury
 
-Types defined in foreign language can be declared in Mercury using 
+Types defined in foreign language can be defined in Mercury using 
 a declaration of the form
 
 @example
-:- pragma foreign_type(@var{MercuryTypeName}, @var{ForeignTypeDescriptor}).
+:- pragma foreign_type(@var{Lang}, @var{MercuryTypeName}, @var{ForeignTypeDescriptor}).
 @end example
 
-This declaration introduces a new abstract type in Mercury which is a
-synonym for a type defined in a foreign language.
+This defines @var{MercuryTypeName} as a synonym for type
+ at var{ForeignTypeDescriptor} defined in the foreign language @var{Lang}.
+You must declare @var{MercuryTypeName} using a @samp{:- type}
+declaration as usual, and the foreign_type pragma must have the same
+visibility as the type declaration (either both in the interface or both
+in the implementation).
 
 @var{ForeignTypeDescriptor} defines how the Mercury type is mapped for a
-particular compilation grade.  Specific syntax is given in the language
-specific information below.
+particular foreign language.  Specific syntax is given in the language
+specific information below.  
 
 @var{MercuryTypeName} is treated as an abstract type at all times in
 Mercury code.
 However, if @var{MercuryTypeName} is one of the parameters of a
-foreign_proc, it will be passed to that foreign_proc as specified by
- at var{ForeignTypeDescriptor}.
+foreign_proc for @var{Lang}, it will be passed to that foreign_proc as
+specified by @var{ForeignTypeDescriptor}.
+Multiple foreign languages definitions may be given for the same type ---
+the appropriate definition will be used for the appropriate language (see the
+language specific inforation below for details).
 
 @c -----------------------------------------------------------------------
 
@@ -5113,7 +5120,7 @@
 
 @menu
 * Interfacing with C 		:: How to write code to interface with C
-* Interfacing with .NET 	:: How to write code to interface with .NET
+* Interfacing with .NET CLR	:: How to write code to interface with .NET CLR
 * Interfacing with C# 		:: How to write code to interface with C#
 * Interfacing with IL 		:: How to write code to interface with IL
 * Interfacing with Managed C++ 	:: How to write code to interface with
@@ -5286,49 +5293,57 @@
 
 @c ----------------------------------------------------------------------------
 
- at node Interfacing with .NET
- at subsection Interfacing with .NET
+ at node Interfacing with .NET CLR
+ at subsection Interfacing with .NET CLR
+
+This section describes how to interface with the .NET Common Language
+Runtime, as specified by the ECMA Common Language Infrastructure (ECMA
+TC39/TG3) standards.
 
 @c XXX
 Currently much of this section is still undocumented, sorry.
 
 @menu
-* Using pragma foreign_type for .NET 	:: Declaring .NET types in Mercury
+* Using pragma foreign_type for .NET CLR :: Declaring .NET CLR types in Mercury
 @end menu
 
- at node Using pragma foreign_type for .NET
- at subsubsection Using pragma foreign_type for .NET
+ at node Using pragma foreign_type for .NET CLR
+ at subsubsection Using pragma foreign_type for .NET CLR
 
-The .NET pragma foreign_type declaration is of the form:
+The .NET CLR @samp{pragma foreign_type} declaration is of
+the form:
 
 @example
-:- pragma foreign_type(@var{MercuryTypeName}, il(@var{DotNetForeignType})).
+:- pragma foreign_type(il, @var{MercuryTypeName}, @var{DotNetForeignType}).
 @end example
 
-If the @var{MercuryTypeName} is a parameter of a procedure defined using
- at samp{pragma foreign_proc}, it will be passed to user code as
- at var{DotNetForeignType}.
-Futhermore, any externally visible Mercury
+If the @var{MercuryTypeName} is the type of a parameter of a procedure
+defined using @samp{pragma foreign_proc} for any of the .NET CLR
+languages, it will be passed to user code as @var{DotNetForeignType}.
+Futhermore, any exported (with @samp{pragma export}) Mercury
 procedure will use @var{DotNetForeignType} as the parameter type for
 parameters whose Mercury type is @var{MercuryTypeName}.
 
-The CIL assembler syntax is used to specify type names for the .NET
+The CIL assembler syntax is used to specify type names for the .NET CLR
 backend (this syntax is documented in the ECMA specifications for .NET).
-Currently on the .NET backend only reference classes are supported using
+Currently on the .NET CLR backend only reference classes are supported using
 @samp{pragma foreign_type}, and hence the only supported syntax for
 DotNetForeignType is @samp{"class [AssemblyName]ClassName"}.
-Note that extra whitespace is not handled, there should only be a single
-space between the class keyword and they assembly specifier.
+ at c XXX this restriction should be lifted
+Note that extra whitespace is not handled --- there should only be a single
+space between the class keyword and the assembly specifier.
+ at c XXX we should handle whitespace better
 
 For example:
 
 @example
-:- pragma foreign_type(xmldoc, il("class [System.Xml]System.Xml.XmlDocument")).
+:- type xmldoc.
+:- pragma foreign_type(il, xmldoc, "class [System.Xml]System.Xml.XmlDocument").
 @end example
 
-ensures that on the .NET backend the mercury type @samp{xmldoc} is
-represented marhsalled by the backend as @samp{System.Xml.XmlDocument}
-from assembly System.Xml.
+ensures that on the .NET CLR backend the Mercury type @samp{xmldoc} is
+marshalled by the backend as @samp{System.Xml.XmlDocument} from assembly
+ at samp{System.Xml}.
 The following example shows how one can use the marshalled data from C#. 
 
 @example


===================================================================


Estimated hours taken: 8
Branches: main

Fix and enable the new foreign_type syntax.  We now accept declarations
such as:

:- pragma foreign_type(il, xmldoc, "class [System.Xml]System.Xml.XmlDocument").

compiler/prog_data.m:
	Remove the foreign type location from the foreign_type pragma,
	it is better to make this part of the backend type.
	Rename backend as backend_type as it specifies a type in a
	particular backend.

compiler/prog_io_pragma.m:
	Uncomment the foreign_type parsing code, change the syntax.
	Write some simple code to parse CIL type names.

compiler/make_hlds.m:
	Check that there is a :- type declaration, and
	that it has the same visibility as the pragma foreign_type.

compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/modules.m:
compiler/recompilation_version.m:
	Handle changes to backend_type and the foreign_type pragma.

doc/reference_manual.texi:
	Document the new syntax.


Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.391
diff -u -r1.391 make_hlds.m
--- compiler/make_hlds.m	12 Nov 2001 11:08:07 -0000	1.391
+++ compiler/make_hlds.m	5 Dec 2001 22:40:16 -0000
@@ -395,18 +395,47 @@
 		{ Pragma = foreign_proc(_, _, _, _, _, _) },
 		{ Module = Module0 }
 	;	
-		{ Pragma = foreign_type(Backend, _MercuryType, Name,
-				ForeignType) },
+		{ Pragma = foreign_type(Backend, _MercuryType, Name) },
 
-		{ Backend = il(ForeignTypeLocation) },
+		{ Backend = il(ForeignTypeLocation, ForeignType) },
 
 		{ varset__init(VarSet) },
 		{ Args = [] },
 		{ Body = foreign_type(ForeignType, ForeignTypeLocation) },
 		{ Cond = true },
 
-		module_add_type_defn_2(Module0, VarSet, Name, Args, Body,
-			Cond, Context, Status, Module)
+		{ TypeId = Name - 0 },
+		{ module_info_types(Module0, Types) },
+		{ TypeStr = error_util__describe_sym_name_and_arity(
+				Name / 0) },
+		( 
+			{ map__search(Types, TypeId, OldDefn) }
+		->
+			{ hlds_data__get_type_defn_status(OldDefn, OldStatus) },
+			{ combine_status(OldStatus, ImportStatus, NewStatus) },
+			( { NewStatus = abstract_exported } ->
+				{ ErrorPieces = [
+					words("Error: pragma foreign_type "),
+					fixed(TypeStr),
+					words("must have the same visibility as the type declaration.")
+				] },
+				error_util__write_error_pieces(Context, 0, ErrorPieces),
+				{ module_info_incr_errors(Module0, Module) }
+
+			;
+				module_add_type_defn_2(Module0, VarSet, Name,
+					Args, Body, Cond, Context, Status,
+					Module)
+			)
+		;
+			{ ErrorPieces = [
+				words("Error: type "),
+				fixed(TypeStr),
+				words("defined as foreign_type without being declared.")
+			] },
+			error_util__write_error_pieces(Context, 0, ErrorPieces),
+			{ module_info_incr_errors(Module0, Module) }
+		)
 	;	
 		% Handle pragma tabled decls later on (when we process
 		% clauses).
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.198
diff -u -r1.198 mercury_to_mercury.m
--- compiler/mercury_to_mercury.m	8 Nov 2001 15:30:31 -0000	1.198
+++ compiler/mercury_to_mercury.m	21 Nov 2001 05:33:10 -0000
@@ -467,18 +467,18 @@
 			PredOrFunc, Vars, VarSet, PragmaCode)
 	;
 		{ Pragma = foreign_type(Backend, _MercuryType,
-				MercuryTypeSymName, ForeignType) },
+				MercuryTypeSymName) },
 		io__write_string(":- pragma foreign_type("),
 		% output_type(varset__init, no, MercuryType),
 		mercury_output_sym_name(MercuryTypeSymName),
 		io__write_string(", "),
-		mercury_output_sym_name(ForeignType),
-		io__write_string(", "),
 
-		{ Backend = il(ForeignLocStr) },
+		{ Backend = il(ForeignLocStr, ForeignType) },
 		io__write_string("il(\""),
 		io__write_string(ForeignLocStr),
-		io__write_string("\")).\n")
+		io__write_string("\", "),
+		mercury_output_sym_name(ForeignType),
+		io__write_string("\").\n")
 	;
 		{ Pragma = import(Pred, PredOrFunc, ModeList, Attributes,
 			C_Function) },
Index: compiler/module_qual.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/module_qual.m,v
retrieving revision 1.70
diff -u -r1.70 module_qual.m
--- compiler/module_qual.m	6 Nov 2001 15:21:05 -0000	1.70
+++ compiler/module_qual.m	21 Nov 2001 05:33:10 -0000
@@ -247,7 +247,7 @@
 collect_mq_info_2(pred_or_func(_,_,__,_,_,_,_,_,_,_), Info, Info).
 collect_mq_info_2(pred_or_func_mode(_,_,_,_,_,_), Info, Info).
 collect_mq_info_2(pragma(Pragma), Info0, Info) :-
-	( Pragma = foreign_type(_, Type, SymName, _ForeignType) ->
+	( Pragma = foreign_type(_, Type, SymName) ->
 		( type_to_type_id(Type, _ - Arity0, _) ->
 			Arity = Arity0
 		;
@@ -893,11 +893,11 @@
 qualify_pragma(source_file(File), source_file(File), Info, Info) --> [].
 qualify_pragma(foreign_decl(L, Code), foreign_decl(L, Code), Info, Info) --> [].
 qualify_pragma(foreign_code(L, C), foreign_code(L, C), Info, Info) --> [].
+qualify_pragma(foreign_type(Backend, Type0, SymName),
+		foreign_type(Backend, Type, SymName), Info0, Info) -->
+	qualify_type(Type0, Type, Info0, Info).
 qualify_pragma(foreign_import_module(L, M), foreign_import_module(L, M),
 		Info, Info) --> [].
-qualify_pragma(foreign_type(Backend, Type0, SymName, F),
-		foreign_type(Backend, Type, SymName, F), Info0, Info) -->
-	qualify_type(Type0, Type, Info0, Info).
 qualify_pragma(
 	    foreign_proc(Rec, SymName, PredOrFunc, PragmaVars0, Varset, Code),
 	    foreign_proc(Rec, SymName, PredOrFunc, PragmaVars, Varset, Code), 
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.209
diff -u -r1.209 modules.m
--- compiler/modules.m	28 Nov 2001 14:46:33 -0000	1.209
+++ compiler/modules.m	3 Dec 2001 01:36:32 -0000
@@ -1147,7 +1147,7 @@
 pragma_allowed_in_interface(foreign_import_module(_, _), no).
 pragma_allowed_in_interface(foreign_code(_, _), no).
 pragma_allowed_in_interface(foreign_proc(_, _, _, _, _, _), no).
-pragma_allowed_in_interface(foreign_type(_, _, _, _), yes).
+pragma_allowed_in_interface(foreign_type(_, _, _), yes).
 pragma_allowed_in_interface(inline(_, _), no).
 pragma_allowed_in_interface(no_inline(_, _), no).
 pragma_allowed_in_interface(obsolete(_, _), yes).
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.72
diff -u -r1.72 prog_data.m
--- compiler/prog_data.m	20 Nov 2001 13:53:19 -0000	1.72
+++ compiler/prog_data.m	22 Nov 2001 02:10:47 -0000
@@ -157,9 +157,8 @@
 			% PredName, Predicate or Function, Vars/Mode, 
 			% VarNames, Foreign Code Implementation Info
 
-	;	foreign_type(backend, (type), sym_name, sym_name)
-			% Backend, MercuryType, MercuryTypeName,
-			% ForeignType, ForeignTypeLocation
+	;	foreign_type(backend_type, (type), sym_name)
+			% BackendType, MercuryType, MercuryTypeName
 
 	;	foreign_import_module(foreign_language, module_name)
 			% Equivalent to
@@ -288,9 +287,10 @@
 % Stuff for the foreign interfacing pragmas.
 %
 
-:- type backend
-			% The location of the il name.
-	--->	il(string).
+:- type backend_type
+			% The location of the il name, and the .NET type name
+			% (represented as a sym_name)
+	--->	il(string, sym_name).
 
 %
 % Stuff for tabling pragmas
Index: compiler/prog_io_pragma.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/prog_io_pragma.m,v
retrieving revision 1.38
diff -u -r1.38 prog_io_pragma.m
--- compiler/prog_io_pragma.m	20 Nov 2001 13:53:20 -0000	1.38
+++ compiler/prog_io_pragma.m	28 Nov 2001 07:37:58 -0000
@@ -70,52 +70,43 @@
 			ErrorTerm)
 	).
 
-/*
 parse_pragma_type(ModuleName, "foreign_type", PragmaTerms,
             ErrorTerm, _VarSet, Result) :-
-    ( PragmaTerms = [MercuryName, ForeignName, Target] ->
-    	(
-	    parse_backend(Target, Backend)
-	->
-	    parse_implicitly_qualified_term(ModuleName, MercuryName,
+    ( PragmaTerms = [LangTerm, MercuryName, BackendTerm] ->
+	( parse_foreign_language(LangTerm, Language) ->
+	    parse_backend(BackendTerm, Language, MaybeBackend),
+	    (
+		MaybeBackend = ok(Backend),
+		parse_implicitly_qualified_term(ModuleName, MercuryName,
 		    ErrorTerm, "`:- pragma foreign_type' declaration",
 		    MaybeMercuryType),
-	    (
-		MaybeMercuryType = ok(MercuryTypeSymName, MercuryArgs),
-		( MercuryArgs = [] ->
-		    parse_qualified_term(ForeignName, ErrorTerm,
-			"`:- pragma foreign_type' declaration",
-			MaybeForeignType),
-		    (
-			MaybeForeignType = ok(ForeignType, ForeignArgs),
-			( ForeignArgs = [] ->
-			    term__coerce(MercuryName, MercuryType),
-			    Result = ok(pragma(foreign_type(Backend,
-				    MercuryType, MercuryTypeSymName,
-				    ForeignType)))
-			;
-			    Result = error("foreign type arity not 0", ErrorTerm)
-			)
+		(
+		    MaybeMercuryType = ok(MercuryTypeSymName, MercuryArgs),
+		    ( MercuryArgs = [] ->
+			term__coerce(MercuryName, MercuryType),
+			Result = ok(pragma(foreign_type(Backend,
+			    MercuryType, MercuryTypeSymName)))
 		    ;
-			MaybeForeignType = error(String, Term),
-			Result = error(String, Term)
+			Result = error("foreign type arity not 0", ErrorTerm)
 		    )
 		;
-		    Result = error("mercury type arity not 0", ErrorTerm)
+		    MaybeMercuryType = error(String, Term),
+		    Result = error(String, Term)
 		)
 	    ;
-		MaybeMercuryType = error(String, Term),
+		MaybeBackend = error(String, Term),
 		Result = error(String, Term)
 	    )
-	;
-	    Result = error("invalid backend parameter", Target)
+	;   
+	   Result = error(
+	   "invalid foreign language in `:- pragma foreign_type' declaration",
+			LangTerm)
 	)
     ;
         Result = error(
     "wrong number of arguments in `:- pragma foreign_type' declaration",
             ErrorTerm)
     ).
-*/
 
 parse_pragma_type(ModuleName, "foreign_decl", PragmaTerms,
 			ErrorTerm, VarSet, Result) :-
@@ -214,13 +205,42 @@
 parse_foreign_language(term__functor(term__atom(String), _, _), Lang) :-
 	globals__convert_foreign_language(String, Lang).
 
-:- pred parse_backend(term, backend).
-:- mode parse_backend(in, out) is semidet.
+:- pred parse_backend(term, foreign_language, maybe1(backend_type)).
+:- mode parse_backend(in, in, out) is det.
+
+parse_backend(InputTerm, Language, Result) :-
+	( 
+		Language = il
+	->
+		( 
+			InputTerm = term__functor(term__string(ILTypeName),
+				[], _)
+		->
+			parse_il_type_name(ILTypeName, InputTerm, Result)
+		;
+			Result = error("invalid backend specification term",
+				InputTerm)
+		)
+	;
+		Result = error("unsupported language specified, unable to parse backend type", InputTerm)
+	).
+
+:- pred parse_il_type_name(string, term, maybe1(backend_type)).
+:- mode parse_il_type_name(in, in, out) is det.
 
-parse_backend(term__functor(Functor, Args, _), Backend) :-
-	Functor = term__atom("il"),
-	Args = [term__functor(term__string(Module), [], _)],
-	Backend = il(Module).
+parse_il_type_name(String0, ErrorTerm, BackendType) :-
+	( 
+		string__append("class [", String1, String0),
+		string__sub_string_search(String1, "]", Index)
+	->
+		string__left(String1, Index, AssemblyName),
+		string__split(String1, Index + 1, _, TypeNameStr),
+		string_to_sym_name(TypeNameStr, ".", TypeSymName),
+		BackendType = ok(il(AssemblyName, TypeSymName))
+	;
+		BackendType = error("invalid backend type description", 
+			ErrorTerm)
+	).
 
 	% This predicate parses both c_header_code and foreign_decl pragmas.
 :- pred parse_pragma_foreign_decl_pragma(module_name, string,
Index: compiler/recompilation_version.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/recompilation_version.m,v
retrieving revision 1.9
diff -u -r1.9 recompilation_version.m
--- compiler/recompilation_version.m	6 Nov 2001 15:21:10 -0000	1.9
+++ compiler/recompilation_version.m	21 Nov 2001 05:33:10 -0000
@@ -454,7 +454,7 @@
 is_pred_pragma(foreign_proc(_, Name, PredOrFunc, Args, _, _),
 		yes(yes(PredOrFunc) - Name / Arity)) :-
 	adjust_func_arity(PredOrFunc, Arity, list__length(Args)).
-is_pred_pragma(foreign_type(_, _, _, _), no).
+is_pred_pragma(foreign_type(_, _, _), no).
 is_pred_pragma(type_spec(Name, _, Arity, MaybePredOrFunc, _, _, _, _),
 		yes(MaybePredOrFunc - Name / Arity)).
 is_pred_pragma(inline(Name, Arity), yes(no - Name / Arity)).
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.228
diff -u -r1.228 reference_manual.texi
--- doc/reference_manual.texi	22 Nov 2001 19:19:54 -0000	1.228
+++ doc/reference_manual.texi	6 Dec 2001 01:56:20 -0000
@@ -4815,6 +4815,9 @@
 				       or function as a call to code
 				       written in a different
 				       programming language.
+* Using foreign types from Mercury::   How to use a type defined in         
+				       a different programming language
+				       in Mercury code.                     
 * Adding foreign declarations::        How to add declarations of
   				       entities in other programming
 				       languages.
@@ -5004,6 +5007,38 @@
 
 @c -----------------------------------------------------------------------
 
+ at node Using foreign types from Mercury
+ at section Using foreign types from Mercury
+
+Types defined in foreign language can be defined in Mercury using 
+a declaration of the form
+
+ at example
+:- pragma foreign_type(@var{Lang}, @var{MercuryTypeName}, @var{ForeignTypeDescriptor}).
+ at end example
+
+This defines @var{MercuryTypeName} as a synonym for type
+ at var{ForeignTypeDescriptor} defined in the foreign language @var{Lang}.
+You must declare @var{MercuryTypeName} using a @samp{:- type}
+declaration as usual, and the foreign_type pragma must have the same
+visibility as the type declaration (either both in the interface or both
+in the implementation).
+
+ at var{ForeignTypeDescriptor} defines how the Mercury type is mapped for a
+particular foreign language.  Specific syntax is given in the language
+specific information below.  
+
+ at var{MercuryTypeName} is treated as an abstract type at all times in
+Mercury code.
+However, if @var{MercuryTypeName} is one of the parameters of a
+foreign_proc for @var{Lang}, it will be passed to that foreign_proc as
+specified by @var{ForeignTypeDescriptor}.
+Multiple foreign languages definitions may be given for the same type ---
+the appropriate definition will be used for the appropriate language (see the
+language specific inforation below for details).
+
+ at c -----------------------------------------------------------------------
+
 @node Adding foreign declarations
 @section Adding foreign declarations
 
@@ -5085,6 +5120,7 @@
 
 @menu
 * Interfacing with C 		:: How to write code to interface with C
+* Interfacing with .NET CLR	:: How to write code to interface with .NET CLR
 * Interfacing with C# 		:: How to write code to interface with C#
 * Interfacing with IL 		:: How to write code to interface with IL
 * Interfacing with Managed C++ 	:: How to write code to interface with
@@ -5126,6 +5162,7 @@
 * Using pragma foreign_proc for C 	:: Calling C code from Mercury
 * Using pragma foreign_decl for C 	:: Including C declarations in Mercury
 * Using pragma foreign_code for C 	:: Including C code in Mercury
+* Using pragma foreign_type for C 	:: Declaring C types in Mercury
 @end menu
 
 @node Using pragma foreign_proc for C
@@ -5248,6 +5285,77 @@
 @end example
 
 Such code is copied verbatim into the generated C file.
+
+ at node Using pragma foreign_type for C
+ at subsubsection Using pragma foreign_type for C
+
+This pragma is currently not implemented for C backends.
+
+ at c ----------------------------------------------------------------------------
+
+ at node Interfacing with .NET CLR
+ at subsection Interfacing with .NET CLR
+
+This section describes how to interface with the .NET Common Language
+Runtime, as specified by the ECMA Common Language Infrastructure (ECMA
+TC39/TG3) standards.
+
+ at c XXX
+Currently much of this section is still undocumented, sorry.
+
+ at menu
+* Using pragma foreign_type for .NET CLR :: Declaring .NET CLR types in Mercury
+ at end menu
+
+ at node Using pragma foreign_type for .NET CLR
+ at subsubsection Using pragma foreign_type for .NET CLR
+
+The .NET CLR @samp{pragma foreign_type} declaration is of
+the form:
+
+ at example
+:- pragma foreign_type(il, @var{MercuryTypeName}, @var{DotNetForeignType}).
+ at end example
+
+If the @var{MercuryTypeName} is the type of a parameter of a procedure
+defined using @samp{pragma foreign_proc} for any of the .NET CLR
+languages, it will be passed to user code as @var{DotNetForeignType}.
+Futhermore, any exported (with @samp{pragma export}) Mercury
+procedure will use @var{DotNetForeignType} as the parameter type for
+parameters whose Mercury type is @var{MercuryTypeName}.
+
+The CIL assembler syntax is used to specify type names for the .NET CLR
+backend (this syntax is documented in the ECMA specifications for .NET).
+Currently on the .NET CLR backend only reference classes are supported using
+ at samp{pragma foreign_type}, and hence the only supported syntax for
+DotNetForeignType is @samp{"class [AssemblyName]ClassName"}.
+ at c XXX this restriction should be lifted
+Note that extra whitespace is not handled --- there should only be a single
+space between the class keyword and the assembly specifier.
+ at c XXX we should handle whitespace better
+
+For example:
+
+ at example
+:- type xmldoc.
+:- pragma foreign_type(il, xmldoc, "class [System.Xml]System.Xml.XmlDocument").
+ at end example
+
+ensures that on the .NET CLR backend the Mercury type @samp{xmldoc} is
+marshalled by the backend as @samp{System.Xml.XmlDocument} from assembly
+ at samp{System.Xml}.
+The following example shows how one can use the marshalled data from C#. 
+
+ at example
+:- 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],
+"
+    XML0.LoadXml(String);
+    XML = XML0;
+").
+ at end example
 
 @c ----------------------------------------------------------------------------
 


-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
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