# HG changeset patch # User Jaroslav Tulach # Date 1443091861 -7200 # Node ID 1e753eabe50380bd7dcfc81b04d2b030a712ffca # Parent 93a6b7597937fcee05a0c8f9366dd61ab80d804a Describing the semantics of Java/Truffle object interop diff -r 93a6b7597937 -r 1e753eabe503 truffle/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaInterop.java --- a/truffle/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaInterop.java Wed Sep 23 23:55:03 2015 +0200 +++ b/truffle/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaInterop.java Thu Sep 24 12:51:01 2015 +0200 @@ -49,6 +49,50 @@ * just encapsulates it into Java facade to make it as natural to access foreign * {@link TruffleObject Truffle objects} as Java programmers are used to when accessing * Java objects and interfaces directly. + * + *

Java/Truffle Object Inter-op Semantics

+ * + * In case your language exposes a {@link TruffleObject} implementation, and somebody wraps your + * object into a JavaInterop interface via + * {@link #asJavaObject(java.lang.Class, com.oracle.truffle.api.interop.TruffleObject)} method, this + * is the set of {@link Message messages} you can expect: + *

+ * Users can send you any message by annotating their interface method with {@link MethodMessage} + * and it is up to them (and you) to negotiate the correct set of messages and their parameters to + * help you understand each other. However there is a default set of {@link Message messages} (for + * methods not annotated by {@link MethodMessage}) which consists of: + *

    + *
  1. First of all {@link Message#createInvoke(int)} is constructed (with the number of parameters + * of the interface method) and delivered to your object. The + * {@link ForeignAccess#getReceiver(com.oracle.truffle.api.frame.Frame) receiver} of the message is + * your {@link TruffleObject}. The first + * {@link ForeignAccess#getArguments(com.oracle.truffle.api.frame.Frame) argument} is name of the + * interface method, followed by the + * {@link ForeignAccess#getArguments(com.oracle.truffle.api.frame.Frame) actual arguments} of the + * interface method. Your language can either handle the message or throw + * {@link IllegalArgumentException} to signal additional processing is needed.
  2. + *
  3. + * If the {@link Message#createInvoke(int) previous message} isn't handled, a {@link Message#READ} + * is sent to your {@link TruffleObject object} (e.g. + * {@link ForeignAccess#getReceiver(com.oracle.truffle.api.frame.Frame) receiver}) with a field name + * equal to the name of the interface method. If the read returns a primitive type, it is returned.
  4. + *
  5. + * If the read value is another {@link TruffleObject}, it is inspected whether it handles + * {@link Message#IS_EXECUTABLE}. If it does, a message {@link Message#createExecute(int)} with name + * of the interface method and its parameters is sent to the object. The result is returned to the + * interface method caller.
  6. + *
  7. + * In case the read value is neither primitive, neither {@link Message#IS_EXECUTABLE executable}, + * and the interface method has no parameters, it is returned back.
  8. + *
  9. + * All other cases yield an {@link IllegalArgumentException}.
  10. + *
+ *

+ * Object oriented languages are expected to handle the initial {@link Message#createInvoke(int)} + * message. Non-OOP languages are expected to ignore it, yield {@link IllegalArgumentException} and + * handle the subsequent {@link Message#READ read} and {@link Message#createExecute(int) execute} + * ones. The real semantic however depends on the actual language one is communicating with. + *

*/ public final class JavaInterop { static final Object[] EMPTY = {}; @@ -351,7 +395,7 @@ if (args.length == 0) { return toJava(attr, method); } - throw new IllegalStateException(attr + " cannot be invoked with " + args.length + " parameters"); + throw new IllegalArgumentException(attr + " cannot be invoked with " + args.length + " parameters"); } List callArgs = new ArrayList<>(args.length + 1); // callArgs.add(attr); @@ -360,7 +404,7 @@ } return toJava(ret, method); } - throw new IllegalStateException("Unknown message: " + message); + throw new IllegalArgumentException("Unknown message: " + message); } }