[m-rev.] for review: merge foreign_type pragma on to the main branch

Tyson Dowd trd at cs.mu.OZ.AU
Tue Oct 23 17:06:38 AEST 2001


On 22-Oct-2001, Peter Ross <peter.ross at miscrit.be> wrote:
> Hi,
> 
> For Tyson to review.
> 
> Tyson can you fix up the documentation for this change I know that you
> will write it much better than me.
> 
> Also how should we handle the compare and unify predicates for foreign
> types?  I have left some XXXs in this diff where we generate the code
> for compare and unify.
> 
> ===================================================================
> 
> 
> Estimated hours taken: 8
> Branches: main
> 
> Merge the foreign_type pragma changes from the dotnet branch to the main
> branch.
> 
> compiler/prog_data.m:
>     Add a type to hold the data from parsing a pragma foreign_type decl.
> 
> compiler/prog_io_pragma.m:
>     Parse the pragma foreign_type.
> 
> compiler/hlds_data.m:
>     Add a new alternative to hlds_type_body where the body of the type
>     is a foreign type.
> 
> compiler/make_hlds.m:
>     Place the foreign_type pragmas into the HLDS.
> 
> compiler/export.m:
>     Change export__type_to_type_string so that we return the
>     foreign type representation if it exists.
> 
> compiler/llds.m:
>     Since export__type_to_type_string needs a module_info, we add a new
>     field to pragma_c_arg_decl which is the result of calling
>     export__type_to_type_string.  This avoids threading the module_info
>     around various llds passes.
> 
> compiler/mlds.m:
>     Table the result of export__type_to_type_string so as to avoid
>     passing the module_info around the MLDS backend.

I'm not really keen on this change, and I never have been.
The real thing I dislike is that we have to run
export__type_to_type_string every time we create a mercury_type in the
MLDS.

I would prefer 
	- that export__type_to_type_string can work without the module_info.
or
	- that we don't call export__type_to_type_string in the MLDS
	  backend.
or
	- that we call export__type_to_type_string much later in the
	  MLDS, when we actually have to output a type.

Why can't the MLDS contain a map of all the foreign types?  Or the type
can contain maybe(type_defn_body) and be yes/1 for foreign types?

(I have no problem calling export__type_to_type_string for
pragma_c_arg_decls).

>     Also add the foreign_type alternative to mlds__type.
>     Update mercury_type_to_mlds_type so that handles types which are
>     foreign types.
>     
> compiler/mlds_to_il.m:
>     Convert a mlds__foreign_type into an ilds__type.  Note that the
>     basic types aren't allowed to appear in the assembler in their
>     System.* form so we detect all these cases and convert to the basic
>     type instead.
> 
> compiler/ilds.m:
>     The CLR spec requires that System.Object and System.String be
>     treated specially in the IL assembly (you have to use the name
>     object and string instead of the System.* names), so add them as
>     base types.

Actually you are adding them as "simple types".

Are you sure this is the case? 

il_string_class_name = il_system_name(["String"]).
il_generic_class_name = il_system_name(["Object"]).

il_generic_type is defined as System.Object, and we don't seem to have
problems with that in the IL assembly code.

Can you tell me what the real problem is, or where this limitation is
documented?  (or show me an error message or something?).

> 
> compiler/ilasm.m:
>     Changes to handle the additions to the simple ilds types.
> 
> doc/reference_manual.texi:
>     Document the new pragma.
> 
> compiler/fact_table.m:
> compiler/llds_out.m:
> compiler/ml_code_gen.m:
> compiler/ml_code_util.m:
> compiler/ml_simplify_switch.m:
> compiler/ml_switch_gen.m:
> compiler/ml_unify_gen.m:
> compiler/mlds_to_c.m:
> compiler/mlds_to_csharp.m:
> compiler/mlds_to_gcc.m:
> compiler/mlds_to_java.m:
> compiler/mlds_to_mcpp.m:
> compiler/pragma_c_gen.m:
> compiler/rtti_to_mlds.m:
>     Changes to handle the tabling of calls to export__type_to_string.
> 
> compiler/hlds_out.m:
> compiler/intermod.m:
> compiler/magic_util.m:
> compiler/ml_type_gen.m:
> compiler/recompilation_usage.m:
> compiler/recompilation_version.m:
> compiler/term_util.m:
> compiler/type_ctor_info.m:
> compiler/unify_proc.m:
>     Changes to hanlde the new hlds_type_body.
> 
> compiler/mercury_to_mercury.m:
>     Output the pragma foreign_type declaration.
> 
> compiler/module_qual.m:
>     Qualify the pragma foreign_type declarations.
> 
> compiler/modules.m:
>     Pragma foreign_type is allowed in the interface.

> 
> 
> Index: compiler/export.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/export.m,v
> retrieving revision 1.48
> diff -u -r1.48 export.m
> --- compiler/export.m	16 Jul 2001 08:09:58 -0000	1.48
> +++ compiler/export.m	22 Oct 2001 14:05:18 -0000

