changeset 22052:446ec33cadbe

Merge
author Mick Jordan <mick.jordan@oracle.com>
date Fri, 31 Jul 2015 14:49:02 -0700
parents b26deb163f16 (current diff) 7a5b874b8d12 (diff)
children 867960de3e9a
files truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java
diffstat 23 files changed, 320 insertions(+), 196 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Jul 31 14:42:26 2015 -0700
+++ b/.hgtags	Fri Jul 31 14:49:02 2015 -0700
@@ -617,3 +617,4 @@
 754f2b20d8bc43053d254826e6b9f09db3f3c992 graal-0.7
 
 7aab14a2bb4e5c06b2fb252753a4beca184eec5f graal-0.8
+7aab14a2bb4e5c06b2fb252753a4beca184eec5f truffle-0.8
--- a/mx.truffle/mx_truffle.py	Fri Jul 31 14:42:26 2015 -0700
+++ b/mx.truffle/mx_truffle.py	Fri Jul 31 14:49:02 2015 -0700
@@ -39,21 +39,6 @@
     opts2 = mx.build(['--source', '1.7'] + args)
     assert len(opts2.remainder) == 0
 
-def maven_install_truffle(args):
-    """install Truffle into your local Maven repository"""
-    for name in mx._dists:
-        dist = mx._dists[name]
-        if dist.isProcessorDistribution:
-            continue
-        mx.archive(["@" + name])
-        path = dist.path
-        slash = path.rfind('/')
-        dot = path.rfind('.')
-        if dot <= slash:
-            mx.abort('Dot should be after / in ' + path)
-        artifactId = path[slash + 1: dot]
-        mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle.' + dist.suite.name, '-DartifactId=' + artifactId, '-Dversion=' + mx.suite('truffle').release_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=' + path])
-
 def sl(args):
     """run an SL program"""
     vmArgs, slArgs = mx.extract_VM_args(args)
@@ -71,7 +56,6 @@
 mx_gate.add_gate_runner(_suite, _truffle_gate_runner)
 
 mx.update_commands(_suite, {
-    'maven-install-truffle' : [maven_install_truffle, ''],
     'sl' : [sl, '[SL args|@VM options]'],
     'sldebug' : [sldebug, '[SL args|@VM options]'],
 })
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java	Fri Jul 31 14:49:02 2015 -0700
@@ -22,9 +22,11 @@
  */
 package com.oracle.truffle.api.dsl.test;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.debug.DebugSupportProvider;
 import com.oracle.truffle.api.instrument.ToolSupportProvider;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import java.io.IOException;
 
@@ -36,7 +38,7 @@
     }
 
     @Override
-    protected Object eval(Source code) throws IOException {
+    protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
         throw new IOException();
     }
 
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java	Fri Jul 31 14:49:02 2015 -0700
@@ -28,6 +28,7 @@
 import com.oracle.truffle.api.debug.*;
 import com.oracle.truffle.api.dsl.test.*;
 import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.*;
 
 public class LanguageRegistrationTest {
@@ -55,8 +56,8 @@
         }
 
         @Override
-        protected Object eval(Source code) throws IOException {
-            return null;
+        protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
+            throw new IOException();
         }
 
         @Override
@@ -94,8 +95,8 @@
         }
 
         @Override
-        protected Object eval(Source code) throws IOException {
-            return null;
+        protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
+            throw new IOException();
         }
 
         @Override
@@ -132,11 +133,6 @@
         }
 
         @Override
-        protected Object eval(Source code) throws IOException {
-            return null;
-        }
-
-        @Override
         protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
             return null;
         }
@@ -161,5 +157,10 @@
             return null;
         }
 
+        @Override
+        protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
+            throw new IOException();
+        }
+
     }
 }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java	Fri Jul 31 14:49:02 2015 -0700
@@ -22,9 +22,11 @@
  */
 package com.oracle.truffle.api.test;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.debug.DebugSupportProvider;
 import com.oracle.truffle.api.instrument.ToolSupportProvider;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import java.io.IOException;
 
@@ -36,7 +38,7 @@
     }
 
     @Override
-    protected Object eval(Source code) throws IOException {
+    protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
         throw new IOException();
     }
 
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java	Fri Jul 31 14:49:02 2015 -0700
@@ -45,13 +45,13 @@
 
     // Temp disable of empty text tests
 
-// @Test(expected = IllegalArgumentException.class)
+    // @Test(expected = IllegalArgumentException.class)
     @Test()
     public void emptyTextTest1() {
         emptySource.getLineNumber(0);
     }
 
-// @Test(expected = IllegalArgumentException.class)
+    // @Test(expected = IllegalArgumentException.class)
     @Test()
     public void emptyTextTest2() {
         emptySource.getColumnNumber(0);
@@ -62,18 +62,18 @@
         emptySource.getLineNumber(-1);
     }
 
-// @Test(expected = IllegalArgumentException.class)
+    // @Test(expected = IllegalArgumentException.class)
     @Test()
     public void emptyTextTest4() {
         emptySource.getLineStartOffset(0);
     }
 
-// @Test(expected = IllegalArgumentException.class)
+    // @Test(expected = IllegalArgumentException.class)
     public void emptyTextTest5() {
         emptySource.getLineStartOffset(1);
     }
 
-// @Test(expected = IllegalArgumentException.class)
+    // @Test(expected = IllegalArgumentException.class)
     public void emptyTextTest6() {
         emptySource.getLineLength(1);
     }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Fri Jul 31 14:49:02 2015 -0700
@@ -32,6 +32,8 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.debug.*;
 import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.vm.*;
 
@@ -115,28 +117,8 @@
         private final Map<String, String> implicit = new HashMap<>();
 
         @Override
-        protected Object eval(Source code) throws IOException {
-            Properties p = new Properties();
-            try (Reader r = code.getReader()) {
-                p.load(r);
-            }
-            Enumeration<Object> en = p.keys();
-            while (en.hasMoreElements()) {
-                Object n = en.nextElement();
-                if (n instanceof String) {
-                    String k = (String) n;
-                    if (k.startsWith("explicit.")) {
-                        explicit.put(k.substring(9), p.getProperty(k));
-                    }
-                    if (k.startsWith("implicit.")) {
-                        implicit.put(k.substring(9), p.getProperty(k));
-                    }
-                    if (k.equals("return")) {
-                        return env().importSymbol(p.getProperty(k));
-                    }
-                }
-            }
-            return null;
+        protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
+            return new ValueCallTarget(code, getClass());
         }
 
         @Override
@@ -150,6 +132,10 @@
             return null;
         }
 
+        public static <Language extends TruffleLanguage> Language findContext(Class<Language> type) {
+            return TruffleLanguage.findContext(type);
+        }
+
         @Override
         protected Object getLanguageGlobal() {
             return null;
@@ -169,6 +155,53 @@
         protected DebugSupportProvider getDebugSupport() {
             return null;
         }
+
+        private Object importExport(Source code) {
+            Properties p = new Properties();
+            try (Reader r = code.getReader()) {
+                p.load(r);
+            } catch (IOException ex) {
+                throw new IllegalStateException(ex);
+            }
+            Enumeration<Object> en = p.keys();
+            while (en.hasMoreElements()) {
+                Object n = en.nextElement();
+                if (n instanceof String) {
+                    String k = (String) n;
+                    if (k.startsWith("explicit.")) {
+                        explicit.put(k.substring(9), p.getProperty(k));
+                    }
+                    if (k.startsWith("implicit.")) {
+                        implicit.put(k.substring(9), p.getProperty(k));
+                    }
+                    if (k.equals("return")) {
+                        return env().importSymbol(p.getProperty(k));
+                    }
+                }
+            }
+            return null;
+        }
+    }
+
+    private static final class ValueCallTarget implements RootCallTarget {
+        private final Source code;
+        private final Class<? extends AbstractExportImportLanguage> language;
+
+        private ValueCallTarget(Source code, Class<? extends AbstractExportImportLanguage> language) {
+            this.code = code;
+            this.language = language;
+        }
+
+        @Override
+        public RootNode getRootNode() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Object call(Object... arguments) {
+            AbstractExportImportLanguage context = AbstractExportImportLanguage.findContext(language);
+            return context.importExport(code);
+        }
     }
 
     static final String L1 = "application/x-test-import-export-1";
