/*******************************************************************************
* Copyright (c) 2009, 2010 Alena Laskavaia
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alena Laskavaia - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.cfg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
import org.eclipse.cdt.codan.core.model.cfg.IControlFlowGraph;
import org.eclipse.cdt.codan.core.model.cfg.IDecisionNode;
import org.eclipse.cdt.codan.core.model.cfg.IExitNode;
import org.eclipse.cdt.codan.core.model.cfg.ISingleOutgoing;
import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
/**
* Implementation of control flow graph
*/
public class ControlFlowGraph implements IControlFlowGraph {
private List<IExitNode> exitNodes;
private List<IBasicBlock> deadNodes = new ArrayList<IBasicBlock>();
private IStartNode start;
public ControlFlowGraph(IStartNode start, Collection<IExitNode> exitNodes) {
setExitNodes(exitNodes);
this.start = start;
}
public Iterator<IExitNode> getExitNodeIterator() {
return exitNodes.iterator();
}
public int getExitNodeSize() {
return exitNodes.size();
}
public void setExitNodes(Collection<IExitNode> exitNodes) {
if (this.exitNodes != null)
throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
this.exitNodes = Collections.unmodifiableList(new ArrayList<IExitNode>(exitNodes));
}
public void setUnconnectedNodes(Collection<IBasicBlock> nodes) {
this.deadNodes = Collections.unmodifiableList(new ArrayList<IBasicBlock>(nodes));
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
* getStartNode()
*/
public IStartNode getStartNode() {
return start;
}
void setStartNode(IStartNode start) {
this.start = start;
}
public void print(IBasicBlock node) {
System.out.println(node.getClass().getSimpleName() + ": " //$NON-NLS-1$
+ ((AbstractBasicBlock) node).toStringData());
if (node instanceof IDecisionNode) {
// todo
IBasicBlock[] branches = ((IDecisionNode) node).getOutgoingNodes();
for (int i = 0; i < branches.length; i++) {
IBasicBlock brNode = branches[i];
System.out.println("{"); //$NON-NLS-1$
print(brNode);
System.out.println("}"); //$NON-NLS-1$
}
print(((IDecisionNode) node).getMergeNode());
} else if (node instanceof ISingleOutgoing) {
IBasicBlock next = ((ISingleOutgoing) node).getOutgoing();
if (!(next instanceof IConnectorNode && !(next instanceof IBranchNode)))
print(next);
}
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
* getUnconnectedNodeIterator()
*/
public Iterator<IBasicBlock> getUnconnectedNodeIterator() {
return deadNodes.iterator();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
* getUnconnectedNodeSize()
*/
public int getUnconnectedNodeSize() {
return deadNodes.size();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.codan.core.model.cfg.IControlFlowGraph#getNodes ()
*/
public Collection<IBasicBlock> getNodes() {
Collection<IBasicBlock> result = new LinkedHashSet<IBasicBlock>();
getNodes(getStartNode(), result);
for (Iterator<IBasicBlock> iterator = deadNodes.iterator(); iterator.hasNext();) {
IBasicBlock d = iterator.next();
getNodes(d, result);
}
return result;
}
/**
* @param d
* @param result
*/
private void getNodes(IBasicBlock start, Collection<IBasicBlock> result) {
if (start == null)
return; // huh
if (result.contains(start))
return;
result.add(start);
IBasicBlock[] outgoingNodes = start.getOutgoingNodes();
for (int i = 0; i < outgoingNodes.length; i++) {
IBasicBlock b = outgoingNodes[i];
getNodes(b, result);
}
}
}