com.dragome.compiler.graph.Graph 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.graph;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import com.dragome.compiler.ast.Block;
import com.dragome.compiler.ast.BooleanExpression;
import com.dragome.compiler.ast.BreakStatement;
import com.dragome.compiler.ast.IfStatement;
import com.dragome.compiler.utils.Log;
public abstract class Graph
{
private Map nodes= new LinkedHashMap(); //super bug!!!
int nodeIdSequence= 0;
Log logger= Log.getLogger();
public Graph()
{
}
public Node getNodeById(String id)
{
return nodes.get(id);
}
public Node createNode(Class nodeClass)
{
return createNode(nodeClass, Integer.toString(nodeIdSequence++, 26));
}
public Node createNode(Class nodeClass, String id)
{
Node node;
try
{
Constructor constructor= nodeClass.getConstructor(new Class[] { Graph.class });
node= (Node) constructor.newInstance(new Object[] { this });
}
catch (InstantiationException e)
{
throw new RuntimeException(e);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (NoSuchMethodException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
node.id= id;
nodes.put(id, node);
return node;
}
public boolean isContained(Set nodesA, Node[] nodesB)
{
Set foo= new LinkedHashSet(Arrays.asList(nodesB));
return foo.containsAll(nodesA);
}
public void replaceAsTarget(Node oldTarget, Node newTarget)
{
for (Edge edge : new ArrayList(oldTarget.getInEdges()))
{
edge.redirect(newTarget);
}
}
public Edge removeEdge(Node source, Node target)
{
Edge edge= getEdge(source, target);
return removeEdge(edge);
}
public Edge removeEdge(Edge edge)
{
edge.source.getOutEdges().remove(edge);
edge.target.getInEdges().remove(edge);
return edge;
}
public String getEdgeId(Node source, Node target)
{
return source.getId() + "->" + target.getId();
}
public void addIfElseEdge(Node source, Node ifTarget, Node elseTarget, BooleanExpression be)
{
ConditionalEdge ifEdge= (ConditionalEdge) addEdge(source, ifTarget, ConditionalEdge.class);
ifEdge.setBooleanExpression(be);
ConditionalEdge elseEdge= (ConditionalEdge) addEdge(source, elseTarget, ConditionalEdge.class);
elseEdge.setBooleanExpression(be);
elseEdge.setNegate(true);
}
public Edge addEdge(Node source, Node target)
{
return addEdge(source, target, Edge.class);
}
public Edge addEdge(Node source, Node target, Class clazz)
{
Edge edge= getEdge(source, target);
if (edge != null)
{
throw new RuntimeException("Edge already exists");
}
if (clazz.equals(Edge.class))
{
edge= new Edge(this, source, target);
}
else if (clazz.equals(SwitchEdge.class))
{
edge= new SwitchEdge(this, source, target);
}
else if (clazz.equals(ConditionalEdge.class))
{
edge= new ConditionalEdge(this, source, target);
}
else
{
throw new RuntimeException("Illegal edge class " + clazz);
}
source.addEdge(edge);
if (source != target)
{
target.addEdge(edge);
}
return edge;
}
public Edge getEdge(Node source, Node target)
{
for (Edge edge : source.getOutEdges())
{
if (edge.target == target)
return edge;
}
return null;
}
public void removeNode(Node node)
{
replaceNode(node, null);
}
public Set removeOutEdges(Node node)
{
Set outEdges= new LinkedHashSet(node.outEdges);
Iterator iter= outEdges.iterator();
while (iter.hasNext())
{
Edge edge= (Edge) iter.next();
removeEdge(edge);
}
return outEdges;
}
public Set removeInEdges(Node node)
{
Set inEdges= new LinkedHashSet(node.inEdges);
Iterator iter= inEdges.iterator();
while (iter.hasNext())
{
Edge edge= iter.next();
removeEdge(edge);
}
return inEdges;
}
public Set removeSelfEdges(Node node)
{
Set selfEdges= new LinkedHashSet();
for (Edge edge : new LinkedHashSet(node.outEdges))
{
if (edge.target != node)
continue;
removeEdge(edge);
selfEdges.add(edge);
}
return selfEdges;
}
public void rerootGlobalOutEdges(Node node, Node newSource)
{
Edge[] edges= node.getOutEdgesArray();
for (int i= 0; i < edges.length; i++)
{
Edge edge= edges[i];
if (edge.isGlobal())
{
edge.reroot(newSource);
}
}
}
public void rerootOutEdges(Node node, Node newSource, boolean localToGlobal)
{
Edge[] edges= node.getOutEdgesArray();
for (int i= 0; i < edges.length; i++)
{
Edge edge= edges[i];
edge.reroot(newSource);
if (localToGlobal && !edge.isGlobal())
{
edge.setOrgSource(node);
}
}
}
public void replaceNode(Node oldNode, Node newNode)
{
nodes.remove(oldNode.getId());
if (newNode != null)
{
replaceAsTarget(oldNode, newNode);
rerootOutEdges(oldNode, newNode, true);
newNode.setDomParent(oldNode.getDomParent());
for (Node child : new ArrayList(oldNode.getDomChildren()))
{
child.setDomParent(newNode);
}
}
if (oldNode.inEdges.size() > 0 || oldNode.outEdges.size() > 0)
throw new RuntimeException("Cannot replace node with edges");
oldNode.setDomParent(null);
}
public Collection getNodes()
{
return nodes.values();
}
public int size()
{
return getNodes().size();
}
public Block reduceDumb()
{
Block block= new Block();
for (Node node : getNodes())
{
block.appendChild(node.block);
if (node.isBranch())
{
IfStatement ifStmt= new IfStatement();
ConditionalEdge cEdge= node.getConditionalEdge(true);
ifStmt.setExpression(cEdge.getBooleanExpression().getExpression());
ifStmt.setIfBlock(new Block());
Block targetBlock= cEdge.target.block;
ifStmt.getIfBlock().appendChild(new BreakStatement(targetBlock));
ifStmt.setElseBlock(new Block());
targetBlock= node.getConditionalEdge(false).target.block;
ifStmt.getElseBlock().appendChild(new BreakStatement(targetBlock));
block.appendChild(ifStmt);
}
else
{
for (Edge e : node.getOutEdges())
{
BreakStatement bStmt= new BreakStatement(e.target.block);
node.block.appendChild(bStmt);
}
}
}
return block;
}
boolean isTarget(Node n, Set edgeSet)
{
Iterator iter= edgeSet.iterator();
while (iter.hasNext())
{
Edge e= (Edge) iter.next();
if (n == e.target)
return true;
}
return false;
}
public void rollOut(Node node, Block targetBlock)
{
if (node.trans != null)
{
node.trans.rollOut(targetBlock);
}
else
{
targetBlock.appendChildren(node.block);
}
}
public void dump(String msg)
{
StringBuffer sb= new StringBuffer();
sb.append(msg + " ...\n");
for (Node node : getNodes())
{
sb.append(node.describe() + "\n");
}
sb.append("... " + msg);
logger.debug(sb.toString());
}
}