--- a/truffle/com.oracle.truffle.api/.checkstyle_checks.xml	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api/.checkstyle_checks.xml	Fri Jul 31 14:49:02 2015 -0700
@@ -209,7 +209,7 @@
   <module name="SuppressionCommentFilter">
     <property name="offCommentFormat" value="CheckStyle: start generated"/>
     <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-    <property name="checkFormat" value=".*Name|.*LineLength"/>
+    <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
   </module>
   <module name="RegexpSingleline">
     <property name="format" value="System\.(out|err)\.print"/>
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Fri Jul 31 14:49:02 2015 -0700
@@ -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 <Lang> 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 <Lang extends TruffleLanguage> Lang findContext(Class<Lang> 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();
         }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java	Fri Jul 31 14:49:02 2015 -0700
@@ -30,12 +30,14 @@
  * needs to turn debugging on when constructing its Truffle virtual machine:
  * <pre>
  * vm = {@link com.oracle.truffle.api.vm.TruffleVM#newVM()}.
- *     {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}{@link com.oracle.truffle.api.debug.ExecutionEvent}{@code >}() {
+ *     {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}
+ *     {@code <}{@link com.oracle.truffle.api.debug.ExecutionEvent}{@code >}() {
  *         <b>public void</b> handle({@link com.oracle.truffle.api.debug.ExecutionEvent} ev) {
  *             <em>// configure the virtual machine as {@link com.oracle.truffle.api.vm.TruffleVM#eval(java.net.URI) new execution} is starting</em>
  *         }
  *     }).
- *     {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}{@link com.oracle.truffle.api.debug.SuspendedEvent}{@code >}() {
+ *     {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}
+ *     {@link com.oracle.truffle.api.debug.SuspendedEvent}{@code >}() {
  *         <b>public void</b> handle({@link com.oracle.truffle.api.debug.SuspendedEvent} ev) {
  *             <em>// execution is suspended on a breakpoint or on a step - decide what next</em>
  *         }
@@ -43,30 +45,31 @@
  * </pre>
  * The debugging is controlled by events emitted by the Truffle virtual machine
  * at important moments. The {@link com.oracle.truffle.api.debug.ExecutionEvent}
- * is sent when a call to {@link com.oracle.truffle.api.vm.TruffleVM#eval(java.net.URI) eval(...)} 
+ * is sent when a call to {@link com.oracle.truffle.api.vm.TruffleVM#eval(java.net.URI) eval(...)}
  * is made and allows one to configure {@link com.oracle.truffle.api.debug.Breakpoint breakpoints} and/or decide whether the
- * program should {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto() step-into} or 
+ * program should {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto() step-into} or
  * {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareContinue() just run}. Once the execution is suspended a
  * {@link com.oracle.truffle.api.debug.SuspendedEvent} is generated which
  * allows one to inspect the stack and choose the further execution mode
- * ({@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepInto(int) step-into}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOver(int) step-over}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOut() step-out}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareContinue() continue}).
+ * ({@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepInto(int) step-into}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOver(int) step-over},
+ *  {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOut() step-out}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareContinue() continue}).
  * <p>
  * The events methods are only available when the event is being delivered and
  * shouldn't be used anytime later. Both events however provide access to
  * {@link com.oracle.truffle.api.debug.Debugger} which can be kept and used
  * during whole existence of the {@link com.oracle.truffle.api.vm.TruffleVM}.
