changeset 22284:33d49924a921

PolyglotEngine.Value.as(String.class) gives the language that produced the value a chance to do its conversion to appropriate textual representation.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 07 Oct 2015 13:32:25 +0200
parents bc0c838ba705
children 58b0a3e41785
files truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java
diffstat 6 files changed, 131 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Wed Oct 07 12:39:09 2015 +0200
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Wed Oct 07 13:32:25 2015 +0200
@@ -53,6 +53,7 @@
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import java.util.Objects;
 
 public class ImplicitExplicitExportTest {
     private static Thread mainThread;
@@ -275,6 +276,19 @@
 
         public ExportImportLanguage1() {
         }
+
+        @Override
+        protected String toString(Ctx ctx, Object value) {
+            if (value instanceof String) {
+                try {
+                    int number = Integer.parseInt((String) value);
+                    return number + ": Int";
+                } catch (NumberFormatException ex) {
+                    // go on
+                }
+            }
+            return Objects.toString(value);
+        }
     }
 
     @TruffleLanguage.Registration(mimeType = L2, name = "ImportExport2", version = "0")
@@ -283,6 +297,19 @@
 
         public ExportImportLanguage2() {
         }
+
+        @Override
+        protected String toString(Ctx ctx, Object value) {
+            if (value instanceof String) {
+                try {
+                    double number = Double.parseDouble((String) value);
+                    return number + ": Double";
+                } catch (NumberFormatException ex) {
+                    // go on
+                }
+            }
+            return Objects.toString(value);
+        }
     }
 
     @TruffleLanguage.Registration(mimeType = L3, name = "ImportExport3", version = "0")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ToStringTest.java	Wed Oct 07 13:32:25 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.vm;
+
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class ToStringTest {
+    @Test
+    public void valueToStringValueWith1() throws Exception {
+        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
+        PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2");
+        language2.eval(Source.fromText("explicit.value=42", "define 42"));
+        PolyglotEngine.Value value = language1.eval(Source.fromText("return=value", "42.value"));
+        assertEquals("It's fourtytwo", "42", value.get());
+
+        String textual = value.as(String.class);
+        assertEquals("Nicely formated as by L1", "42: Int", textual);
+    }
+
+    @Test
+    public void valueToStringValueWith2() throws Exception {
+        PolyglotEngine engine = PolyglotEngine.buildNew().build();
+        PolyglotEngine.Language language1 = engine.getLanguages().get("application/x-test-import-export-1");
+        PolyglotEngine.Language language2 = engine.getLanguages().get("application/x-test-import-export-2");
+        language1.eval(Source.fromText("explicit.value=42", "define 42"));
+        PolyglotEngine.Value value = language2.eval(Source.fromText("return=value", "42.value"));
+        assertEquals("It's fourtytwo", "42", value.get());
+
+        String textual = value.as(String.class);
+        assertEquals("Nicely formated as by L2", "42.0: Double", textual);
+    }
+
+}
--- a/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Wed Oct 07 12:39:09 2015 +0200
+++ b/truffle/com.oracle.truffle.api.vm/src/com/oracle/truffle/api/vm/PolyglotEngine.java	Wed Oct 07 13:32:25 2015 +0200
@@ -707,7 +707,10 @@
          * Obtains Java view of the object represented by this symbol. The method basically
          * delegates to
          * {@link JavaInterop#asJavaObject(java.lang.Class, com.oracle.truffle.api.interop.TruffleObject)}
-         * just handles primitive types as well.
+         * . The method handles primitive types (like {@link Number}, etc.) by casting and returning
+         * them. When a {@link String}.<code>class</code> is requested, the method let's the
+         * language that produced the value to do the
+         * {@link TruffleLanguage#toString(java.lang.Object, java.lang.Object) necessary formating}.
          *
          * @param <T> the type of the view one wants to obtain
          * @param representation the class of the view interface (it has to be an interface)
@@ -723,6 +726,10 @@
                     return representation.cast(eto.getDelegate());
                 }
             }
+            if (representation == String.class) {
+                final Class<? extends TruffleLanguage> clazz = language.getClass();
+                return representation.cast(SPI.toString(language, findEnv(clazz), obj));
+            }
             if (representation.isInstance(obj)) {
                 return representation.cast(obj);
             }
@@ -1043,5 +1050,10 @@
         protected void dispose(TruffleLanguage<?> impl, TruffleLanguage.Env env) {
             super.dispose(impl, env);
         }
+
+        @Override
+        protected String toString(TruffleLanguage language, TruffleLanguage.Env env, Object obj) {
+            return super.toString(language, env, obj);
+        }
     } // end of SPIAccessor
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Wed Oct 07 12:39:09 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Wed Oct 07 13:32:25 2015 +0200
@@ -56,6 +56,7 @@
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
+import java.util.Objects;
 
 /**
  * An entry point for everyone who wants to implement a Truffle based language. By providing an
@@ -271,6 +272,23 @@
     protected abstract Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws IOException;
 
     /**
+     * Generates language specific textual representation of a value. Each language may have special
+     * formating conventions - even primitive values may not follow the traditional Java formating
+     * rules. As such when
+     * {@link com.oracle.truffle.api.vm.PolyglotEngine.Value#as(java.lang.Class)
+     * value.as(String.class)} is requested, it consults the language that produced the value by
+     * calling this method. By default this method calls {@link Objects#toString(java.lang.Object)}.
+     *
+     * @param context the execution context for doing the conversion
+     * @param value the value to convert. Either primitive type or
+     *            {@link com.oracle.truffle.api.interop.TruffleObject}
+     * @return textual representation of the value in this language
+     */
+    protected String toString(C context, Object value) {
+        return Objects.toString(value);
+    }
+
+    /**
      * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
      * that, when executed, computes the result of a textual expression in the language; used to
      * create an
@@ -343,6 +361,11 @@
         void dispose() {
             lang.disposeContext(ctx);
         }
+
+        String toString(TruffleLanguage<?> language, Object obj) {
+            assert lang == language;
+            return lang.toString(ctx, obj);
+        }
     }
 
     /**
@@ -526,6 +549,11 @@
             assert impl == env.langCtx.lang;
             env.langCtx.dispose();
         }
+
+        @Override
+        protected String toString(TruffleLanguage<?> language, Env env, Object obj) {
+            return env.langCtx.toString(language, obj);
+        }
     }
 
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Wed Oct 07 12:39:09 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Wed Oct 07 13:32:25 2015 +0200
@@ -342,4 +342,8 @@
     protected void dispose(TruffleLanguage<?> impl, Env env) {
         API.dispose(impl, env);
     }
+
+    protected String toString(TruffleLanguage<?> language, Env env, Object obj) {
+        return API.toString(language, env, obj);
+    }
 }
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Wed Oct 07 12:39:09 2015 +0200
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Wed Oct 07 13:32:25 2015 +0200
@@ -375,8 +375,8 @@
         final PolyglotEngine.Value result = apply.invoke(null, fn);
 
         try {
-            String res = result.as(String.class);
-            fail("Cannot be converted to String: " + res);
+            Boolean res = result.as(Boolean.class);
+            fail("Cannot be converted to Boolean: " + res);
         } catch (ClassCastException ex) {
             // correct
         }