diff --git a/samples/.nocopyright b/samples/.nocopyright index 009991fb2..43c371851 100644 --- a/samples/.nocopyright +++ b/samples/.nocopyright @@ -1 +1,2 @@ .cvsignore +README diff --git a/samples/README b/samples/README index ef3ad58fd..051d5b44a 100644 --- a/samples/README +++ b/samples/README @@ -58,6 +58,10 @@ diff This directory contains an implementation of a c_interface This directory contains some examples of mixed Mercury/C/C++/Fortran programs using the C interface. +java_interface This directory contains some examples of mixed + Mercury/Java programs using the foreign language + interface. + rot13 This directory contains a few implementations of rot-13 encoding. diff --git a/samples/java_interface/.nocopyright b/samples/java_interface/.nocopyright new file mode 100644 index 000000000..e845566c0 --- /dev/null +++ b/samples/java_interface/.nocopyright @@ -0,0 +1 @@ +README diff --git a/samples/java_interface/README b/samples/java_interface/README new file mode 100644 index 000000000..d4bc3b801 --- /dev/null +++ b/samples/java_interface/README @@ -0,0 +1,10 @@ + +This directory contains some examples of mixed Mercury/Java programs using +the Java interface. + +mercury_calls_java A detailed example of Mercury code + calling Java code. + +java_calls_mercury A detailed example of Java code calling + Mercury code. + diff --git a/samples/java_interface/java_calls_mercury/JavaMain.java b/samples/java_interface/java_calls_mercury/JavaMain.java new file mode 100644 index 000000000..1220f5c7c --- /dev/null +++ b/samples/java_interface/java_calls_mercury/JavaMain.java @@ -0,0 +1,88 @@ +// This source file is hereby placed in the public domain. + +package my_package; + +import jmercury.list; +import jmercury.mercury_lib; +import static java.lang.System.out; + +public class JavaMain { + public static void java_main() { + out.println("In java_main()."); + + /* + ** call the Java method foo_test(), which is the interface + ** to the Mercury predicate foo/1 in mode + ** :- mode foo(in) is semidet. + */ + out.print("foo_test(42) returns "); + out.println(mercury_lib.foo_test(42) ? "TRUE" : "FALSE"); + out.print("foo_test(43) returns "); + out.println(mercury_lib.foo_test(43) ? "TRUE" : "FALSE"); + + /* + ** call the Java method one_foo(), which is the interface + ** to the Mercury predicate foo/1 in mode + ** :- mode foo(out) is cc_multi. + */ + int value = mercury_lib.one_foo(); + out.println("one_foo() gives value = " + value); + + /* + ** call the Java method foo_list(), which is the interface + ** to the Mercury predicate foo/1 in mode + ** :- mode foo(out) is multi. + */ + list.List_1 lst = mercury_lib.foo_list(); + out.print("foo_list() = "); + print_list(lst); + + /* + ** call the Java methods bar(), bar_test(), and bar_inverse(), + ** which are the interfaces to the Mercury function bar/1 + ** in the modes + ** :- mode bar(in) = out is det. + ** :- mode bar(out) = in is det. + ** :- mode bar(in) = in is det. + ** respectively. + */ + out.println("bar(100) = " + mercury_lib.bar(100)); + out.print("bar_test(100, 101) returns "); + out.println(mercury_lib.bar_test(100, 101) ? "TRUE" : "FALSE"); + out.print("bar_test(100, 200) returns "); + out.println(mercury_lib.bar_test(100, 200) ? "TRUE" : "FALSE"); + value = mercury_lib.bar_inverse(101); + out.println("bar_inverse(101) gives value = " + value); + value = mercury_lib.bar_inverse(200); + out.println("bar_inverse(200) gives value = " + value); + + jmercury.runtime.Ref ref = new jmercury.runtime.Ref(); + if (mercury_lib.baz(1, ref)) { + out.println("baz(1, ref) returns TRUE with value = " + ref.val); + } else { + out.println("baz(100, ref) returns FALSE"); + } + if (mercury_lib.baz(100, ref)) { + out.println("baz(100, ref) returns TRUE with value = " + ref.val); + } else { + out.println("baz(100, ref) returns FALSE"); + } + + out.println("Returning from java_main()..."); + } + + static void print_list(list.List_1 lst) { + if (list.is_empty(lst)) { + out.println("[]"); + } else { + out.print("["); + out.print(list.det_head(lst)); + lst = list.det_tail(lst); + while (!list.is_empty(lst)) { + out.print(", " + list.det_head(lst)); + lst = list.det_tail(lst); + } + out.println("]"); + } + } +} diff --git a/samples/java_interface/java_calls_mercury/Makefile b/samples/java_interface/java_calls_mercury/Makefile new file mode 100644 index 000000000..5a51ab777 --- /dev/null +++ b/samples/java_interface/java_calls_mercury/Makefile @@ -0,0 +1,25 @@ +#-----------------------------------------------------------------------------# +# This source file is hereby placed in the public domain. +#-----------------------------------------------------------------------------# + +# We need to tell javac about the Mercury libraries. +GRADE = java +MER_LIB_DIR = $(dir $(shell which mmc))../lib/mercury/lib/$(GRADE) +MER_JARS = $(MER_LIB_DIR)/mer_std.jar:$(MER_LIB_DIR)/mer_rt.jar + +.PHONY: all +all: mercury_main + +mercury_main: mercury_main.m my_package/JavaMain.class + mmc --grade $(GRADE) --make mercury_main --java-classpath . + +my_package/JavaMain.class: JavaMain.java libmercury_lib.jar + javac JavaMain.java -cp $(MER_JARS):Mercury/classs -d . + +libmercury_lib.jar: mercury_lib.m + mmc --grade $(GRADE) --make libmercury_lib + +.PHONY: clean +clean: + $(RM) mercury_main mercury_lib.jar *.err + $(RM) -r Mercury my_package diff --git a/samples/java_interface/java_calls_mercury/java_main_int.m b/samples/java_interface/java_calls_mercury/java_main_int.m new file mode 100644 index 000000000..d1d1c130a --- /dev/null +++ b/samples/java_interface/java_calls_mercury/java_main_int.m @@ -0,0 +1,32 @@ +% This module java_main_int defines a Mercury predicate java_main which acts as an +% interface to the Java method java_main(), which is defined in JavaMain.java. + +% This source file is hereby placed in the public domain. + +:- module java_main_int. + +:- interface. +:- import_module io. + +% Since the java_main() function has side effects, we declare the corresponding +% Mercury predicate as one that takes an io__state pair. If we didn't do +% this, the Mercury compiler might optimize away calls to it! + +:- pred java_main(io::di, io::uo) is det. + +:- implementation. + + % Import the Java class containing the method java_main. + % As usual for Java, this is not necessary; you may also + % fully qualify the method at the call site. +:- pragma foreign_decl("Java", "import my_package.JavaMain;"). + + % Define the Mercury predicate java_main to call the Java method + % java_main. +:- pragma foreign_proc("Java", + java_main(IO0::di, IO::uo), + [may_call_mercury, promise_pure], +" + JavaMain.java_main(); + IO = IO0; +"). diff --git a/samples/java_interface/java_calls_mercury/mercury_lib.m b/samples/java_interface/java_calls_mercury/mercury_lib.m new file mode 100644 index 000000000..a0d2edcbf --- /dev/null +++ b/samples/java_interface/java_calls_mercury/mercury_lib.m @@ -0,0 +1,72 @@ +% This source file is hereby placed in the public domain. -fjh (the author). + +%-----------------------------------------------------------------------------% +:- module mercury_lib. +:- interface. + + % A Mercury predicate with multiple modes. + % +:- pred foo(int). +:- mode foo(in) is semidet. +:- mode foo(out) is multi. + + % A Mercury function with multiple modes. + % +:- func bar(int) = int. +:- mode bar(in) = out is det. +:- mode bar(out) = in is det. +:- mode bar(in) = in is semidet. + + % A semidet (i.e. partial) Mercury function. +:- func baz(int) = int. +:- mode baz(in) = out is semidet. + +%-----------------------------------------------------------------------------% +%-----------------------------------------------------------------------------% + +:- implementation. + +:- import_module int. +:- import_module list. +:- import_module solutions. + +% well, this is just a silly example... +foo(42). +foo(53). +foo(197). + +bar(X) = X + 1. + +baz(1) = 9. +baz(2) = 16. +baz(3) = 27. + +%-----------------------------------------------------------------------------% + +% The following code provides provides access to the Mercury predicate foo +% from Java code. + +:- pragma foreign_export("Java", foo(in), "foo_test"). + +:- pragma foreign_export("Java", bar(in) = out, "bar"). +:- pragma foreign_export("Java", bar(in) = in, "bar_test"). +:- pragma foreign_export("Java", bar(out) = in, "bar_inverse"). + +:- pragma foreign_export("Java", baz(in) = out, "baz"). + + % The nondet mode of `foo' cannot be exported directly with + % the current Mercury/C interface. To get all solutions, + % must define a predicate which returns all the solutions of foo, + % and export it to C. We give it the name foo_list() in C. +:- pred all_foos(list(int)::out) is det. +:- pragma foreign_export("Java", all_foos(out), "foo_list"). +all_foos(L) :- solutions((pred(X::out) is multi :- foo(X)), L). + + % If we just want one solution, and don't care which one, then + % we can export a `cc_multi' (committed-choice nondeterminism) + % version of `foo'. We give it the name one_foo(). +:- pred cc_foo(int::out) is cc_multi. +:- pragma foreign_export("Java", cc_foo(out), "one_foo"). +cc_foo(X) :- foo(X). + +%-----------------------------------------------------------------------------% diff --git a/samples/java_interface/java_calls_mercury/mercury_main.m b/samples/java_interface/java_calls_mercury/mercury_main.m new file mode 100644 index 000000000..f0200b637 --- /dev/null +++ b/samples/java_interface/java_calls_mercury/mercury_main.m @@ -0,0 +1,24 @@ +% This source file is hereby placed in the public domain. -fjh (the author). + +:- module mercury_main. +:- interface. +:- import_module io. + +:- pred main(io::di, io::uo) is det. + +:- implementation. + + % Nothing from mercury_lib is used in mercury_main. + % The import is needed to make sure mmake includes + % mercury_lib in the executable. +:- import_module mercury_lib. + +% import the module which defines the Mercury interface to the +% Java method java_main(). +:- import_module java_main_int. + +% main just invokes java_main +main(!IO) :- + io.write_string("In Mercury main, about to call java_main...\n", !IO), + java_main(!IO), + io.write_string("Back in Mercury main.\n", !IO). diff --git a/samples/java_interface/mercury_calls_java/JavaMain.java b/samples/java_interface/mercury_calls_java/JavaMain.java new file mode 100644 index 000000000..ced9e6f4d --- /dev/null +++ b/samples/java_interface/mercury_calls_java/JavaMain.java @@ -0,0 +1,9 @@ +// This source file is hereby placed in the public domain. + +package my_package; + +public class JavaMain { + public static void java_main() { + System.out.println("In java_main()."); + } +} diff --git a/samples/java_interface/mercury_calls_java/Makefile b/samples/java_interface/mercury_calls_java/Makefile new file mode 100644 index 000000000..dc9c988ee --- /dev/null +++ b/samples/java_interface/mercury_calls_java/Makefile @@ -0,0 +1,17 @@ +#-----------------------------------------------------------------------------# +# This source file is hereby placed in the public domain. +#-----------------------------------------------------------------------------# + +.PHONY: all +all: mercury_main + +mercury_main: mercury_main.m my_package/JavaMain.class + mmc --java --make mercury_main --java-classpath . + +my_package/JavaMain.class: JavaMain.java + javac JavaMain.java -d . + +.PHONY: clean +clean: + $(RM) mercury_main *.err + $(RM) -r Mercury my_package diff --git a/samples/java_interface/mercury_calls_java/java_main_int.m b/samples/java_interface/mercury_calls_java/java_main_int.m new file mode 100644 index 000000000..b16b6cebc --- /dev/null +++ b/samples/java_interface/mercury_calls_java/java_main_int.m @@ -0,0 +1,31 @@ +% This module java_main_int defines a Mercury predicate java_main which acts as an +% interface to the Java method java_main(), which is defined in JavaMain.java. + +% This source file is hereby placed in the public domain. + +:- module java_main_int. +:- interface. +:- import_module io. + +% Since the java_main() function has side effects, we declare the corresponding +% Mercury predicate as one that takes an io__state pair. If we didn't do +% this, the Mercury compiler might optimize away calls to it! + +:- pred java_main(io::di, io::uo) is det. + +:- implementation. + + % Import the Java class containing the method java_main. + % As usual for Java, this is not necessary; you may also + % fully qualify the method at the call site. +:- pragma foreign_decl("Java", "import my_package.JavaMain;"). + + % Define the Mercury predicate java_main to call the Java function + % java_main. +:- pragma foreign_proc("Java", + java_main(IO0::di, IO::uo), + [promise_pure, will_not_call_mercury], +" + JavaMain.java_main(); + IO = IO0; +"). diff --git a/samples/java_interface/mercury_calls_java/mercury_main.m b/samples/java_interface/mercury_calls_java/mercury_main.m new file mode 100644 index 000000000..729990227 --- /dev/null +++ b/samples/java_interface/mercury_calls_java/mercury_main.m @@ -0,0 +1,19 @@ +% This source file is hereby placed in the public domain. + +:- module mercury_main. +:- interface. +:- import_module io. + +:- pred main(io::di, io::uo) is det. + +:- implementation. + +% import the module which defines the Mercury interface to the +% Java method JavaMain.java_main(). +:- import_module java_main_int. + +% main just invokes java_main +main(!IO) :- + io.write_string("In Mercury main, about to call java_main...\n", !IO), + java_main(!IO), + io.write_string("Back in Mercury main.\n", !IO).