- * {@link com.oracle.truffle.api.debug.Debugger} is the central class that 
+ * {@link com.oracle.truffle.api.debug.Debugger} is the central class that
  * keeps information about {@link com.oracle.truffle.api.debug.Debugger#getBreakpoints() registered breakpoints}
  * and allows one create new {@link com.oracle.truffle.api.debug.Breakpoint ones}.
- * 
+ *
  * <h4>Turning on Stepping Mode</h4>
- * 
+ *
  * In case you want your execution to pause on first statement, register for
  * {@link com.oracle.truffle.api.debug.ExecutionEvent} and once delivered
  * call {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto()}.
  *
  * <h4>Register a {@link com.oracle.truffle.api.debug.Breakpoint}</h4>
- * 
+ *
  * Wait for execution to be started - which generates an
  * {@link com.oracle.truffle.api.debug.ExecutionEvent}. Use its
  * {@link com.oracle.truffle.api.debug.Debugger ev.getDebugger}()
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Fri Jul 31 14:49:02 2015 -0700
@@ -45,15 +45,11 @@
     private static Accessor NODES;
     private static Accessor INSTRUMENT;
     private static Accessor DEBUG;
+    private static final ThreadLocal<TruffleVM> CURRENT_VM = new ThreadLocal<>();
 
     static {
         TruffleLanguage lng = new TruffleLanguage(null) {
             @Override
-            protected Object eval(Source code) throws IOException {
-                return null;
-            }
-
-            @Override
             protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
                 return null;
             }
@@ -77,6 +73,11 @@
             protected DebugSupportProvider getDebugSupport() {
                 return null;
             }
+
+            @Override
+            protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException {
+                throw new IOException();
+            }
         };
         lng.hashCode();
         new Node(null) {
@@ -161,12 +162,31 @@
         return INSTRUMENT.findLanguage(probe);
     }
 
-    protected TruffleLanguage findLanguage(TruffleVM vm, Class<? extends TruffleLanguage> languageClass) {
+    protected TruffleLanguage findLanguage(TruffleVM known, Class<? extends TruffleLanguage> languageClass) {
+        TruffleVM vm;
+        if (known == null) {
+            vm = CURRENT_VM.get();
+            if (vm == null) {
+                throw new IllegalStateException();
+            }
+        } else {
+            vm = known;
+        }
         return SPI.findLanguage(vm, languageClass);
     }
 
     protected Closeable executionStart(TruffleVM vm, Debugger[] fillIn, Source s) {
-        return DEBUG.executionStart(vm, fillIn, s);
+        final Closeable debugClose = DEBUG.executionStart(vm, fillIn, s);
+        final TruffleVM prev = CURRENT_VM.get();
+        CURRENT_VM.set(vm);
+        class ContextCloseable implements Closeable {
+            @Override
+            public void close() throws IOException {
+                CURRENT_VM.set(prev);
+                debugClose.close();
+            }
+        }
+        return new ContextCloseable();
     }
 
     protected void dispatchEvent(TruffleVM vm, Object event) {
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Fri Jul 31 14:49:02 2015 -0700
@@ -164,5 +164,4 @@
         }
         return new DefaultLoopNode(repeating);
     }
-
 }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Fri Jul 31 14:49:02 2015 -0700
@@ -814,7 +814,7 @@
 
         @Override
         public int hashCode() {
-            return description.hashCode();
+            return description.hashCode() * code.hashCode();
         }
 
         @Override
@@ -827,7 +827,7 @@
             }
             if (obj instanceof LiteralSource) {
                 LiteralSource other = (LiteralSource) obj;
-                return description.equals(other.description);
+                return description.equals(other.description) && code.equals(other.code);
             }
             return false;
         }
--- a/truffle/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml	Fri Jul 31 14:49:02 2015 -0700
@@ -207,6 +207,6 @@
   <module name="SuppressionCommentFilter">
     <property name="offCommentFormat" value="CheckStyle: start generated"/>
     <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-    <property name="checkFormat" value=".*Name|.*LineLength"/>
+    <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
   </module>
 </module>
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Fri Jul 31 14:49:02 2015 -0700
@@ -70,6 +70,14 @@
             "function apply(f) {\n" +
             "  return f(18, 32) + 10;\n" +
             "}\n" +
