template.ast.ASTNode.tt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jastadd Show documentation
Show all versions of jastadd Show documentation
A metacompilation framework for Java using attribute grammars.
# Copyright (c) 2013-2016, The JastAdd Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the Lund University nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# This template file contains templates for implicit aspect declarations
# for the ASTNode AST node type
ASTNode.declarations [[
/**
* Cached child index. Child indices are assumed to never change (AST should
* not change after construction).
* @apilevel internal
*/
private int $ASTNode.childIndex = -1;
/** @apilevel low-level */
public int $ASTNode.getIndexOfChild($ASTNode node) {
if (node == null) {
return -1;
}
$if(RewriteCircularNTA)
if (node.childIndex >= 0) {
return node.childIndex;
}
for (int i = 0; children != null && i < children.length; i++) {
if (getChild(i) == node) {
node.childIndex = i;
return i;
}
}
$else
$if(LegacyRewrite)
// Legacy rewrites with rewrite in list can change child position, so update may be needed.
if (node.childIndex >= 0 && node.childIndex < numChildren && node == children[node.childIndex]) {
$else
if (node.childIndex >= 0) {
$endif
return node.childIndex;
}
for (int i = 0; children != null && i < children.length; i++) {
if (children[i] == node) {
node.childIndex = i;
return i;
}
}
$endif
return -1;
}
/** @apilevel internal */
public static final boolean $ASTNode.generatedWithCacheCycle = $CacheCycle;
/** @apilevel internal */
public static final boolean $ASTNode.generatedWithComponentCheck = $ComponentCheck;
$if(!JJTree)
/** @apilevel low-level */
protected $ASTNode $ASTNode.parent;
/** @apilevel low-level */
protected $ASTNode[] $ASTNode.children;
$endif
$if(TracingEnabled)
public final $StateClass.Trace $ASTNode.trace() {
return state().trace();
}
$endif
$if(StaticState)
/** @apilevel internal */
private static $StateClass $ASTNode.state = new $StateClass();
/** @apilevel internal */
public final $StateClass $ASTNode.state() {
return state;
}
$else
/** @apilevel internal */
private $StateClass $ASTNode.state = null;
/** @apilevel internal */
public final $StateClass $ASTNode.state() {
if (state == null) {
if (parent == null) {
state = new $StateClass();
#debugASTNodeState
} else {
state = parent.state();
}
}
return state;
}
$endif
$if(LegacyRewrite)
/** @apilevel internal */
public boolean $ASTNode.in$$Circle = false;
/** @apilevel internal */
public boolean $ASTNode.in$$Circle() {
return in$$Circle;
}
/** @apilevel internal */
public void $ASTNode.in$$Circle(boolean b) {
in$$Circle = b;
}
/** @apilevel internal */
public boolean $ASTNode.is$$Final = false;
/** @apilevel internal */
public boolean $ASTNode.is$$Final() {
return is$$Final;
}
/** @apilevel internal */
public void $ASTNode.is$$Final(boolean b) {
is$$Final = b;
}
$endif
/**
* @return an iterator that can be used to iterate over the children of this node.
* The iterator does not allow removing children.
*/
public java.util.Iterator $ASTNode.astChildIterator() {
$SynchBegin
return new java.util.Iterator() {
private int index = 0;
@Override
public boolean hasNext() {
return index < getNumChild();
}
@Override
public T next() {
return hasNext() ? (T) getChild(index++) : null;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
$SynchEnd
}
/** @return an object that can be used to iterate over the children of this node */
public Iterable $ASTNode.astChildren() {
return new Iterable() {
@Override
public java.util.Iterator iterator() {
return astChildIterator();
}
};
}
$include(ASTNode.nodeToStringMethod)
]]
# Adds debug checks for tree construction.
ASTNode.debugDecls [[
$if(DebugMode)
/** @apilevel internal */
protected boolean $ASTNode.debugNodeAttachmentIsRoot() {
return false;
}
/** @apilevel internal */
private static void $ASTNode.debugNodeAttachment($ASTNode node) {
if (node == null) {
throw new RuntimeException("Trying to assign null to a tree child node");
}
while (node != null && !node.debugNodeAttachmentIsRoot()) {
$if(LegacyRewrite)
if (node.in$$Circle()) {
return;
}
$endif
$ASTNode parent = ($ASTNode) node.parent;
if (parent != null && parent.getIndexOfChild(node) == -1) {
return;
}
node = parent;
}
if (node != null) {
throw new RuntimeException("Trying to insert the same tree at multiple tree locations");
}
}
$endif
]]
ASTNode.setParent [[
/** @apilevel low-level */
public void $ASTNode.setParent($ASTNode node) {
$SynchBegin
$include(ASTNode.incHookSetParent)
parent = node;
$SynchEnd
}
]]
ASTNode.getParent [[
/** @apilevel low-level */
public $ASTNode $ASTNode.getParent() {
$SynchBegin
$if(LegacyRewrite)
if (parent != null && (($ASTNode) parent).is$$Final() != is$$Final()) {
state().boundariesCrossed++;
}
$endif
$include(ASTNode.incHookGetParent)
return ($ASTNode) parent;
$SynchEnd
}
]]
ASTNode.addChild [[
/** @apilevel low-level */
public void $ASTNode.addChild(T node) {
setChild(node, getNumChildNoTransform());
$include(ASTNode.incHookAddChild)
}
]]
ASTNode.numChildren [[
/** @apilevel low-level */
protected int $ASTNode.numChildren;
/** @apilevel low-level */
protected int $ASTNode.numChildren() {
$include(ASTNode.incHookNumChildren)
return numChildren;
}
/** @apilevel low-level */
public int $ASTNode.getNumChild() {
$SynchBegin
return numChildren();
$SynchEnd
}
/**
* Behaves like getNumChild, but does not invoke AST transformations (rewrites).
* @apilevel low-level
*/
public final int $ASTNode.getNumChildNoTransform() {
$SynchBegin
return numChildren();
$SynchEnd
}
]]
ASTNode.setChild [[
/** @apilevel low-level */
public void $ASTNode.setChild($ASTNode node, int i) {
$SynchBegin
$if(DebugMode)
debugNodeAttachment(node);
$endif
$include(ASTNode.incHookSetChild1)
if (children == null) {
children = new $ASTNode[#initialChildArraySize];
$include(ASTNode.incHookSetChild2)
} else if (i >= children.length) {
$ASTNode c[] = new $ASTNode[i << 1];
System.arraycopy(children, 0, c, 0, children.length);
children = c;
$include(ASTNode.incHookSetChild3)
}
$include(ASTNode.incHookSetChild4)
children[i] = node;
if (i >= numChildren) {
numChildren = i+1;
}
if (node != null) {
node.setParent(this);
node.childIndex = i;
}
$include(ASTNode.incHookSetChild5)
$SynchEnd
}
]]
ASTNode.insertChild [[
/** @apilevel low-level */
public void $ASTNode.insertChild($ASTNode node, int i) {
$SynchBegin
$if(DebugMode)
debugNodeAttachment(node);
$endif
$include(ASTNode.incHookInsertChild1)
if (children == null) {
children = new $ASTNode[#initialChildArraySize];
children[i] = node;
$include(ASTNode.incHookInsertChild2)
} else {
$ASTNode c[] = new $ASTNode[children.length + 1];
System.arraycopy(children, 0, c, 0, i);
c[i] = node;
if (i < children.length) {
System.arraycopy(children, i, c, i+1, children.length-i);
for(int j = i+1; j < c.length; ++j) {
if (c[j] != null) {
c[j].childIndex = j;
}
}
}
children = c;
$include(ASTNode.incHookInsertChild3)
}
numChildren++;
if (node != null) {
node.setParent(this);
node.childIndex = i;
}
$SynchEnd
}
]]
ASTNode.removeChild [[
/** @apilevel low-level */
public void $ASTNode.removeChild(int i) {
$SynchBegin
if (children != null) {
$include(ASTNode.incHookRemoveChild1)
$ASTNode child = ($ASTNode) children[i];
if (child != null) {
$include(ASTNode.incHookRemoveChild2)
child.parent = null;
child.childIndex = -1;
}
// Adding a check of this instance to make sure its a List, a move of children doesn't make
// any sense for a node unless its a list. Also, there is a problem if a child of a non-List node is removed
// and siblings are moved one step to the right, with null at the end.
if (this instanceof $List || this instanceof $Opt) {
System.arraycopy(children, i+1, children, i, children.length-i-1);
children[children.length-1] = null;
numChildren--;
// fix child indices
for(int j = i; j < numChildren; ++j) {
if (children[j] != null) {
child = ($ASTNode) children[j];
child.childIndex = j;
}
}
} else {
children[i] = null;
}
$include(ASTNode.incHookRemoveChild3)
}
$SynchEnd
}
]]
ASTNode.getChild [[
/** @apilevel low-level */
public T $ASTNode.getChild(int i) {
$if(RewriteEnabled)
$if(RewriteCircularNTA)
$ASTNode node = this.getChildNoTransform(i);
if (node != null && node.mayHaveRewrite()) {
$ASTNode rewritten = node.rewrittenNode();
if (rewritten != node) {
rewritten.setParent(this);
node = rewritten;
}
}
return (T) node;
$else
$SynchBegin
$ASTNode node = this.getChildNoTransform(i);
if (node == null) {
return null;
}
if (node.is$$Final()) {
$include(ASTNode.incHookGetChild4)
$include(ASTNode.incHookGetChild12)
return (T) node;
}
if (!node.mayHaveRewrite()) {
node.is$$Final(this.is$$Final());
$include(ASTNode.incHookGetChild4)
$include(ASTNode.incHookGetChild12)
return (T) node;
}
if (!node.in$$Circle()) {
$include(ASTNode.traceRewriteEnterCase1)
$include(ASTNode.incHookGetChild1)
int rewriteState;
int _boundaries = state().boundariesCrossed;
do {
state().push($StateClass.REWRITE_CHANGE);
$ASTNode oldNode = node;
oldNode.in$$Circle(true);
$include(ASTNode.incHookGetChild5)
node = node.rewriteTo();
$include(ASTNode.traceRewriteChange)
if (node != oldNode) {
$include(ASTNode.incHookGetChild7)
this.setChild(node, i);
$include(ASTNode.incHookGetChild8)
}
oldNode.in$$Circle(false);
rewriteState = state().pop();
$include(ASTNode.incHookGetChild3)
$include(ASTNode.incHookGetChild6)
} while(rewriteState == $StateClass.REWRITE_CHANGE);
if (rewriteState == $StateClass.REWRITE_NOCHANGE && this.is$$Final()) {
node.is$$Final(true);
state().boundariesCrossed = _boundaries;
$include(ASTNode.traceRewriteCached)
} else {
$include(ASTNode.traceRewriteCacheAbort)
}
$include(ASTNode.incHookGetChild2)
$include(ASTNode.traceRewriteExitCase1)
} else if (this.is$$Final() != node.is$$Final()) {
state().boundariesCrossed++;
$include(ASTNode.traceRewriteExitCase2)
} else {
$include(ASTNode.traceRewriteExitCase3)
}
$include(ASTNode.incHookGetChild11)
$include(ASTNode.incHookGetChild12)
return (T) node;
$SynchEnd
$endif
$else
$ASTNode child = getChildNoTransform(i);
$include(ASTNode.incHookGetChildNT)
return (T) child;
$endif
}
]]
ASTNode.getChildNoTransform [[
/**
* This method does not invoke AST transformations.
* @apilevel low-level
*/
$if(IncrementalEnabled)
public T $ASTNode.getChildNoTransform(int i) {
// Must be able to override get child methods for incremental evaluation
$else
public final T $ASTNode.getChildNoTransform(int i) {
$endif
$SynchBegin
if (children == null) {
return null;
}
T child = (T)children[i];
$include(ASTNode.incHookGetChildNT)
return child;
$SynchEnd
}
]]
ASTNode.lineColumnNumbers [[
/**
* Line and column information.
*/
protected int $ASTNode.startLine;
protected short $ASTNode.startColumn;
protected int $ASTNode.endLine;
protected short $ASTNode.endColumn;
public int $ASTNode.getStartLine() {
return startLine;
}
public short $ASTNode.getStartColumn() {
return startColumn;
}
public int $ASTNode.getEndLine() {
return endLine;
}
public short $ASTNode.getEndColumn() {
return endColumn;
}
public void $ASTNode.setStart(int startLine, short startColumn) {
this.startLine = startLine;
this.startColumn = startColumn;
}
public void $ASTNode.setEnd(int endLine, short endColumn) {
this.endLine = endLine;
this.endColumn = endColumn;
}
]]