# HG changeset patch # User Michael Van De Vanter # Date 1433902059 25200 # Node ID 9fe51d8fae0fa6819bdf63f9a868219d397f77a3 # Parent ccaf9eb1f5eb006894ea86f7fcff5f2cade33919# Parent 878786299d2d72bf0bdbd4002ccffcd1fad69b7a Merge with 878786299d2d72bf0bdbd4002ccffcd1fad69b7a diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java --- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java Tue Jun 09 19:07:39 2015 -0700 @@ -25,28 +25,30 @@ import java.io.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.debug.*; import com.oracle.truffle.api.dsl.test.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; public class LanguageRegistrationTest { @ExpectError("Registered language class must be public") - @TruffleLanguage.Registration(name = "myLang", mimeType = "text/x-my") + @TruffleLanguage.Registration(name = "myLang", version = "0", mimeType = "text/x-my") private static final class MyLang { } @ExpectError("Registered language inner-class must be static") - @TruffleLanguage.Registration(name = "myLangNonStatic", mimeType = "text/x-my") + @TruffleLanguage.Registration(name = "myLangNonStatic", version = "0", mimeType = "text/x-my") public final class MyLangNonStatic { } @ExpectError("Registered language class must subclass TruffleLanguage") - @TruffleLanguage.Registration(name = "myLang", mimeType = "text/x-my") + @TruffleLanguage.Registration(name = "myLang", version = "0", mimeType = "text/x-my") public static final class MyLangNoSubclass { } @ExpectError("Language must have a public constructor accepting TruffleLanguage.Env as parameter") - @TruffleLanguage.Registration(name = "myLangNoCnstr", mimeType = "text/x-my") + @TruffleLanguage.Registration(name = "myLangNoCnstr", version = "0", mimeType = "text/x-my") public static final class MyLangWrongConstr extends TruffleLanguage { private MyLangWrongConstr() { super(null); @@ -71,10 +73,21 @@ protected boolean isObjectOfLanguage(Object object) { return false; } + + @Override + protected ToolSupportProvider getToolSupport() { + return null; + } + + @Override + protected DebugSupportProvider getDebugSupport() { + return null; + } + } @ExpectError("Language must have a public constructor accepting TruffleLanguage.Env as parameter") - @TruffleLanguage.Registration(name = "myLangNoCnstr", mimeType = "text/x-my") + @TruffleLanguage.Registration(name = "myLangNoCnstr", version = "0", mimeType = "text/x-my") public static final class MyLangNoConstr extends TruffleLanguage { public MyLangNoConstr() { super(null); @@ -99,9 +112,20 @@ protected boolean isObjectOfLanguage(Object object) { return false; } + + @Override + protected ToolSupportProvider getToolSupport() { + return null; + } + + @Override + protected DebugSupportProvider getDebugSupport() { + return null; + } + } - @TruffleLanguage.Registration(name = "myLangGood", mimeType = "text/x-my") + @TruffleLanguage.Registration(name = "myLangGood", version = "0", mimeType = "text/x-my") public static final class MyLangGood extends TruffleLanguage { public MyLangGood(TruffleLanguage.Env env) { super(env); @@ -126,5 +150,16 @@ protected boolean isObjectOfLanguage(Object object) { return false; } + + @Override + protected ToolSupportProvider getToolSupport() { + return null; + } + + @Override + protected DebugSupportProvider getDebugSupport() { + return null; + } + } } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Tue Jun 09 19:07:39 2015 -0700 @@ -22,18 +22,18 @@ */ package com.oracle.truffle.api.test.vm; -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.TruffleVM; -import java.io.IOException; -import java.io.Reader; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; import static org.junit.Assert.*; -import org.junit.Before; -import org.junit.Test; + +import java.io.*; +import java.util.*; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.debug.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.vm.*; public class ImplicitExplicitExportTest { private TruffleVM vm; @@ -159,27 +159,37 @@ protected boolean isObjectOfLanguage(Object object) { return false; } + + @Override + protected ToolSupportProvider getToolSupport() { + return null; + } + + @Override + protected DebugSupportProvider getDebugSupport() { + return null; + } } private static final String L1 = "application/x-test-import-export-1"; private static final String L2 = "application/x-test-import-export-2"; private static final String L3 = "application/x-test-import-export-3"; - @TruffleLanguage.Registration(mimeType = L1, name = "ImportExport1") + @TruffleLanguage.Registration(mimeType = L1, name = "ImportExport1", version = "0") public static final class ExportImportLanguage1 extends AbstractExportImportLanguage { public ExportImportLanguage1(Env env) { super(env); } } - @TruffleLanguage.Registration(mimeType = L2, name = "ImportExport2") + @TruffleLanguage.Registration(mimeType = L2, name = "ImportExport2", version = "0") public static final class ExportImportLanguage2 extends AbstractExportImportLanguage { public ExportImportLanguage2(Env env) { super(env); } } - @TruffleLanguage.Registration(mimeType = L3, name = "ImportExport3") + @TruffleLanguage.Registration(mimeType = L3, name = "ImportExport3", version = "0") public static final class ExportImportLanguage3 extends AbstractExportImportLanguage { public ExportImportLanguage3(Env env) { super(env); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java Tue Jun 09 19:07:39 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,44 +25,17 @@ package com.oracle.truffle.api; import com.oracle.truffle.api.impl.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.instrument.impl.*; /** * Access to information and basic services in the runtime context for a Truffle-implemented guest * language. - *