+            "function cnt() {\n" +
+            "  return 0;\n" +
+            "}\n" +
+            "function count() {\n" +
+            "  n = cnt() + 1;\n" +
+            "  defineFunction(\"function cnt() { return \" + n + \"; }\");\n" +
+            "  return n;\n" +
+            "}\n" +
             "function null() {\n" +
             "}\n"
         );
@@ -111,4 +119,9 @@
             "}\n";
         // @formatter:on
     }
+
+    @Override
+    protected String countInvocations() {
+        return "count";
+    }
 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Fri Jul 31 14:49:02 2015 -0700
@@ -56,7 +56,6 @@
 import com.oracle.truffle.api.vm.*;
 import com.oracle.truffle.api.vm.TruffleVM.Symbol;
 import com.oracle.truffle.sl.builtins.*;
-import com.oracle.truffle.sl.factory.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.nodes.call.*;
 import com.oracle.truffle.sl.nodes.controlflow.*;
@@ -155,7 +154,6 @@
  */
 @TruffleLanguage.Registration(name = "SL", version = "0.5", mimeType = "application/x-sl")
 public class SLLanguage extends TruffleLanguage {
-    private static SLLanguage LAST;
     private static List<NodeFactory<? extends SLBuiltinNode>> builtins = Collections.emptyList();
     private static Visualizer visualizer = new SLDefaultVisualizer();
     private static ASTProber registeredASTProber; // non-null if prober already registered
@@ -164,10 +162,9 @@
 
     public SLLanguage(Env env) {
         super(env);
-        context = SLContextFactory.create(this, new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true));
-        LAST = this;
+        context = new SLContext(this, new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true));
         for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) {
-            context.installBuiltin(builtin);
+            context.installBuiltin(builtin, true);
         }
     }
 
@@ -258,7 +255,7 @@
         /* Change to dump the AST to IGV over the network. */
         boolean dumpASTToIGV = false;
 
