public static ICode ToAst(Ctx ctx, bool verbose = false) {
var ast = AstGenerator.CreateBlockedCilAst(ctx);
//int step = 0;
//Action<Stmt, string> print = (s, name) => {
// if (verbose) {
// if (name != null && name.StartsWith("Visitor")) {
// name = name.Substring(7);
// }
// Console.WriteLine(" --- AST Transform Step {0}{1} ---", step++, name == null ? "" : (" '" + name + "'"));
// Console.WriteLine(ShowVisitor.V(s));
// Console.WriteLine();
// }
//};
//Func<Func<Stmt, Stmt>, Stmt, string, Stmt> doStep = (fn, s0, name) => {
// var s1 = fn(s0);
// if (s1 != s0) {
// print(s1, name);
// var dupStmts = VisitorFindDuplicateStmts.Find(s1);
// if (dupStmts.Any()) {
// Console.WriteLine("*** ERROR *** {0} DUPLICATE STMT(S) ***", dupStmts.Count());
// foreach (var dup in dupStmts) {
// Console.WriteLine();
// Console.WriteLine(ShowVisitor.V(dup));
// }
// throw new InvalidOperationException("Duplicate stmt(s) found");
// }
// }
// return s1;
//};
//print(ast, null);
Print(ast, null, verbose);
ast = DoStep(s => (Stmt)VisitorConvertCilToSsa.V(s), ast, "VisitorConvertCilToSsa", verbose);
// Reduce to AST with no continuations
for (int i = 0; ; i++) {
var astOrg = ast;
ast = DoStep(s => (Stmt)VisitorSubstitute.V(s), ast, "VisitorSubstitute", verbose);
ast = DoStep(s => (Stmt)VisitorTryCatchFinallySequencing.V(s), ast, "VisitorTryCatchFinallySequencing", verbose);
ast = DoStep(s => (Stmt)VisitorIfDistribution.V(s), ast, "VisitorIfDistribution", verbose);
ast = DoStep(s => (Stmt)VisitorDerecurse.V(s), ast, "VisitorDerecurse", verbose);
ast = DoStep(s => (Stmt)VisitorBooleanSimplification.V(s), ast, "VisitorBooleanSimplification", verbose);
ast = DoStep(s => (Stmt)VisitorIfSimplification.V(s), ast, "VisitorIfSimplification", verbose);
ast = DoStep(s => (Stmt)VisitorIfReorder.V(s), ast, "VisitorIfReorder", verbose);
ast = DoStep(s => (Stmt)VisitorEmptyBlockRemoval.V(s), ast, "VisitorEmptyBlockRemoval", verbose);
ast = DoStep(s => (Stmt)VisitorSwitchSequencing.V(s, false), ast, "VisitorSwitchSequencing", verbose);
if (ast == astOrg) {
if (!VisitorFindContinuations.Any(ast)) {
break;
} else {
ast = DoStep(s => (Stmt)VisitorSwitchSequencing.V(s, true), ast, "VisitorSwitchSequencing-LastChance", verbose);
if (ast != astOrg) {
continue;
}
ast = DoStep(s => (Stmt)VisitorSubstituteIrreducable.V(s), ast, "VisitorSubstituteIrreducable", verbose);
if (ast != astOrg) {
continue;
}
ast = DoStep(s => (Stmt)VisitorDuplicateCode.V(s), ast, "VisitorDuplicateCode", verbose);
if (ast != astOrg) {
continue;
}
throw new InvalidOperationException("Error: Cannot reduce IL to AST with no continuations");
}
}
if (i > 20) {
// After 20 iterations even the most complex method should be sorted out
throw new InvalidOperationException("Error: Stuck in loop trying to reduce AST");
}
}
// PhiSimplifier must be done before DefiniteAssignment
ast = DoStep(s => (Stmt)VisitorPhiSimplifier.V(s), ast, "VisitorPhiSimplifier", verbose);
// DefiniteAssignment must be done before SsaCopyPropagation
ast = DoStep(s => (Stmt)VisitorDefiniteAssignment.V(s), ast, "VisitorDefiniteAssignment", verbose);
// Simplify AST
for (int i = 0; ; i++) {
var astOrg = ast;
// TODO: VisitorBooleanSimplification may re-order logic, which should not be done at this stage
ast = DoStep(s => (Stmt)VisitorBooleanSimplification.V(s), ast, "VisitorBooleanSimplification", verbose);
ast = DoStep(s => (Stmt)VisitorIfSimplification.V(s), ast, "VisitorIfSimplification", verbose);
ast = DoStep(s => (Stmt)VisitorMoveOutOfLoop.V(s), ast, "VisitorMoveOutOfLoop", verbose);
ast = DoStep(s => (Stmt)VisitorSsaCopyPropagation.V(s), ast, "VisitorSsaCopyPropagation", verbose);
ast = DoStep(s => (Stmt)VisitorPhiSimplifier.V(s), ast, "VisitorPhiSimplifier", verbose);
ast = DoStep(s => (Stmt)VisitorExpressionSimplifier.V(s), ast, "VisitorExpressionSimplifier", verbose);
ast = DoStep(s => (Stmt)VisitorEmptyBlockRemoval.V(s), ast, "VisitorEmptyBlockRemoval", verbose);
if (ast == astOrg) {
break;
}
if (i > 20) {
// After 20 iterations even the most complex method should be sorted out
throw new InvalidOperationException("Error: Stuck in loop trying to simplify AST");
}
}
ast = DoStep(s => (Stmt)VisitorRemoveCasts.V(s), ast, "VisitorRemoveCasts", verbose);
ast = DoStep(s => (Stmt)VisitorRemoveFinalReturn.V(s), ast, "VisitorRemoveFinalReturn", verbose);
ast = DoStep(s => (Stmt)VisitorTypeCorrector.V(s), ast, "VisitorTypeCorrector", verbose);
return ast;
}