# HG changeset patch # User David Piorkowski # Date 1406243684 25200 # Node ID 618d92152d3cdff2533b01ef7645f62b3ee1c3a0 # Parent 8084d44c78d3626f2400b251d4a2b6862f44489a SL: Added support for instrumentation. diff -r 8084d44c78d3 -r 618d92152d3c 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 Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java Thu Jul 24 16:14:44 2014 -0700 @@ -152,7 +152,7 @@ if (sourceCallback != null) { sourceCallback.startLoading(source); } - Parser.parseSL(context, source); + Parser.parseSL(context, source, null); if (sourceCallback != null) { sourceCallback.endLoading(source); } diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java Thu Jul 24 16:14:44 2014 -0700 @@ -50,6 +50,6 @@ private static void doDefineFunction(SLContext context, String code) { Source source = Source.fromText(code, "[defineFunction]"); /* The same parsing code as for parsing the initial source. */ - Parser.parseSL(context, source); + Parser.parseSL(context, source, null); } } diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 2014, 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.factory; + +import java.io.*; + +import com.oracle.truffle.sl.nodes.instrument.*; +import com.oracle.truffle.sl.runtime.*; + +public final class SLContextFactory { + + private static SLASTProber astProber; + + private SLContextFactory() { + + } + + public static SLContext create() { + final SLContext slContext = new SLContext(new BufferedReader(new InputStreamReader(System.in)), System.out); + slContext.initialize(); + slContext.setVisualizer(new SLDefaultVisualizer()); + astProber = new SLASTProber(); + slContext.setASTNodeProber(astProber); + return slContext; + } + + public static void addNodeProber(SLNodeProber nodeProber) { + astProber.addNodeProber(nodeProber); + } +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java Thu Jul 24 16:14:44 2014 -0700 @@ -42,4 +42,8 @@ * Execute this node as as statement, where no return value is necessary. */ public abstract void executeVoid(VirtualFrame frame); + + public SLStatementNode getNonWrapperNode() { + return this; + } } diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2012, 2014, 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.nodes.instrument; + +import java.io.*; +import java.util.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.NodeClass; +import com.oracle.truffle.api.nodes.NodeUtil.NodeField; +import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind; +import com.oracle.truffle.api.source.*; + +/** + * SLASTPrinter is used to print for SL's internal Truffle AST. This is used by + * {@link SLDefaultVisualizer} to provide a means of displaying the internal Truffle AST + */ +public final class SLASTPrinter implements ASTPrinter { + public SLASTPrinter() { + } + + public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) { + printTree(p, node, maxDepth, markNode, 1); + p.println(); + p.flush(); + } + + public String printTreeToString(Node node, int maxDepth, Node markNode) { + StringWriter out = new StringWriter(); + printTree(new PrintWriter(out), node, maxDepth, markNode); + return out.toString(); + } + + public String printTreeToString(Node node, int maxDepth) { + return printTreeToString(node, maxDepth, null); + } + + private static void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) { + if (node == null) { + p.print("null"); + return; + } + + p.print(nodeName(node)); + + String sep = ""; + p.print("("); + + final SourceSection src = node.getSourceSection(); + if (src != null) { + if (!(src instanceof NullSourceSection)) { + p.print(src.getSource().getName() + ":" + src.getStartLine()); + } else if (src instanceof NullSourceSection) { + final NullSourceSection nullSection = (NullSourceSection) src; + p.print(nullSection.getShortDescription()); + } + } + if (node instanceof SyntaxTagged) { + final SyntaxTagged taggedNode = (SyntaxTagged) node; + p.print("["); + String prefix = ""; + for (SyntaxTag tag : taggedNode.getSyntaxTags()) { + p.print(prefix); + prefix = ","; + p.print(tag.toString()); + } + p.print("]"); + } + + ArrayList childFields = new ArrayList<>(); + + for (NodeField field : NodeClass.get(node.getClass()).getFields()) { + if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) { + childFields.add(field); + } else if (field.getKind() == NodeFieldKind.DATA) { + // p.print(sep); + // sep = ", "; + // + // final String fieldName = field.getName(); + // switch (fieldName) { + // + // } + // p.print(fieldName); + // p.print(" = "); + // p.print(field.loadValue(node)); + } + } + p.print(")"); + + if (level <= maxDepth) { + + if (childFields.size() != 0) { + p.print(" {"); + for (NodeField field : childFields) { + + Object value = field.loadValue(node); + if (value == null) { + printNewLine(p, level); + p.print(field.getName()); + p.print(" = null "); + } else if (field.getKind() == NodeFieldKind.CHILD) { + final Node valueNode = (Node) value; + printNewLine(p, level, valueNode == markNode); + p.print(field.getName()); + p.print(" = "); + printTree(p, valueNode, maxDepth, markNode, level + 1); + } else if (field.getKind() == NodeFieldKind.CHILDREN) { + printNewLine(p, level); + p.print(field.getName()); + Node[] children = (Node[]) value; + p.print(" = ["); + sep = ""; + for (Node child : children) { + p.print(sep); + sep = ", "; + printTree(p, child, maxDepth, markNode, level + 1); + } + p.print("]"); + } else { + printNewLine(p, level); + p.print(field.getName()); + } + } + printNewLine(p, level - 1); + p.print("}"); + } + } + } + + private static void printNewLine(PrintWriter p, int level, boolean mark) { + p.println(); + for (int i = 0; i < level; i++) { + if (mark && i == 0) { + p.print(" -->"); + } else { + p.print(" "); + } + } + } + + private static void printNewLine(PrintWriter p, int level) { + printNewLine(p, level, false); + } + + private static String nodeName(Node node) { + return node.getClass().getSimpleName(); + } +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012, 2014, 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.nodes.instrument; + +import java.util.*; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; + +/** + * SLASTProber contains the collection of {@link SLNodeProber}s and methods to attach the probers to + * nodes. + */ +public final class SLASTProber implements ASTProber, SLNodeProber { + + private ArrayList nodeProbers = new ArrayList<>(); + + public SLASTProber() { + } + + /** + * Adds a {@link SLNodeProber} to this SLASTProber. Probes must be of type {@link SLNodeProber} + * and must not already have been added. + * + * @param nodeProber the {@link SLNodeProber} to add. + */ + public void addNodeProber(ASTNodeProber nodeProber) { + if (nodeProber instanceof SLNodeProber) { + assert !nodeProbers.contains(nodeProber); + nodeProbers.add((SLNodeProber) nodeProber); + } else { + throw new IllegalArgumentException("invalid prober for SL implementation"); + } + } + + /** + * Unimplemented, does nothing. + */ + public Node probeAs(Node astNode, SyntaxTag tag, Object... args) { + return astNode; + } + + /** + * Attaches the current probers to the given {@link SLStatementNode} as a statement. + * + * @param node The {@link SLStatementNode} to attach the stored set of probers to. + */ + @Override + public SLStatementNode probeAsStatement(SLStatementNode node) { + SLStatementNode result = node; + for (SLNodeProber nodeProber : nodeProbers) { + result = nodeProber.probeAsStatement(result); + } + return result; + } + + /** + * Attaches the current probers to the given {@link SLExpressionNode} as a call. This will wrap + * the passed in node in an {@link SLExpressionWrapper}, tag it as a call and attach an + * instrument to it. + * + * @param node The {@link SLExpressionNode} to attach the stored set of probers to. + * @param callName The name of the call ??? + * + */ + @Override + public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) { + SLExpressionNode result = node; + for (SLNodeProber nodeProber : nodeProbers) { + result = nodeProber.probeAsCall(node, callName); + } + return result; + } + + /** + * Attaches the current probers to the given {@link SLExpressionNode} as an assignment. This + * will wrap the passed in node in an {@link SLExpressionWrapper}, tag it as an assignment and + * attach an instrument to it. + * + * @param node The {@link SLExpressionNode} to attached the stored set of probers to. + * @param localName The name of the assignment ??? + * + */ + @Override + public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) { + SLExpressionNode result = node; + for (SLNodeProber nodeProber : nodeProbers) { + result = nodeProber.probeAsLocalAssignment(result, localName); + } + return result; + } + + public ASTNodeProber getCombinedNodeProber() { + return nodeProbers.isEmpty() ? null : this; + } + +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012, 2014, 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.nodes.instrument; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.instrument.impl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * SLDefaultVisualizer provides methods to get the names of SL's internal Truffle AST nodes. + * + */ +public class SLDefaultVisualizer extends DefaultVisualizer { + + private final SLASTPrinter astPrinter; + + public SLDefaultVisualizer() { + this.astPrinter = new SLASTPrinter(); + } + + @Override + public ASTPrinter getASTPrinter() { + return astPrinter; + } + + @Override + public String displayMethodName(Node node) { + + if (node == null) { + return null; + } + RootNode root = node.getRootNode(); + if (root instanceof SLRootNode) { + SLRootNode slRootNode = (SLRootNode) root; + return slRootNode.toString(); + + } + return "unknown"; + } + + @Override + public String displayCallTargetName(CallTarget callTarget) { + if (callTarget instanceof RootCallTarget) { + final RootCallTarget rootCallTarget = (RootCallTarget) callTarget; + SLRootNode slRootNode = (SLRootNode) rootCallTarget.getRootNode(); + return slRootNode.toString(); + } + return callTarget.toString(); + } + + @Override + public String displayValue(ExecutionContext context, Object value) { + if (value == SLNull.SINGLETON) { + return "null"; + } + return value.toString(); + } + + @Override + public String displayIdentifier(FrameSlot slot) { + + final Object id = slot.getIdentifier(); + return id.toString(); + } +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2012, 2014, 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.nodes.instrument; + +import java.math.*; + +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * SLExpressionWrapper is a Truffle AST node that gets inserted as the parent to the node that it is + * wrapping. Any debugging instruments are attached to this wrapper through {@link Probe}s (which + * themselves contain the instruments. It is through this mechanism that tools can interact directly + * with the AST.
+ * {@link SLExpressionWrapper} specifically wraps {@link SLExpressionNode}s and overrides the + * various execute functions in {@link SLExpressionNode} to operate on the child of the wrapper + * instead of the wrapper itself. + * + */ +public final class SLExpressionWrapper extends SLExpressionNode implements Wrapper { + @Child private SLExpressionNode child; + + private final Probe probe; + + public SLExpressionWrapper(SLContext context, SLExpressionNode child) { + super(child.getSourceSection()); + assert !(child instanceof SLExpressionWrapper); + this.child = insert(child); + this.probe = context.getProbe(child.getSourceSection()); + } + + @Override + public SLExpressionNode getNonWrapperNode() { + return child; + } + + @Override + public Node getChild() { + return child; + } + + @Override + public Probe getProbe() { + return probe; + } + + @Override + @SlowPath + public boolean isTaggedAs(SyntaxTag tag) { + return probe.isTaggedAs(tag); + } + + @Override + @SlowPath + public Iterable getSyntaxTags() { + return probe.getSyntaxTags(); + } + + @SlowPath + public void tagAs(SyntaxTag tag) { + probe.tagAs(tag); + } + + @Override + public Object executeGeneric(VirtualFrame frame) { + this.tagAs(StandardSyntaxTag.STATEMENT); + probe.enter(child, frame); + Object result; + + try { + result = child.executeGeneric(frame); + probe.leave(child, frame, result); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + return result; + } + + @Override + public long executeLong(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectLong(executeGeneric(frame)); + } + + @Override + public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectBigInteger(executeGeneric(frame)); + } + + @Override + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectBoolean(executeGeneric(frame)); + } + + @Override + public String executeString(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + return SLTypesGen.SLTYPES.expectString(executeGeneric(frame)); + } + + @Override + public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException { + this.tagAs(StandardSyntaxTag.STATEMENT); + probe.enter(child, frame); + SLFunction result; + + try { + result = child.executeFunction(frame); + probe.leave(child, frame, result); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + return result; + } + + @Override + public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException { + return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame)); + } +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLNodeProber.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, 2014, 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.nodes.instrument; + +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.sl.nodes.*; + +public interface SLNodeProber extends ASTNodeProber { + + SLStatementNode probeAsStatement(SLStatementNode result); + + SLExpressionNode probeAsCall(SLExpressionNode node, String callName); + + SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName); +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java Thu Jul 24 16:14:44 2014 -0700 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012, 2014, 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.nodes.instrument; + +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.runtime.*; + +/** + * SLStatmentWrapper is a Truffle AST node that gets inserted as the parent to the node that it is + * wrapping. Any debugging instruments are attached to this wrapper through {@link Probe}s (which + * themselves contain the instruments). It is through this mechanism that tools can interact + * directly with the AST.
+ * SLStatmentWrapper specifically wraps {@link SLStatementWrapper}s and overrides the executeVoid + * function of {@link SLStatementNode} to operate on the child of the wrapper instead of the wrapper + * itself. + * + */ +public final class SLStatementWrapper extends SLStatementNode implements Wrapper { + + @Child private SLStatementNode child; + + private final Probe probe; + + public SLStatementWrapper(SLContext context, SLStatementNode child) { + super(child.getSourceSection()); + assert !(child instanceof SLStatementWrapper); + this.child = insert(child); + this.probe = context.getProbe(child.getSourceSection()); + } + + @Override + public SLStatementNode getNonWrapperNode() { + return child; + } + + public Node getChild() { + return child; + } + + public Probe getProbe() { + return probe; + } + + @SlowPath + public boolean isTaggedAs(SyntaxTag tag) { + return probe.isTaggedAs(tag); + } + + @SlowPath + public Iterable getSyntaxTags() { + return probe.getSyntaxTags(); + } + + @SlowPath + public void tagAs(SyntaxTag tag) { + probe.tagAs(tag); + } + + @Override + public void executeVoid(VirtualFrame frame) { + this.tagAs(StandardSyntaxTag.STATEMENT); + probe.enter(child, frame); + + try { + child.executeVoid(frame); + probe.leave(child, frame); + } catch (KillException e) { + throw (e); + } catch (Exception e) { + probe.leaveExceptional(child, frame, e); + throw (e); + } + + } +} diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame Thu Jul 24 16:14:44 2014 -0700 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -51,9 +52,9 @@ public final Errors errors; private final SLNodeFactory factory; -->declarations - public Parser(SLContext context, Source source) { + public Parser(SLContext context, Source source, SLNodeProber astProber) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source); + this.factory = new SLNodeFactory(context, source, astProber); errors = new Errors(); } @@ -134,8 +135,8 @@ -->initialization }; - public static void parseSL(SLContext context, Source source) { - Parser parser = new Parser(context, source); + public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { + Parser parser = new Parser(context, source, astProber); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Thu Jul 24 16:14:44 2014 -0700 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.source.*; import com.oracle.truffle.sl.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.runtime.*; // Checkstyle: stop @@ -52,10 +53,10 @@ public final Scanner scanner; public final Errors errors; private final SLNodeFactory factory; - - public Parser(SLContext context, Source source) { + + public Parser(SLContext context, Source source, SLNodeProber astProber) { this.scanner = new Scanner(source.getInputStream()); - this.factory = new SLNodeFactory(context, source); + this.factory = new SLNodeFactory(context, source, astProber); errors = new Errors(); } @@ -133,41 +134,41 @@ void Function() { Expect(4); Expect(1); - factory.startFunction(t); + factory.startFunction(t); Expect(5); if (la.kind == 1) { Get(); - factory.addFormalParameter(t); + factory.addFormalParameter(t); while (la.kind == 6) { Get(); Expect(1); - factory.addFormalParameter(t); + factory.addFormalParameter(t); } } Expect(7); SLStatementNode body = Block(false); - factory.finishFunction(body); + factory.finishFunction(body); } SLStatementNode Block(boolean inLoop) { SLStatementNode result; factory.startBlock(); - List body = new ArrayList<>(); + List body = new ArrayList<>(); Expect(8); - int lBracePos = t.charPos; + int lBracePos = t.charPos; while (StartOf(1)) { SLStatementNode s = Statement(inLoop); - body.add(s); + body.add(s); } Expect(9); - int length = (t.charPos + t.val.length()) - lBracePos; - result = factory.finishBlock(body, lBracePos, length); + int length = (t.charPos + t.val.length()) - lBracePos; + result = factory.finishBlock(body, lBracePos, length); return result; } SLStatementNode Statement(boolean inLoop) { SLStatementNode result; - result = null; + result = null; switch (la.kind) { case 13: { result = WhileStatement(); @@ -175,13 +176,13 @@ } case 10: { Get(); - if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } + if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } Expect(11); break; } case 12: { Get(); - if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } + if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } Expect(11); break; } @@ -207,11 +208,11 @@ SLStatementNode result; Expect(13); Expect(5); - Token whileToken = t; + Token whileToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode body = Block(true); - result = factory.createWhile(whileToken, condition, body); + result = factory.createWhile(whileToken, condition, body); return result; } @@ -219,16 +220,16 @@ SLStatementNode result; Expect(14); Expect(5); - Token ifToken = t; + Token ifToken = t; SLExpressionNode condition = Expression(); Expect(7); SLStatementNode thenPart = Block(inLoop); - SLStatementNode elsePart = null; + SLStatementNode elsePart = null; if (la.kind == 15) { Get(); elsePart = Block(inLoop); } - result = factory.createIf(ifToken, condition, thenPart, elsePart); + result = factory.createIf(ifToken, condition, thenPart, elsePart); return result; } @@ -236,11 +237,11 @@ SLStatementNode result; Expect(16); Token returnToken = t; - SLExpressionNode value = null; + SLExpressionNode value = null; if (StartOf(2)) { value = Expression(); } - result = factory.createReturn(returnToken, value); + result = factory.createReturn(returnToken, value); Expect(11); return result; } @@ -250,9 +251,9 @@ result = LogicTerm(); while (la.kind == 17) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicTerm(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -262,9 +263,9 @@ result = LogicFactor(); while (la.kind == 18) { Get(); - Token op = t; + Token op = t; SLExpressionNode right = LogicFactor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -299,9 +300,9 @@ break; } } - Token op = t; + Token op = t; SLExpressionNode right = Arithmetic(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -315,9 +316,9 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Term(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } @@ -331,48 +332,48 @@ } else { Get(); } - Token op = t; + Token op = t; SLExpressionNode right = Factor(); - result = factory.createBinary(op, result, right); + result = factory.createBinary(op, result, right); } return result; } SLExpressionNode Factor() { SLExpressionNode result; - result = null; + result = null; if (la.kind == 1) { Get(); - Token nameToken = t; + Token nameToken = t; if (la.kind == 5) { Get(); List parameters = new ArrayList<>(); - SLExpressionNode parameter; + SLExpressionNode parameter; if (StartOf(2)) { parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); while (la.kind == 6) { Get(); parameter = Expression(); - parameters.add(parameter); + parameters.add(parameter); } } Expect(7); - Token finalToken = t; - result = factory.createCall(nameToken, parameters, finalToken); + Token finalToken = t; + result = factory.createCall(nameToken, parameters, finalToken); } else if (la.kind == 29) { Get(); SLExpressionNode value = Expression(); - result = factory.createAssignment(nameToken, value); + result = factory.createAssignment(nameToken, value); } else if (StartOf(4)) { - result = factory.createRead(nameToken); + result = factory.createRead(nameToken); } else SynErr(32); } else if (la.kind == 2) { Get(); - result = factory.createStringLiteral(t); + result = factory.createStringLiteral(t); } else if (la.kind == 3) { Get(); - result = factory.createNumericLiteral(t); + result = factory.createNumericLiteral(t); } else if (la.kind == 5) { Get(); result = Expression(); @@ -401,8 +402,8 @@ }; - public static void parseSL(SLContext context, Source source) { - Parser parser = new Parser(context, source); + public static void parseSL(SLContext context, Source source, SLNodeProber astProber) { + Parser parser = new Parser(context, source, astProber); parser.Parse(); if (parser.errors.errors.size() > 0) { StringBuilder msg = new StringBuilder("Error(s) parsing script:\n"); diff -r 8084d44c78d3 -r 618d92152d3c graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Thu Jul 24 16:14:44 2014 -0700 @@ -32,6 +32,7 @@ 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.runtime.*; @@ -72,9 +73,12 @@ /* State while parsing a block. */ private LexicalScope lexicalScope; - public SLNodeFactory(SLContext context, Source source) { + private final SLNodeProber prober; + + public SLNodeFactory(SLContext context, Source source, SLNodeProber prober) { this.context = context; this.source = source; + this.prober = prober; } public void startFunction(Token nameToken) { @@ -179,6 +183,14 @@ public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { final int start = t.charPos; final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex(); + + // if (prober != null) { + // SLStatementNode wrappedThenNode = prober.probeAsStatement(thenPartNode); + // // SLStatementNode wrappedElseNode = prober.probeAsStatement(elsePartNode); + // return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, + // wrappedThenNode, elsePartNode); + // } + return new SLIfNode(source.createSection(t.val, start, end - start), conditionNode, thenPartNode, elsePartNode); } @@ -227,6 +239,10 @@ final int endPos = finalToken.charPos + finalToken.val.length(); final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos); SLExpressionNode functionNode = createRead(nameToken); + if (prober != null) { + SLExpressionNode wrappedNode = prober.probeAsCall(functionNode, nameToken.val); + return SLInvokeNode.create(src, wrappedNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); + } return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()])); } @@ -235,6 +251,10 @@ lexicalScope.locals.put(nameToken.val, frameSlot); final int start = nameToken.charPos; final int length = valueNode.getSourceSection().getCharEndIndex() - start; + if (prober != null) { + final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(valueNode, nameToken.val); + return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), wrappedNode, frameSlot); + } return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot); } diff -r 8084d44c78d3 -r 618d92152d3c 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 Thu Jul 24 12:22:54 2014 -0700 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Thu Jul 24 16:14:44 2014 -0700 @@ -29,8 +29,11 @@ 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.builtins.*; import com.oracle.truffle.sl.nodes.*; +import com.oracle.truffle.sl.nodes.instrument.*; import com.oracle.truffle.sl.nodes.local.*; import com.oracle.truffle.sl.parser.*; @@ -49,6 +52,7 @@ private final PrintStream output; private final SLFunctionRegistry functionRegistry; private SourceCallback sourceCallback = null; + private SLASTProber astProber; public SLContext(BufferedReader input, PrintStream output) { this.input = input; @@ -133,4 +137,28 @@ /* Register the builtin function in our function registry. */ getFunctionRegistry().register(name, rootNode); } + + public void executeMain(Source source) { + + if (sourceCallback != null) { + sourceCallback.startLoading(source); + } + + Parser.parseSL(this, source, astProber); + + if (sourceCallback != null) { + sourceCallback.endLoading(source); + } + + SLFunction main = getFunctionRegistry().lookup("main"); + if (main.getCallTarget() == null) { + throw new SLException("No function main() defined in SL source file."); + } + main.getCallTarget().call(); + } + + public void setASTNodeProber(SLASTProber astProber) { + // TODO Auto-generated method stub + this.astProber = astProber; + } }