[m-rev.] document Java foreign language interface

Ralph Becket rafe at cs.mu.OZ.AU
Wed Dec 3 15:25:30 AEDT 2003


Fergus Henderson, Wednesday,  3 December 2003:
> Workspace: /home/jupiter/fjh/ws-jupiter/mercury
> Index: doc/reference_manual.texi
> ===================================================================
> @@ -5632,7 +5633,66 @@
>  then the IL function should return the Mercury function result value.
>  Otherwise the function result is appended as an extra argument.
>  Arguments of type @samp{io__state} or @samp{store__store(_)} are not
> -passed at all;
> +passed or returned at all;
> +that's because these types represent mutable state, and in IL
> +modifications to mutable state are done via side effects,
> +rather than argument passing.

I think the following reads better:

   Arguments of type @samp{io__state} or @samp{store__store(_)} are not
  -passed at all;
  +passed or returned at all
  +because these types represent mutable state.  In IL,
  +modifications to mutable state occur via side effects
  +rather than argument passing.

> +
> + at node Java data passing conventions
> + at subsection Java data passing conventions
> +
> +The Mercury types @code{int}, @code{float}, @code{char},
> +and @code{string} are mapped to the Java types 
> + at code{int}, @code{double}, @code{char} and
> + at code{java.lang.String} respectively.
> +
> +Mercury variables whose type is a type variable will be passed as
> + at code{java.lang.Object}.
> +Mercury array types are mapped to Java array types.
> +When compiling with @samp{--no-high-level-data}, all other Mercury variables
> +are passed as @code{java.lang.Object[]}.
> +When compiling with @samp{--high-level-data},
> +Mercury variables whose type is a Mercury discriminated union type
> +will be passed as a Java type whose type name is determined from
> +the Mercury type name (ignoring any type parameters) followed by
> +an underscore and then the type arity,
> +expressed as a decimal integer.
> +Mercury module qualifiers are converted to Java namespace qualifiers.
> +For example the Mercury type @samp{foo__bar__baz/1} will be passed as the Java
> +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
> +equivalence type.

Just out of interest, is the reason for the extra namespace qualifier
documented somewhere?

> +This mapping is subject to change and you should try to avoid writing
> +code that relies heavily upon a particular representation of Mercury
> +terms.

Perhaps this should be in italics?

> +Mercury arguments declared with input modes are passed by value to the
> +corresponding Java function.  If the Mercury procedure is a function
> +whose result has an input mode, then the Mercury function result is
> +appended to the list of input parameters, so that the Mercury function
> +result becomes the last parameter to the corresponding Java function.
> +
> +The return values from the Java function consist of the following:
> +first, any arguments with output modes; next, if the Mercury procedure
> +is a function whose result has an output mode, the function result;
> +finally, if the Mercury procedure can fail, the success indicator.
> +The success indicator is a truth value of type

s/of type/with Java type/?

> + at samp{boolean} indicating success or failure:
> + at code{true} indicates success, and @code{false} indicates failure.
> +If there are no return values, then the return type of the Java
> +function will be @samp{void}.  If there is exactly one return
> +value, then the Java return type will be the type of that value.
> +If there is more than one return value, then the Java return type
> +will be @samp{java.lang.Object[]}, and the Java function will return
> +an array of type @samp{java.lang.Object[]} containing all the return
> +values in the order described above.

I think the last two paragraphs could be made clearer.  How about
this:

   The arguments to the Java function will be precisely the input
   arguments of the corresponding Mercury procedure (in the same order).
   (If the Mercury procedure is a function with an input mode result,
   then this will be the last argument to the Java function.)

   The result of the Java function will be a vector comprised of the
   output arguments of the Mercury procedure (in the same order).
   (If the Mercury procedure can fail then the last item in the vector
   will be a @samp{boolean} success indicator, with a @samp{true} value
   denoting success and a @samp{false} value denoting failure.)

   If the results vector has length zero then the return type of the
   Java function is @samp{void}.

   If the results vector has length one then the return type of the
   Java function is the type of the item in question.

   Otherwise, the Java function will return an array of type
   @same{java.lang.Object[]}.

> +
> +Arguments of type @samp{io__state} or @samp{store__store(_)} are not
> +passed or returned at all;
>  that's because these types represent mutable state, and in IL
>  modifications to mutable state are done via side effects,
>  rather than argument passing.

As before, I think this is better:

   Arguments of type @samp{io__state} or @samp{store__store(_)} are not
  -passed at all;
  +passed or returned at all
  +because these types represent mutable state.  In IL,
  +modifications to mutable state occur via side effects
  +rather than argument passing.

> @@ -5746,8 +5806,8 @@
>  before the object file for the module containing the
>  @samp{pragma foreign_import_module} declaration.
>  
> -A cycle of @samp{pragma foreign_import_module}, where the language is either
> - at samp{"MC++"} or @samp{"C#"}, is not permitted.
> +A cycle of @samp{pragma foreign_import_module}, where the language is
> + at samp{"MC++"}, @samp{"C#"}, or @samp{"Java"}, is not permitted.
>  
>  @node Adding foreign definitions
>  @section Adding foreign definitions
> @@ -5775,9 +5835,12 @@
>  @node Language specific bindings
>  @section Language specific bindings
>  
> + at c Please keep this menu in alphabetical order
> +
>  @menu
>  * Interfacing with C 		:: How to write code to interface with C
>  * Interfacing with C# 		:: How to write code to interface with C#
> +* Interfacing with Java 	:: How to write code to interface with Java
>  * Interfacing with IL 		:: How to write code to interface with IL
>  * Interfacing with Managed C++ 	:: How to write code to interface with
>    				   Managed C++

Ditto Pete's comment re: the alphabet :-)

> @@ -5800,6 +5863,9 @@
>  
>  @item @samp{C#}
>  Use the string @code{"C#"} to set the foreign language to C#.
> +      
> + at item @samp{Java}
> +Use the string @code{"Java"} to set the foreign language to Java.
>  
>  @item @samp{IL}
>  Use the string @code{"IL"} to set the foreign language to IL.
> @@ -5867,8 +5933,8 @@

As an aside, does capitalisation matter for the GRADE variable?

>  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
> +succeeds, the C code must set the values of all output arguments.
> +If the procedure fails, the C code need only
>  set @code{SUCCESS_INDICATOR} to false (zero).
>  
>  @node Using pragma foreign_decl for C
> @@ -5953,7 +6019,7 @@
>  The C @samp{pragma foreign_type} declaration is of the form:
>  
>  @example
> -:- pragma foreign_type(c, @var{MercuryTypeName}, @var{CForeignType}).
> +:- pragma foreign_type("C", @var{MercuryTypeName}, @var{CForeignType}).
>  @end example
>  
>  The @var{CForeignType} can be any C type name that obeys the following
> @@ -5965,10 +6031,8 @@
>  @samp{void (*)(void)}.  However, it would be OK to use a typedef name
>  which was defined as a function pointer type.)
>  
> - at c XXX No point documenting this until `--gc accurate'
> - at c     is officially supported.
> - at c With @samp{--gc accurate}, foreign_types which are C pointer types
> - at c must not point to the Mercury heap.
> +With @samp{--gc accurate}, foreign_types which are C pointer types
> +must not point to the Mercury heap.

Again, I wonder whether this should be highlighted.

>  If the @var{MercuryTypeName} is the type of a parameter of a procedure
>  defined using @samp{pragma foreign_proc},
> @@ -6022,8 +6086,8 @@
>  
>  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{SUCCESS_INDICATOR}.
> -For example:
> +must assign a value of type @samp{bool} to the variable
> + at samp{SUCCESS_INDICATOR}.  For example:
>  
>  @example
>  :- pred string__contains_char(string, character).
> @@ -6041,8 +6105,8 @@
>  
>  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
> +succeeds, the C# code must set the values of all output arguments.
> +If the procedure fails, the C# code need only
>  set @code{SUCCESS_INDICATOR} to false.
>  
>  @node Using pragma foreign_decl for C#
> @@ -6060,7 +6124,7 @@
>  	using System;
>  ").
>  :- pred hello(io__state::di, io__state::uo) is det.
> -:- pragma foreign_decl("C#",
> +:- pragma foreign_proc("C#",
>  	hello(_IO0::di, _IO::uo),
>  	[will_not_call_mercury],
>  "
> @@ -6099,6 +6163,144 @@
>  
>  @c ----------------------------------------------------------------------------
>  
> + at node Interfacing with Java
> + at subsection Interfacing with Java
> +
> + at menu
> +* Using pragma foreign_type for Java :: Declaring Java types in Mercury
> +* Using pragma foreign_proc for Java :: Calling Java code from Mercury
> +* Using pragma foreign_decl for Java :: Including Java declarations in Mercury
> +* Using pragma foreign_code for Java :: Including Java code in Mercury
> + at end menu
> +
> + at node Using pragma foreign_type for Java
> + at subsubsection Using pragma foreign_type for Java
> +
> +The Java @samp{pragma foreign_type} declaration is of the form:

s/The/A/
s/is of/takes/ or //has/

> +
> + at example
> +:- pragma foreign_type("Java", @var{MercuryTypeName}, @var{JavaType}).
> + at end example
> +
> +The @var{JavaType} can be any accessible Java type.
> +

> +If the @var{MercuryTypeName} is the type of a parameter of a procedure
> +defined using @samp{pragma foreign_proc},
> +it will be passed to the foreign_proc's foreign language code
> +as @var{JavaType}.

How about:

   The effect of this declaration is that Mercury values of type
   @var{MercuryTypeName} will be passed to and from Java foreign_procs
   as having type @var{JavaType}.

Does this apply to nested values of type MercuryTypeName or just
top-level arguments?

> +
> + at c XXX `pragma export' not supported yet for Java
> + at c Furthermore, any Mercury procedure exported with @samp{pragma export}
> + at c will use @var{JavaType} as the type for any
> + at c parameters whose Mercury type is @var{MercuryTypeName}.
> +
> + at node Using pragma foreign_proc for Java
> + at subsubsection Using pragma foreign_proc for Java
> +
> +The Java code from Java pragma foreign_proc declarations will be placed in
> +the bodies of static member functions of an automatically-generated Java class.
> +Since such Java 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}.

