changeset 22147:5857f5ee9486

More precise description of inter-operability messages and examples of their usage. Step #1 - e.g. the trivial messages.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Mon, 14 Sep 2015 13:33:03 +0200
parents d5f809827bf1
children 4125eb882b7e
files truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java
diffstat 2 files changed, 93 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java	Mon Sep 14 12:23:58 2015 +0200
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java	Mon Sep 14 13:33:03 2015 +0200
@@ -24,6 +24,7 @@
  */
 package com.oracle.truffle.api.interop;
 
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.interop.ForeignAccess.Factory;
 
@@ -36,26 +37,67 @@
     /**
      * Message to read an object field. The
      * {@link Factory#access(com.oracle.truffle.api.interop.Message) target} created for this
-     * message accepts single {@link ForeignAccess#getArguments(com.oracle.truffle.api.frame.Frame)
-     * argument} identifying a field to read - e.g. either {@link String} or an {@link Integer} - if
-     * access to an array at particular index is requested.
+     * message accepts (in addition to a
+     * {@link ForeignAccess#getReceiver(com.oracle.truffle.api.frame.Frame) receiver}) a single
+     * {@link ForeignAccess#getArguments(com.oracle.truffle.api.frame.Frame) argument} identifying a
+     * field to read - e.g. either {@link String} or an {@link Integer} - if access to an array at
+     * particular index is requested. The code that wants to send this message should use:
+     * 
+     * <pre>
+     * {@link ForeignAccess}.{@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) execute}(
+     *   {@link Message#READ}.{@link Message#createNode()}, {@link VirtualFrame currentFrame}, receiver, nameOfTheField
+     * );
+     * </pre>
+     * 
+     * Where <code>receiver</code> is the {@link TruffleObject foreign object} to access and
+     * <code>nameOfTheField</code> is the name (or index) of its field.
+     * <p>
+     * To achieve good performance it is essential to cache/keep reference to the
+     * {@link Message#createNode() created node}.
      */
     public static final Message READ = Read.INSTANCE;
 
     /**
      * Converts {@link TruffleObject truffle value} to Java primitive type. Primitive types are
-     * subclasses of {@link Number}, {@link Boolean}, {@link Character} and {@link String}. Related
-     * to {@link #IS_BOXED} message.
+     * subclasses of {@link Number}, {@link Boolean}, {@link Character} and {@link String}. Before
+     * sending the {@link #UNBOX} message, it is desirable to send the {@link #IS_BOXED} one and
+     * verify that the object can really be unboxed. To unbox an object, use:
+     * 
+     * <pre>
+     * {@link ForeignAccess}.{@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) execute}(
+     *   {@link Message#UNBOX}.{@link Message#createNode()}, {@link VirtualFrame currentFrame}, objectToUnbox
+     * );
+     * </pre>
+     * 
+     * The returned value should be subclass of {@link Number}, {@link Boolean}, {@link Character}
+     * or {@link String}.
+     * <p>
+     * To achieve good performance it is essential to cache/keep reference to the
+     * {@link Message#createNode() created node}.
      */
     public static final Message UNBOX = Unbox.INSTANCE;
 
     /**
      * Message to write a field. The {@link Factory#access(com.oracle.truffle.api.interop.Message)
-     * target} created for this message accepts two
+     * target} created for this message accepts the object to modify as a
+     * {@link ForeignAccess#getReceiver(com.oracle.truffle.api.frame.Frame) receiver} and two
      * {@link ForeignAccess#getArguments(com.oracle.truffle.api.frame.Frame) arguments}. The first
      * one identifies a field to read - e.g. either {@link String} or an {@link Integer} - if access
      * to an array at particular index is requested. The second one is the value to assign to such
-     * field.
+     * field. Use following style to construct field modification message:
+     * 
+     * <pre>
+     * {@link ForeignAccess}.{@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) execute}(
+     *   {@link Message#WRITE}.{@link Message#createNode()}, {@link VirtualFrame currentFrame}, receiver, nameOfTheField, newValue
+     * );
+     * </pre>
+     * 
+     * Where <code>receiver</code> is the {@link TruffleObject foreign object} to access,
+     * <code>nameOfTheField</code> is the name (or index) of its field and <code>newValue</code> is
+     * the value to assign to the receiver's field.
+     * <p>
+     * To achieve good performance it is essential to cache/keep reference to the
+     * {@link Message#createNode() created node}.
      */
     public static Message WRITE = Write.INSTANCE;
 
@@ -72,10 +114,25 @@
     }
 
     /**
-     * Message to check for executability.
+     * Message to check executability of a
+     * {@link ForeignAccess#getReceiver(com.oracle.truffle.api.frame.Frame) foreign object}.
      * <p>
      * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
-     * this message should yield value of {@link Boolean}.
+     * this message accepts {@link ForeignAccess#getArguments(com.oracle.truffle.api.frame.Frame) no
+     * arguments} and a single non-null
+     * {@link ForeignAccess#getReceiver(com.oracle.truffle.api.frame.Frame) receiver}. The call
+     * should yield value of {@link Boolean}. Either {@link Boolean#TRUE} if the receiver can be
+     * executed (e.g. accepts {@link #createExecute(int)} message, or {@link Boolean#FALSE}
+     * otherwise. This is the way to send the <code>IS_EXECUTABLE</code> message:
+     * 
+     * <pre>
+     * {@link Boolean} canBeExecuted = ({@link Boolean}) {@link ForeignAccess}.{@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) execute}(
+     *   {@link Message#IS_EXECUTABLE}.{@link Message#createNode()}, {@link VirtualFrame currentFrame}, receiver
+     * );
+     * </pre>
+     * <p>
+     * To achieve good performance it is essential to cache/keep reference to the
+     * {@link Message#createNode() created node}.
      */
     public static final Message IS_EXECUTABLE = IsExecutable.INSTANCE;
 
@@ -110,10 +167,20 @@
      * Check for <code>null</code> message. The Truffle languages are suggested to have their own
      * object representing <code>null</code> like values in their languages. For purposes of
      * inter-operability it is essential to canonicalize such values from time to time - sending
-     * this message is a way to recognize such <code>null</code> representing values.
+     * this message is a way to recognize such <code>null</code> representing values:
+     * 
+     * <pre>
+     * {@link Boolean} isNull = ({@link Boolean}) {@link ForeignAccess}.{@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) execute}(
+     *   {@link Message#IS_NULL}.{@link Message#createNode()}, {@link VirtualFrame currentFrame}, objectToCheckForNull
+     * );
+     * </pre>
+     *
      * <p>
      * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
      * this message should yield value of {@link Boolean}.
+     * <p>
+     * To achieve good performance it is essential to cache/keep reference to the
+     * {@link Message#createNode() created node}.
      */
     public static final Message IS_NULL = IsNull.INSTANCE;
 
@@ -135,13 +202,21 @@
     public static final Message GET_SIZE = GetSize.INSTANCE;
 
     /**
-     * Check for value being boxed. Can you value be converted to one of the basic Java types? Many
-     * languages have a special representation for types like number, string, etc. To ensure
-     * inter-operability, these types should support unboxing - if they do, they should handle this
-     * message.
-     * <p>
+     * Check for value being boxed. Can the {@link TruffleObject foreign object} be converted to one
+     * of the basic Java types? Many languages have a special representation for types like number,
+     * string, etc. To ensure inter-operability, these types should support unboxing - if they do,
+     * they should handle this message and return {@link Boolean#TRUE}. The way to check whether an
+     * object is boxed is:
+     * 
+     * <pre>
+     * {@link Boolean} isBoxed = ({@link Boolean}) {@link ForeignAccess}.{@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) execute}(
+     *   {@link Message#IS_BOXED}.{@link Message#createNode()}, {@link VirtualFrame currentFrame}, objectToCheck
+     * );
+     * </pre>
+     * 
      * Calling {@link Factory#accessMessage(com.oracle.truffle.api.interop.Message) the target}
-     * created for this message should yield value of {@link Boolean}.
+     * created for this message should yield value of {@link Boolean}. If the object responds with
+     * {@link Boolean#TRUE}, it is safe to continue by sending it {@link #UNBOX} message.
      */
     public static final Message IS_BOXED = IsBoxed.INSTANCE;
 
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Mon Sep 14 12:23:58 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Mon Sep 14 13:33:03 2015 +0200
@@ -197,8 +197,8 @@
 
     /**
      * Helper method to create a root node that always returns the same value. Certain operations
-     * (expecially {@link com.oracle.truffle.api.interop inter-operability} API) require return
-     * of stable {@link RootNode root nodes}. To simplify creation of such nodes, here is a factory
+     * (expecially {@link com.oracle.truffle.api.interop inter-operability} API) require return of
+     * stable {@link RootNode root nodes}. To simplify creation of such nodes, here is a factory
      * method that can create {@link RootNode} that returns always the same value.
      *
      * @param constant the constant to return