public override void ExitIfStatement(IfStatement ifStatement) { var block = (BlockStatement)ifStatement.Parent; var trueBranchGotoTarget = new GotoTargetStatement(ifStatement.Context); var endGotoTarget = new GotoTargetStatement(ifStatement.Context); var trueBranch = ifStatement.TrueBranch; var falseBranch = ifStatement.FalseBranch; if (falseBranch != null) { block.AddChildBefore(ifStatement, new GotoStatement(ifStatement.Context, ifStatement.Condition, trueBranchGotoTarget)); block.AddChildBefore(ifStatement, falseBranch); block.AddChildBefore(ifStatement, new GotoStatement(ifStatement.Context, endGotoTarget)); block.AddChildBefore(ifStatement, trueBranchGotoTarget); block.AddChildBefore(ifStatement, trueBranch); block.AddChildBefore(ifStatement, endGotoTarget); } else { var condition = new UnaryExpression(ifStatement.Context, new INode[] { new Token(ifStatement.Context, "!"), ifStatement.Condition }); block.AddChildBefore(ifStatement, new GotoStatement(ifStatement.Context, condition, endGotoTarget)); block.AddChildBefore(ifStatement, trueBranch); block.AddChildBefore(ifStatement, endGotoTarget); } ifStatement.Remove(); BlockFlattener.FlattenAllSubBlocks(block); }
public override void EnterForStatement(ForStatement forStatement) { var block = (BlockStatement)forStatement.Parent; var addedStatements = new List <IStatement>(); var allowedConditionOperators = new[] { "==", "!=", "<", ">", "<=", ">=" }; var allowedUpdateOperators = new[] { "+", "-", "*", "/", "%" }; if (forStatement.Variables.Count() == 1 && forStatement.Variables.Single() is VariableDeclaration singleVariable && singleVariable.Type is NumberType && singleVariable.InitExpression is NumberLiteral initLiteral && !forStatement.InitExpressions.Any() && forStatement.Condition is BinaryExpression condition && condition.Left is SimpleNameExpression conditionVar && conditionVar.Declaration == singleVariable && condition.Right is NumberLiteral && allowedConditionOperators.Contains(condition.Operator.Text) && forStatement.NextExpressions.Count() == 1 && forStatement.NextExpressions.Single() is AssignmentExpression update && update.Left is SimpleNameExpression updateVarWrite && updateVarWrite.Declaration == singleVariable && update.Right is BinaryExpression updateBinaryExpression && allowedUpdateOperators.Contains(updateBinaryExpression.Operator.Text) && updateBinaryExpression.Left is SimpleNameExpression updateVarRead && updateVarRead.Declaration == singleVariable && updateBinaryExpression.Right is NumberLiteral && CountIterations(initLiteral, condition, updateBinaryExpression) is List <double> iterations) { var breakGotoTarget = new GotoTargetStatement(forStatement.Context); foreach (var iteration in iterations) { var continueGotoTarget = new GotoTargetStatement(forStatement.Context); var clone = AstCloner.Clone(forStatement); ReplaceContinueAndBreakStatements( clone, new GotoStatement(clone.Context, breakGotoTarget), new GotoStatement(clone.Context, continueGotoTarget)); var variable = clone.Variables.Single(); variable.InitExpression.ReplaceWith(new NumberLiteral(variable.Context, iteration)); var variableDeclarationStatement = new VariableDeclarationStatement(variable.Context, variable); block.AddChildBefore(forStatement, variableDeclarationStatement); block.AddChildBefore(forStatement, clone.Body); block.AddChildBefore(forStatement, continueGotoTarget); addedStatements.Add(variableDeclarationStatement); addedStatements.Add(clone.Body); addedStatements.Add(continueGotoTarget); } block.AddChildBefore(forStatement, breakGotoTarget); addedStatements.Add(breakGotoTarget); forStatement.Remove(); }
//private void ReplaceGenerics() private void ReplaceReturnStatements(INode node, GotoTargetStatement gotoTarget, VariableDeclaration returnValueVar) { if (!(node is IStatement)) { return; } switch (node) { case ReturnStatement returnStatement: var block = (BlockStatement)returnStatement.Parent; if (returnValueVar != null) { block.AddChildBefore(returnStatement, new ExpressionStatement( returnStatement.Context, new AssignmentExpression( returnStatement.Context, new INode[] { new SimpleNameExpression(returnStatement.Context, returnValueVar.Name) { Declaration = returnValueVar, Type = returnValueVar.Type }, new AssignmentOperator(returnStatement.Context, "="), returnStatement.Value }) )); } block.AddChildBefore(returnStatement, new GotoStatement(returnStatement.Context, gotoTarget)); returnStatement.Remove(); return; } //Any other statement foreach (var child in node.Children.ToList()) { ReplaceReturnStatements(child, gotoTarget, returnValueVar); } }
public override INode VisitGotoTargetStatement(GotoTargetStatement gotoTargetStatement) { return(new GotoTargetStatement(gotoTargetStatement.Context)); }
public virtual void ExitGotoTargetStatement(GotoTargetStatement gotoTargetStatement) { }
public virtual void EnterGotoTargetStatement(GotoTargetStatement gotoTargetStatement) { }
private void UnwrapMethodInvocation(MethodInvocationExpression invocation, MethodDeclaration declaration) { if (invocation.Parent == null) { return; } var context = invocation.Context; var parentStatement = invocation.NearestAncestorOfType <IStatement>(); var discardReturnValue = invocation.Parent is ExpressionStatement; var block = (BlockStatement)parentStatement.Parent; var addedStatements = new List <IStatement>(); VariableDeclaration returnValueVar = null; if (!discardReturnValue) { returnValueVar = new VariableDeclaration( context, declaration.Name + NumberWheel.Next(), new INode[] { AstCloner.Clone(declaration.ReturnType) }); var variableDeclarationStatement = new VariableDeclarationStatement(context, returnValueVar); block.AddChildBefore(parentStatement, variableDeclarationStatement); block.VariableDeclarations.Add(returnValueVar); invocation.ReplaceWith(new SimpleNameExpression(context, returnValueVar.Name) { Type = returnValueVar.Type, Declaration = returnValueVar }); addedStatements.Add(variableDeclarationStatement); } else { invocation.Remove(); } var clonedDeclaration = AstCloner.Clone(declaration); var parameters = clonedDeclaration.Variables.ToList(); var arguments = invocation.Arguments.ToList(); for (int i = 0; i < parameters.Count; i++) { if (arguments.Count > i) { if (parameters[i].InitExpression != null) { parameters[i].InitExpression.ReplaceWith(arguments[i]); } else { parameters[i].AddChild(arguments[i]); } } parameters[i].Remove(); parameters[i].Name += NumberWheel.Next(); var variableDeclarationStatement = new VariableDeclarationStatement(parameters[i].Context, parameters[i]); block.AddChildBefore(parentStatement, variableDeclarationStatement); block.VariableDeclarations.Add(parameters[i]); addedStatements.Add(variableDeclarationStatement); } foreach (var expression in clonedDeclaration.AllDescendantsAndSelf().OfType <SimpleNameExpression>()) { var index = parameters.IndexOf(expression.Declaration); if (index == -1) { continue; } expression.Name = parameters[index].Name; } var body = clonedDeclaration.Body; block.AddChildBefore(parentStatement, body); addedStatements.Add(body); var gotoTarget = new GotoTargetStatement(invocation.Context); block.AddChildBefore(parentStatement, gotoTarget); addedStatements.Add(gotoTarget); ReplaceReturnStatements(clonedDeclaration.Body, gotoTarget, returnValueVar); if (discardReturnValue) { parentStatement.Remove(); } foreach (var subInvocation in addedStatements.SelectMany(x => x.AllDescendantsAndSelf()).OfType <MethodInvocationExpression>().ToList()) { var subTarget = ((MethodReferenceType)subInvocation.Base.Type).Declaration; UnwrapMethodInvocation(subInvocation, subTarget); } BlockFlattener.FlattenAllSubBlocks(block); }
public virtual T VisitGotoTargetStatement(GotoTargetStatement gotoTargetStatement) { return(VisitChildren(gotoTargetStatement)); }