Mercurial > hg > truffle
diff truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @ 22266:0d36601f233e
Merge revised Instrumentation framework into the Polyglot API
- Required language implementation support now in TruffleLanguage
- Instrumentation services provided by the new Instrumenter class
- Reduced public API exposure; communication with other components via Accessor
- Several methods removed from the Node class
- Many test rewritten or using a new "test mode" because of limited access to Engine services
Merge with c66f520ad8562b906a878e9b3293aaf54270db90
author | Michael Van De Vanter <michael.van.de.vanter@oracle.com> |
---|---|
date | Wed, 30 Sep 2015 16:33:56 -0700 |
parents | 09d91119929f b73205fe7cf3 |
children | b56fe0d3b560 |
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Tue Sep 29 18:04:11 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Wed Sep 30 16:33:56 2015 -0700 @@ -24,12 +24,6 @@ */ package com.oracle.truffle.api; -import com.oracle.truffle.api.debug.DebugSupportProvider; -import com.oracle.truffle.api.impl.Accessor; -import com.oracle.truffle.api.impl.FindContextNode; -import com.oracle.truffle.api.instrument.ToolSupportProvider; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.source.Source; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -45,6 +39,21 @@ import java.util.Map; import java.util.WeakHashMap; +import com.oracle.truffle.api.debug.Debugger; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.impl.Accessor; +import com.oracle.truffle.api.impl.FindContextNode; +import com.oracle.truffle.api.instrument.ASTProber; +import com.oracle.truffle.api.instrument.AdvancedInstrumentResultListener; +import com.oracle.truffle.api.instrument.AdvancedInstrumentRoot; +import com.oracle.truffle.api.instrument.AdvancedInstrumentRootFactory; +import com.oracle.truffle.api.instrument.Instrumenter; +import com.oracle.truffle.api.instrument.SyntaxTag; +import com.oracle.truffle.api.instrument.Visualizer; +import com.oracle.truffle.api.instrument.WrapperNode; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.source.Source; + /** * An entry point for everyone who wants to implement a Truffle based language. By providing an * implementation of this type and registering it using {@link Registration} annotation, your @@ -52,6 +61,13 @@ * polyglot execution engine} - all they will need to do is to include your JAR into their * application and all the Truffle goodies (multi-language support, multitenant hosting, debugging, * etc.) will be made available to them. + * <p> + * The use of {@linkplain Instrumenter Instrument-based services} requires that the language + * {@linkplain Instrumenter#registerASTProber(com.oracle.truffle.api.instrument.ASTProber) register} + * an instance of {@link ASTProber} suitable for the language implementation that can be applied to + * "mark up" each newly created AST with {@link SyntaxTag "tags"} that identify standard syntactic + * constructs in order to configure tool behavior. See also {@linkplain #createContext(Env) + * createContext(Env)}. * * @param <C> internal state of the language associated with every thread that is executing program * {@link #parse(com.oracle.truffle.api.source.Source, com.oracle.truffle.api.nodes.Node, java.lang.String...) @@ -67,18 +83,18 @@ /** * The annotation to use to register your language to the - * {@link com.oracle.truffle.api.vm.TruffleVM Truffle} system. By annotating your implementation - * of {@link TruffleLanguage} by this annotation you are just a + * {@link com.oracle.truffle.api.vm.PolyglotEngine Truffle} system. By annotating your + * implementation of {@link TruffleLanguage} by this annotation you are just a * <em>one JAR drop to the class path</em> away from your users. Once they include your JAR in * their application, your language will be available to the - * {@link com.oracle.truffle.api.vm.TruffleVM Truffle virtual machine}. + * {@link com.oracle.truffle.api.vm.PolyglotEngine Truffle virtual machine}. */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface Registration { /** * Unique name of your language. This name will be exposed to users via the - * {@link com.oracle.truffle.api.vm.TruffleVM.Language#getName()} getter. + * {@link com.oracle.truffle.api.vm.PolyglotEngine.Language#getName()} getter. * * @return identifier of your language */ @@ -86,7 +102,7 @@ /** * Unique string identifying the language version. This name will be exposed to users via - * the {@link com.oracle.truffle.api.vm.TruffleVM.Language#getVersion()} getter. + * the {@link com.oracle.truffle.api.vm.PolyglotEngine.Language#getVersion()} getter. * * @return version of your language */ @@ -95,7 +111,7 @@ /** * List of MIME types associated with your language. Users will use them (directly or * indirectly) when - * {@link com.oracle.truffle.api.vm.TruffleVM#eval(com.oracle.truffle.api.source.Source) + * {@link com.oracle.truffle.api.vm.PolyglotEngine#eval(com.oracle.truffle.api.source.Source) * executing} their code snippets or their {@link Source files}. * * @return array of MIME types assigned to your language files @@ -117,6 +133,15 @@ * {@link Node findNode} and later {@link #findContext(com.oracle.truffle.api.nodes.Node) * findContext(findNode)} to get back your language context. * + * If it is expected that any {@linkplain Instrumenter Instrumentation Services} or tools that + * depend on those services (e.g. the {@link Debugger}, then part of the preparation in the new + * context is to + * {@linkplain Instrumenter#registerASTProber(com.oracle.truffle.api.instrument.ASTProber) + * register} a "default" {@link ASTProber} for the language implementation. Instrumentation + * requires that this be available to "mark up" each newly created AST with + * {@linkplain SyntaxTag "tags"} that identify standard syntactic constructs in order to + * configure tool behavior. + * * @param env the environment the language is supposed to operate in * @return internal data of the language in given environment */ @@ -152,7 +177,7 @@ * just parsed <code>code</code> * @throws IOException thrown when I/O or parsing goes wrong. Here-in thrown exception is * propagate to the user who called one of <code>eval</code> methods of - * {@link com.oracle.truffle.api.vm.TruffleVM} + * {@link com.oracle.truffle.api.vm.PolyglotEngine} */ protected abstract CallTarget parse(Source code, Node context, String... argumentNames) throws IOException; @@ -201,9 +226,59 @@ */ protected abstract boolean isObjectOfLanguage(Object object); - protected abstract ToolSupportProvider getToolSupport(); + /** + * Gets visualization services for language-specific information. + */ + protected abstract Visualizer getVisualizer(); + + /** + * Returns {@code true} for a node can be "instrumented" by + * {@linkplain Instrumenter#probe(Node) probing}. + * <p> + * <b>Note:</b> instrumentation requires a appropriate {@link WrapperNode} + * + * @see WrapperNode + */ + protected abstract boolean isInstrumentable(Node node); - protected abstract DebugSupportProvider getDebugSupport(); + /** + * For nodes in this language that are <em>instrumentable</em>, this method returns an + * {@linkplain Node AST node} that: + * <ol> + * <li>implements {@link WrapperNode};</li> + * <li>has the node argument as it's child; and</li> + * <li>whose type is safe for replacement of the node in the parent.</li> + * </ol> + * + * @return an appropriately typed {@link WrapperNode} + */ + protected abstract WrapperNode createWrapperNode(Node node); + + /** + * 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 IOException if the evaluation cannot be performed + */ + protected abstract Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws IOException; + + /** + * 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 Instrumenter#attach(com.oracle.truffle.api.instrument.Probe, AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)} + * . + * + * @param expr a guest language expression + * @param resultListener optional listener for the result of each evaluation. + * @return a new factory + * @throws IOException if the factory cannot be created, for example if the expression is badly + * formed. + */ + protected abstract AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws IOException; /** * Allows a language implementor to create a node that can effectively lookup up the context @@ -278,13 +353,15 @@ private final InputStream in; private final OutputStream err; private final OutputStream out; + private final Instrumenter instrumenter; - Env(Object vm, TruffleLanguage<?> lang, OutputStream out, OutputStream err, InputStream in) { + Env(Object vm, TruffleLanguage<?> lang, OutputStream out, OutputStream err, InputStream in, Instrumenter instrumenter) { this.vm = vm; this.in = in; this.err = err; this.out = out; this.lang = lang; + this.instrumenter = instrumenter; this.langCtx = new LangCtx<>(lang, this); } @@ -302,8 +379,8 @@ } /** - * Input associated with {@link com.oracle.truffle.api.vm.TruffleVM} this language is being - * executed in. + * Input associated with {@link com.oracle.truffle.api.vm.PolyglotEngine} this language is + * being executed in. * * @return reader, never <code>null</code> */ @@ -317,8 +394,8 @@ } /** - * Standard output writer for {@link com.oracle.truffle.api.vm.TruffleVM} this language is - * being executed in. + * Standard output writer for {@link com.oracle.truffle.api.vm.PolyglotEngine} this language + * is being executed in. * * @return writer, never <code>null</code> */ @@ -332,8 +409,8 @@ } /** - * Standard error writer for {@link com.oracle.truffle.api.vm.TruffleVM} this language is - * being executed in. + * Standard error writer for {@link com.oracle.truffle.api.vm.PolyglotEngine} this language + * is being executed in. * * @return writer, never <code>null</code> */ @@ -345,6 +422,10 @@ public Writer stdErr() { return new OutputStreamWriter(err); } + + public Instrumenter instrumenter() { + return instrumenter; + } } private static final AccessAPI API = new AccessAPI(); @@ -352,8 +433,8 @@ @SuppressWarnings("rawtypes") private static final class AccessAPI extends Accessor { @Override - protected Env attachEnv(Object vm, TruffleLanguage<?> language, OutputStream stdOut, OutputStream stdErr, InputStream stdIn) { - Env env = new Env(vm, language, stdOut, stdErr, stdIn); + protected Env attachEnv(Object vm, TruffleLanguage<?> language, OutputStream stdOut, OutputStream stdErr, InputStream stdIn, Instrumenter instrumenter) { + Env env = new Env(vm, language, stdOut, stdErr, stdIn, instrumenter); return env; } @@ -382,6 +463,14 @@ } @Override + protected AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(Object vm, Class<? extends TruffleLanguage> languageClass, String expr, + AdvancedInstrumentResultListener resultListener) throws IOException { + + final TruffleLanguage language = findLanguageImpl(vm, languageClass); + return language.createAdvancedInstrumentRootFactory(expr, resultListener); + } + + @Override protected Object findExportedSymbol(TruffleLanguage.Env env, String globalName, boolean onlyExplicit) { return env.langCtx.findExportedSymbol(globalName, onlyExplicit); } @@ -407,13 +496,13 @@ } @Override - protected ToolSupportProvider getToolSupport(TruffleLanguage<?> l) { - return l.getToolSupport(); + protected boolean isInstrumentable(Node node, TruffleLanguage language) { + return language.isInstrumentable(node); } @Override - protected DebugSupportProvider getDebugSupport(TruffleLanguage<?> l) { - return l.getDebugSupport(); + protected WrapperNode createWrapperNode(Node node, TruffleLanguage language) { + return language.createWrapperNode(node); } @Override