com.oracle.truffle.sl.nodes.SLStatementNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of truffle-sl Show documentation
Show all versions of truffle-sl Show documentation
Truffle SL is an example language implemented using the Truffle API.
The newest version!
/*
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oracle.truffle.sl.nodes;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.GenerateWrapper;
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
import com.oracle.truffle.api.instrumentation.ProbeNode;
import com.oracle.truffle.api.instrumentation.StandardTags;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.sl.nodes.local.SLScopedNode;
/**
* The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as
* statements, i.e., without returning a value. The {@link VirtualFrame} provides access to the
* local variables.
*/
@NodeInfo(language = "SL", description = "The abstract base node for all SL statements")
@GenerateWrapper
public abstract class SLStatementNode extends SLScopedNode implements InstrumentableNode {
private static final int NO_SOURCE = -1;
private static final int UNAVAILABLE_SOURCE = -2;
private int sourceCharIndex = NO_SOURCE;
private int sourceLength;
private boolean hasStatementTag;
private boolean hasRootTag;
/*
* The creation of source section can be implemented lazily by looking up the root node source
* and then creating the source section object using the indices stored in the node. This avoids
* the eager creation of source section objects during parsing and creates them only when they
* are needed. Alternatively, if the language uses source sections to implement language
* semantics, then it might be more efficient to eagerly create source sections and store it in
* the AST.
*
* For more details see {@link InstrumentableNode}.
*/
@Override
@TruffleBoundary
public final SourceSection getSourceSection() {
if (sourceCharIndex == NO_SOURCE) {
// AST node without source
return null;
}
RootNode rootNode = getRootNode();
if (rootNode == null) {
// not yet adopted yet
return null;
}
SourceSection rootSourceSection = rootNode.getSourceSection();
if (rootSourceSection == null) {
return null;
}
Source source = rootSourceSection.getSource();
if (sourceCharIndex == UNAVAILABLE_SOURCE) {
if (hasRootTag && !rootSourceSection.isAvailable()) {
return rootSourceSection;
} else {
return source.createUnavailableSection();
}
} else {
return source.createSection(sourceCharIndex, sourceLength);
}
}
public final boolean hasSource() {
return sourceCharIndex != NO_SOURCE;
}
public final boolean isInstrumentable() {
return hasSource();
}
public final int getSourceCharIndex() {
return sourceCharIndex;
}
public final int getSourceEndIndex() {
return sourceCharIndex + sourceLength;
}
public final int getSourceLength() {
return sourceLength;
}
// invoked by the parser to set the source
public final void setSourceSection(int charIndex, int length) {
assert sourceCharIndex == NO_SOURCE : "source must only be set once";
if (charIndex < 0) {
throw new IllegalArgumentException("charIndex < 0");
} else if (length < 0) {
throw new IllegalArgumentException("length < 0");
}
this.sourceCharIndex = charIndex;
this.sourceLength = length;
}
public final void setUnavailableSourceSection() {
assert sourceCharIndex == NO_SOURCE : "source must only be set once";
this.sourceCharIndex = UNAVAILABLE_SOURCE;
}
public boolean hasTag(Class extends Tag> tag) {
if (tag == StandardTags.StatementTag.class) {
return hasStatementTag;
} else if (tag == StandardTags.RootTag.class || tag == StandardTags.RootBodyTag.class) {
return hasRootTag;
}
return false;
}
public WrapperNode createWrapper(ProbeNode probe) {
return new SLStatementNodeWrapper(this, probe);
}
/**
* Execute this node as as statement, where no return value is necessary.
*/
public abstract void executeVoid(VirtualFrame frame);
/**
* Marks this node as being a {@link StandardTags.StatementTag} for instrumentation purposes.
*/
public final void addStatementTag() {
hasStatementTag = true;
}
/**
* Marks this node as being a {@link StandardTags.RootTag} and {@link StandardTags.RootBodyTag}
* for instrumentation purposes.
*/
public final void addRootTag() {
hasRootTag = true;
}
@Override
public String toString() {
return formatSourceSection(this);
}
/**
* Formats a source section of a node in human readable form. If no source section could be
* found it looks up the parent hierarchy until it finds a source section. Nodes where this was
* required append a '~'
at the end.
*
* @param node the node to format.
* @return a formatted source section string
*/
public static String formatSourceSection(Node node) {
if (node == null) {
return "";
}
SourceSection section = node.getSourceSection();
boolean estimated = false;
if (section == null) {
section = node.getEncapsulatingSourceSection();
estimated = true;
}
if (section == null || section.getSource() == null) {
return "";
} else {
String sourceName = section.getSource().getName();
int startLine = section.getStartLine();
return String.format("%s:%d%s", sourceName, startLine, estimated ? "~" : "");
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy