[m-rev.] diff: foreign export bool for java
Peter Wang
novalazy at gmail.com
Tue Aug 11 17:31:44 AEST 2009
On 2009-08-11, Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
>
> On Tue, 11 Aug 2009, Peter Wang wrote:
>
> >Branches: main
> >
> >library/bool.m:
> > Export `bool' enumeration values for Java foreign code.
> >
> >diff --git a/library/bool.m b/library/bool.m
> >index a620e98..f997bfb 100644
> >--- a/library/bool.m
> >+++ b/library/bool.m
> >@@ -77,6 +77,12 @@
> >% The representation of bool values should correspond with the definitions of
> >% MR_TRUE and MR_FALSE in runtime/mercury_std.h.
> >
> >+:- pragma foreign_export_enum("Java", bool/0, [],
> >+ [
> >+ no - "ML_NO",
> >+ yes - "ML_YES"
> >+ ]).
> >+
>
> For consistency with the C version perhaps they should be called MR_NO
> and MR_YES? (Or at least add a second foreign_export_enum pragma that
> uses those names.)
I've changed it in this patch (and builtin.comparison_result) but I'm
not really sure about it.
> You should also update the Java data passing conventions section of the
> reference manual. (You may as well add the foreign export for
> builtin.comparison_result that the C grades have as well).
For review:
Branches: main
library/bool.m:
library/builtin.m:
Rename exported enumeration values for Java to MR_* for consistency with
the C version.
library/list.m:
Add `MR_empty_list', `MR_cons', `MR_is_empty', `MR_det_head' and
`MR_det_tail' for manipulating lists from Java foreign code.
Add wrapper class `MR_ListIterator<E>' that allows iteration over
Mercury lists using Java for-each syntax (undocumented for now).
doc/reference_manual.texi:
doc/user_guide.texi:
Update documentation pertaining to Java foreign language interface.
library/bitmap.m:
library/rtti_implementation.m:
library/string.m:
Conform to renamings.
Use for-each syntax in some places.
diff --git a/doc/reference_manual.texi b/doc/reference_manual.texi
index 946c2e5..c55041d 100644
--- a/doc/reference_manual.texi
+++ b/doc/reference_manual.texi
@@ -6948,6 +6948,24 @@ and @code{string} are mapped to the Java types
@code{int}, @code{double}, @code{char} and
@code{java.lang.String} respectively.
+For the Mercury standard library type @samp{bool.bool}, there is a
+corresponding Java type, @code{bool.Bool_0}. Java code can refer to the
+boolean data constructors @samp{yes} and @samp{no}, as @code{bool.MR_YES}
+and @code{bool.MR_NO} respectively.
+
+For the Mercury standard library type @samp{builtin.comparison_result}, there
+is a corresponding Java type, @code{builtin.Comparison_result_0}. Java code
+can refer to the data constructors of this type, @samp{(<)}, @samp{(=)} and
+ at samp{(>)}, as @code{builtin.MR_COMPARE_LESS}, @code{builtin.MR_COMPARE_EQUAL}
+and @code{builtin.MR_COMPARE_GREATER} respectively.
+
+Mercury variables of a type for which there is a Java @samp{pragma
+foreign_type} declaration (@pxref{Using foreign types from Mercury}) will be
+passed as the corresponding Java type.
+
+Mercury tuple types are passed as @samp{java.lang.Object[]} where
+the length of the array is the number of elements in the tuple.
+
Mercury variables whose type is a type variable will be passed as
@code{java.lang.Object}.
Mercury array types are mapped to Java array types.
@@ -6959,11 +6977,15 @@ 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.
+The first character of the type name will have its case inverted,
+and the name may be mangled to satisfy Java lexical rules.
+
+Java code generated by the Mercury compiler is placed in the @samp{jmercury}
+package. Mercury module qualifiers are converted into a Java class name by
+concatenating the components with double underscore separators (@samp{__}).
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.
+type @samp{jmercury.foo__bar.Baz_1}.
+
Mercury variables whose type is a Mercury equivalence type
will be passed as the representation of the right hand side of the
equivalence type.
@@ -6999,6 +7021,17 @@ passed or returned at all.
and in Java modifications to mutable state are done via side effects,
rather than argument passing.)
+Mercury lists can be manipulated by Java code using the following methods,
+which are defined by the Mercury implementation.
+
+ at example
+list.MR_is_empty(list) /* test if a list is empty */
+list.MR_det_head(list) /* get the head of a list */
+list.MR_det_tail(list) /* get the tail of a list */
+list.MR_empty_list() /* create an empty list */
+list.MR_cons(head, tail) /* construct a list with the given head and tail */
+ at end example
+
@node Erlang data passing conventions
@subsection Erlang data passing conventions
@@ -8088,16 +8121,15 @@ A Java @samp{pragma foreign_type} declaration has the form:
:- pragma foreign_type("Java", @var{MercuryTypeName}, "@var{JavaType}").
@end example
-The @var{JavaType} can be any accessible Java type.
+The @var{JavaType} can be any accessible non-primitive Java type.
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}.
- at c XXX `pragma foreign_export' not supported yet for Java
- at c Furthermore, any Mercury procedure exported with @samp{pragma foreign_export}
- at c will use @var{JavaType} as the type for any
- at c parameters whose Mercury type is @var{MercuryTypeName}.
+Furthermore, any Mercury procedure exported with @samp{pragma foreign_export}
+will use @var{JavaType} as the type for any
+parameters whose Mercury type is @var{MercuryTypeName}.
@node Using pragma foreign_proc for Java
@subsubsection Using pragma foreign_proc for Java
@@ -8146,7 +8178,38 @@ of all output variables, even if the procedure fails
@node Using pragma foreign_export for Java
@subsubsection Using pragma foreign_export for Java
- at samp{pragma foreign_export} is not currently supported for Java.
+A @samp{pragma foreign_export} declaration for Java has the form:
+
+ at example
+:- pragma foreign_export("Java", @var{MercuryMode}, "@var{Java_Name}").
+ at end example
+
+For example,
+
+ at example
+:- pragma foreign_export("Java", foo(in, in, out), "FOO").
+ at end example
+
+The type signature of the Java interface to a Mercury procedure is as
+described in @ref{Java data passing conventions}.
+
+Calling polymorphically typed Mercury procedures from Java is a little bit more
+difficult than calling ordinary (monomorphically typed) Mercury procedures.
+The simplest method is to just create monomorphic forwarding procedures that
+call the polymorphic procedures, and export them, rather than exporting the
+polymorphic procedures.
+
+If you do export a polymorphically typed Mercury procedure, the compiler
+will prepend one @samp{type_info} argument to the parameter list of
+the Java interface function for each polymorphic type variable in the
+Mercury procedure's type signature. The caller must arrange to pass
+in appropriate @samp{type_info} values corresponding to the types
+of the other arguments passed.
+ at c XXX the following won't work while type_descs and type_infos have
+ at c different representations in Java.
+ at c These @samp{type_info} arguments can
+ at c be obtained using the Mercury @samp{type_of} function in the Mercury
+ at c standard library module @samp{type_desc}.
@node Using pragma foreign_decl for Java
@subsubsection Using pragma foreign_decl for Java
diff --git a/doc/user_guide.texi b/doc/user_guide.texi
index a43a106..2a0ddf1 100644
--- a/doc/user_guide.texi
+++ b/doc/user_guide.texi
@@ -10134,6 +10134,9 @@ Runtime (sometimes also known as CIL or MSIL).
Only available on backends that compile to IL.
This is the preferred foreign language for IL code generation.
+ at item @samp{Java}
+This is the only foreign language for backends which compile to Java.
+
@end table
@c ----------------------------------------------------------------------------
diff --git a/library/bitmap.m b/library/bitmap.m
index c37a540..4bd2a0a 100644
--- a/library/bitmap.m
+++ b/library/bitmap.m
@@ -1631,21 +1631,21 @@ bytes_equal(Index, MaxIndex, BM1, BM2) :-
may_not_duplicate],
"
if (BM1.num_bits < BM2.num_bits) {
- Result = builtin.ML_COMPARE_LESS;
+ Result = builtin.MR_COMPARE_LESS;
} else if (BM1.num_bits > BM2.num_bits) {
- Result = builtin.ML_COMPARE_GREATER;
+ Result = builtin.MR_COMPARE_GREATER;
} else {
- Result = builtin.ML_COMPARE_EQUAL;
+ Result = builtin.MR_COMPARE_EQUAL;
for (int i = 0; i < BM1.elements.length; i++) {
// Mask off sign bits.
int b1 = ((int) BM1.elements[i]) & 0xff;
int b2 = ((int) BM2.elements[i]) & 0xff;
if (b1 < b2) {
- Result = builtin.ML_COMPARE_LESS;
+ Result = builtin.MR_COMPARE_LESS;
break;
}
if (b1 > b2) {
- Result = builtin.ML_COMPARE_GREATER;
+ Result = builtin.MR_COMPARE_GREATER;
break;
}
}
diff --git a/library/bool.m b/library/bool.m
index 73b0ace..6322ab1 100644
--- a/library/bool.m
+++ b/library/bool.m
@@ -79,8 +79,8 @@
:- pragma foreign_export_enum("Java", bool/0, [],
[
- no - "ML_NO",
- yes - "ML_YES"
+ no - "MR_NO",
+ yes - "MR_YES"
]).
:- instance enum(bool) where [
diff --git a/library/builtin.m b/library/builtin.m
index 5894503..9a6aedc 100644
--- a/library/builtin.m
+++ b/library/builtin.m
@@ -604,9 +604,9 @@ get_one_solution_io(Pred, X, !IO) :-
:- pragma foreign_export_enum("Java", comparison_result/0, [],
[
- (=) - "ML_COMPARE_EQUAL",
- (<) - "ML_COMPARE_LESS",
- (>) - "ML_COMPARE_GREATER"
+ (=) - "MR_COMPARE_EQUAL",
+ (<) - "MR_COMPARE_LESS",
+ (>) - "MR_COMPARE_GREATER"
]).
ordering(X, Y) = R :-
diff --git a/library/list.m b/library/list.m
index 63f6509..58aa296 100644
--- a/library/list.m
+++ b/library/list.m
@@ -2775,3 +2775,81 @@ list_to_doc_2([X | Xs]) = Doc :-
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
+
+:- pragma foreign_code("Java", "
+
+/*
+** We don't use `:- pragma foreign_export' to generate these methods because
+** the interfaces would expect type_info arguments.
+*/
+
+public static List_1 MR_empty_list()
+{
+ return new List_1.F_nil_0();
+}
+
+public static List_1 MR_cons(Object H, List_1 T)
+{
+ return new List_1.F_cons_2(H, T);
+}
+
+public static boolean MR_is_empty(List_1 lst)
+{
+ return (lst instanceof List_1.F_nil_0);
+}
+
+public static Object MR_det_head(List_1 lst)
+{
+ return ((List_1.F_cons_2) lst).F1;
+}
+
+public static List_1 MR_det_tail(List_1 lst)
+{
+ return ((List_1.F_cons_2) lst).F2;
+}
+
+/*
+** A wrapper class to allow for-each syntax.
+** You must use a new instance of this class for each loop!
+*/
+
+public static class MR_ListIterator<E>
+ implements java.lang.Iterable, java.util.Iterator<E>
+{
+ private List_1 lst;
+
+ public MR_ListIterator(List_1 lst)
+ {
+ this.lst = lst;
+ }
+
+ public java.util.Iterator<E> iterator()
+ {
+ return this;
+ }
+
+ public boolean hasNext()
+ {
+ return lst instanceof List_1.F_cons_2;
+ }
+
+ public E next()
+ {
+ if (lst instanceof List_1.F_cons_2) {
+ E head = (E) ((List_1.F_cons_2) lst).F1;
+ lst = ((List_1.F_cons_2) lst).F2;
+ return head;
+ } else {
+ throw new java.util.NoSuchElementException();
+ }
+ }
+
+ public void remove()
+ {
+ throw new java.lang.UnsupportedOperationException();
+ }
+}
+").
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
diff --git a/library/rtti_implementation.m b/library/rtti_implementation.m
index 1f0a872..bb36992 100644
--- a/library/rtti_implementation.m
+++ b/library/rtti_implementation.m
@@ -1342,17 +1342,17 @@ iterate(Start, Max, Func) = Results :-
}
private static Object[]
- ML_univ_list_to_array(list.List_1 list, int arity)
+ ML_univ_list_to_array(list.List_1 lst, int arity)
{
final Object[] args = new Object[arity];
for (int i = 0; i < arity; i++) {
- univ.Univ_0 head = (univ.Univ_0) ((list.List_1.F_cons_2) list).F1;
- args[i] = head.F2;
- list = ((list.List_1.F_cons_2) list).F2;
+ univ.Univ_0 head = (univ.Univ_0) list.MR_det_head(lst);
+ args[i] = univ.ML_unravel_univ(head)[1];
+ lst = list.MR_det_tail(lst);
}
- if (list instanceof list.List_1.F_nil_0) {
+ if (list.MR_is_empty(lst)) {
return args;
} else {
return null;
@@ -1429,13 +1429,13 @@ iterate(Start, Max, Func) = Results :-
}
private static Object[]
- ML_list_to_array(list.List_1 list, int arity)
+ ML_list_to_array(list.List_1 lst, int arity)
{
final Object[] array = new Object[arity];
for (int i = 0; i < arity; i++) {
- array[i] = ((list.List_1.F_cons_2) list).F1;
- list = ((list.List_1.F_cons_2) list).F2;
+ array[i] = list.MR_det_head(lst);
+ lst = list.MR_det_tail(lst);
}
return array;
@@ -1462,14 +1462,13 @@ construct(_, _, _) = _ :-
[will_not_call_mercury, promise_pure, thread_safe,
may_not_duplicate],
"
+ list.List_1 args_list = (list.List_1) Args;
Object[] args_array = new Object[Arity];
for (int i = 0; i < Arity; i++) {
- univ.Univ_0 head = (univ.Univ_0) ((list.List_1.F_cons_2) Args).F1;
- Object[] rc = univ.ML_unravel_univ(head);
- args_array[i] = rc[1];
-
- Args = ((list.List_1.F_cons_2) Args).F2;
+ univ.Univ_0 head = (univ.Univ_0) list.MR_det_head(args_list);
+ args_array[i] = univ.ML_unravel_univ(head)[1];
+ args_list = list.MR_det_tail(args_list);
}
Object[] args = ML_list_to_array((list.List_1) ArgTypes, Arity);
diff --git a/library/string.m b/library/string.m
index 6d63b87..4ec4b36 100644
--- a/library/string.m
+++ b/library/string.m
@@ -1339,10 +1339,10 @@ string.to_char_list(Str::uo, CharList::in) :-
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness, no_sharing],
"
- list.List_1 lst = new list.List_1.F_nil_0();
+ list.List_1 lst = list.MR_empty_list();
for (int i = Str.length() - 1; i >= 0; i--) {
char c = Str.charAt(i);
- lst = new list.List_1.F_cons_2(c, lst);
+ lst = list.MR_cons(c, lst);
}
CharList = lst;
").
@@ -1438,11 +1438,9 @@ string.from_char_list(Chars::in, Str::uo) :-
does_not_affect_liveness],
"
java.lang.StringBuilder sb = new StringBuilder();
- while (CharList instanceof list.List_1.F_cons_2) {
- list.List_1.F_cons_2 cons = (list.List_1.F_cons_2) CharList;
- char c = ((java.lang.Character) cons.F1).charValue();
+ Iterable<Character> iterable = new list.MR_ListIterator((list.List_1) CharList);
+ for (char c : iterable) {
sb.append(c);
- CharList = cons.F2;
}
Str = sb.toString();
succeeded = true;
@@ -1667,12 +1665,12 @@ string.append_list(Lists, string.append_list(Lists)).
does_not_affect_liveness],
"
java.lang.StringBuilder sb = new java.lang.StringBuilder();
- while (Strs instanceof list.List_1.F_cons_2) {
- list.List_1.F_cons_2 cons = (list.List_1.F_cons_2) Strs;
- java.lang.String s = (java.lang.String) cons.F1;
+
+ Iterable<String> iterable = new list.MR_ListIterator((list.List_1) Strs);
+ for (String s : iterable) {
sb.append(s);
- Strs = cons.F2;
}
+
Str = sb.toString();
").
@@ -1752,15 +1750,13 @@ string.append_list(Strs::in) = (Str::uo) :-
java.lang.StringBuilder sb = new java.lang.StringBuilder();
boolean add_sep = false;
- while (Strs instanceof list.List_1.F_cons_2) {
- list.List_1.F_cons_2 cons = (list.List_1.F_cons_2) Strs;
- java.lang.String s = (java.lang.String) cons.F1;
+ Iterable<String> iterable = new list.MR_ListIterator((list.List_1) Strs);
+ for (String s : iterable) {
if (add_sep) {
sb.append(Sep);
}
sb.append(s);
add_sep = true;
- Strs = cons.F2;
}
Str = sb.toString();
--------------------------------------------------------------------------
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