public void ConditionalStatementProducesIfWithEmptyThen() { var c = new ConditionalStatement(); c.Condition = JS.Id("a"); Assert.AreEqual("if(a);", c.ToString()); }
private bool ReplaceChainedShortCircuitBooleanPattern(List <IStatement> statements, int i) { ConditionalStatement conditionalStatement = (ConditionalStatement)statements[i]; if (!this.ReplaceShortCircuitPattern(statements, i + 1)) { if (!this.ReplaceShortCircuitPatternCreatedByCCI2(statements, i + 1)) { return(false); } } //if (!this.ReplaceShortCircuitPattern(statements, i+1)) return false; PushStatement /*?*/ push = statements[i + 1] as PushStatement; if (push == null) { return(false); } Conditional /*?*/ chainedConditional = push.ValueToPush as Conditional; if (chainedConditional == null) { return(false); } return(this.ReplaceShortCircuitPattern(statements, i)); }
public IStatement GenerateIf(FieldDefinition field, List <int> toStateIds, Epa epa, Dictionary <State, int> stateNumberMap) { var toStates = new List <State>(); foreach (var kvp in stateNumberMap) { var id = kvp.Value; var state = kvp.Key; if (toStateIds.Contains(id)) { toStates.Add(state); } } var conditions = GenerateStatesConditions(toStates); var stmt = new AssignmentGenerator().GenerateAssign(field, toStateIds[0]); for (var i = 1; i < toStateIds.Count; ++i) { stmt = new ConditionalStatement { Condition = conditions[i], TrueBranch = new AssignmentGenerator().GenerateAssign(field, toStateIds[i]), FalseBranch = stmt }; } return(stmt); }
public void ConditionalStatementProducesIfThenElseIfThenElse() { var c1 = JS.If(a).Then(JS.Return(a)); var c2 = new ConditionalStatement(JS.Not(a), null, null); c2.Parent = c1; c2.ThenStatement = JS.Return(); c2.ElseStatement = JS.Return(); Assert.AreEqual("if(a)return a; else if(!a)return; else return;", c2.ToString()); }
public void ConditionalStatementHelpersRequireStatement() { ConditionalStatement statement = null; Expect.Throw <ArgumentNullException>(() => statement.Then()); Expect.Throw <ArgumentNullException>(() => statement.Then(new List <Statement>())); Expect.Throw <ArgumentNullException>(() => statement.Else()); Expect.Throw <ArgumentNullException>(() => statement.Else(new List <Statement>())); Expect.Throw <ArgumentNullException>(() => statement.ElseIf(null)); }
private static void TestDeterminedLastElseClause(IfStatementSyntax conditionalNode, bool expected) { Assert.IsNotNull(conditionalNode, "Found node should be of type `{0}`!", typeof(IfStatementSyntax).Name); ConditionalStatement conditionalStatement = new ConditionalStatement(conditionalNode); bool lastElsePresent = conditionalStatement.HasElseBlock; Assert.AreEqual(expected, lastElsePresent, "Expected last ELSE clause presence does not match!"); }
private static void TestRetrievedNumberOfBodies(IfStatementSyntax conditionalNode, int expected) { Assert.IsNotNull(conditionalNode, "Found node should be of type `{0}`!", typeof(IfStatementSyntax).Name); ConditionalStatement conditionalStatement = new ConditionalStatement(conditionalNode); int blocksNumber = conditionalStatement.BlocksNumber; Assert.AreEqual(expected, blocksNumber, "Number of retrieved blocks does not match!"); }
/// <summary> /// Factory method for class <see cref="ConditionalStatementASTWalker"/>. /// </summary> /// <param name="node"><see cref="CSharpSyntaxNode"/> Used to initialize the walker.</param> /// <param name="semanticModel">The semantic model.</param> /// <returns></returns> public static ConditionalStatementASTWalker Create(CSharpSyntaxNode node, SemanticModel semanticModel = null) { // TODO: Use TranslationUnitFactory in order to have AST walkers decoupled from helpers // via factories (which will be using helpers) ConditionalStatement helper = new ConditionalStatement(node as IfStatementSyntax); var statement = ConditionalStatementTranslationUnit.Create(helper.BlocksNumber, helper.HasElseBlock); return(new ConditionalStatementASTWalker(node, statement, semanticModel)); }
private static void UpdateConditionalStatement(ConditionalStatement stmt) { var builder = (BoundSpillSequenceBuilder)stmt.Condition; Debug.Assert(stmt.ParentNode.NodeType == NodeType.Block); Debug.Assert(builder.Value.ExpressionType == My <TypeSystemServices> .Instance.BoolType); var spills = new Block(builder.GetStatements().ToArray()); var statements = ((Block)stmt.ParentNode).Statements; statements.Insert(statements.IndexOf(stmt), spills); stmt.Condition = builder.Value; }
void OrlyStatement(out Statement stat) { ConditionalStatement cs = new ConditionalStatement(GetPragma(la)); stat = cs; ConditionalStatement cur = cs; Statement st; Expression e; cs.condition = new VariableLValue(GetPragma(la), GetVariable("IT")); Expect(33); Expect(34); Expect(23); SetEndPragma(cs); while (la.kind == 5) { Get(); } if (la.kind == 35) { Get(); Expect(34); while (la.kind == 5) { Get(); } } BeginScope(); Statements(out cs.trueStatements); EndScope(); while (la.kind == 36) { Get(); cur.falseStatements = new ConditionalStatement(GetPragma(la)); Expression(out e); (cur.falseStatements as ConditionalStatement).condition = e; SetEndPragma(cur.falseStatements); cur = (ConditionalStatement)cur.falseStatements; BeginScope(); while (la.kind == 5) { Get(); } Statements(out cur.trueStatements); EndScope(); } if (la.kind == 37) { Get(); Expect(38); while (la.kind == 5) { Get(); } BeginScope(); Statements(out cur.falseStatements); EndScope(); } Expect(39); }
/// <summary> /// Génère le code pour des statements conditionnels. /// </summary> /// <param name="statement"></param> /// <returns></returns> string GenerateConditionalStatement(ConditionalStatement statement) { StringBuilder builder = new StringBuilder(); switch (statement.StatementType) { case ConditionalStatement.Type.If: builder.Append("if"); break; case ConditionalStatement.Type.Elsif: builder.Append("else if"); break; case ConditionalStatement.Type.Else: builder.Append("else"); break; case ConditionalStatement.Type.While: builder.Append("while"); break; default: throw new NotImplementedException(); } // Ajout de la condition if (statement.StatementType != ConditionalStatement.Type.Else) { builder.Append("("); builder.Append(GenerateEvaluable(statement.Condition)); builder.Append(")"); } // Ajout du code builder.Append("\r\n{\r\n"); foreach (Instruction inst in statement.Code) { builder.Append(Tools.StringUtils.Indent(GenerateInstruction(inst))); } builder.Append("\r\n}\r\n"); return(builder.ToString()); }
public override IStatement VisitIfStatement(IfStatementSyntax node) { var e = this.expressionVisitor.Visit(node.Condition); var thenStmt = this.Visit(node.Statement); var cond = new ConditionalStatement() { Condition = e, Locations = Helper.SourceLocation(this.tree, node), //.Condition), TrueBranch = thenStmt, }; IStatement elseStmt = new EmptyStatement(); if (node.Else != null) { elseStmt = this.Visit(node.Else); } cond.FalseBranch = elseStmt; return(cond); }
public override void RewriteChildren(ConditionalStatement conditionalStatement) { // exactly the same code as the base visitor. just need to reset stack // depth for each branch. this.RewriteChildren((Statement)conditionalStatement); conditionalStatement.Condition = this.Rewrite(conditionalStatement.Condition); var savedInThenBranch = this.inThenBranch; var savedInElseBranch = this.inElseBranch; this.inThenBranch = true; this.inElseBranch = false; var savedThenBranchPushes = this.thenBranchPushes; this.thenBranchPushes = new Dictionary <int, Assignment>(); var savedStack = Copy(this.locals); conditionalStatement.TrueBranch = this.Rewrite(conditionalStatement.TrueBranch); var stackAfterTrue = Copy(this.locals); this.locals = Copy(savedStack); this.inThenBranch = false; this.inElseBranch = true; conditionalStatement.FalseBranch = this.Rewrite(conditionalStatement.FalseBranch); Contract.Assume(stackAfterTrue.Count == this.locals.Count); // and that the things pushed in both branches are type-compatible // (one branch might push a bool and the other an int) // continuing on with the stack being the one from the else-branch. // is that okay? should it be the one from the then-branch? // currently it is important that it is the one from the else-branch // because of the fixup code in Rewrite(IPushStatement) that deals // with the bool/int confusion this.inThenBranch = savedInThenBranch; this.inElseBranch = savedInElseBranch; this.thenBranchPushes = savedThenBranchPushes; }
// i : loc := e0; // i+1 : if (loc) S0; else S1; // // ==> // // if (e0) S0; else S1; // // and delete statement i // // This is done only if loc is in this.branchConditionLocals // private void FindPattern(List <IStatement> statements) { for (int i = 0; i < statements.Count - 1; i++) { IExpressionStatement /*?*/ expressionStatement = statements[i] as IExpressionStatement; if (expressionStatement == null) { continue; } IAssignment /*?*/ assignmentStatement = expressionStatement.Expression as IAssignment; if (assignmentStatement == null) { continue; } if (assignmentStatement.Source is Pop) { continue; } ILocalDefinition /*?*/ localDefinition = assignmentStatement.Target.Definition as ILocalDefinition; if (localDefinition == null) { continue; } if (localDefinition.Type.TypeCode != PrimitiveTypeCode.Boolean) { continue; // cheaper test than looking in the table } if (!this.branchConditionLocals.ContainsKey(localDefinition)) { continue; } IConditionalStatement /*?*/ conditional = statements[i + 1] as IConditionalStatement; if (conditional == null) { continue; } BoundExpression /*?*/ boundExpression = conditional.Condition as BoundExpression; if (boundExpression == null) { continue; } ILocalDefinition /*?*/ localDefinition2 = boundExpression.Definition as ILocalDefinition; if (localDefinition2 == null) { continue; } if (localDefinition != localDefinition2) { continue; } var newLocs = new List <ILocation>(expressionStatement.Locations); newLocs.AddRange(conditional.Locations); statements[i + 1] = new ConditionalStatement() { Condition = assignmentStatement.Source, TrueBranch = conditional.TrueBranch, FalseBranch = conditional.FalseBranch, Locations = newLocs, }; this.sourceMethodBody.numberOfAssignments[localDefinition]--; this.sourceMethodBody.numberOfReferences[localDefinition]--; statements.RemoveAt(i); } }
/* * public static T First<T>(this List<T> available, string query){ * ConditionalStatement statement = Parse(query); * if (statement == null) * return available.PopLast(); * List<T> candidates = new List<T>(available.Where(o => statement.Evaluate(o))); * return (candidates.Count > 0) ? candidates.PopLast() : available.PopLast(); * } */ /// <summary> /// Parse the input string s and extracts the conditional statement contained within /// </summary> /// <param name="s">The string to evaluate or null if the parsing failed.</param> public static ConditionalStatement Parse(string s) { // This far, unary operators and parentheses are not supported char type; ConditionalStatement statement = new ConditionalStatement(); int cc = 0; int bcc = cc; string next; // STEP 1: Read first element. next = ReadNext(s, ref cc, out type); // There are three valid options: identifier, unary and end $ // Identifier resets cc and goes to Condition.Parse // Unary writes the operator in statement and expects Condition // Whatever other option has the same effect of end: terminate (return null). switch (type) { case 'i': cc = bcc; statement.A = Condition.Parse(s, ref cc); break; case 'u': statement.Operator = next; statement.A = Condition.Parse(s, ref cc); // As an unary operator works as a whole statement, the statement // is stacked and left clean. statement = new ConditionalStatement() { A = statement }; break; default: return(null); } while (cc < s.Length) { // STEP 2: Whatever happened before, either $ or a binary operator is expected; // Again, any other option works like end: termination (return null). next = ReadNext(s, ref cc, out type); if (type != 'b') { return(statement); } statement.Operator = next; // STEP 3: Read second element. bcc = cc; next = ReadNext(s, ref cc, out type); // Again, there are three valid options: identifier, unary and end $ // Identifier resets cc and goes to Condition.Parse // Unary writes the operator in statement and expects Condition // Whatever other option has the same effect of end: terminate (return null). switch (type) { case 'i': cc = bcc; statement.B = Condition.Parse(s, ref cc); break; case 'u': // As an unary operator works as a whole statement, another statement // the negated conditional is stored as a statement within B statement.B = new ConditionalStatement() { Operator = next, A = Condition.Parse(s, ref cc) }; break; default: return(statement); } // The statement is complete, it is now stacked and we return to STEP 2; statement = new ConditionalStatement() { A = statement }; } return(statement); }
public override void RewriteChildren(ConditionalStatement conditionalStatement) { base.RewriteChildren(conditionalStatement); var trueBlock = conditionalStatement.TrueBranch as BlockStatement; if (trueBlock == null || trueBlock.Statements.Count != 1) { return; } if (!(conditionalStatement.FalseBranch is IEmptyStatement)) { return; } var equals = conditionalStatement.Condition as IEquality; if (equals == null || !(equals.RightOperand is IDefaultValue)) { return; } var binding = equals.LeftOperand as IBoundExpression; if (binding == null) { return; } var exprStat = trueBlock.Statements[0] as IExpressionStatement; if (exprStat == null) { return; } var assignment = exprStat.Expression as IAssignment; if (assignment == null) { return; } var anonDel = assignment.Source as AnonymousDelegate; if (anonDel == null) { return; } if (!TypeHelper.TypesAreEquivalent(assignment.Type, binding.Type)) { return; } var local = binding.Definition as LocalDefinition; if (local != null) { //Unfortunately the C# compiler does not mark such locals as being compiler generated. //So we'll use a heuristic to try and prevent us from deleting user written code. //The local should be (optionally) initialized to null and then assign the anonymous delegate uint numAssigns; if (!this.numberOfAssignmentsToLocal.TryGetValue(local, out numAssigns) || numAssigns > 2) { return; } //The local should be tested for null and then used one more time to get the non-null value. uint numRefs; if (!this.numberOfReferencesToLocal.TryGetValue(local, out numRefs) || numRefs != 2) { return; } if (this.delegatesCachedInLocals == null) { this.delegatesCachedInLocals = new Hashtable <LocalDefinition, AnonymousDelegate>(); } this.delegatesCachedInLocals.Add(local, anonDel); } }
private Statement ParseIf(TokenSet followers) //^ requires this.currentToken == Token.If; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.CurrentSourceLocation); this.GetNextToken(); Expression ifCondition = this.ParseExpression(followers|Token.Else|Token.EndIf|Parser.StatementStart|Token.EndOfLine); this.Skip(Token.EndOfLine); BlockStatement ifTrue = this.ParseStatementBlock(followers|Token.Else|Token.EndIf); Statement ifFalse; if (this.currentToken == Token.Else) { this.GetNextToken(); this.Skip(Token.EndOfLine); ifFalse = this.ParseStatementBlock(followers|Token.EndIf); } else { ifFalse = new EmptyStatement(false, this.scanner.CurrentSourceLocation); } slb.UpdateToSpan(this.scanner.CurrentSourceLocation); Statement result = new ConditionalStatement(ifCondition, ifTrue, ifFalse, slb); this.SkipClosingKeyword(Token.EndIf, followers); return result; }
private Statement ParseGoto(TokenSet followers) //^ requires this.currentToken == Token.Goto; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.CurrentSourceLocation); this.GetNextToken(); SimpleName targetLabel = this.ParseSimpleName(followers|Token.EndOfLine|Token.If); Statement result = new GotoStatement(targetLabel, slb); slb.UpdateToSpan(targetLabel.SourceLocation); if (this.currentToken == Token.If) { this.GetNextToken(); slb = new SourceLocationBuilder(slb.GetSourceLocation()); Expression condition = this.ParseExpression(followers|Token.EndOfLine); slb.UpdateToSpan(condition.SourceLocation); result = new ConditionalStatement(condition, result, new EmptyStatement(false, this.scanner.CurrentSourceLocation), slb); } this.SkipOverTo(Token.EndOfLine, followers); return result; }
public void ConditionalStatementProducesErrorWithMissingCondition() { var c = new ConditionalStatement(); Expect.Throw <InvalidOperationException>(() => c.ToString()); }
public override void TraverseChildren(IMethodCall methodCall) { var resolvedMethod = Sink.Unspecialize(methodCall.MethodToCall).ResolvedMethod; var methodName = Microsoft.Cci.MemberHelper.GetMethodSignature(resolvedMethod); if (methodName.Equals("System.Object.GetHashCode") || methodName.Equals("System.Object.ToString")) { base.TraverseChildren(methodCall); return; } bool isEventAdd = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("add_"); bool isEventRemove = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("remove_"); if (isEventAdd || isEventRemove) { base.TraverseChildren(methodCall); return; } if (!methodCall.IsVirtualCall) { base.TraverseChildren(methodCall); return; } var containingType = TypeHelper.UninstantiateAndUnspecialize(methodCall.MethodToCall.ContainingType); List <ITypeReference> subTypesOfContainingType; if (!this.subTypes.TryGetValue(containingType, out subTypesOfContainingType)) { base.TraverseChildren(methodCall); return; } Contract.Assert(0 < subTypesOfContainingType.Count); Contract.Assert(!methodCall.IsStaticCall); Contract.Assert(!resolvedMethod.IsConstructor); var overrides = FindOverrides(containingType, resolvedMethod); bool same = true; foreach (var o in overrides) { IMethodDefinition resolvedOverride = Sink.Unspecialize(o.Item2).ResolvedMethod; if (resolvedOverride != resolvedMethod) { same = false; } } if (!(containingType.ResolvedType.IsInterface) && (0 == overrides.Count || same)) { base.TraverseChildren(methodCall); return; } Contract.Assume(1 <= overrides.Count); var getType = new Microsoft.Cci.MethodReference( this.sink.host, this.sink.host.PlatformType.SystemObject, CallingConvention.HasThis, this.sink.host.PlatformType.SystemType, this.sink.host.NameTable.GetNameFor("GetType"), 0); var op_Type_Equality = new Microsoft.Cci.MethodReference( this.sink.host, this.sink.host.PlatformType.SystemType, CallingConvention.Default, this.sink.host.PlatformType.SystemBoolean, this.sink.host.NameTable.GetNameFor("op_Equality"), 0, this.sink.host.PlatformType.SystemType, this.sink.host.PlatformType.SystemType); // Depending on whether the method is a void method or not // Turn into expression: // (o.GetType() == typeof(T1)) ? ((T1)o).M(...) : ( (o.GetType() == typeof(T2)) ? ((T2)o).M(...) : ... // Or turn into statements: // if (o.GetType() == typeof(T1)) ((T1)o).M(...) else if ... var turnIntoStatements = resolvedMethod.Type.TypeCode == PrimitiveTypeCode.Void; IStatement elseStatement = null; IExpression elseValue = new MethodCall() { Arguments = new List <IExpression>(methodCall.Arguments), IsStaticCall = false, IsVirtualCall = false, MethodToCall = methodCall.MethodToCall, ThisArgument = methodCall.ThisArgument, Type = methodCall.Type, }; if (turnIntoStatements) { elseStatement = new ExpressionStatement() { Expression = elseValue, } } ; Conditional ifConditional = null; ConditionalStatement ifStatement = null; foreach (var typeMethodPair in overrides) { var t = typeMethodPair.Item1; var m = typeMethodPair.Item2; if (m.IsGeneric) { var baseMethod = m.ResolvedMethod; m = new GenericMethodInstanceReference() { CallingConvention = baseMethod.CallingConvention, ContainingType = baseMethod.ContainingTypeDefinition, GenericArguments = new List <ITypeReference>(IteratorHelper.GetConversionEnumerable <IGenericMethodParameter, ITypeReference>(baseMethod.GenericParameters)), GenericMethod = baseMethod, InternFactory = this.sink.host.InternFactory, Name = baseMethod.Name, Parameters = baseMethod.ParameterCount == 0 ? null : new List <IParameterTypeInformation>(baseMethod.Parameters), Type = baseMethod.Type, }; } var cond = new MethodCall() { Arguments = new List <IExpression>() { new MethodCall() { Arguments = new List <IExpression>(), IsStaticCall = false, IsVirtualCall = false, MethodToCall = getType, ThisArgument = methodCall.ThisArgument, }, new TypeOf() { TypeToGet = t, }, }, IsStaticCall = true, IsVirtualCall = false, MethodToCall = op_Type_Equality, Type = this.sink.host.PlatformType.SystemBoolean, }; Expression thenValue = new MethodCall() { Arguments = new List <IExpression>(methodCall.Arguments), IsStaticCall = false, IsVirtualCall = false, MethodToCall = m, ThisArgument = methodCall.ThisArgument, Type = m.Type, }; thenValue = new Conversion() { Type = m.Type, TypeAfterConversion = methodCall.Type, ValueToConvert = thenValue, }; if (turnIntoStatements) { ifStatement = new ConditionalStatement() { Condition = cond, FalseBranch = elseStatement, TrueBranch = new ExpressionStatement() { Expression = thenValue, }, }; elseStatement = ifStatement; } else { ifConditional = new Conditional() { Condition = cond, ResultIfFalse = elseValue, ResultIfTrue = thenValue, }; elseValue = ifConditional; } } if (turnIntoStatements) { Contract.Assume(ifStatement != null); this.StmtTraverser.Traverse(ifStatement); } else { Contract.Assume(ifConditional != null); base.Traverse(ifConditional); } return; }
private Statement ParseIf(TokenSet followers) //^ requires this.currentToken == Token.If; //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { SourceLocationBuilder slb = new SourceLocationBuilder(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); Expression ifCondition = this.ParseParenthesizedExpression(false, followers|Parser.StatementStart); Statement ifTrue = this.ParseStatement(followers|Token.Else); if (ifTrue is EmptyStatement) this.HandleError(ifTrue.SourceLocation, Error.PossibleMistakenNullStatement); Statement ifFalse; if (this.currentToken == Token.Else) { this.GetNextToken(); ifFalse = this.ParseStatement(followers); if (ifFalse is EmptyStatement) this.HandleError(ifFalse.SourceLocation, Error.PossibleMistakenNullStatement); } else { ifFalse = new EmptyStatement(false, ifTrue.SourceLocation); } slb.UpdateToSpan(ifFalse.SourceLocation); Statement result = new ConditionalStatement(ifCondition, ifTrue, ifFalse, slb); this.SkipTo(followers); return result; }
/// <summary> /// Finds the following pattern: /// i : c ? A : B; // either A or B must be an empty statement and the other is "goto L1;" /// i+1 : push x; /// i+2 : goto L2; /// i+3 : Block1 /// 0 : L1; /// 1 : push y; /// 2 : goto L2; /// 3 : Block2 /// 0 : whatever (but presumably it is the label L2) /// /// Transforms it into: /// i : push d ? X : Y; /// i+1 : goto L1; /// i+2 : Block 2 /// /// Where if A is the empty statement, /// d == c, X == x, Y == y /// If B is the empty statement and y is zero /// d == !c, X == x, Y == y /// If B is the empty statement and y is not zero /// d == c, X == y, Y == x /// And Block1 is deleted from the list. /// </summary> private bool ReplaceShortCircuitPatternCreatedByCCI2(List <IStatement> statements, int i) { if (i > statements.Count - 4) { return(false); } ConditionalStatement /*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) { return(false); } PushStatement /*?*/ push1 = statements[i + 1] as PushStatement; if (push1 == null) { return(false); } GotoStatement /*?*/ Goto = statements[i + 2] as GotoStatement; if (Goto == null) { return(false); } BasicBlock /*?*/ block1 = statements[i + 3] as BasicBlock; if (block1 == null) { return(false); } if (block1.Statements.Count < 4) { return(false); } LabeledStatement /*?*/ label = block1.Statements[0] as LabeledStatement; if (label == null) { return(false); } List <IGotoStatement> branchesToThisLabel; if (this.predecessors.TryGetValue(label, out branchesToThisLabel)) { if (1 < branchesToThisLabel.Count) { return(false); } } // TODO? Should we make sure that one of the branches in the conditionalStatement is // to label? PushStatement /*?*/ push2 = block1.Statements[1] as PushStatement; if (push2 == null) { return(false); } GotoStatement /*?*/ Goto2 = block1.Statements[2] as GotoStatement; if (Goto2 == null) { return(false); } if (Goto.TargetStatement != Goto2.TargetStatement) { return(false); } BasicBlock /*?*/ block2 = block1.Statements[3] as BasicBlock; if (block2 == null) { return(false); } if (conditionalStatement.TrueBranch is EmptyStatement) { Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push1.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); push1.ValueToPush = conditional; push1.Locations = conditionalStatement.Locations; statements[i] = push1; statements[i + 1] = statements[i + 2]; // move the goto up statements[i + 2] = block2; statements.RemoveRange(i + 3, 1); return(true); } if (conditionalStatement.FalseBranch is EmptyStatement) { Conditional conditional = new Conditional(); if (ExpressionHelper.IsIntegralZero(push2.ValueToPush)) { conditional.Condition = InvertCondition(conditionalStatement.Condition); conditional.ResultIfTrue = push1.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; } else { conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push2.ValueToPush; conditional.ResultIfFalse = push1.ValueToPush; } conditional.Locations = conditionalStatement.Locations; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); push1.ValueToPush = conditional; push1.Locations = conditionalStatement.Locations; statements[i] = push1; statements[i + 1] = statements[i + 2]; // move the goto up statements[i + 2] = block2; statements.RemoveRange(i + 3, 1); return(true); } return(false); }
private void DecompileIfThenElseStatement(BasicBlock b, int i) { List <IStatement> statements = b.Statements; ConditionalStatement /*?*/ conditionalStatement = statements[i++] as ConditionalStatement; if (conditionalStatement == null) { return; } IExpression condition; var trueBranch = UnwrapSingletonBlock(conditionalStatement.TrueBranch); GotoStatement /*?*/ gotoAfterThen = trueBranch as GotoStatement; if (gotoAfterThen == null) { gotoAfterThen = UnwrapSingletonBlock(conditionalStatement.FalseBranch) as GotoStatement; if (gotoAfterThen == null || !(trueBranch is EmptyStatement)) { return; } condition = conditionalStatement.Condition; } else { if (!(conditionalStatement.FalseBranch is EmptyStatement)) { return; } LogicalNot not = new LogicalNot(); not.Operand = conditionalStatement.Condition; condition = not; } //At this point we have: //if (!condition) goto afterThen; var afterThen = this.FindLabeledStatement(statements, i, gotoAfterThen.TargetStatement.Label); if (afterThen == null) { return; } List <IGotoStatement> branchesToThisLabel; if (this.predecessors.TryGetValue(afterThen, out branchesToThisLabel)) { branchesToThisLabel.Remove(gotoAfterThen); } BasicBlock ifBlock = this.ExtractBasicBlockUpto(b, i, afterThen); GotoStatement /*?*/ gotoEndif = this.RemoveAndReturnLastGotoStatement(ifBlock); this.Traverse(ifBlock); BasicBlock elseBlock = null; if (gotoEndif != null) { var endif = this.FindLabeledStatement(statements, i, gotoEndif.TargetStatement.Label); if (endif != null) { if (this.predecessors.TryGetValue(gotoEndif.TargetStatement, out branchesToThisLabel)) { branchesToThisLabel.Remove(gotoEndif); } elseBlock = this.ExtractBasicBlockUpto(b, i, gotoEndif.TargetStatement); elseBlock.Statements.Add(gotoEndif.TargetStatement); this.Traverse(elseBlock); elseBlock.Statements.Remove(gotoEndif.TargetStatement); } else { ifBlock.Statements.Add(gotoEndif); } } conditionalStatement.Condition = condition; conditionalStatement.TrueBranch = ifBlock; if (elseBlock != null) { conditionalStatement.FalseBranch = elseBlock; } else { conditionalStatement.FalseBranch = new EmptyStatement(); } return; }
public void ConditionalStatementProducesErrorWithMissingCondition() { var c = new ConditionalStatement(); Expect.Throw<InvalidOperationException>(() => c.ToString()); }
private bool ReplaceShortCircuitPattern3(List <IStatement> statements, int i) { if (i > statements.Count - 3) { return(false); } ConditionalStatement /*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) { return(false); } ConditionalStatement /*?*/ conditionalStatement2 = statements[i + 1] as ConditionalStatement; if (conditionalStatement2 == null) { return(false); } if (statements[i + 2] is ConditionalStatement) { if (!this.ReplaceShortCircuitPattern2(statements, i + 1)) { return(false); } if (i > statements.Count - 3) { return(false); } conditionalStatement2 = statements[i + 1] as ConditionalStatement; if (conditionalStatement2 == null) { return(false); } } GotoStatement /*?*/ gotoStatement = conditionalStatement.FalseBranch as GotoStatement; if (gotoStatement == null) { return(false); } if (!(conditionalStatement.TrueBranch is EmptyStatement)) { return(false); } GotoStatement /*?*/ gotoStatement2 = conditionalStatement2.FalseBranch as GotoStatement; if (gotoStatement2 == null) { gotoStatement2 = conditionalStatement2.TrueBranch as GotoStatement; if (gotoStatement2 == null) { return(false); } if (!(conditionalStatement2.FalseBranch is EmptyStatement)) { return(false); } //brfalse, brtrue, ... could be A && B || C BasicBlock /*?*/ bb = statements[i + 2] as BasicBlock; if (bb == null) { return(false); } if (bb.Statements.Count < 1 || !(bb.Statements[0] == gotoStatement.TargetStatement)) { return(false); } //we have: //i+0: if (cond1) {} else goto lab1; //i+1: if (cond2) goto lab2; //i+2: {....} Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.Locations = conditionalStatement.Locations; conditional.ResultIfTrue = conditionalStatement2.Condition; conditional.ResultIfFalse = new CompileTimeConstant() { Value = 0, Type = this.sourceMethodBody.MethodDefinition.Type.PlatformType.SystemInt32 }; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditionalStatement2.Condition = conditional; statements.RemoveAt(i); //we now have: //i+0: if (cond1 ? cond2 : 0) goto lab2; //i+1: {....} //which amounts to: // if (cond1 && cond2) goto lab2; // {...} return(this.ReplaceShortCircuitPattern2(statements, i)); } if (!(conditionalStatement2.TrueBranch is EmptyStatement)) { return(false); } if (gotoStatement.TargetStatement == gotoStatement2.TargetStatement) { Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.Locations = conditionalStatement.Locations; conditional.ResultIfTrue = conditionalStatement2.Condition; conditional.ResultIfFalse = new CompileTimeConstant() { Value = 0, Type = this.sourceMethodBody.MethodDefinition.Type.PlatformType.SystemInt32 }; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditionalStatement2.Condition = conditional; statements.RemoveAt(i); return(true); } return(false); }
private bool ReplaceShortCircuitPattern2(List <IStatement> statements, int i) { if (i > statements.Count - 3) { return(false); } ConditionalStatement /*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) { return(false); } ConditionalStatement /*?*/ conditionalStatement2 = statements[i + 1] as ConditionalStatement; if (conditionalStatement2 == null) { return(false); } if (statements[i + 2] is ConditionalStatement) { if (!ReplaceShortCircuitPattern2(statements, i + 1)) { return(false); } if (i > statements.Count - 3) { return(false); } conditionalStatement2 = statements[i + 1] as ConditionalStatement; if (conditionalStatement2 == null) { return(false); } } BasicBlock /*?*/ block = statements[i + 2] as BasicBlock; if (block == null) { return(this.ReplaceShortCircuitPattern3(statements, i)); } if (block.Statements.Count < 1) { return(false); } GotoStatement /*?*/ gotoStatement = conditionalStatement.TrueBranch as GotoStatement; if (gotoStatement == null) { return(this.ReplaceShortCircuitPattern3(statements, i)); } if (!(conditionalStatement.FalseBranch is EmptyStatement)) { return(false); } if (gotoStatement.TargetStatement != block.Statements[0]) { return(false); } if (!(conditionalStatement2.TrueBranch is EmptyStatement)) { if (!(conditionalStatement2.TrueBranch is GotoStatement)) { return(false); } if (!(conditionalStatement2.FalseBranch is EmptyStatement)) { return(false); } //Now have: //if (cond1) goto lab1; //if (cond2) goto lab2; //lab1:... conditionalStatement2.Condition = InvertCondition(conditionalStatement2.Condition); IStatement temp = conditionalStatement2.TrueBranch; conditionalStatement2.TrueBranch = conditionalStatement2.FalseBranch; conditionalStatement2.FalseBranch = temp; //Now have: //if (cond1) goto lab1; //if (!cond2) {} else goto lab2; //lab1:... } else { if (!(conditionalStatement2.FalseBranch is GotoStatement)) { return(false); } } //Now have: //if (cond1) goto lab1; //if (cond2a) {} else goto lab2; //lab1:... Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.Locations = conditionalStatement.Locations; conditional.ResultIfTrue = new CompileTimeConstant() { Value = 1, Type = this.sourceMethodBody.MethodDefinition.Type.PlatformType.SystemInt32 }; conditional.ResultIfFalse = conditionalStatement2.Condition; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditionalStatement2.Condition = conditional; statements.RemoveAt(i); //Now have: //if (cond1 ? true : cond2a) {} goto lab2; //lab1:.... // //Which amounts to //if (!(cond1 || cond2a)) goto lab2; //lab1:... return(true); }
/// <summary> /// Finds the following pattern: /// i : if (c) A else B; // either A or B must be an empty statement and the other is "goto L1;" /// i+1 : push x; /// i+2 : goto L2; /// i+3 : Block1 /// 0 : L1; /// 1 : push y; /// 2 : Block2 /// 0 : L2; /// 1 : (rest of statements in Block2) /// /// Transforms it into: /// i : push (d ? X : Y); /// i+1 : (rest of statements in Block2, preceded by L2 if there are more branches to L2 than just the one that was at i+2) /// /// Where if A is the empty statement, then /// d == c, X == x, Y == y /// If B is the empty statement, then if y is zero, /// d == !c, X == x, Y == y /// If B is the empty statement, then if y is not zero, /// d == c, X == y, Y == x /// </summary> private bool ReplaceShortCircuitPattern(List <IStatement> statements, int i) { if (i > statements.Count - 4) { return(false); } ConditionalStatement /*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) { return(false); } if (statements[i + 1] is ConditionalStatement) { return(this.ReplaceChainedShortCircuitBooleanPattern(statements, i)); } GotoStatement /*?*/ gotoL1 = null; if (conditionalStatement.TrueBranch is EmptyStatement) { gotoL1 = conditionalStatement.FalseBranch as GotoStatement; } else if (conditionalStatement.FalseBranch is EmptyStatement) { gotoL1 = conditionalStatement.TrueBranch as GotoStatement; } if (gotoL1 == null) { return(false); } PushStatement /*?*/ push = statements[i + 1] as PushStatement; if (push == null) { return(false); } GotoStatement /*?*/ gotoL2 = statements[i + 2] as GotoStatement; if (gotoL2 == null) { return(false); } BasicBlock /*?*/ block = statements[i + 3] as BasicBlock; if (block == null) { return(false); } if (block.Statements.Count < 3) { return(false); } LabeledStatement /*?*/ l1 = block.Statements[0] as LabeledStatement; if (l1 == null) { return(false); } if (l1 != gotoL1.TargetStatement) { return(false); } List <IGotoStatement> branchesToThisLabel; if (this.predecessors.TryGetValue(l1, out branchesToThisLabel)) { if (branchesToThisLabel.Count > 1) { return(false); } } PushStatement /*?*/ push2 = block.Statements[1] as PushStatement; if (push2 == null) { return(false); } BasicBlock /*?*/ block2 = block.Statements[2] as BasicBlock; if (block2 == null || block2.Statements.Count < 1 || block2.Statements[0] != gotoL2.TargetStatement) { return(false); } Conditional conditional = new Conditional(); if (conditionalStatement.TrueBranch is EmptyStatement) { conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; } else if (conditionalStatement.FalseBranch is EmptyStatement) { if (ExpressionHelper.IsIntegralZero(push2.ValueToPush)) { conditional.Condition = InvertCondition(conditionalStatement.Condition); conditional.ResultIfTrue = push.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; } else { conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push2.ValueToPush; conditional.ResultIfFalse = push.ValueToPush; } } conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditional.Locations = conditionalStatement.Locations; push.ValueToPush = conditional; push.Locations = conditional.Locations; statements[i] = push; statements.RemoveRange(i + 1, 3); var l2 = gotoL2.TargetStatement; this.predecessors.TryGetValue(l2, out branchesToThisLabel); branchesToThisLabel.Remove(gotoL2); if (branchesToThisLabel.Count == 0) { block2.Statements.RemoveAt(0); } statements.InsertRange(i + 1, block2.Statements); return(true); }
public ConditionalExpressionInterpreter(ExpressionInterpreterHandler expressionInterpreterHandler, ConditionalStatement conditionalStatement) { this.expressionInterpreterHandler = expressionInterpreterHandler; this.conditionalStatement = conditionalStatement; }