-        printScript("before execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
+        printScript("before execution", null, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
         long totalRuntime = 0;
         try {
             for (int i = 0; i < repeats; i++) {
@@ -283,7 +280,7 @@
             }
 
         } finally {
-            printScript("after execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
+            printScript("after execution", null, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
         }
         return totalRuntime;
     }
@@ -381,14 +378,43 @@
         return result.toString();
     }
 
+    public static SLLanguage find() {
+        return SLLanguage.findContext(SLLanguage.class);
+    }
+
     @Override
-    protected Object eval(Source code) throws IOException {
+    protected CallTarget parse(Source code, Node node, String... argumentNames) throws IOException {
+        final SLContext c = new SLContext(this);
+        final Exception[] failed = {null};
         try {
-            context.evalSource(code);
+            c.evalSource(code);
+            failed[0] = null;
         } catch (Exception e) {
-            throw new IOException(e);
+            failed[0] = e;
         }
-        return null;
+        return new CallTarget() {
+            @Override
+            public Object call(Object... arguments) {
+                if (failed[0] instanceof RuntimeException) {
+                    throw (RuntimeException) failed[0];
+                }
+                if (failed[0] != null) {
+                    throw new IllegalStateException(failed[0]);
+                }
+                SLLanguage current = SLLanguage.find();
+                SLContext fillIn = current.context;
+                final SLFunctionRegistry functionRegistry = fillIn.getFunctionRegistry();
+                for (SLFunction f : c.getFunctionRegistry().getFunctions()) {
+                    RootCallTarget callTarget = f.getCallTarget();
+                    if (callTarget == null) {
+                        continue;
+                    }
+                    functionRegistry.lookup(f.getName());
+                    functionRegistry.register(f.getName(), (SLRootNode) f.getCallTarget().getRootNode());
+                }
+                return null;
+            }
+        };
     }
 
     @Override
@@ -465,6 +491,10 @@
         }
     }
 
+    public SLContext getContext() {
+        return context;
+    }
+
     private final class SLDebugProvider implements DebugSupportProvider {
 
         public SLDebugProvider() {
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Fri Jul 31 14:42:26 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * The Universal Permissive License (UPL), Version 1.0
- * 
- * Subject to the condition set forth below, permission is hereby granted to any
- * person obtaining a copy of this software, associated documentation and/or
- * data (collectively the "Software"), free of charge and under any and all
- * copyright rights in the Software, and any and all patent rights owned or
- * freely licensable by each licensor hereunder covering either (i) the
- * unmodified Software as contributed to or provided by such licensor, or (ii)
- * the Larger Works (as defined below), to deal in both
- * 
- * (a) the Software, and
- * 
- * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
- * one is included with the Software each a "Larger Work" to which the Software
- * is contributed by such licensors),
- * 
- * without restriction, including without limitation the rights to copy, create
- * derivative works of, display, perform, and distribute the Software and make,
- * use, sell, offer for sale, import, export, have made, and have sold the
- * Software and the Larger Work(s), and to sublicense the foregoing rights on
- * either these or other terms.
- * 
- * This license is subject to the following condition:
- * 
- * The above copyright notice and either this complete permission notice or at a
- * minimum a reference to the UPL must be included in all copies or substantial
- * portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package com.oracle.truffle.sl.factory;
-
-import com.oracle.truffle.sl.SLLanguage;
-import java.io.*;
-
-import com.oracle.truffle.sl.runtime.*;
-
-public final class SLContextFactory {
-
-    private SLContextFactory() {
-    }
-
-    public static SLContext create(SLLanguage sl, BufferedReader input, PrintWriter output) {
-        return new SLContext(sl, input, output);
-    }
-}
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Fri Jul 31 14:49:02 2015 -0700
@@ -41,7 +41,6 @@
 package com.oracle.truffle.sl.nodes;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.nodes.*;
@@ -65,16 +64,13 @@
     /** The name of the function, for printing purposes only. */
     private final String name;
 
-    /** The Simple execution context for this tree. **/
-    private final SLContext context;
-
     @CompilationFinal private boolean isCloningAllowed;
 
-    public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) {
+    @SuppressWarnings("unused")
+    public SLRootNode(SLContext ignore, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) {
         super(SLLanguage.class, null, frameDescriptor);
         this.bodyNode = bodyNode;
         this.name = name;
-        this.context = context;
     }
 
     @Override
@@ -108,13 +104,4 @@
     public String toString() {
         return "root " + name;
     }
-
-    public SLContext getSLContext() {
-        return this.context;
-    }
-
-    @Override
-    public ExecutionContext getExecutionContext() {
-        return this.context;
-    }
 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Fri Jul 31 14:49:02 2015 -0700
@@ -44,6 +44,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.SLLanguage;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
@@ -56,15 +57,16 @@
 @NodeInfo(shortName = "func")
 public final class SLFunctionLiteralNode extends SLExpressionNode {
 
-    private final SLFunction value;
+    private final String value;
 
-    public SLFunctionLiteralNode(SourceSection src, SLFunction value) {
+    public SLFunctionLiteralNode(SourceSection src, String value) {
         super(src);
         this.value = value;
     }
 
     @Override
     public SLFunction executeGeneric(VirtualFrame frame) {
-        return value;
+        SLLanguage language = SLLanguage.find();
+        return language.getContext().getFunctionRegistry().lookup(value);
     }
 }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Fri Jul 31 14:49:02 2015 -0700
@@ -331,7 +331,7 @@
             return SLReadLocalVariableNodeGen.create(src, frameSlot);
         } else {
             /* Read of a global name. In our language, the only global names are functions. */
-            return new SLFunctionLiteralNode(src, context.getFunctionRegistry().lookup(nameToken.val));
+            return new SLFunctionLiteralNode(src, nameToken.val);
         }
     }
 
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Fri Jul 31 14:49:02 2015 -0700
@@ -74,11 +74,19 @@
     private final Shape emptyShape;
 
     public SLContext(SLLanguage language, BufferedReader input, PrintWriter output) {
+        this(language, input, output, true);
+    }
+
+    public SLContext(SLLanguage language) {
+        this(language, null, null, false);
+    }
+
+    private SLContext(SLLanguage language, BufferedReader input, PrintWriter output, boolean installBuiltins) {
         this.language = language;
         this.input = input;
         this.output = output;
         this.functionRegistry = new SLFunctionRegistry();
-        installBuiltins();
+        installBuiltins(installBuiltins);
 
         this.emptyShape = LAYOUT.createShape(new ObjectType());
     }
@@ -114,19 +122,19 @@
      * Adds all builtin functions to the {@link SLFunctionRegistry}. This method lists all
      * {@link SLBuiltinNode builtin implementation classes}.
      */
-    private void installBuiltins() {
-        installBuiltin(SLReadlnBuiltinFactory.getInstance());
-        installBuiltin(SLPrintlnBuiltinFactory.getInstance());
-        installBuiltin(SLNanoTimeBuiltinFactory.getInstance());
-        installBuiltin(SLDefineFunctionBuiltinFactory.getInstance());
-        installBuiltin(SLStackTraceBuiltinFactory.getInstance());
-        installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance());
-        installBuiltin(SLAssertTrueBuiltinFactory.getInstance());
-        installBuiltin(SLAssertFalseBuiltinFactory.getInstance());
-        installBuiltin(SLNewObjectBuiltinFactory.getInstance());
+    private void installBuiltins(boolean registerRootNodes) {
+        installBuiltin(SLReadlnBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLPrintlnBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLNanoTimeBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLDefineFunctionBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLStackTraceBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLAssertTrueBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLAssertFalseBuiltinFactory.getInstance(), registerRootNodes);
+        installBuiltin(SLNewObjectBuiltinFactory.getInstance(), registerRootNodes);
     }
 
-    public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {
+    public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory, boolean registerRootNodes) {
         /*
          * The builtin node factory is a class that is automatically generated by the Truffle DSL.
          * The signature returned by the factory reflects the signature of the @Specialization
@@ -149,8 +157,13 @@
         /* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */
         SLRootNode rootNode = new SLRootNode(this, new FrameDescriptor(), builtinBodyNode, name);
 
-        /* Register the builtin function in our function registry. */
-        getFunctionRegistry().register(name, rootNode);
+        if (registerRootNodes) {
+            /* Register the builtin function in our function registry. */
+            getFunctionRegistry().register(name, rootNode);
+        } else {
+            // make sure the function is known
+            getFunctionRegistry().lookup(name);
+        }
     }
 
     public static NodeInfo lookupNodeInfo(Class<?> clazz) {
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/MaxMinObject.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/MaxMinObject.java	Fri Jul 31 14:49:02 2015 -0700
@@ -47,16 +47,10 @@
 
     @Override
     public ForeignAccess getForeignAccess() {
-        return ForeignAccess.create(MaxMinObject.class, new AF(max));
+        return ForeignAccess.create(MaxMinObject.class, new AF());
     }
 
     static final class AF implements ForeignAccess.Factory10 {
-        private final boolean max;
-
-        public AF(boolean max) {
-            this.max = max;
-        }
-
         @Override
         public CallTarget accessIsNull() {
             return null;
@@ -100,7 +94,7 @@
         @Override
         public CallTarget accessExecute(int argumentsLength) {
             if (argumentsLength == 2) {
-                MaxMinNode maxNode = MaxMinObjectFactory.MaxMinNodeGen.create(max, MaxMinObjectFactory.UnboxNodeGen.create(new ReadArgNode(0)),
+                MaxMinNode maxNode = MaxMinObjectFactory.MaxMinNodeGen.create(new ReadReceiverNode(), MaxMinObjectFactory.UnboxNodeGen.create(new ReadArgNode(0)),
                                 MaxMinObjectFactory.UnboxNodeGen.create(new ReadArgNode(1)));
                 return Truffle.getRuntime().createCallTarget(maxNode);
             }
@@ -130,6 +124,12 @@
         }
     }
 
+    static class ReadReceiverNode extends Node {
+        public Object execute(VirtualFrame frame) {
+            return ForeignAccess.getReceiver(frame);
+        }
+    }
+
     @NodeChildren({@NodeChild(value = "valueNode", type = ReadArgNode.class)})
     abstract static class UnboxNode extends Node {
         @Child private Node unbox;
@@ -171,28 +171,26 @@
 
     }
 
-    @NodeChildren({@NodeChild(value = "firstNode", type = UnboxNode.class), @NodeChild(value = "secondNode", type = UnboxNode.class)})
+    @NodeChildren({@NodeChild(value = "receiver", type = ReadReceiverNode.class), @NodeChild(value = "firstNode", type = UnboxNode.class), @NodeChild(value = "secondNode", type = UnboxNode.class)})
     abstract static class MaxMinNode extends RootNode {
-        private final boolean max;
 
-        MaxMinNode(boolean max) {
+        MaxMinNode() {
             super(MMLanguage.class, null, null);
-            this.max = max;
         }
 
         @Specialization
-        public int execute(int first, int second) {
-            return max ? Math.max(first, second) : Math.min(first, second);
+        public int execute(MaxMinObject receiver, int first, int second) {
+            return receiver.max ? Math.max(first, second) : Math.min(first, second);
         }
 
         @Specialization
-        public long execute(long first, long second) {
-            return max ? Math.max(first, second) : Math.min(first, second);
+        public long execute(MaxMinObject receiver, long first, long second) {
+            return receiver.max ? Math.max(first, second) : Math.min(first, second);
         }
 
         @Specialization
-        public double execute(double first, double second) {
-            return max ? Math.max(first, second) : Math.min(first, second);
+        public double execute(MaxMinObject receiver, double first, double second) {
+            return receiver.max ? Math.max(first, second) : Math.min(first, second);
         }
     }
 
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Fri Jul 31 14:42:26 2015 -0700
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Fri Jul 31 14:49:02 2015 -0700
@@ -102,6 +102,19 @@
     protected abstract String applyNumbers();
 
     /**
+     * Name of a function that counts number of its invocations in current {@link TruffleVM}
+     * context. Your function should somehow keep a counter to remember number of its invocations
+     * and always increment it. The first invocation should return <code>1</code>, the second
+     * <code>2</code> and so on. The returned values are expected to be instances of {@link Number}.
+     * <p>
+     * The function will be used to test that two instances of your language can co-exist next to
+     * each other. Without being mutually influenced.
+     *
+     * @return name of globally expected symbol
+     */
+    protected abstract String countInvocations();
+
+    /**
      * Return a code snippet that is invalid in your language. Its
      * {@link TruffleVM#eval(java.lang.String, java.lang.String) evaluation} should fail and yield
      * an exception.
@@ -197,6 +210,33 @@
         assert 28 == n.intValue() : "18 < 32 and plus 10";
     }
 
+    @Test
+    public void testCoExistanceOfMultipleLanguageInstances() throws Exception {
+        final String countMethod = countInvocations();
+        TruffleVM.Symbol count1 = findGlobalSymbol(countMethod);
+        tckVM = null; // clean-up
+        TruffleVM.Symbol count2 = findGlobalSymbol(countMethod);
+
+        int prev1 = 0;
+        int prev2 = 0;
+        Random r = new Random();
+        for (int i = 0; i < 10; i++) {
+            int quantum = r.nextInt(10);
+            for (int j = 0; j < quantum; j++) {
+                Object res = count1.invoke(null);
+                assert res instanceof Number : "expecting number: " + res;
+                assert ((Number) res).intValue() == ++prev1 : "expecting " + prev1 + " but was " + res;
+            }
+            for (int j = 0; j < quantum; j++) {
+                Object res = count2.invoke(null);
+                assert res instanceof Number : "expecting number: " + res;
+                assert ((Number) res).intValue() == ++prev2 : "expecting " + prev2 + " but was " + res;
+            }
+            assert prev1 == prev2 : "At round " + i + " the same number of invocations " + prev1 + " vs. " + prev2;
+        }
+
+    }
+
     private TruffleVM.Symbol findGlobalSymbol(String name) throws Exception {
         TruffleVM.Symbol s = vm().findGlobalSymbol(name);
         assert s != null : "Symbol " + name + " is not found!";