public static bool TryOptimizeShortCircuit(Node head) { if ((head is BasicBlock) && (head as BasicBlock).BranchBasicBlock != null && (head as BasicBlock).FallThroughBasicBlock != null) { head.Parent.MergeChilds<SimpleBranch>(head); return true; } Branch top = head as Branch; if (top == null) return false; Branch left = head.FloatUpToNeighbours(top.TrueSuccessor) as Branch; Branch right = head.FloatUpToNeighbours(top.FalseSuccessor) as Branch; // A & B if (left != null && left.Predecessors.Count == 1 && left.FalseSuccessor == top.FalseSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left); scBranch.Operator = ShortCircuitOperator.LeftAndRight; return true; } // ~A | B if (left != null && left.Predecessors.Count == 1 && left.TrueSuccessor == top.FalseSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left); scBranch.Operator = ShortCircuitOperator.NotLeftOrRight; return true; } // A | B if (right != null && right.Predecessors.Count == 1 && right.TrueSuccessor == top.TrueSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right); scBranch.Operator = ShortCircuitOperator.LeftOrRight; return true; } // ~A & B if (right != null && right.Predecessors.Count == 1 && right.FalseSuccessor == top.TrueSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right); scBranch.Operator = ShortCircuitOperator.NotLeftAndRight; return true; } return false; }
IEnumerable<Ast.INode> TransformNode(Node node) { if (Options.NodeComments) { yield return MakeComment("// " + node.Description); } yield return new Ast.LabelStatement(node.Label); if (node is BasicBlock) { foreach(ILNode expr in ((BasicBlock)node).Body) { if (expr is ILLabel) { yield return new Ast.LabelStatement(((ILLabel)expr).Name); } else { Statement stmt = TransformExpressionToStatement((ILExpression)expr); if (stmt != null) { yield return stmt; } } } foreach(Ast.INode inode in TransformNodes(node.Childs)) { yield return inode; } Node fallThroughNode = ((BasicBlock)node).FallThroughBasicBlock; // If there is default branch and it is not the following node if (fallThroughNode != null) { yield return new Ast.GotoStatement(fallThroughNode.Label); } } else if (node is AcyclicGraph) { foreach(Ast.INode inode in TransformNodes(node.Childs)) { yield return inode; } } else if (node is Loop) { Ast.BlockStatement blockStatement = new Ast.BlockStatement(); blockStatement.Children.AddRange(TransformNodes(node.Childs)); yield return new Ast.ForStatement( null, null, null, blockStatement ); } else if (node is Block) { foreach(Ast.INode inode in TransformNodes(node.Childs)) { yield return inode; } } else if (node is Branch) { yield return new Ast.LabelStatement(((Branch)node).FirstBasicBlock.Label); Ast.BlockStatement trueBlock = new Ast.BlockStatement(); trueBlock.Children.Add(new Ast.GotoStatement(((Branch)node).TrueSuccessor.Label)); Ast.BlockStatement falseBlock = new Ast.BlockStatement(); falseBlock.Children.Add(new Ast.GotoStatement(((Branch)node).FalseSuccessor.Label)); Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement( MakeBranchCondition((Branch)node), trueBlock, falseBlock ); trueBlock.Parent = ifElseStmt; falseBlock.Parent = ifElseStmt; yield return ifElseStmt; } else if (node is ConditionalNode) { ConditionalNode conditionalNode = (ConditionalNode)node; yield return new Ast.LabelStatement(conditionalNode.Condition.FirstBasicBlock.Label); Ast.BlockStatement trueBlock = new Ast.BlockStatement(); // The block entry code trueBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.TrueSuccessor.Label)); // Sugested content trueBlock.Children.AddRange(TransformNode(conditionalNode.TrueBody)); Ast.BlockStatement falseBlock = new Ast.BlockStatement(); // The block entry code falseBlock.Children.Add(new Ast.GotoStatement(conditionalNode.Condition.FalseSuccessor.Label)); // Sugested content falseBlock.Children.AddRange(TransformNode(conditionalNode.FalseBody)); Ast.IfElseStatement ifElseStmt = new Ast.IfElseStatement( // Method bodies are swapped new Ast.UnaryOperatorExpression( new Ast.ParenthesizedExpression( MakeBranchCondition(conditionalNode.Condition) ), UnaryOperatorType.Not ), falseBlock, trueBlock ); trueBlock.Parent = ifElseStmt; falseBlock.Parent = ifElseStmt; yield return ifElseStmt; } else if (node is TryCatchNode) { TryCatchNode tryCachNode = ((TryCatchNode)node); Ast.BlockStatement tryBlock = new Ast.BlockStatement(); tryBlock.Children.AddRange(TransformNode(tryCachNode.Childs[0])); Ast.BlockStatement finallyBlock = null; if (tryCachNode.Childs[1].Childs.Count > 0) { finallyBlock = new Ast.BlockStatement(); finallyBlock.Children.AddRange(TransformNode(tryCachNode.Childs[1])); } List<Ast.CatchClause> ccs = new List<CatchClause>(); for (int i = 0; i < tryCachNode.Types.Count; i++) { Ast.BlockStatement catchBlock = new Ast.BlockStatement(); catchBlock.Children.AddRange(TransformNode(tryCachNode.Childs[i + 2])); Ast.CatchClause cc = new Ast.CatchClause( new Ast.TypeReference(tryCachNode.Types[i].FullName), "exception", catchBlock ); ccs.Add(cc); } Ast.TryCatchStatement tryCachStmt = new Ast.TryCatchStatement(tryBlock, ccs, finallyBlock); yield return tryCachStmt; } else { throw new Exception("Bad node type"); } if (Options.NodeComments) { yield return MakeComment(""); } }