public override void TraverseChildren(IBlockStatement block) { base.TraverseChildren(block); Contract.Assume(block is BlockStatement); var decompiledBlock = (BlockStatement)block; var statements = decompiledBlock.Statements; for (int i = 0; i < statements.Count-1; i++) { var switchInstruction = statements[i] as SwitchInstruction; if (switchInstruction == null) continue; SwitchStatement result = new SwitchStatement(); result.Expression = switchInstruction.switchExpression; statements[i] = result; for (int j = 0, n = switchInstruction.SwitchCases.Count; j < n; j++) { CompileTimeConstant caseLabel = new CompileTimeConstant() { Value = j, Type = this.host.PlatformType.SystemInt32 }; var gotoCaseBody = switchInstruction.SwitchCases[j]; Contract.Assume(gotoCaseBody != null); SwitchCase currentCase = new SwitchCase() { Expression = caseLabel }; result.Cases.Add(currentCase); if (j < n-1) { Contract.Assume(switchInstruction.SwitchCases[j+1] != null); if (gotoCaseBody.TargetStatement == switchInstruction.SwitchCases[j+1].TargetStatement) continue; } currentCase.Body.Add(gotoCaseBody); } if (i == statements.Count-1) return; Contract.Assert(i+1 <= statements.Count); var gotoStatement = statements[i+1] as IGotoStatement; if (gotoStatement != null) { SwitchCase defaultCase = new SwitchCase() { }; // Default case is represented by a dummy Expression. defaultCase.Body.Add(statements[i + 1]); statements.RemoveAt(i + 1); result.Cases.Add(defaultCase); } } }
/// <summary> /// Visits the specified switch statement. /// </summary> /// <param name="switchStatement">The switch statement.</param> public override void Visit(ISwitchStatement switchStatement) { SwitchStatement mutableSwitchStatement = new SwitchStatement(switchStatement); this.resultStatement = this.myCodeCopier.DeepCopy(mutableSwitchStatement); }
/// <summary> /// Visits the specified switch statement. /// </summary> /// <param name="switchStatement">The switch statement.</param> /// <returns></returns> protected virtual IStatement DeepCopy(SwitchStatement switchStatement) { switchStatement.Expression = this.Substitute(switchStatement.Expression); switchStatement.Cases = this.DeepCopy(switchStatement.Cases); return switchStatement; }
/// <summary> /// Build the state machine. /// /// We start from state 0. For each yield return, we assign a unique state, which we call continueing state. For a yield return /// assigned with state x, we move the state machine from the previous state to x. Whenever we see a yield break, we transit /// the state to -1. /// /// When we return from state x, we jump to a label that is inserted right after the previous yield return (that is assigned with state x). /// </summary> private BlockStatement BuildStateMachine(IteratorClosureInformation iteratorClosure, BlockStatement oldBody, Dictionary<int, ILabeledStatement> stateEntries) { // Switch on cases. StateEntries, which have been computed previously, map a state number (for initial and continuing states) to a label that has been inserted // right after the associated yield return. BlockStatement result = new BlockStatement(); var returnFalse = new ReturnStatement() { Expression = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean } }; var returnFalseLabel = new LabeledStatement() { Label = this.host.NameTable.GetNameFor("return false"), Statement = returnFalse }; List<ISwitchCase> cases = new List<ISwitchCase>(); foreach (int i in stateEntries.Keys) { SwitchCase c = new SwitchCase() { Expression = new CompileTimeConstant() { Type = this.host.PlatformType.SystemInt32, Value = i }, Body = new List<IStatement>(), }; c.Body.Add(new GotoStatement() { TargetStatement = stateEntries[i] }); cases.Add(c); } // Default case. SwitchCase defaultCase = new SwitchCase(); defaultCase.Body.Add(new GotoStatement() { TargetStatement = returnFalseLabel }); cases.Add(defaultCase); SwitchStatement switchStatement = new SwitchStatement() { Cases = cases, Expression = new BoundExpression() { Type = this.host.PlatformType.SystemInt32, Instance = new ThisReference(), Definition = iteratorClosure.StateFieldReference } }; result.Statements.Add(switchStatement); result.Statements.Add(oldBody); result.Statements.Add(returnFalseLabel); return result; }
private void DecompileSwitch(List<IStatement> statements, int i) { if (i >= statements.Count-1) return; SwitchInstruction/*?*/ switchInstruction = statements[i] as SwitchInstruction; if (switchInstruction == null) return; SwitchStatement result = new SwitchStatement(); result.Expression = switchInstruction.switchExpression; statements[i] = result; for (int j = 0, n = switchInstruction.switchCases.Count; j < n; j++) { CompileTimeConstant caseLabel = new CompileTimeConstant() { Value = j, Type = this.platformType.SystemInt32 }; var gotoCaseBody = switchInstruction.switchCases[j]; SwitchCase currentCase = new SwitchCase() { Expression = caseLabel }; result.Cases.Add(currentCase); if (j < n-1 && gotoCaseBody.TargetStatement == switchInstruction.switchCases[j+1].TargetStatement) continue; currentCase.Body.Add(gotoCaseBody); } if (i == statements.Count-1) return; var gotoStatement = statements[i+1] as IGotoStatement; if (gotoStatement != null) { SwitchCase defaultCase = new SwitchCase() { }; // Default case is represented by a dummy Expression. defaultCase.Body.Add(statements[i + 1]); statements.RemoveAt(i + 1); result.Cases.Add(defaultCase); } }
/// <summary> /// Rewrites the children of the given switch statement. /// </summary> public virtual void RewriteChildren(SwitchStatement switchStatement) { this.RewriteChildren((Statement)switchStatement); switchStatement.Expression = this.Rewrite(switchStatement.Expression); switchStatement.Cases = this.Rewrite(switchStatement.Cases); }
/// <summary> /// Visits the specified switch statement. /// </summary> /// <param name="switchStatement">The switch statement.</param> public override void Visit(ISwitchStatement switchStatement) { SwitchStatement mutableSwitchStatement = switchStatement as SwitchStatement; if (alwaysMakeACopy || mutableSwitchStatement == null) mutableSwitchStatement = new SwitchStatement(switchStatement); this.resultStatement = this.myCodeMutator.Visit(mutableSwitchStatement); }
/// <summary> /// Visits the specified switch statement. /// </summary> /// <param name="switchStatement">The switch statement.</param> /// <returns></returns> public virtual IStatement Visit(SwitchStatement switchStatement) { switchStatement.Expression = Visit(switchStatement.Expression); switchStatement.Cases = Visit(switchStatement.Cases); return switchStatement; }