/// <summary> /// Visits the specified addition. /// </summary> /// <param name="addition">The addition.</param> /// <returns></returns> protected virtual IExpression DeepCopy(Addition addition) { return this.DeepCopy((BinaryOperation)addition); }
private Expression ParseAddition(OperationCode currentOpcode) { Addition addition = new Addition(); addition.CheckOverflow = currentOpcode != OperationCode.Add; if (currentOpcode == OperationCode.Add_Ovf_Un) { addition.TreatOperandsAsUnsignedIntegers = true; //force use of unsigned addition, even for cases where the operands are expressions that result in signed values return this.ParseUnsignedBinaryOperation(addition); } else return this.ParseBinaryOperation(addition); }
/// <summary> /// Visits the specified addition. /// </summary> /// <param name="addition">The addition.</param> public override void Visit(IAddition addition) { Addition/*?*/ mutableAddition = new Addition(addition); this.resultExpression = this.myCodeCopier.DeepCopy(mutableAddition); }
/// <summary> /// For a string field, s, the source expression e.s += "" /// turns into a specific pattern. /// That pattern here looks like: /// i: push e /// i+1: push dup.s /// i+2: (!= dup (default_value string)) ? goto L2 : empty /// i+3: L1 /// i+4: pop /// i+5: push "" /// i+6: L2 /// i+7: pop.s = pop /// </summary> private bool ReplacePlusAssignForStringPattern(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count - 7; i++) { var push1 = statements[i] as PushStatement; if (push1 == null) continue; var push2 = statements[i + 1] as PushStatement; if (push2 == null) continue; var boundExpression = push2.ValueToPush as IBoundExpression; if (boundExpression == null) continue; var dupValue = boundExpression.Instance as IDupValue; if (dupValue == null) continue; var field = boundExpression.Definition as IFieldReference; if (field == null) continue; var conditionalStatement = statements[i + 2] as IConditionalStatement; if (conditionalStatement == null) continue; var notEquality = conditionalStatement.Condition as INotEquality; if (notEquality == null) continue; var gotoStatement = conditionalStatement.TrueBranch as IGotoStatement; if (gotoStatement == null) continue; var branchTarget = gotoStatement.TargetStatement; var emptyStatement = conditionalStatement.FalseBranch as IEmptyStatement; if (emptyStatement == null) continue; var labeledStatement = statements[i + 3] as ILabeledStatement; if (labeledStatement == null) continue; var popStatement = statements[i + 4] as IExpressionStatement; if (popStatement == null) continue; if (!(popStatement.Expression is IPopValue)) continue; var pushEmptyString = statements[i + 5] as IPushStatement; if (pushEmptyString == null) continue; var emptyString = pushEmptyString.ValueToPush as ICompileTimeConstant; if (emptyString == null) continue; if (emptyString.Type.TypeCode != PrimitiveTypeCode.String) continue; if ((string)emptyString.Value != "") continue; labeledStatement = statements[i + 6] as ILabeledStatement; if (labeledStatement == null) continue; if (labeledStatement.Label != branchTarget.Label) continue; var assignStatement = statements[i + 7] as IExpressionStatement; if (assignStatement == null) continue; var assignment = assignStatement.Expression as IAssignment; if (assignment == null) continue; if (!(assignment.Source is IPopValue)) continue; if (!(assignment.Target.Instance is IPopValue)) continue; // REVIEW: should the definition of the target be checked to be the same as "field"? If so, how? var plusEqual = new Addition() { LeftOperand = new TargetExpression() { Definition = assignment.Target.Definition, Instance = push1.ValueToPush, }, RightOperand = emptyString, ResultIsUnmodifiedLeftOperand = false, Type = assignment.Type, }; statements[i] = new ExpressionStatement() { Expression = plusEqual, Locations = new List<ILocation>(push1.Locations), }; statements.RemoveRange(i + 1, 7); replacedPattern = true; } return replacedPattern; }
/// <summary> /// Visits the specified addition. /// </summary> /// <param name="addition">The addition.</param> /// <returns></returns> public virtual IExpression Visit(Addition addition) { return this.Visit((BinaryOperation)addition); }
/// <summary> /// Rewrites the children of the given addition. /// </summary> /// <param name="addition"></param> public virtual void RewriteChildren(Addition addition) { this.RewriteChildren((BinaryOperation)addition); }
/// <summary> /// Visits the specified addition. /// </summary> /// <param name="addition">The addition.</param> public override void Visit(IAddition addition) { Addition/*?*/ mutableAddition = addition as Addition; if (alwaysMakeACopy || mutableAddition == null) mutableAddition = new Addition(addition); this.resultExpression = this.myCodeMutator.Visit(mutableAddition); }