package ru.bmstu.iu9.compiler.ir;
import com.sun.org.apache.bcel.internal.generic.GOTO;
import ru.bmstu.iu9.compiler.syntax.tree.IntegerConstantLeaf;
import ru.bmstu.iu9.compiler.syntax.tree.StructDeclNode;
import java.util.LinkedList;
import java.util.List;
import java.util.Hashtable;
/**
* Created by natalia on 20.03.14.
*/
class Edge<V> {
int true_false;//1 -true, 0 -false, -1 -none
V in_vertex, out_vertex;
public Edge(int i, V in, V out) {
true_false = i;
in_vertex = in;
out_vertex = out;
}
int getTrue_false() { return true_false; }
}
class BaseBlock<E> {
List<Statement> statements;
public BaseBlock() {
statements = new LinkedList<Statement>();
}
public BaseBlock(Statement s) {
statements = new LinkedList<Statement>();
statements.add(s);
}
public void AddStatement(Statement s) {
statements.add(s);
}
public String toString() {
String result = "next BB: \n";
int i = 0;
for(Statement s: statements) {
result += ("\t" + i + ": " + s.toString() + "\n");
i++;
}
return result;
}
}
public class CFG {
Digraph<BaseBlock, Edge> G = new Digraph<BaseBlock, Edge>();
public CFG(List<Statement> statements) {
Hashtable<Long, Integer> StToBB = new Hashtable<Long, Integer>();//match index of statement to index of base block in vBB
List<BaseBlock> vBB = new LinkedList<BaseBlock>();
StToBB.put((long) 0, 0);//нулевому statement соответствует нулевой base block в vBB
BaseBlock bb = new BaseBlock();
vBB.add(bb);
G.add(bb);
for (Statement s: statements) {
if(s.baseOperation == Statement.Operation.IF_GOTO) {
IfGoToStatement a = (IfGoToStatement)s;
long ltrue = a.labelTrue.index();
long lfalse = a.labelFalse.index();
if(!StToBB.containsKey(ltrue)) {
StToBB.put(ltrue, vBB.size());
BaseBlock b = new BaseBlock();
vBB.add(b);
G.add(b);
}
if(!StToBB.containsKey(lfalse)) {
StToBB.put(lfalse, vBB.size());
BaseBlock b = new BaseBlock();
vBB.add(b);
G.add(b);
}
} else if (s.baseOperation == Statement.Operation.GOTO) {
GoToStatement a = (GoToStatement)s;
long l = a.label.index();
if(!StToBB.containsKey(l)) {
StToBB.put(l, vBB.size());
BaseBlock b = new BaseBlock();
//System.out.println("got found: l=" + l + "; vBB.size()=" + vBB.size() + ";\n");
vBB.add(b);
//System.out.println("got found: l=" + l + "; vBB.size()=" + vBB.size() + ";\n");
G.add(b);
}
}
}
//System.out.println("Started\n");
long i = 0;
BaseBlock curBB = vBB.get(0);
//System.out.println("contains: " + G.contains(curBB));
for (Statement s: statements) {
curBB.AddStatement(s);
if(s.baseOperation == Statement.Operation.IF_GOTO) {
IfGoToStatement igt = (IfGoToStatement)s;
G.add(curBB, vBB.get(StToBB.get(igt.labelTrue.index())));
G.add(curBB, vBB.get(StToBB.get(igt.labelFalse.index())));
//System.out.println("contains ifgoto: " + G.contains(curBB) + " and i+1=" + (i+1));
if(StToBB.containsKey((long)(i+1))) {
//cur = ;
curBB = vBB.get(StToBB.get((long)(i+1)));
} else {
//cur = vBB.size();
BaseBlock b = new BaseBlock();
vBB.add(b);
G.add(curBB);
curBB = b;
}
} else if (s.baseOperation == Statement.Operation.GOTO) {
GoToStatement gt = (GoToStatement)s;
//System.out.println("contains goto: " + vBB.get(StToBB.get(gt.label.index())).toString() + " and i+1=" + (i+1));
G.add(curBB, vBB.get(StToBB.get(gt.label.index())));
if(StToBB.containsKey((long)(i+1))) {
//System.out.println("ok");
curBB = vBB.get(StToBB.get((long)(i+1)));
} else {
//cur = vBB.size();
BaseBlock b = new BaseBlock();
vBB.add(b);
G.add(curBB);
curBB = b;
}
} else if(s.baseOperation == Statement.Operation.RETURN) {
//System.out.println("contains return: " + G.contains(curBB) + " and " + i + "; St.keys: " + StToBB.keySet());
if(StToBB.containsKey((long)(i+1))) {
//cur = ;
System.out.println("ok2");
curBB = vBB.get(StToBB.get((long)(i+1)));
} else {
//cur = vBB.size();
BaseBlock b = new BaseBlock();
vBB.add(b);
G.add(curBB);
curBB = b;
}
//System.out.println("finished");
} else if(StToBB.containsKey((long)(i+1))) {
G.add(curBB, vBB.get(StToBB.get((long)(i+1))));
curBB = vBB.get(StToBB.get((long)(i+1)));
}
i++;
}
//System.out.println("BB: " + vBB.get(StToBB.get((long)(12))).toString() + "; " + G.toString());
}
public String toString() {
return G.toString();
}
}