I take it this means the Java wrapper class also holds the foreign_code?

> +
> +The input and output variables for a Java @samp{pragma foreign_proc} will
> +have Java types corresponding to their Mercury types.  The exact rules
> +for mapping Mercury types to Java types are described in
> + at ref{Java data passing conventions}.

How about:

   Values are passed to and from Java foreign_procs using the mapping
   between Mercury and Java types described in @ref{Java data passing
   conventions}.

> +
> +Java code in a @code{pragma foreign_proc} declaration
> +for any procedure whose determinism indicates that it could fail
> +must assign a value of type @samp{boolean} to the variable @samp{succeeded}.

How about:

   The Java code in a @code{pragma foreign_proc} declaration for a
   procedure whose determinism indicates it can fail must assign
   either @code{true} or @code{false} 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("Java",
> +	string__contains_char(Str::in, Ch::in),
> +        [will_not_call_mercury, promise_pure],
> +        "succeeded = (Str.IndexOf(Ch) != -1);").
> + at end example
> +
> + at noindent
> +Java code for procedures whose determinism indicates that they cannot fail
> +should not access the @code{succeeded} variable.

s/access/make reference to/

> +
> +Arguments whose mode is input will have their values set by the
> +Mercury implementation on entry to the Java code.
> +With our current implementation, the Java code must set the values
> +of all output variables, even if the procedure fails

I'd change this

> +(i.e. the Java code sets the @samp{succeeded} variable to @code{false}).

to

   setting @samp{succeeded} to @code{false}.

> + at c If the procedure
> + at c succeeds, the Java code must set the values of all output arguments
> + at c If the procedure fails, the Java code need only
> + at c set the @code{succeeded} variable to false.
> +
> + at node Using pragma foreign_decl for Java
> + at subsubsection Using pragma foreign_decl for Java
> +
> + at samp{pragma foreign_decl} declarations for Java can be used to provide
> +any top-level Java declarations (e.g.@: @samp{import} declarations
> +or auxiliary class definitions) which are needed by Java code in
> + at samp{pragma foreign_proc} declarations in that module.
> +
> +For example:
> +
> + at example
> +:- pragma foreign_decl("Java", "
> +import javax.swing.*;
> +import java.awt.*;
> +
> +class MyApplet extends JApplet @{
> +    public void init() @{
> +        JLabel label = new JLabel(""Hello, world"");
> +        label.setHorizontalAlignment(JLabel.CENTER);
> +        getContentPane().add(label);
> +    @}
> +@}
> +").
> +:- pred hello(io__state::di, io__state::uo) is det.
> +:- pragma foreign_proc("Java",
> +	hello(_IO0::di, _IO::uo),
> +	[will_not_call_mercury],
> +"
> +	MyApplet app = new MyApplet();
> +	// ...
> +").
> + at end example
> +
> + at node Using pragma foreign_code for Java
> + at subsubsection Using pragma foreign_code for Java
> +
> +The Java code from @samp{pragma foreign_proc} declarations for Java will be
> +placed in the bodies of static member functions of an
> +automatically-generated Java 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 Java from that module.
> +
> +For example:
> +
> + at example
> +:- pragma foreign_code("Java", "
> +	static int counter = 0;
> +").
> +
> +:- impure pred incr_counter is det.
> +:- pragma foreign_proc("Java", incr_counter,
> +	[will_not_call_mercury], "counter++;").
> +
> +:- semipure func get_counter = int.
> +:- pragma foreign_proc("Java",
> +	get_counter = (Result::out),
> +	[will_not_call_mercury, promise_semipure],
> +	"Result = counter;").
> + at end example
> +
> + at c ----------------------------------------------------------------------------

And everything else looks fine to me.

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