> @@ -636,7 +643,28 @@
>  	; Type = term__functor(term__atom("character"), [], _) ->
>  		Result = "MR_Char"
>  	;
> -		Result = "MR_Word"
> +		module_info_types(ModuleInfo, Types),
> +		(
> +			type_to_type_id(Type, TypeId, _),
> +			map__search(Types, TypeId, TypeDefn)
> +		->
> +				% XXX how we output the type depends on
> +				% which foreign language we are using.
> +			hlds_data__get_type_defn_body(TypeDefn, Body),
> +			( Body = foreign_type(ForeignType, _) ->
> +				Result = sym_name_to_string(ForeignType) ++ " *"
> +			;
> +				Result = "MR_Word"
> +			)

The XXX is quite true, and it might also depend on which backend we are
using.

This is why it might be better to leave the sym_name_to_string call
until make later in the compiler.  

Like mlds_to_il for instance.

> Index: compiler/hlds_data.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/hlds_data.m,v
> retrieving revision 1.56
> diff -u -r1.56 hlds_data.m
> --- compiler/hlds_data.m	10 Jul 2001 10:45:22 -0000	1.56
> +++ compiler/hlds_data.m	22 Oct 2001 14:05:19 -0000
> @@ -291,6 +291,12 @@
>  		)
>  	;	uu_type(list(type))	% not yet implemented!
>  	;	eqv_type(type)
> +	;	foreign_type(
> +			sym_name,	% structured name of foreign type
> +					% which represents the mercury type.
> +			string		% String which represents where I can
> +					% find a definition for this type.
> +		)

I think:
			string		% Location of the definition for
				        % this type (such as assembly or
					% library name)

is beter.

> Index: compiler/intermod.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/intermod.m,v
> retrieving revision 1.107
> diff -u -r1.107 intermod.m
> --- compiler/intermod.m	18 Aug 2001 11:33:47 -0000	1.107
> +++ compiler/intermod.m	22 Oct 2001 14:05:23 -0000
> @@ -1175,6 +1175,9 @@
>  	;
>  		{ Body = abstract_type },
>  		{ TypeBody = abstract_type }
> +	;
> +		{ Body = foreign_type(_, _) },
> +		{ error("foreign types not implemented") }
>  	),
>  	mercury_output_item(type_defn(VarSet, Name, Args, TypeBody, true),
>  		Context).

You can't do this if you want to commit on the main branch.
It should be implemented...

If you want you can leave it to me, but then it needs a big XXX with my
name on it so I fix it when I settle on the syntax.

> Index: compiler/mlds_to_il.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
> retrieving revision 1.85
> diff -u -r1.85 mlds_to_il.m
> --- compiler/mlds_to_il.m	17 Oct 2001 05:10:29 -0000	1.85
> +++ compiler/mlds_to_il.m	22 Oct 2001 14:05:37 -0000
> @@ -1016,7 +1016,8 @@
>  
>  		{ UnivMercuryType = term__functor(term__atom("univ"), [], 
>  			context("", 0)) },
> -		{ UnivMLDSType = mercury_type(UnivMercuryType, user_type) },
> +		{ UnivMLDSType = mercury_type(UnivMercuryType,
> +				user_type, "XXX") },

I don't like this XXX much at all. 

It also reminds me that if this XXX is unused, how many other types are
hanging around that have completely unused strings?

> Index: compiler/unify_proc.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/unify_proc.m,v
> retrieving revision 1.95
> diff -u -r1.95 unify_proc.m
> --- compiler/unify_proc.m	31 Jul 2001 14:29:56 -0000	1.95
> +++ compiler/unify_proc.m	22 Oct 2001 14:05:45 -0000
> @@ -756,6 +756,16 @@
>  		unify_proc__quantify_clauses_body([H1, H2], Goal, Context,
>  			Clauses)
>  	;
> +		{ TypeBody = foreign_type(_, _) },
> +			% XXX Is this the correct thing to do?
> +			% I assume at code gen time I could examine the types
> +			% of the unification and output different code because
> +			% they are foreign types.
> +		{ create_atomic_unification(H1, var(H2), Context, explicit, [],
> +			Goal) },
> +		unify_proc__quantify_clauses_body([H1, H2], Goal, Context,
> +			Clauses)
> +	;

I'm not sure whether this is the right thing to do right now either. 
I'm not entirely sure what code that unification is going to eventually
generate.

> Index: doc/reference_manual.texi
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
> retrieving revision 1.219
> diff -u -r1.219 reference_manual.texi
> --- doc/reference_manual.texi	12 Oct 2001 05:23:46 -0000	1.219
> +++ doc/reference_manual.texi	22 Oct 2001 14:05:53 -0000
> @@ -6656,6 +6656,8 @@
>                                  @samp{#@var{line}} directives provide support
>                                  for preprocessors and other tools that
>                                  generate Mercury code.
> +* Interfacing::                 Pragmas can be used to ease interfacing
> +                                with other languages.
>  @end menu
>  
>  @node Inlining
> @@ -6832,6 +6834,32 @@
>  to reset the source file name and line number to point back to the
>  generated file for the automatically generated text, as in the above
>  example.
> +
> + at node Interfacing
> + at section Interfacing
> +
> +A declaration of the form
> +
> + at example
> +:- pragma foreign_type(xmldoc, 'System__Xml__XmlDocument', il("System.Xml")).
> + at end example
> +
> +ensures that on the IL backend the mercury type @samp{xmldoc} is
> +represented by the backend as a @samp{System.Xml.XmlDocument}.  This
> +avoids the need to marshall values when interfacing with libraries
> +written in other languages.  The following example shows how to do this
> +interfacing.
> +
> + 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
>  
>  @node Implementation-dependent extensions
>  @chapter Implementation-dependent extensions

Should go in the foreign language interface section, not this one.
I think I will take what you have here and work on it some more.
Best not to commit it with this change just yet.

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