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> /// Get the mutable copy of a switch case. /// </summary> /// <param name="swithCase"></param> /// <returns></returns> public virtual SwitchCase GetMutableCopy(ISwitchCase swithCase) { object cachedValue; if (this.cache.TryGetValue(swithCase, out cachedValue)) return (SwitchCase)cachedValue; var result = new SwitchCase(swithCase); // Probably not necessary, no two switch cases are shared. this.cache.Add(swithCase, result); this.cache.Add(result, result); return result; }
/// <summary> /// Visits the specified switch case. /// </summary> /// <param name="switchCase">The switch case.</param> /// <returns></returns> protected virtual ISwitchCase DeepCopy(SwitchCase switchCase) { if (!switchCase.IsDefault) switchCase.Expression = (ICompileTimeConstant)Substitute(switchCase.Expression); switchCase.Body = this.Substitute(switchCase.Body); return switchCase; }
/// <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 case. /// </summary> public virtual void RewriteChildren(SwitchCase switchCase) { if (!switchCase.IsDefault) switchCase.Expression = this.Rewrite((CompileTimeConstant)switchCase.Expression); switchCase.Body = this.Rewrite(switchCase.Body); }
/// <summary> /// Visits the specified switch case. /// </summary> /// <param name="switchCase">The switch case.</param> /// <returns></returns> public virtual ISwitchCase Visit(ISwitchCase switchCase) { SwitchCase mutableSwitchCase = switchCase as SwitchCase; if (!this.copyOnlyIfNotAlreadyMutable || mutableSwitchCase == null) mutableSwitchCase = new SwitchCase(switchCase); return Visit(mutableSwitchCase); }
/// <summary> /// Visits the specified switch case. /// </summary> /// <param name="switchCase">The switch case.</param> /// <returns></returns> public virtual ISwitchCase Visit(SwitchCase switchCase) { if (!switchCase.IsDefault) switchCase.Expression = Visit(switchCase.Expression); switchCase.Body = Visit(switchCase.Body); return switchCase; }