changeset 21689:ed234a3178af

Behavior of null-like values is now part of the TCK
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 03 Jun 2015 10:17:19 +0200
parents 889b45a0dedd
children c8418635b575
files graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleTCK.java graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/SymbolInvokerImpl.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java
diffstat 6 files changed, 94 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleTCK.java	Tue Jun 02 21:15:59 2015 -0700
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleTCK.java	Wed Jun 03 10:17:19 2015 +0200
@@ -27,6 +27,7 @@
 import org.junit.*;
 
 import com.oracle.truffle.api.vm.*;
+import static org.junit.Assert.*;
 
 /**
  * A collection of tests that can certify language implementaiton to be complient with most recent
@@ -66,6 +67,18 @@
     }
 
     /**
+     * Name of a function that returns <code>null</code>. Truffle languages are encouraged to have
+     * their own type representing <code>null</code>, but when such value is returned from
+     * {@link TruffleVM#eval}, it needs to be converted to real Java <code>null</code> by sending a
+     * foreign access <em>isNull</em> message. There is a test to verify it is really true.
+     *
+     * @return name of globally exported symbol
+     */
+    protected String returnsNull() { // abstract
+        return null;
+    }
+
+    /**
      * Name of function to add two integer values together. The symbol will be invoked with two
      * parameters of type {@link Integer} and expects result of type {@link Number} which's
      * {@link Number#intValue()} is equivalent of <code>param1 + param2</code>.
@@ -104,6 +117,18 @@
     }
 
     @Test
+    public void testNull() throws Exception {
+        if (getClass() == TruffleTCK.class) {
+            return;
+        }
+        TruffleVM.Symbol retNull = findGlobalSymbol(returnsNull());
+
+        Object res = retNull.invoke(null);
+
+        assertNull("Should yield real Java null", res);
+    }
+
+    @Test
     public void testPlusWithInts() throws Exception {
         if (getClass() == TruffleTCK.class) {
             return;
--- a/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/SymbolInvokerImpl.java	Tue Jun 02 21:15:59 2015 -0700
+++ b/graal/com.oracle.truffle.interop/src/com/oracle/truffle/interop/SymbolInvokerImpl.java	Wed Jun 03 10:17:19 2015 +0200
@@ -30,6 +30,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.interop.*;
+import com.oracle.truffle.api.interop.exception.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.interop.messages.*;
 import com.oracle.truffle.interop.node.*;
@@ -39,10 +40,39 @@
 
     @Override
     protected Object invoke(Object symbol, Object... arr) throws IOException {
-        ForeignObjectAccessNode executeMain = ForeignObjectAccessNode.getAccess(Execute.create(Receiver.create(), arr.length));
-        CallTarget callTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(executeMain, (TruffleObject) symbol, arr));
+        ForeignObjectAccessNode callMain = ForeignObjectAccessNode.getAccess(Execute.create(Receiver.create(), arr.length));
+        CallTarget callMainTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(callMain, (TruffleObject) symbol, arr));
         VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(arr, UNUSED_FRAMEDESCRIPTOR);
-        return callTarget.call(frame);
+        Object ret = callMainTarget.call(frame);
+        if (ret instanceof TruffleObject) {
+            TruffleObject tret = (TruffleObject) ret;
+            Object isBoxedResult;
+            try {
+                ForeignObjectAccessNode isBoxed = ForeignObjectAccessNode.getAccess(IsBoxed.create(Receiver.create()));
+                CallTarget isBoxedTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(isBoxed, tret));
+                isBoxedResult = isBoxedTarget.call(frame);
+            } catch (UnsupportedMessageException ex) {
+                isBoxedResult = false;
+            }
+            if (Boolean.TRUE.equals(isBoxedResult)) {
+                ForeignObjectAccessNode unbox = ForeignObjectAccessNode.getAccess(Unbox.create(Receiver.create()));
+                CallTarget unboxTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(unbox, tret));
+                Object unboxResult = unboxTarget.call(frame);
+                return unboxResult;
+            } else {
+                try {
+                    ForeignObjectAccessNode isNull = ForeignObjectAccessNode.getAccess(IsNull.create(Receiver.create()));
+                    CallTarget isNullTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(isNull, tret));
+                    Object isNullResult = isNullTarget.call(frame);
+                    if (Boolean.TRUE.equals(isNullResult)) {
+                        return null;
+                    }
+                } catch (UnsupportedMessageException ex) {
+                    // fallthrough
+                }
+            }
+        }
+        return ret;
     }
 
     private static class TemporaryRoot extends RootNode {
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Tue Jun 02 21:15:59 2015 -0700
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Wed Jun 03 10:17:19 2015 +0200
@@ -41,14 +41,18 @@
     @Override
     protected TruffleVM prepareVM() throws Exception {
         TruffleVM vm = TruffleVM.newVM().build();
-        vm.eval("application/x-sl", // your langage
-                        "function fourtyTwo() {\n" + // your script
-                                        "  return 42;\n" + //
-                                        "}\n" + //
-                                        "function plus(a, b) {\n" + //
-                                        "  return a + b;\n" + //
-                                        "}\n" //
+        // @formatter:off
+        vm.eval("application/x-sl",
+            "function fourtyTwo() {\n" +
+            "  return 42;\n" + //
+            "}\n" +
+            "function plus(a, b) {\n" +
+            "  return a + b;\n" +
+            "}\n" +
+            "function null() {\n" +
+            "}\n"
         );
+        // @formatter:on
         return vm;
     }
 
@@ -61,4 +65,9 @@
     protected String plusInt() {
         return "plus";
     }
+
+    @Override
+    protected String returnsNull() {
+        return "null";
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Tue Jun 02 21:15:59 2015 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Wed Jun 03 10:17:19 2015 +0200
@@ -242,7 +242,7 @@
                 /* Call the main entry point, without any arguments. */
                 try {
                     result = main.invoke(null);
-                    if (result != SLNull.SINGLETON) {
+                    if (result != null) {
                         out.println(result);
                     }
                 } catch (UnsupportedSpecializationException ex) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java	Tue Jun 02 21:15:59 2015 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java	Wed Jun 03 10:17:19 2015 +0200
@@ -32,6 +32,7 @@
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.interop.ForeignAccessArguments;
 import com.oracle.truffle.interop.messages.Execute;
+import com.oracle.truffle.interop.messages.IsNull;
 import com.oracle.truffle.interop.messages.Receiver;
 import com.oracle.truffle.sl.nodes.call.SLDispatchNode;
 import com.oracle.truffle.sl.nodes.call.SLDispatchNodeGen;
@@ -55,6 +56,8 @@
     public CallTarget getAccess(Message tree) {
         if (Execute.create(Receiver.create(), 0).matchStructure(tree)) {
             return Truffle.getRuntime().createCallTarget(new SLForeignCallerRootNode());
+        } else if (IsNull.create(Receiver.create()).matchStructure(tree)) {
+            return Truffle.getRuntime().createCallTarget(new SLForeignNullCheckNode());
         } else {
             throw new UnsupportedMessageException(tree.toString() + " not supported");
         }
@@ -87,4 +90,11 @@
 
     }
 
+    private static class SLForeignNullCheckNode extends RootNode {
+        @Override
+        public Object execute(VirtualFrame frame) {
+            Object receiver = ForeignAccessArguments.getReceiver(frame.getArguments());
+            return SLNull.SINGLETON == receiver;
+        }
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java	Tue Jun 02 21:15:59 2015 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java	Wed Jun 03 10:17:19 2015 +0200
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.sl.runtime;
 
+import com.oracle.truffle.api.interop.ForeignAccessFactory;
+import com.oracle.truffle.api.interop.TruffleObject;
+
 /**
  * The SL type for a {@code null} (i.e., undefined) value. In Truffle, it is generally discouraged
  * to use the Java {@code null} value to represent the guest language {@code null} value. It is not
@@ -30,7 +33,7 @@
  * language {@code null} as a singleton, as in {@link #SINGLETON this class}, is the recommended
  * practice.
  */
-public final class SLNull {
+public final class SLNull implements TruffleObject {
 
     /**
      * The canonical value to represent {@code null} in SL.
@@ -52,4 +55,9 @@
     public String toString() {
         return "null";
     }
+
+    @Override
+    public ForeignAccessFactory getForeignAccessFactory() {
+        return SLFunctionForeignAccess.INSTANCE;
+    }
 }