com.dragome.compiler.ast.Block Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dragome-bytecode-js-compiler Show documentation
Show all versions of dragome-bytecode-js-compiler Show documentation
Dragome SDK module: bytecode to javascript compiler
package com.dragome.compiler.ast;
import org.w3c.dom.DOMException;
import com.dragome.compiler.generators.AbstractVisitor;
import com.dragome.compiler.utils.Log;
public class Block extends ASTNode
{
public static int TAG= 0;
private String label;
private ASTNode firstChild= null;
private ASTNode lastChild= null;
private int childCount= 0;
public Block()
{
super();
}
public Block(int theBeginIndex)
{
setBeginIndex(theBeginIndex);
}
public Block(int theBeginIndex, int theEndIndex)
{
this(theBeginIndex);
setRange(theBeginIndex, theEndIndex);
}
public int getTargetPc()
{
if (lastChild instanceof Jump)
{
return ((Jump) lastChild).getTargetIndex();
}
return Integer.MAX_VALUE;
}
public int getTargetIndex()
{
return beginIndex;
}
public void setBeginIndex(int theBeginIndex)
{
super.setBeginIndex(theBeginIndex);
}
public void visit(AbstractVisitor visitor)
{
visitor.visit(this);
}
public void appendChildren(ASTNode begin, ASTNode end)
{
if (begin == null || end == null)
{
throw new RuntimeException("Illegal null parameters");
}
if (begin.getParentBlock() != null)
(begin.getParentBlock()).removeChildren(begin, end);
if (firstChild == null)
{
setFirstChildInternal(begin);
}
else
{
ASTNode prev= getLastChild();
prev.setNextSibling(begin);
begin.setPreviousSibling(prev);
}
setLastChildInternal(end);
ASTNode node= begin;
while (node != null)
{
node.setParentNode(this);
childCount++;
if (node == end)
break;
node= node.getNextSibling();
}
}
public void appendChildren(Block sourceBlock)
{
if (sourceBlock.getChildCount() > 0)
{
appendChildren(sourceBlock.getFirstChild(), sourceBlock.getLastChild());
}
}
public ASTNode setChildAt(int index, ASTNode newChild)
{
if (index == childCount)
{
appendChild(newChild);
return null;
}
else if (index < 0 || index > childCount)
{
throw new RuntimeException("Index " + index + " out of range [0, " + childCount + "]");
}
return replaceChild(newChild, getChildAt(index));
}
public ASTNode getChildAt(int index)
{
if (childCount == 0)
{
throw new RuntimeException("Requested child at index " + index + ", but block has no children");
}
if (index < 0 || index >= childCount)
{
throw new RuntimeException("Index " + index + " out of range [0, " + (childCount - 1) + "]");
}
if (index == childCount - 1)
{
return getLastChild();
}
ASTNode node= getFirstChild();
int i= 0;
while (i < index)
{
i++;
node= node.getNextSibling();
}
return node;
}
public ASTNode appendChild(ASTNode newChild)
{
Log.getLogger().debug("Appending " + newChild + " to " + this);
unlink(newChild);
if (firstChild == null)
{
newChild.setPreviousSibling(null);
setFirstChildInternal(newChild);
}
else
{
ASTNode prev= getLastChild();
prev.setNextSibling(newChild);
newChild.setPreviousSibling(prev);
}
setLastChildInternal(newChild);
newChild.setParentNode(this);
childCount++;
return newChild;
}
public ASTNode replaceChild(ASTNode newChild, ASTNode oldChild)
{
Log.getLogger().debug("Replacing " + oldChild + " by " + newChild + " in " + this);
if (oldChild.getParentNode() != this)
{
throw new DOMException(DOMException.NOT_FOUND_ERR, "Node " + oldChild + " is not a child of " + this);
}
unlink(newChild);
if (oldChild.getPreviousSibling() != null)
{
oldChild.getPreviousSibling().setNextSibling(newChild);
}
if (oldChild.getNextSibling() != null)
{
oldChild.getNextSibling().setPreviousSibling(newChild);
}
newChild.setPreviousSibling(oldChild.getPreviousSibling());
newChild.setNextSibling(oldChild.getNextSibling());
newChild.setParentNode(this);
if (getFirstChild() == oldChild)
{
setFirstChildInternal(newChild);
}
if (getLastChild() == oldChild)
{
setLastChildInternal(newChild);
}
oldChild.setPreviousSibling(null);
oldChild.setNextSibling(null);
oldChild.setParentNode(null);
return oldChild;
}
public ASTNode removeChild(ASTNode oldChild)
{
Log.getLogger().debug("Removing " + oldChild + " from " + this);
removeChildren(oldChild, oldChild);
oldChild.setPreviousSibling(null);
oldChild.setNextSibling(null);
return oldChild;
}
private void removeChildren(ASTNode begin, ASTNode end)
{
if (begin == null || end == null)
throw new RuntimeException("Illegal null parameters");
ASTNode node= begin;
while (node != null)
{
if (node.getParentNode() != this)
{
throw new DOMException(DOMException.NOT_FOUND_ERR, "Node " + node + " is not a child of " + this);
}
node.setParentNode(null);
childCount--;
if (node == end)
break;
node= node.getNextSibling();
}
if (node != end)
{
throw new RuntimeException("Node " + end + " is not a right-sibling of " + begin);
}
if (begin.getPreviousSibling() != null)
{
begin.getPreviousSibling().setNextSibling(end.getNextSibling());
}
if (end.getNextSibling() != null)
{
end.getNextSibling().setPreviousSibling(begin.getPreviousSibling());
}
if (getFirstChild() == begin)
{
setFirstChildInternal(end.getNextSibling());
}
if (getLastChild() == end)
{
setLastChildInternal(begin.getPreviousSibling());
}
}
public void removeChildren()
{
if (getFirstChild() != null)
{
removeChildren(getFirstChild(), getLastChild());
}
}
public int getChildCount()
{
return childCount;
}
public ASTNode insertBefore(ASTNode newChild, ASTNode refChild)
{
if (refChild == null)
{
return appendChild(newChild);
}
Log.getLogger().debug("Inserting " + newChild + " before " + refChild + " in " + this);
if (refChild.getParentNode() != this)
{
throw new DOMException(DOMException.NOT_FOUND_ERR, "Reference " + refChild + " is not a child of " + this);
}
unlink(newChild);
if (refChild.getPreviousSibling() != null)
{
refChild.getPreviousSibling().setNextSibling(newChild);
}
newChild.setPreviousSibling(refChild.getPreviousSibling());
newChild.setNextSibling(refChild);
newChild.setParentNode(this);
childCount++;
refChild.setPreviousSibling(newChild);
if (getFirstChild() == refChild)
{
setFirstChildInternal(newChild);
}
return newChild;
}
public void addStatements(java.util.List statements)
{
for (int i= 0; i < statements.size(); i++)
{
appendChild((ASTNode) statements.get(i));
}
}
public ASTNode getFirstChild()
{
return firstChild;
}
public ASTNode getLastChild()
{
return lastChild;
}
private void setFirstChildInternal(ASTNode newFirstChild)
{
firstChild= newFirstChild;
if (firstChild != null)
{
firstChild.setPreviousSibling(null);
beginIndex= Math.min(beginIndex, firstChild.getBeginIndex());
}
}
private void setLastChildInternal(ASTNode newLastChild)
{
lastChild= newLastChild;
if (lastChild != null)
{
lastChild.setNextSibling(null);
endIndex= Math.max(endIndex, lastChild.getEndIndex());
}
}
private void unlink(ASTNode node)
{
if (node.getParentBlock() != null)
{
node.getParentBlock().removeChild(node);
}
}
public String getLabel()
{
if (label == null)
throw new RuntimeException("Statement is not labeled");
return label;
}
public void setLabel(String theLabel)
{
label= theLabel;
}
public boolean isLabeled()
{
return label != null;
}
public String setLabeled()
{
if (label == null)
label= "L" + (++TAG);
return label;
}
}