- * Disclaimer: this class is under development and will change. */ public abstract class ExecutionContext { - private Visualizer visualizer = new DefaultVisualizer(); - protected ExecutionContext() { } /** - * Access to information visualization services for the specific language. - */ - public final Visualizer getVisualizer() { - return visualizer; - } - - /** - * Assign guest language-specific visualization support for tools. This must be assigned outside - * the implementation context to avoid build circularities. - */ - public final void setVisualizer(Visualizer visualizer) { - this.visualizer = visualizer; - } - - /** - * Gets the name of the language, possibly with version number. in short enough form that it - * might be used for an interactive prompt. - */ - public abstract String getLanguageShortName(); - - /** * Get compiler options specific to this ExecutionContext. */ public CompilerOptions getCompilerOptions() { diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Tue Jun 09 19:07:39 2015 -0700 @@ -28,7 +28,9 @@ import java.lang.annotation.*; import java.lang.reflect.*; +import com.oracle.truffle.api.debug.*; import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.vm.*; import com.oracle.truffle.api.vm.TruffleVM.Language; @@ -72,6 +74,14 @@ String name(); /** + * Unique string identifying the language version. This name will be exposed to users via + * the {@link Language#getVersion()} getter. + * + * @return version of your language + */ + String version(); + + /** * List of MIME types associated with your language. Users will use them (directly or * indirectly) when {@link TruffleVM#eval(java.lang.String, java.lang.String) executing} * their code snippets or their {@link TruffleVM#eval(java.net.URI) files}. @@ -96,10 +106,10 @@ * somebody asks for it (by calling this method). *

* The exported object can either be TruffleObject (e.g. a native object from the - * other language) to support inter-operability between languages, {@link String} or one of Java + * other language) to support interoperability between languages, {@link String} or one of Java * primitive wrappers ( {@link Integer}, {@link Double}, {@link Short}, {@link Boolean}, etc.). *

- * The way a symbol becomes exported is language dependant. In general it is preferred + * The way a symbol becomes exported is language dependent. In general it is preferred * to make the export explicit - e.g. call some function or method to register an object under * specific name. Some languages may however decide to support implicit export of symbols (for * example from global scope, if they have one). However explicit exports should always be @@ -135,6 +145,10 @@ */ protected abstract boolean isObjectOfLanguage(Object object); + protected abstract ToolSupportProvider getToolSupport(); + + protected abstract DebugSupportProvider getDebugSupport(); + /** * Represents execution environment of the {@link TruffleLanguage}. Each active * {@link TruffleLanguage} receives instance of the environment before any code is executed upon @@ -229,5 +243,16 @@ protected Object languageGlobal(TruffleLanguage l) { return l.getLanguageGlobal(); } + + @Override + protected ToolSupportProvider getToolSupport(TruffleLanguage l) { + return l.getToolSupport(); + } + + @Override + protected DebugSupportProvider getDebugSupport(TruffleLanguage l) { + return l.getDebugSupport(); + } } + } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportException.java Tue Jun 09 19:07:39 2015 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.debug; + +public class DebugSupportException extends Exception { + + private static final long serialVersionUID = 3039074861617372741L; + + public DebugSupportException(String string) { + super(string); + } + + public DebugSupportException(Exception ex) { + super(ex); + } + +} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportProvider.java Tue Jun 09 19:07:39 2015 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.debug; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; + +/** + * Access to language-specific information and execution services to enable debugging. + */ +public interface DebugSupportProvider extends ToolSupportProvider { + + /** + * Runs source code. + * + * @param source code + * @throws DebugSupportException if unable to run successfully + */ + void run(Source source) throws DebugSupportException; + + /** + * Runs source code in a halted execution context, or at top level. + * + * @param source the code to run + * @param node node where execution halted, {@code null} if no execution context + * @param mFrame frame where execution halted, {@code null} if no execution context + * @return result of running the code in the context, or at top level if no execution context. + * @throws DebugSupportException if the evaluation cannot be performed + */ + Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugSupportException; + + /** + * 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 + * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String) + * Advanced Instrument}. + * + * @param expr a guest language expression + * @param resultListener optional listener for the result of each evaluation. + * @return a new factory + * @throws DebugSupportException if the factory cannot be created, for example if the expression + * is badly formed. + */ + AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugSupportException; +} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Tue Jun 09 19:07:39 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,6 +29,8 @@ import java.util.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.debug.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.vm.*; @@ -59,6 +61,16 @@ protected boolean isObjectOfLanguage(Object object) { return false; } + + @Override + protected ToolSupportProvider getToolSupport() { + return null; + } + + @Override + protected DebugSupportProvider getDebugSupport() { + return null; + } }; lng.hashCode(); } @@ -97,6 +109,14 @@ return API.languageGlobal(l); } + protected ToolSupportProvider getToolSupport(TruffleLanguage l) { + return API.getToolSupport(l); + } + + protected DebugSupportProvider getDebugSupport(TruffleLanguage l) { + return API.getDebugSupport(l); + } + protected Object invoke(Object obj, Object[] args) throws IOException { for (SymbolInvoker si : ServiceLoader.load(SymbolInvoker.class)) { return si.invoke(obj, args); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ToolSupportProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ToolSupportProvider.java Tue Jun 09 19:07:39 2015 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.instrument; + +/** + * Access to language-specific information and execution services for external tools. + */ +public interface ToolSupportProvider { + + /** + * Gets visualization services for language-specific information. + */ + Visualizer getVisualizer(); + + /** + * Enables AST probing on all subsequently created ASTs (sources parsed). + * + * @param astProber optional AST prober to enable; the default for the language used if + * {@code null} + */ + void enableASTProbing(ASTProber astProber); + +} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java Tue Jun 09 19:07:39 2015 -0700 @@ -61,11 +61,11 @@ /** * Converts a value in the guest language to a display string. If - * + * * @param trim if {@code > 0}, them limit size of String to either the value of trim or the * number of characters in the first line, whichever is lower. */ - String displayValue(ExecutionContext context, Object value, int trim); + String displayValue(Object value, int trim); /** * Converts a slot identifier in the guest language to a display string. diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java Tue Jun 09 19:07:39 2015 -0700 @@ -73,7 +73,7 @@ return callTarget.toString(); } - public String displayValue(ExecutionContext context, Object value, int trim) { + public String displayValue(Object value, int trim) { return trim(value.toString(), trim); } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java Tue Jun 09 19:07:39 2015 -0700 @@ -34,7 +34,9 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.TruffleLanguage.Registration; +import com.oracle.truffle.api.debug.*; import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.source.*; /** @@ -416,6 +418,7 @@ private final Properties props; private TruffleLanguage impl; private final String prefix; + private String shortName; Language(String prefix, Properties props) { this.prefix = prefix; @@ -448,6 +451,35 @@ return props.getProperty(prefix + "name"); } + /** + * Name of the language version. + * + * @return string specifying the language version + */ + public String getVersion() { + return props.getProperty(prefix + "version"); + } + + /** + * Human readable string that identifies the language and version. + * + * @return string describing the specific language version + */ + public String getShortName() { + if (shortName == null) { + shortName = getName() + "(" + getVersion() + ")"; + } + return shortName; + } + + public ToolSupportProvider getToolSupport() { + return SPI.getToolSupport(getImpl()); + } + + public DebugSupportProvider getDebugSupport() { + return SPI.getDebugSupport(getImpl()); + } + TruffleLanguage getImpl() { if (impl == null) { String n = props.getProperty(prefix + "className"); @@ -456,7 +488,7 @@ Constructor constructor = langClazz.getConstructor(Env.class); impl = SPI.attachEnv(TruffleVM.this, constructor, out, err, in); } catch (Exception ex) { - throw new IllegalStateException("Cannot initialize " + getName() + " language with implementation " + n, ex); + throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + n, ex); } } return impl; @@ -464,7 +496,7 @@ @Override public String toString() { - return "[" + getName() + " for " + getMimeTypes() + "]"; + return "[" + getShortName() + " for " + getMimeTypes() + "]"; } } // end of Language @@ -519,5 +551,15 @@ public Object invoke(Object obj, Object[] args) throws IOException { return super.invoke(obj, args); } + + @Override + public ToolSupportProvider getToolSupport(TruffleLanguage l) { + return super.getToolSupport(l); + } + + @Override + public DebugSupportProvider getDebugSupport(TruffleLanguage l) { + return super.getDebugSupport(l); + } } // end of SPIAccessor } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java Tue Jun 09 19:07:39 2015 -0700 @@ -56,6 +56,7 @@ String prefix = "language" + ++cnt + "."; String className = processingEnv.getElementUtils().getBinaryName(l).toString(); p.setProperty(prefix + "name", annotation.name()); + p.setProperty(prefix + "version", annotation.version()); p.setProperty(prefix + "className", className); String[] mimes = annotation.mimeType(); for (int i = 0; i < mimes.length; i++) { diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java --- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java Tue Jun 09 19:07:39 2015 -0700 @@ -168,7 +168,7 @@ TruffleVM vm = TruffleVM.newVM().stdIn(new BufferedReader(new StringReader(repeat(testCase.testInput, repeats)))).stdOut(printer).build(); String script = readAllLines(testCase.path); - SLMain.run(vm, testCase.path.toUri(), null, printer, repeats, builtins); + SLLanguage.run(vm, testCase.path.toUri(), null, printer, repeats, builtins); printer.flush(); String actualOutput = new String(out.toByteArray()); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java --- a/graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java Tue Jun 09 19:07:39 2015 -0700 @@ -24,20 +24,18 @@ */ package com.oracle.truffle.sl.tools.debug; -import java.io.*; import java.util.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.vm.*; +import com.oracle.truffle.api.vm.TruffleVM.Language; import com.oracle.truffle.tools.debug.engine.*; import com.oracle.truffle.tools.debug.shell.*; import com.oracle.truffle.tools.debug.shell.client.*; import com.oracle.truffle.tools.debug.shell.server.*; -import com.oracle.truffle.sl.factory.*; -import com.oracle.truffle.sl.runtime.*; /** * Instantiation of the "server" side of the "REPL*" debugger for the Simple language. @@ -49,10 +47,11 @@ * @see SimpleREPLClient */ public final class SLREPLServer implements REPLServer { + public static void main(String[] args) { // Cheating for the prototype: start from SL, rather than from the client. final SLREPLServer server = new SLREPLServer(); - final SimpleREPLClient client = new SimpleREPLClient(server.slContext, server); + final SimpleREPLClient client = new SimpleREPLClient(server.language.getShortName(), server); // Cheating for the prototype: allow server access to client for recursive debugging server.setClient(client); @@ -63,7 +62,7 @@ } } - private final SLContext slContext; + private final Language language; private final DebugEngine slDebugEngine; private final String statusPrefix; private final Map handlerMap = new HashMap<>(); @@ -99,13 +98,14 @@ add(REPLHandler.TRUFFLE_HANDLER); add(REPLHandler.TRUFFLE_NODE_HANDLER); - // Set up an SL context - this.slContext = SLContextFactory.create(null, new PrintWriter(System.out)); + TruffleVM vm = TruffleVM.newVM().build(); + this.language = vm.getLanguages().get("application/x-sl"); + assert language != null; - final SLSourceExecutionProvider slSourceExecution = new SLSourceExecutionProvider(slContext); - final SLREPLDebugClient slDebugClient = new SLREPLDebugClient(this.slContext); - this.slDebugEngine = DebugEngine.create(slDebugClient, slSourceExecution); - this.statusPrefix = slContext.getLanguageShortName() + " REPL:"; + final SLREPLDebugClient slDebugClient = new SLREPLDebugClient(language); + this.slDebugEngine = DebugEngine.create(slDebugClient, language); + + this.statusPrefix = language.getShortName() + " REPL:"; } private void setClient(SimpleREPLClient replClient) { @@ -119,7 +119,7 @@ // SL doesn't load modules (like other languages), so we just return a success final REPLMessage reply = new REPLMessage(); reply.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED); - reply.put(REPLMessage.DISPLAY_MSG, slContext.getLanguageShortName() + " started"); + reply.put(REPLMessage.DISPLAY_MSG, language.getShortName() + " started"); return reply; } @@ -163,8 +163,8 @@ } @Override - public SLContext getLanguageContext() { - return slContext; + public Language getLanguage() { + return language; } @Override @@ -186,10 +186,10 @@ */ private final class SLREPLDebugClient implements DebugClient { - private final SLContext slContext; + private final Language language; - SLREPLDebugClient(SLContext slContext) { - this.slContext = slContext; + SLREPLDebugClient(Language language) { + this.language = language; } public void haltedAt(Node node, MaterializedFrame mFrame, List warnings) { @@ -225,8 +225,8 @@ } } - public ExecutionContext getExecutionContext() { - return slContext; + public Language getLanguage() { + return language; } } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLSourceExecutionProvider.java --- a/graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLSourceExecutionProvider.java Tue Jun 09 23:00:38 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.sl.tools.debug; - -import java.io.*; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.sl.*; -import com.oracle.truffle.sl.nodes.instrument.*; -import com.oracle.truffle.sl.runtime.*; -import com.oracle.truffle.tools.debug.engine.*; - -/** - * Specialization of the Truffle debugging engine for the Simple language. The engine implements - * basic debugging operations during Truffle-based execution. - */ -public final class SLSourceExecutionProvider extends SourceExecutionProvider { - - @SuppressWarnings("unused") private final SLContext slContext; - - public SLSourceExecutionProvider(SLContext context) { - this.slContext = context; - Probe.registerASTProber(new SLStandardASTProber()); - } - - @Override - public void languageRun(Source source) { - try { - SLMain.run(source); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * {@inheritDoc} - *

