diff truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @ 22046:e7c2d36daf72

TruffleLanguage.parse method to convert a source to CallTarget. Basic caching to make sure the code is shared among tenants in one JVM.
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Thu, 30 Jul 2015 17:36:34 +0200
parents 9c8c0937da41
children 6dd4ab4d76d3
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Thu Jul 30 17:16:59 2015 +0200
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Thu Jul 30 17:36:34 2015 +0200
@@ -31,9 +31,13 @@
 import com.oracle.truffle.api.debug.*;
 import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.vm.*;
 import com.oracle.truffle.api.vm.TruffleVM.Language;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * An entry point for everyone who wants to implement a Truffle based language. By providing
@@ -98,7 +102,24 @@
         return this.env;
     }
 
-    protected abstract Object eval(Source code) throws IOException;
+    /**
+     * Parses the provided source and generates appropriate AST. The parsing should execute no user
+     * code, it should only create the {@link Node} tree to represent the source. The parsing may be
+     * performed in a context (specified as another {@link Node}) or without context. The
+     * {@code argumentNames} may contain symbolic names for actual parameters of the call to the
+     * returned value. The result should be a call target with method
+     * {@link CallTarget#call(java.lang.Object...)} that accepts as many arguments as were provided
+     * via the {@code argumentNames} array.
+     *
+     * @param code source code to parse
+     * @param context a {@link Node} defining context for the parsing
+     * @param argumentNames symbolic names for parameters of
+     *            {@link CallTarget#call(java.lang.Object...)}
+     * @return a call target to invoke which also keeps in memory the {@link Node} tree representing
+     *         just parsed <code>code</code>
+     * @throws IOException thrown when I/O or parsing goes wrong
+     */
+    protected abstract CallTarget parse(Source code, Node context, String... argumentNames) throws IOException;
 
     /**
      * Called when some other language is seeking for a global symbol. This method is supposed to do
@@ -150,6 +171,18 @@
     protected abstract DebugSupportProvider getDebugSupport();
 
     /**
+     * Finds the currently executing context for current thread.
+     *
+     * @param <Language> type of language making the query
+     * @param language the language class
+     * @return the context associated with current execution
+     * @throws IllegalStateException if no context is associated with the execution
+     */
+    protected static <Language extends TruffleLanguage> Language findContext(Class<Language> language) {
+        return language.cast(API.findLanguage(null, language));
+    }
+
+    /**
      * Represents execution environment of the {@link TruffleLanguage}. Each active
      * {@link TruffleLanguage} receives instance of the environment before any code is executed upon
      * it. The environment has knowledge of all active languages and can exchange symbols between
@@ -229,9 +262,23 @@
             return super.importSymbol(vm, queryingLang, globalName);
         }
 
+        private static final Map<Source, CallTarget> COMPILED = Collections.synchronizedMap(new WeakHashMap<Source, CallTarget>());
+
         @Override
-        protected Object eval(TruffleLanguage l, Source s) throws IOException {
-            return l.eval(s);
+        protected Object eval(TruffleLanguage language, Source source) throws IOException {
+            CallTarget target = COMPILED.get(source);
+            if (target == null) {
+                target = language.parse(source, null);
+                if (target == null) {
+                    throw new IOException("Parsing has not produced a CallTarget for " + source);
+                }
+                COMPILED.put(source, target);
+            }
+            try {
+                return target.call();
+            } catch (Exception ex) {
+                throw new IOException(ex);
+            }
         }
 
         @Override
@@ -240,6 +287,11 @@
         }
 
         @Override
+        protected TruffleLanguage findLanguage(TruffleVM vm, Class<? extends TruffleLanguage> languageClass) {
+            return super.findLanguage(vm, languageClass);
+        }
+
+        @Override
         protected Object languageGlobal(TruffleLanguage l) {
             return l.getLanguageGlobal();
         }