- * The implementation of Simple is too, well, simple to support eval. Just for starters, the - * parser can only produce a whole program. - */ - @Override - public Object languageEval(Source source, Node node, MaterializedFrame mFrame) { - throw new UnsupportedOperationException(); - } - - /** - * {@inheritDoc} - *

- * The implementation of Simple is too, well, simple to support this. Just for starters, the - * parser can only produce a whole program. - */ - @Override - public AdvancedInstrumentRootFactory languageAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugException { - throw new UnsupportedOperationException(); - } -} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Tue Jun 09 19:07:39 2015 -0700 @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2012, 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.sl; + +import java.io.*; +import java.math.*; +import java.net.*; +import java.util.*; +import java.util.Scanner; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.debug.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +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.*; +import com.oracle.truffle.sl.nodes.expression.*; +import com.oracle.truffle.sl.nodes.instrument.*; +import com.oracle.truffle.sl.nodes.local.*; +import com.oracle.truffle.sl.parser.*; +import com.oracle.truffle.sl.runtime.*; +import com.oracle.truffle.tools.*; + +/** + * SL is a simple language to demonstrate and showcase features of Truffle. The implementation is as + * simple and clean as possible in order to help understanding the ideas and concepts of Truffle. + * The language has first class functions, but no object model. + *

+ * SL is dynamically typed, i.e., there are no type names specified by the programmer. SL is + * strongly typed, i.e., there is no automatic conversion between types. If an operation is not + * available for the types encountered at run time, a type error is reported and execution is + * stopped. For example, {@code 4 - "2"} results in a type error because subtraction is only defined + * for numbers. + * + *

+ * Types: + *

+ * The class {@link SLTypes} lists these types for the Truffle DSL, i.e., for type-specialized + * operations that are specified using Truffle DSL annotations. + * + *

+ * Language concepts: + *

+ * + *

+ * Syntax and parsing:
+ * The syntax is described as an attributed grammar. The {@link Parser} and {@link Scanner} are + * automatically generated by the parser generator Coco/R (available from http://ssw.jku.at/coco/). The grammar contains semantic + * actions that build the AST for a method. To keep these semantic actions short, they are mostly + * calls to the {@link SLNodeFactory} that performs the actual node creation. All functions found in + * the SL source are added to the {@link SLFunctionRegistry}, which is accessible from the + * {@link SLContext}. + * + *

+ * Builtin functions:
+ * Library functions that are available to every SL source without prior definition are called + * builtin functions. They are added to the {@link SLFunctionRegistry} when the {@link SLContext} is + * created. There current builtin functions are + *

+ * + *

+ * Tools:
+ * The use of some of Truffle's support for developer tools (based on the Truffle Instrumentation + * Framework) are demonstrated in this file, for example: + *

+ * In each case, the tool is enabled if a corresponding local boolean variable in this file is set + * to {@code true}. Results are printed at the end of the execution using each tool's + * default printer. + * + */ +@TruffleLanguage.Registration(name = "SL", version = "0.5", mimeType = "application/x-sl") +public class SLLanguage extends TruffleLanguage { + private static SLLanguage LAST; + private static List> builtins = Collections.emptyList(); + private static Visualizer visualizer = new SLDefaultVisualizer(); + private static ASTProber registeredASTProber; // non-null if prober already registered + private final SLContext context; + private DebugSupportProvider debugSupport; + + public SLLanguage(Env env) { + super(env); + context = SLContextFactory.create(new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true)); + LAST = this; + for (NodeFactory builtin : builtins) { + context.installBuiltin(builtin); + } + } + + // TODO (mlvdv) command line options + /* Enables demonstration of per-type tabulation of node execution counts */ + private static boolean nodeExecCounts = false; + /* Enables demonstration of per-line tabulation of STATEMENT node execution counts */ + private static boolean statementCounts = false; + /* Enables demonstration of per-line tabulation of STATEMENT coverage */ + private static boolean coverage = false; + + /* Small tools that can be installed for demonstration */ + private static NodeExecCounter nodeExecCounter = null; + private static NodeExecCounter statementExecCounter = null; + private static CoverageTracker coverageTracker = null; + + /** + * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup. + */ + public static void main(String[] args) throws IOException { + TruffleVM vm = TruffleVM.newVM().build(); + assert vm.getLanguages().containsKey("application/x-sl"); + + setupToolDemos(); + + int repeats = 1; + if (args.length >= 2) { + repeats = Integer.parseInt(args[1]); + } + + if (args.length == 0) { + vm.eval("application/x-sl", new InputStreamReader(System.in)); + } else { + vm.eval(new File(args[0]).toURI()); + } + Symbol main = vm.findGlobalSymbol("main"); + if (main == null) { + throw new SLException("No function main() defined in SL source file."); + } + while (repeats-- > 0) { + main.invoke(null); + } + reportToolDemos(); + } + + /** + * Temporary method during API evolution, supports debugger integration. + */ + public static void run(Source source) throws IOException { + TruffleVM vm = TruffleVM.newVM().build(); + assert vm.getLanguages().containsKey("application/x-sl"); + vm.eval(new File(source.getPath()).toURI()); + Symbol main = vm.findGlobalSymbol("main"); + if (main == null) { + throw new SLException("No function main() defined in SL source file."); + } + main.invoke(null); + } + + /** + * Parse and run the specified SL source. Factored out in a separate method so that it can also + * be used by the unit test harness. + */ + public static long run(TruffleVM context, URI source, PrintWriter logOutput, PrintWriter out, int repeats, List> currentBuiltins) throws IOException { + builtins = currentBuiltins; + + if (logOutput != null) { + logOutput.println("== running on " + Truffle.getRuntime().getName()); + // logOutput.println("Source = " + source.getCode()); + } + + /* Parse the SL source file. */ + Object result = context.eval(source); + if (result != null) { + out.println(result); + } + + /* Lookup our main entry point, which is per definition always named "main". */ + Symbol main = context.findGlobalSymbol("main"); + if (main == null) { + throw new SLException("No function main() defined in SL source file."); + } + + /* Change to true if you want to see the AST on the console. */ + boolean printASTToLog = false; + /* Change to true if you want to see source attribution for the AST to the console */ + boolean printSourceAttributionToLog = false; + /* Change to dump the AST to IGV over the network. */ + boolean dumpASTToIGV = false; + + printScript("before execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); + long totalRuntime = 0; + try { + for (int i = 0; i < repeats; i++) { + long start = System.nanoTime(); + /* Call the main entry point, without any arguments. */ + try { + result = main.invoke(null); + if (result != null) { + out.println(result); + } + } catch (UnsupportedSpecializationException ex) { + out.println(formatTypeError(ex)); + } catch (SLUndefinedFunctionException ex) { + out.println(String.format("Undefined function: %s", ex.getFunctionName())); + } + long end = System.nanoTime(); + totalRuntime += end - start; + + if (logOutput != null && repeats > 1) { + logOutput.println("== iteration " + (i + 1) + ": " + ((end - start) / 1000000) + " ms"); + } + } + + } finally { + printScript("after execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); + } + return totalRuntime; + } + + /** + * When dumpASTToIGV is true: dumps the AST of all functions to the IGV visualizer, via a socket + * connection. IGV can be started with the mx command "mx igv". + *

+ * When printASTToLog is true: prints the ASTs to the console. + */ + private static void printScript(String groupName, SLContext context, PrintWriter logOutput, boolean printASTToLog, boolean printSourceAttributionToLog, boolean dumpASTToIGV) { + if (dumpASTToIGV) { + GraphPrintVisitor graphPrinter = new GraphPrintVisitor(); + graphPrinter.beginGroup(groupName); + for (SLFunction function : context.getFunctionRegistry().getFunctions()) { + RootCallTarget callTarget = function.getCallTarget(); + if (callTarget != null) { + graphPrinter.beginGraph(function.toString()).visit(callTarget.getRootNode()); + } + } + graphPrinter.printToNetwork(true); + } + if (printASTToLog && logOutput != null) { + for (SLFunction function : context.getFunctionRegistry().getFunctions()) { + RootCallTarget callTarget = function.getCallTarget(); + if (callTarget != null) { + logOutput.println("=== " + function); + NodeUtil.printTree(logOutput, callTarget.getRootNode()); + } + } + } + if (printSourceAttributionToLog && logOutput != null) { + for (SLFunction function : context.getFunctionRegistry().getFunctions()) { + RootCallTarget callTarget = function.getCallTarget(); + if (callTarget != null) { + logOutput.println("=== " + function); + NodeUtil.printSourceAttributionTree(logOutput, callTarget.getRootNode()); + } + } + } + } + + /** + * Provides a user-readable message for run-time type errors. SL is strongly typed, i.e., there + * are no automatic type conversions of values. Therefore, Truffle does the type checking for + * us: if no matching node specialization for the actual values is found, then we have a type + * error. Specialized nodes use the {@link UnsupportedSpecializationException} to report that no + * specialization was found. We therefore just have to convert the information encapsulated in + * this exception in a user-readable form. + */ + private static String formatTypeError(UnsupportedSpecializationException ex) { + StringBuilder result = new StringBuilder(); + result.append("Type error"); + if (ex.getNode() != null && ex.getNode().getSourceSection() != null) { + SourceSection ss = ex.getNode().getSourceSection(); + if (ss != null && !(ss instanceof NullSourceSection)) { + result.append(" at ").append(ss.getSource().getShortName()).append(" line ").append(ss.getStartLine()).append(" col ").append(ss.getStartColumn()); + } + } + result.append(": operation"); + if (ex.getNode() != null) { + NodeInfo nodeInfo = SLContext.lookupNodeInfo(ex.getNode().getClass()); + if (nodeInfo != null) { + result.append(" \"").append(nodeInfo.shortName()).append("\""); + } + } + result.append(" not defined for"); + + String sep = " "; + for (int i = 0; i < ex.getSuppliedValues().length; i++) { + Object value = ex.getSuppliedValues()[i]; + Node node = ex.getSuppliedNodes()[i]; + if (node != null) { + result.append(sep); + sep = ", "; + + if (value instanceof Long || value instanceof BigInteger) { + result.append("Number ").append(value); + } else if (value instanceof Boolean) { + result.append("Boolean ").append(value); + } else if (value instanceof String) { + result.append("String \"").append(value).append("\""); + } else if (value instanceof SLFunction) { + result.append("Function ").append(value); + } else if (value == SLNull.SINGLETON) { + result.append("NULL"); + } else if (value == null) { + // value is not evaluated because of short circuit evaluation + result.append("ANY"); + } else { + result.append(value); + } + } + } + return result.toString(); + } + + @Override + protected Object eval(Source code) throws IOException { + try { + context.evalSource(code); + } catch (Exception e) { + throw new IOException(e); + } + return null; + } + + @Override + protected Object findExportedSymbol(String globalName, boolean onlyExplicit) { + for (SLFunction f : context.getFunctionRegistry().getFunctions()) { + if (globalName.equals(f.getName())) { + return f; + } + } + return null; + } + + @Override + protected Object getLanguageGlobal() { + return context; + } + + @Override + protected boolean isObjectOfLanguage(Object object) { + return object instanceof SLFunction; + } + + @Override + protected ToolSupportProvider getToolSupport() { + return getDebugSupport(); + } + + @Override + protected DebugSupportProvider getDebugSupport() { + if (debugSupport == null) { + debugSupport = new SLDebugProvider(); + } + return debugSupport; + } + + // TODO (mlvdv) remove the static hack when we no longer have the static demo variables + private static void setupToolDemos() { + if (statementCounts || coverage) { + if (registeredASTProber == null) { + final ASTProber newProber = new SLStandardASTProber(); + // This should be registered on the TruffleVM + Probe.registerASTProber(newProber); + registeredASTProber = newProber; + } + } + if (nodeExecCounts) { + nodeExecCounter = new NodeExecCounter(); + nodeExecCounter.install(); + } + + if (statementCounts) { + statementExecCounter = new NodeExecCounter(StandardSyntaxTag.STATEMENT); + statementExecCounter.install(); + } + + if (coverage) { + coverageTracker = new CoverageTracker(); + coverageTracker.install(); + } + } + + private static void reportToolDemos() { + if (nodeExecCounter != null) { + nodeExecCounter.print(System.out); + nodeExecCounter.dispose(); + } + if (statementExecCounter != null) { + statementExecCounter.print(System.out); + statementExecCounter.dispose(); + } + if (coverageTracker != null) { + coverageTracker.print(System.out); + coverageTracker.dispose(); + } + } + + private final class SLDebugProvider implements DebugSupportProvider { + + public SLDebugProvider() { + if (registeredASTProber == null) { + registeredASTProber = new SLStandardASTProber(); + // This should be registered on the TruffleVM + Probe.registerASTProber(registeredASTProber); + } + } + + public Visualizer getVisualizer() { + if (visualizer == null) { + visualizer = new SLDefaultVisualizer(); + } + return visualizer; + } + + public void enableASTProbing(ASTProber prober) { + if (prober != null) { + // This should be registered on the TruffleVM + Probe.registerASTProber(prober); + } + } + + public void run(Source source) throws DebugSupportException { + // TODO (mlvdv) fix to run properly in the current VM + try { + SLLanguage.run(source); + } catch (Exception e) { + throw new DebugSupportException(e); + } + } + + public Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugSupportException { + throw new DebugSupportException("evalInContext not supported in this language"); + } + + public AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugSupportException { + throw new DebugSupportException("createAdvancedInstrumentRootFactory not supported in this language"); + } + + } + +} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Tue Jun 09 23:00:38 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2012, 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.sl; - -import java.io.*; -import java.math.*; -import java.net.*; -import java.util.*; -import java.util.Scanner; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -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.*; -import com.oracle.truffle.sl.nodes.expression.*; -import com.oracle.truffle.sl.nodes.instrument.*; -import com.oracle.truffle.sl.nodes.local.*; -import com.oracle.truffle.sl.parser.*; -import com.oracle.truffle.sl.runtime.*; -import com.oracle.truffle.tools.*; - -/** - * SL is a simple language to demonstrate and showcase features of Truffle. The implementation is as - * simple and clean as possible in order to help understanding the ideas and concepts of Truffle. - * The language has first class functions, but no object model. - *

- * SL is dynamically typed, i.e., there are no type names specified by the programmer. SL is - * strongly typed, i.e., there is no automatic conversion between types. If an operation is not - * available for the types encountered at run time, a type error is reported and execution is - * stopped. For example, {@code 4 - "2"} results in a type error because subtraction is only defined - * for numbers. - * - *

- * Types: - *

    - *
  • Number: arbitrary precision integer numbers. The implementation uses the Java primitive type - * {@code long} to represent numbers that fit into the 64 bit range, and {@link BigInteger} for - * numbers that exceed the range. Using a primitive type such as {@code long} is crucial for - * performance. - *
  • Boolean: implemented as the Java primitive type {@code boolean}. - *
  • String: implemented as the Java standard type {@link String}. - *
  • Function: implementation type {@link SLFunction}. - *
  • Null (with only one value {@code null}): implemented as the singleton - * {@link SLNull#SINGLETON}. - *
- * The class {@link SLTypes} lists these types for the Truffle DSL, i.e., for type-specialized - * operations that are specified using Truffle DSL annotations. - * - *

- * Language concepts: - *

    - *
  • Literals for {@link SLBigIntegerLiteralNode numbers} , {@link SLStringLiteralNode strings}, - * and {@link SLFunctionLiteralNode functions}. - *
  • Basic arithmetic, logical, and comparison operations: {@link SLAddNode +}, {@link SLSubNode - * -}, {@link SLMulNode *}, {@link SLDivNode /}, {@link SLLogicalAndNode logical and}, - * {@link SLLogicalOrNode logical or}, {@link SLEqualNode ==}, !=, {@link SLLessThanNode <}, - * {@link SLLessOrEqualNode ≤}, >, ≥. - *
  • Local variables: local variables must be defined (via a {@link SLWriteLocalVariableNode - * write}) before they can be used (by a {@link SLReadLocalVariableNode read}). Local variables are - * not visible outside of the block where they were first defined. - *
  • Basic control flow statements: {@link SLBlockNode blocks}, {@link SLIfNode if}, - * {@link SLWhileNode while} with {@link SLBreakNode break} and {@link SLContinueNode continue}, - * {@link SLReturnNode return}. - *
  • Function calls: {@link SLInvokeNode invocations} are efficiently implemented with - * {@link SLDispatchNode polymorphic inline caches}. - *
- * - *

- * Syntax and parsing:
- * The syntax is described as an attributed grammar. The {@link Parser} and {@link Scanner} are - * automatically generated by the parser generator Coco/R (available from http://ssw.jku.at/coco/). The grammar contains semantic - * actions that build the AST for a method. To keep these semantic actions short, they are mostly - * calls to the {@link SLNodeFactory} that performs the actual node creation. All functions found in - * the SL source are added to the {@link SLFunctionRegistry}, which is accessible from the - * {@link SLContext}. - * - *

- * Builtin functions:
- * Library functions that are available to every SL source without prior definition are called - * builtin functions. They are added to the {@link SLFunctionRegistry} when the {@link SLContext} is - * created. There current builtin functions are - *

    - *
  • {@link SLReadlnBuiltin readln}: Read a String from the {@link SLContext#getInput() standard - * input}. - *
  • {@link SLPrintlnBuiltin println}: Write a value to the {@link SLContext#getOutput() standard - * output}. - *
  • {@link SLNanoTimeBuiltin nanoTime}: Returns the value of a high-resolution time, in - * nanoseconds. - *
  • {@link SLDefineFunctionBuiltin defineFunction}: Parses the functions provided as a String - * argument and adds them to the function registry. Functions that are already defined are replaced - * with the new version. - *
- * - *

- * Tools:
- * The use of some of Truffle's support for developer tools (based on the Truffle Instrumentation - * Framework) are demonstrated in this file, for example: - *

    - *
  • a {@linkplain NodeExecCounter counter for node executions}, tabulated by node type; and
  • - *
  • a simple {@linkplain CoverageTracker code coverage engine}.
  • - *
- * In each case, the tool is enabled if a corresponding local boolean variable in this file is set - * to {@code true}. Results are printed at the end of the execution using each tool's - * default printer. - * - */ -@TruffleLanguage.Registration(name = "sl", mimeType = "application/x-sl") -public class SLMain extends TruffleLanguage { - private static SLMain LAST; - private static List> builtins = Collections.emptyList(); - private final SLContext context; - - public SLMain(Env env) { - super(env); - context = SLContextFactory.create(new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true)); - LAST = this; - for (NodeFactory builtin : builtins) { - context.installBuiltin(builtin); - } - } - - /* Enables demonstration of per-type tabulation of node execution counts */ - private static boolean nodeExecCounts = false; - /* Enables demonstration of per-line tabulation of STATEMENT node execution counts */ - private static boolean statementCounts = false; - /* Enables demonstration of er-line tabulation of STATEMENT coverage */ - private static boolean coverage = false; - - /* Small tools that can be installed for demonstration */ - private static NodeExecCounter nodeExecCounter = null; - private static NodeExecCounter statementExecCounter = null; - private static CoverageTracker coverageTracker = null; - - /** - * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup. - */ - public static void main(String[] args) throws IOException { - TruffleVM vm = TruffleVM.newVM().build(); - assert vm.getLanguages().containsKey("application/x-sl"); - - setupToolDemos(); - - int repeats = 1; - if (args.length >= 2) { - repeats = Integer.parseInt(args[1]); - } - - if (args.length == 0) { - vm.eval("application/x-sl", new InputStreamReader(System.in)); - } else { - vm.eval(new File(args[0]).toURI()); - } - Symbol main = vm.findGlobalSymbol("main"); - if (main == null) { - throw new SLException("No function main() defined in SL source file."); - } - while (repeats-- > 0) { - main.invoke(null); - } - reportToolDemos(); - } - - /** - * Temporary method during API evolution, supports debugger integration. - */ - public static void run(Source source) throws IOException { - TruffleVM vm = TruffleVM.newVM().build(); - assert vm.getLanguages().containsKey("application/x-sl"); - vm.eval(new File(source.getPath()).toURI()); - Symbol main = vm.findGlobalSymbol("main"); - if (main == null) { - throw new SLException("No function main() defined in SL source file."); - } - main.invoke(null); - } - - /** - * Parse and run the specified SL source. Factored out in a separate method so that it can also - * be used by the unit test harness. - */ - public static long run(TruffleVM context, URI source, PrintWriter logOutput, PrintWriter out, int repeats, List> currentBuiltins) throws IOException { - builtins = currentBuiltins; - - if (logOutput != null) { - logOutput.println("== running on " + Truffle.getRuntime().getName()); - // logOutput.println("Source = " + source.getCode()); - } - - /* Parse the SL source file. */ - Object result = context.eval(source); - if (result != null) { - out.println(result); - } - - /* Lookup our main entry point, which is per definition always named "main". */ - Symbol main = context.findGlobalSymbol("main"); - if (main == null) { - throw new SLException("No function main() defined in SL source file."); - } - - /* Change to true if you want to see the AST on the console. */ - boolean printASTToLog = false; - /* Change to true if you want to see source attribution for the AST to the console */ - boolean printSourceAttributionToLog = false; - /* Change to dump the AST to IGV over the network. */ - boolean dumpASTToIGV = false; - - printScript("before execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); - long totalRuntime = 0; - try { - for (int i = 0; i < repeats; i++) { - long start = System.nanoTime(); - /* Call the main entry point, without any arguments. */ - try { - result = main.invoke(null); - if (result != null) { - out.println(result); - } - } catch (UnsupportedSpecializationException ex) { - out.println(formatTypeError(ex)); - } catch (SLUndefinedFunctionException ex) { - out.println(String.format("Undefined function: %s", ex.getFunctionName())); - } - long end = System.nanoTime(); - totalRuntime += end - start; - - if (logOutput != null && repeats > 1) { - logOutput.println("== iteration " + (i + 1) + ": " + ((end - start) / 1000000) + " ms"); - } - } - - } finally { - printScript("after execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); - } - return totalRuntime; - } - - /** - * When dumpASTToIGV is true: dumps the AST of all functions to the IGV visualizer, via a socket - * connection. IGV can be started with the mx command "mx igv". - *

- * When printASTToLog is true: prints the ASTs to the console. - */ - private static void printScript(String groupName, SLContext context, PrintWriter logOutput, boolean printASTToLog, boolean printSourceAttributionToLog, boolean dumpASTToIGV) { - if (dumpASTToIGV) { - GraphPrintVisitor graphPrinter = new GraphPrintVisitor(); - graphPrinter.beginGroup(groupName); - for (SLFunction function : context.getFunctionRegistry().getFunctions()) { - RootCallTarget callTarget = function.getCallTarget(); - if (callTarget != null) { - graphPrinter.beginGraph(function.toString()).visit(callTarget.getRootNode()); - } - } - graphPrinter.printToNetwork(true); - } - if (printASTToLog && logOutput != null) { - for (SLFunction function : context.getFunctionRegistry().getFunctions()) { - RootCallTarget callTarget = function.getCallTarget(); - if (callTarget != null) { - logOutput.println("=== " + function); - NodeUtil.printTree(logOutput, callTarget.getRootNode()); - } - } - } - if (printSourceAttributionToLog && logOutput != null) { - for (SLFunction function : context.getFunctionRegistry().getFunctions()) { - RootCallTarget callTarget = function.getCallTarget(); - if (callTarget != null) { - logOutput.println("=== " + function); - NodeUtil.printSourceAttributionTree(logOutput, callTarget.getRootNode()); - } - } - } - } - - /** - * Provides a user-readable message for run-time type errors. SL is strongly typed, i.e., there - * are no automatic type conversions of values. Therefore, Truffle does the type checking for - * us: if no matching node specialization for the actual values is found, then we have a type - * error. Specialized nodes use the {@link UnsupportedSpecializationException} to report that no - * specialization was found. We therefore just have to convert the information encapsulated in - * this exception in a user-readable form. - */ - private static String formatTypeError(UnsupportedSpecializationException ex) { - StringBuilder result = new StringBuilder(); - result.append("Type error"); - if (ex.getNode() != null && ex.getNode().getSourceSection() != null) { - SourceSection ss = ex.getNode().getSourceSection(); - if (ss != null && !(ss instanceof NullSourceSection)) { - result.append(" at ").append(ss.getSource().getShortName()).append(" line ").append(ss.getStartLine()).append(" col ").append(ss.getStartColumn()); - } - } - result.append(": operation"); - if (ex.getNode() != null) { - NodeInfo nodeInfo = SLContext.lookupNodeInfo(ex.getNode().getClass()); - if (nodeInfo != null) { - result.append(" \"").append(nodeInfo.shortName()).append("\""); - } - } - result.append(" not defined for"); - - String sep = " "; - for (int i = 0; i < ex.getSuppliedValues().length; i++) { - Object value = ex.getSuppliedValues()[i]; - Node node = ex.getSuppliedNodes()[i]; - if (node != null) { - result.append(sep); - sep = ", "; - - if (value instanceof Long || value instanceof BigInteger) { - result.append("Number ").append(value); - } else if (value instanceof Boolean) { - result.append("Boolean ").append(value); - } else if (value instanceof String) { - result.append("String \"").append(value).append("\""); - } else if (value instanceof SLFunction) { - result.append("Function ").append(value); - } else if (value == SLNull.SINGLETON) { - result.append("NULL"); - } else if (value == null) { - // value is not evaluated because of short circuit evaluation - result.append("ANY"); - } else { - result.append(value); - } - } - } - return result.toString(); - } - - @Override - protected Object eval(Source code) throws IOException { - try { - context.executeMain(code); - } catch (Exception e) { - throw new IOException(e); - } - return null; - } - - @Override - protected Object findExportedSymbol(String globalName, boolean onlyExplicit) { - for (SLFunction f : context.getFunctionRegistry().getFunctions()) { - if (globalName.equals(f.getName())) { - return f; - } - } - return null; - } - - @Override - protected Object getLanguageGlobal() { - return context; - } - - @Override - protected boolean isObjectOfLanguage(Object object) { - return object instanceof SLFunction; - } - - private static void setupToolDemos() { - if (statementCounts || coverage) { - Probe.registerASTProber(new SLStandardASTProber()); - } - if (nodeExecCounts) { - nodeExecCounter = new NodeExecCounter(); - nodeExecCounter.install(); - } - - if (statementCounts) { - statementExecCounter = new NodeExecCounter(StandardSyntaxTag.STATEMENT); - statementExecCounter.install(); - } - - if (coverage) { - coverageTracker = new CoverageTracker(); - coverageTracker.install(); - } - } - - private static void reportToolDemos() { - if (nodeExecCounter != null) { - nodeExecCounter.print(System.out); - nodeExecCounter.dispose(); - } - if (statementExecCounter != null) { - statementExecCounter.print(System.out); - statementExecCounter.dispose(); - } - if (coverageTracker != null) { - coverageTracker.print(System.out); - coverageTracker.dispose(); - } - } - -} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Tue Jun 09 19:07:39 2015 -0700 @@ -24,7 +24,6 @@ import java.io.*; -import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; public final class SLContextFactory { @@ -33,8 +32,6 @@ } public static SLContext create(BufferedReader input, PrintWriter output) { - final SLContext slContext = new SLContext(input, output); - slContext.setVisualizer(new SLDefaultVisualizer()); - return slContext; + return new SLContext(input, output); } } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java Tue Jun 09 19:07:39 2015 -0700 @@ -30,7 +30,7 @@ import com.oracle.truffle.sl.runtime.*; /** - * The type system of SL, as explained in {@link SLMain}. Based on the {@link TypeSystem} + * The type system of SL, as explained in {@link SLLanguage}. Based on the {@link TypeSystem} * annotation, the Truffle DSL generates the subclass {@link SLTypesGen} with type test and type * conversion methods for all types. In this class, we only cover types where the automatically * generated ones would not be sufficient. diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java Tue Jun 09 19:07:39 2015 -0700 @@ -73,7 +73,7 @@ } @Override - public String displayValue(ExecutionContext context, Object value, int trim) { + public String displayValue(Object value, int trim) { if (value == SLNull.SINGLETON) { return "null"; } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java Tue Jun 09 19:07:39 2015 -0700 @@ -44,7 +44,7 @@ */ public boolean visit(Node node) { - if (node instanceof SLStatementNode && node.getParent() != null && node.getSourceSection() != null) { + if (!(node instanceof InstrumentationNode) && node instanceof SLStatementNode && node.getParent() != null && node.getSourceSection() != null) { // All SL nodes are instrumentable, but treat expressions specially if (node instanceof SLExpressionNode) { diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Tue Jun 09 19:07:39 2015 -0700 @@ -62,11 +62,6 @@ this.emptyShape = LAYOUT.createShape(new ObjectType()); } - @Override - public String getLanguageShortName() { - return "Simple"; - } - /** * Returns the default input, i.e., the source for the {@link SLReadlnBuiltin}. To allow unit * testing, we do not use {@link System#in} directly. @@ -146,16 +141,11 @@ } /** - * This function will parse the given source code, parse the code using the {@link Parser}, and - * then execute the function named main. To use this method with instrumentation, - * setASTNodeProber must have been already called. There is currently no guard to check if this - * is the case.
- * Due to the experimental nature of the instrumentation framework, the parse that happens in - * this method will remove any previously added instrumentation. + * Evaluate a source, causing any definitions to be registered (but not executed). * - * @param source The {@link Source} to execute. + * @param source The {@link Source} to parse. */ - public void executeMain(Source source) { + public void evalSource(Source source) { Parser.parseSL(this, source); } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java --- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java Tue Jun 09 19:07:39 2015 -0700 @@ -26,9 +26,9 @@ import java.util.*; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.vm.TruffleVM.Language; /** * A client of the debugger where certain events should be posted. @@ -43,13 +43,12 @@ * * @param astNode AST node that is just about to be executed * @param mFrame frame that will be passed to the node when executed - * @param warnings any warnings generated since thie most recent halt. + * @param warnings any warnings generated since the most recent halt. */ void haltedAt(Node astNode, MaterializedFrame mFrame, List warnings); - // TODO (mlvdv) temporary; will eventually be accessible by a new Truffle language API /** - * Gets the context for the language being debugged. + * Gets information and services for the language being debugged. */ - ExecutionContext getExecutionContext(); + Language getLanguage(); } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java --- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java Tue Jun 09 19:07:39 2015 -0700 @@ -33,7 +33,8 @@ import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; -import com.oracle.truffle.tools.debug.engine.SourceExecutionProvider.ExecutionListener; +import com.oracle.truffle.api.vm.TruffleVM.Language; +import com.oracle.truffle.tools.debug.engine.DebugExecutionSupport.DebugExecutionListener; /** * Language-agnostic engine for running Truffle languages under debugging control. @@ -70,12 +71,14 @@ void addWarning(String warning); } + private final Language language; + /** * The client of this engine. */ private final DebugClient debugClient; - private final SourceExecutionProvider sourceExecutionProvider; + private final DebugExecutionSupport executionSupport; /** * Implementation of line-oriented breakpoints. @@ -94,11 +97,12 @@ /** * @param debugClient - * @param sourceExecutionProvider + * @param language */ - private DebugEngine(DebugClient debugClient, SourceExecutionProvider sourceExecutionProvider) { + private DebugEngine(DebugClient debugClient, Language language) { this.debugClient = debugClient; - this.sourceExecutionProvider = sourceExecutionProvider; + this.language = language; + this.executionSupport = new DebugExecutionSupport(language.getShortName(), language.getDebugSupport()); Source.setFileCaching(true); @@ -107,7 +111,7 @@ prepareContinue(); debugContext.contextTrace("START EXEC DEFAULT"); - sourceExecutionProvider.addExecutionListener(new ExecutionListener() { + executionSupport.addExecutionListener(new DebugExecutionListener() { public void executionStarted(Source source, boolean stepInto) { // Push a new execution context onto stack @@ -146,13 +150,13 @@ } }; - this.lineBreaks = new LineBreakpointFactory(sourceExecutionProvider, breakpointCallback, warningLog); + this.lineBreaks = new LineBreakpointFactory(executionSupport, breakpointCallback, warningLog); - this.tagBreaks = new TagBreakpointFactory(sourceExecutionProvider, breakpointCallback, warningLog); + this.tagBreaks = new TagBreakpointFactory(executionSupport, breakpointCallback, warningLog); } - public static DebugEngine create(DebugClient debugClient, SourceExecutionProvider sourceExecutionProvider) { - return new DebugEngine(debugClient, sourceExecutionProvider); + public static DebugEngine create(DebugClient debugClient, Language language) { + return new DebugEngine(debugClient, language); } /** @@ -162,7 +166,7 @@ * @throws DebugException if an unexpected failure occurs */ public void run(Source source, boolean stepInto) throws DebugException { - sourceExecutionProvider.run(source, stepInto); + executionSupport.run(source, stepInto); } /** @@ -316,9 +320,11 @@ /** * Evaluates code in a halted execution context, at top-level if mFrame==null. + * + * @throws DebugException */ - public Object eval(Source source, Node node, MaterializedFrame mFrame) { - return sourceExecutionProvider.eval(source, node, mFrame); + public Object eval(Source source, Node node, MaterializedFrame mFrame) throws DebugException { + return executionSupport.evalInContext(source, node, mFrame); } /** @@ -806,9 +812,7 @@ if (frames == null) { stream.println(""); } else { - // TODO (mlvdv) get visualizer via the (to be developed) Truffle langauge API - final Visualizer visualizer = debugClient.getExecutionContext().getVisualizer(); - + final Visualizer visualizer = language.getDebugSupport().getVisualizer(); for (FrameDebugDescription frameDesc : frames) { final StringBuilder sb = new StringBuilder(" frame " + Integer.toString(frameDesc.index())); sb.append(":at " + visualizer.displaySourceLocation(frameDesc.node())); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java --- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java Tue Jun 09 19:07:39 2015 -0700 @@ -33,6 +33,10 @@ super(string); } + public DebugException(Exception ex) { + super(ex); + } + private static final long serialVersionUID = 3307454453821997224L; } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugExecutionSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugExecutionSupport.java Tue Jun 09 19:07:39 2015 -0700 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.tools.debug.engine; + +import java.util.*; + +import com.oracle.truffle.api.debug.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; + +/** + * Access to language-specific support for debugging. + */ +final class DebugExecutionSupport { + + interface DebugExecutionListener { + + /** + * Notifies that execution is about to start and requests initial execution mode. + */ + void executionStarted(Source source, boolean stepInto); + + /** + * Notification that the current execution has just ended. + */ + void executionEnded(); + } + + private final String languageName; + private final DebugSupportProvider provider; + private final List listeners = new ArrayList<>(); + + DebugExecutionSupport(String languageName, DebugSupportProvider provider) { + this.languageName = languageName; + this.provider = provider; + } + + void addExecutionListener(DebugExecutionListener listener) { + assert listener != null; + listeners.add(listener); + } + + String getLanguageName() { + return languageName; + } + + Visualizer getVisualizer() { + return provider.getVisualizer(); + } + + /** + * Runs a script. If "StepInto" is specified, halts at the first location tagged as a + * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}. + */ + void run(Source source, boolean stepInto) throws DebugException { + for (DebugExecutionListener listener : listeners) { + listener.executionStarted(source, stepInto); + } + try { + provider.run(source); + } catch (DebugSupportException ex) { + throw new DebugException(ex); + } finally { + for (DebugExecutionListener listener : listeners) { + listener.executionEnded(); + } + } + } + + /** + * Evaluates string of language code in a halted execution context, at top level if + * mFrame==null. + * + * @throws DebugException + */ + Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugException { + for (DebugExecutionListener listener : listeners) { + listener.executionStarted(source, false); + } + try { + return provider.evalInContext(source, node, mFrame); + } catch (DebugSupportException ex) { + throw new DebugException(ex); + } finally { + for (DebugExecutionListener listener : listeners) { + listener.executionEnded(); + } + } + } + + /** + * 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 + * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String) + * Advanced Instrument}. + * + * @param expr a guest language expression + * @param resultListener optional listener for the result of each evaluation. + * @return a new factory + * @throws DebugException if the factory cannot be created, for example if the expression is + * badly formed. + */ + AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugException { + try { + return provider.createAdvancedInstrumentRootFactory(expr, resultListener); + } catch (DebugSupportException ex) { + throw new DebugException(ex); + } + } + +} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java --- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java Tue Jun 09 19:07:39 2015 -0700 @@ -90,7 +90,7 @@ } }; - private final SourceExecutionProvider sourceExecutionProvider; + private final DebugExecutionSupport executionSupport; private final BreakpointCallback breakpointCallback; private final WarningLog warningLog; @@ -113,8 +113,8 @@ @CompilationFinal private boolean breakpointsActive = true; private final CyclicAssumption breakpointsActiveUnchanged = new CyclicAssumption(BREAKPOINT_NAME + " globally active"); - LineBreakpointFactory(SourceExecutionProvider sourceExecutionProvider, BreakpointCallback breakpointCallback, WarningLog warningLog) { - this.sourceExecutionProvider = sourceExecutionProvider; + LineBreakpointFactory(DebugExecutionSupport executionSupport, BreakpointCallback breakpointCallback, WarningLog warningLog) { + this.executionSupport = executionSupport; this.breakpointCallback = breakpointCallback; this.warningLog = warningLog; @@ -376,7 +376,7 @@ if (conditionExpr == null) { newInstrument = Instrument.create(new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME); } else { - newInstrument = Instrument.create(this, sourceExecutionProvider.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME); + newInstrument = Instrument.create(this, executionSupport.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME); } newProbe.attach(newInstrument); instruments.add(newInstrument); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/SourceExecutionProvider.java --- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/SourceExecutionProvider.java Tue Jun 09 23:00:38 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright (c) 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.tools.debug.engine; - -import java.util.*; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.instrument.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; - -/** - * Base for language-specific support required by the {@link DebugEngine} and any other tools that - * run sources. - */ -public abstract class SourceExecutionProvider { - - interface ExecutionListener { - - /** - * Notifies that execution is about to start and requests initial execution mode. - */ - void executionStarted(Source source, boolean stepInto); - - /** - * Notification that the current execution has just ended. - */ - void executionEnded(); - } - - private final List listeners = new ArrayList<>(); - - final void addExecutionListener(ExecutionListener listener) { - assert listener != null; - listeners.add(listener); - } - - /** - * Runs a script. If "StepInto" is specified, halts at the first location tagged as a - * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}. - */ - final void run(Source source, boolean stepInto) throws DebugException { - for (ExecutionListener listener : listeners) { - listener.executionStarted(source, stepInto); - } - try { - languageRun(source); - } finally { - for (ExecutionListener listener : listeners) { - listener.executionEnded(); - } - } - } - - /** - * Evaluates string of language code in a halted execution context, at top level if - * mFrame==null. - */ - final Object eval(Source source, Node node, MaterializedFrame mFrame) { - for (ExecutionListener listener : listeners) { - listener.executionStarted(source, false); - } - try { - return languageEval(source, node, mFrame); - } finally { - for (ExecutionListener listener : listeners) { - listener.executionEnded(); - } - } - } - - /** - * 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 - * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String) - * Advanced Instrument}. - * - * @param expr a guest language expression - * @param resultListener optional listener for the result of each evaluation. - * @return a new factory - * @throws DebugException if the factory cannot be created, for example if the expression is - * badly formed. - */ - final AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugException { - return languageAdvancedInstrumentRootFactory(expr, resultListener); - } - - /** - * Runs source code. - * - * @param source code - * @throws DebugException if unable to run successfully - */ - public abstract void languageRun(Source source) throws DebugException; - - /** - * Runs source code in a halted execution context, or at top level. - * - * @param source the code to run - * @param node node where execution halted, {@code null} if no execution context - * @param mFrame frame where execution halted, {@code null} if no execution context - * @return result of running the code in the context, or at top level if no execution context. - */ - public abstract Object languageEval(Source source, Node node, MaterializedFrame mFrame); - - /** - * Creates a {@linkplain AdvancedInstrumentRootFactory factory} that produces AST fragments from - * a textual expression, suitable for execution in context by the Instrumentation Framework. - * - * @param expr - * @param resultListener - * @return a factory that returns AST fragments that compute the expression - * @throws DebugException if the expression cannot be processed - * - * @see Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, - * Class, String) - */ - public abstract AdvancedInstrumentRootFactory languageAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugException; -} diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java --- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java Tue Jun 09 19:07:39 2015 -0700 @@ -86,7 +86,7 @@ } }; - private final SourceExecutionProvider sourceExecutionProvider; + private final DebugExecutionSupport executionSupport; private final BreakpointCallback breakpointCallback; private final WarningLog warningLog; @@ -102,8 +102,8 @@ @CompilationFinal private boolean breakpointsActive = true; private final CyclicAssumption breakpointsActiveUnchanged = new CyclicAssumption(BREAKPOINT_NAME + " globally active"); - TagBreakpointFactory(SourceExecutionProvider sourceExecutionProvider, BreakpointCallback breakpointCallback, WarningLog warningLog) { - this.sourceExecutionProvider = sourceExecutionProvider; + TagBreakpointFactory(DebugExecutionSupport executionSupport, BreakpointCallback breakpointCallback, WarningLog warningLog) { + this.executionSupport = executionSupport; this.breakpointCallback = breakpointCallback; this.warningLog = warningLog; @@ -338,7 +338,7 @@ if (conditionExpr == null) { newInstrument = Instrument.create(new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME); } else { - newInstrument = Instrument.create(this, sourceExecutionProvider.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME); + newInstrument = Instrument.create(this, executionSupport.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME); } newProbe.attach(newInstrument); instruments.add(newInstrument); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java --- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Tue Jun 09 19:07:39 2015 -0700 @@ -29,7 +29,6 @@ import jline.console.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.tools.debug.shell.*; @@ -84,7 +83,7 @@ private static final String STACK_FRAME_FORMAT = " %3d: at %s in %s line =\"%s\"\n"; private static final String STACK_FRAME_SELECTED_FORMAT = "==> %3d: at %s in %s line =\"%s\"\n"; - private final ExecutionContext executionContext; // Language context + private final String languageName; // Top level commands private final Map commandMap = new HashMap<>(); @@ -139,8 +138,8 @@ */ private Source selectedSource = null; - public SimpleREPLClient(ExecutionContext context, REPLServer replServer) { - this.executionContext = context; + public SimpleREPLClient(String languageName, REPLServer replServer) { + this.languageName = languageName; this.replServer = replServer; this.writer = System.out; try { @@ -211,7 +210,7 @@ try { clientContext.startSession(); } finally { - clientContext.displayReply("Goodbye from " + executionContext.getLanguageShortName() + "/REPL"); + clientContext.displayReply("Goodbye from " + languageName + "/REPL"); } } @@ -282,8 +281,7 @@ if (level == 0) { // 0-level context; no executions halted. if (selectedSource == null) { - final String languageName = executionContext.getLanguageShortName(); - currentPrompt = languageName == null ? "() " : "(" + languageName + ") "; + currentPrompt = languageName == null ? "() " : "( " + languageName + " ) "; } else { currentPrompt = "(" + selectedSource.getShortName() + ") "; } diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java --- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Tue Jun 09 19:07:39 2015 -0700 @@ -26,13 +26,13 @@ import java.util.*; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.vm.TruffleVM.Language; +import com.oracle.truffle.tools.debug.engine.*; import com.oracle.truffle.tools.debug.shell.*; -import com.oracle.truffle.tools.debug.engine.*; /** * Server-side REPL implementation of an {@linkplain REPLMessage "op"}. @@ -115,7 +115,7 @@ } protected static REPLMessage createFrameInfoMessage(final REPLServerContext serverContext, FrameDebugDescription frame) { - final Visualizer visualizer = serverContext.getLanguageContext().getVisualizer(); + final Visualizer visualizer = serverContext.getLanguage().getDebugSupport().getVisualizer(); final REPLMessage infoMessage = new REPLMessage(REPLMessage.OP, REPLMessage.FRAME_INFO); infoMessage.put(REPLMessage.FRAME_NUMBER, Integer.toString(frame.index())); final Node node = frame.node(); @@ -402,15 +402,16 @@ final FrameDebugDescription frameDescription = stack.get(frameNumber); final REPLMessage frameMessage = createFrameInfoMessage(serverContext, frameDescription); final Frame frame = frameDescription.frameInstance().getFrame(FrameInstance.FrameAccess.READ_ONLY, true); - final ExecutionContext context = serverContext.getLanguageContext(); + final Language language = serverContext.getLanguage(); + final Visualizer visualizer = language.getDebugSupport().getVisualizer(); final FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); try { final StringBuilder sb = new StringBuilder(); for (FrameSlot slot : frameDescriptor.getSlots()) { - sb.append(Integer.toString(slot.getIndex()) + ": " + context.getVisualizer().displayIdentifier(slot) + " = "); + sb.append(Integer.toString(slot.getIndex()) + ": " + visualizer.displayIdentifier(slot) + " = "); try { final Object value = frame.getValue(slot); - sb.append(context.getVisualizer().displayValue(context, value, 0)); + sb.append(visualizer.displayValue(value, 0)); } catch (Exception ex) { sb.append("???"); } @@ -513,7 +514,7 @@ @Override public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) { final REPLMessage reply = createReply(); - final ASTPrinter astPrinter = serverContext.getLanguageContext().getVisualizer().getASTPrinter(); + final ASTPrinter astPrinter = serverContext.getLanguage().getDebugSupport().getVisualizer().getASTPrinter(); final String topic = request.get(REPLMessage.TOPIC); reply.put(REPLMessage.TOPIC, topic); Node node = serverContext.getNode(); @@ -574,7 +575,7 @@ @Override public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) { final REPLMessage reply = createReply(); - final ASTPrinter astPrinter = serverContext.getLanguageContext().getVisualizer().getASTPrinter(); + final ASTPrinter astPrinter = serverContext.getLanguage().getDebugSupport().getVisualizer().getASTPrinter(); final Node node = serverContext.getNode(); if (node == null) { return finishReplyFailed(reply, "no current AST node"); diff -r 878786299d2d -r 9fe51d8fae0f graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java --- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java Tue Jun 09 23:00:38 2015 +0200 +++ b/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java Tue Jun 09 19:07:39 2015 -0700 @@ -24,11 +24,11 @@ */ package com.oracle.truffle.tools.debug.shell.server; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.vm.TruffleVM.Language; +import com.oracle.truffle.tools.debug.engine.*; import com.oracle.truffle.tools.debug.shell.*; -import com.oracle.truffle.tools.debug.engine.*; public abstract class REPLServerContext { @@ -63,7 +63,7 @@ return mFrame; } - public abstract ExecutionContext getLanguageContext(); + public abstract Language getLanguage(); public abstract DebugEngine getDebugEngine(); diff -r 878786299d2d -r 9fe51d8fae0f mx/mx_graal.py --- a/mx/mx_graal.py Tue Jun 09 23:00:38 2015 +0200 +++ b/mx/mx_graal.py Tue Jun 09 19:07:39 2015 -0700 @@ -2369,7 +2369,7 @@ def sl(args): """run an SL program""" vmArgs, slArgs = _extract_VM_args(args) - vm(vmArgs + ['-cp', mx.classpath(["TRUFFLE", "com.oracle.truffle.sl"]), "com.oracle.truffle.sl.SLMain"] + slArgs) + vm(vmArgs + ['-cp', mx.classpath(["TRUFFLE", "com.oracle.truffle.sl"]), "com.oracle.truffle.sl.SLLanguage"] + slArgs) def sldebug(args): """run a simple command line debugger for the Simple Language""" diff -r 878786299d2d -r 9fe51d8fae0f mx/suite.py --- a/mx/suite.py Tue Jun 09 23:00:38 2015 +0200 +++ b/mx/suite.py Tue Jun 09 19:07:39 2015 -0700 @@ -1227,10 +1227,7 @@ "com.oracle.truffle.sl.tools" : { "subDir" : "graal", "sourceDirs" : ["src"], - "dependencies" : [ - "com.oracle.truffle.sl", - "com.oracle.truffle.tools.debug.shell", - ], + "dependencies" : ["com.oracle.truffle.tools.debug.shell"], "checkstyle" : "com.oracle.truffle.api", "javaCompliance" : "1.8", "workingSets" : "Truffle,SimpleLanguage,Tools",