public void AndIsShortcircuit() { IExpression falseexpr = new ConstantExpression(false); IExpression dividebyzero = new BinaryOperatorExpression(new ConstantExpression(1), new ConstantExpression(0), BinaryOperator.Divide); Assert.IsFalse((bool)(new BooleanExpression(falseexpr, dividebyzero, BooleanOperator.And)).Evaluate(null)); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { bool forceSpaces = false; switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Equality: case BinaryOperatorType.InEquality: forceSpaces = policy.SpaceAroundEqualityOperator; break; case BinaryOperatorType.GreaterThan: case BinaryOperatorType.GreaterThanOrEqual: case BinaryOperatorType.LessThan: case BinaryOperatorType.LessThanOrEqual: forceSpaces = policy.SpaceAroundRelationalOperator; break; case BinaryOperatorType.ConditionalAnd: case BinaryOperatorType.ConditionalOr: forceSpaces = policy.SpaceAroundLogicalOperator; break; case BinaryOperatorType.BitwiseAnd: case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: forceSpaces = policy.SpaceAroundBitwiseOperator; break; case BinaryOperatorType.Add: case BinaryOperatorType.Subtract: forceSpaces = policy.SpaceAroundAdditiveOperator; break; case BinaryOperatorType.Multiply: case BinaryOperatorType.Divide: case BinaryOperatorType.Modulus: forceSpaces = policy.SpaceAroundMultiplicativeOperator; break; case BinaryOperatorType.ShiftLeft: case BinaryOperatorType.ShiftRight: forceSpaces = policy.SpaceAroundShiftOperator; break; case BinaryOperatorType.NullCoalescing: forceSpaces = policy.SpaceAroundNullCoalescingOperator; break; } var opToken = binaryOperatorExpression.OperatorToken; if (opToken.PrevSibling != null && opToken.PrevSibling.Role != Roles.NewLine) { ForceSpacesBefore(opToken, forceSpaces); } else { ForceSpacesAfter(binaryOperatorExpression.Left, false); FixIndentation(opToken); } ForceSpacesAfter(opToken, opToken.NextSibling != null && opToken.NextSibling.Role != Roles.NewLine && forceSpaces); binaryOperatorExpression.Left.AcceptVisitor(this); // Handle line breaks in binary opeartor expression. if (binaryOperatorExpression.Left.EndLocation.Line != binaryOperatorExpression.Right.StartLocation.Line) { if (opToken.StartLocation.Line == binaryOperatorExpression.Right.StartLocation.Line) { FixStatementIndentation(opToken.StartLocation); } else { FixStatementIndentation(binaryOperatorExpression.Right.StartLocation); } } binaryOperatorExpression.Right.AcceptVisitor(this); }
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd) UnlockWith(binaryOperatorExpression); return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression (binaryOperatorExpression); if (binaryOperatorExpression.Operator != BinaryOperatorType.Equality && binaryOperatorExpression.Operator != BinaryOperatorType.InEquality) return; string floatType; if (IsNaN(binaryOperatorExpression.Left, out floatType)) { AddIsNaNIssue (binaryOperatorExpression, binaryOperatorExpression.Right, floatType); } else if (IsNaN (binaryOperatorExpression.Right, out floatType)) { AddIsNaNIssue (binaryOperatorExpression, binaryOperatorExpression.Left, floatType); } else if (IsFloatingPoint(binaryOperatorExpression.Left) || IsFloatingPoint(binaryOperatorExpression.Right)) { if (IsConstantInfinity(binaryOperatorExpression.Left) || IsConstantInfinity(binaryOperatorExpression.Right)) return; AddIssue (binaryOperatorExpression, ctx.TranslateString ("Compare a difference with EPSILON"), script => { // Math.Abs(diff) op EPSILON var builder = ctx.CreateTypeSytemAstBuilder(binaryOperatorExpression); var diff = new BinaryOperatorExpression (binaryOperatorExpression.Left.Clone (), BinaryOperatorType.Subtract, binaryOperatorExpression.Right.Clone ()); var abs = builder.ConvertType(new TopLevelTypeName("System", "Math")).Invoke("Abs", diff); var op = binaryOperatorExpression.Operator == BinaryOperatorType.Equality ? BinaryOperatorType.LessThan : BinaryOperatorType.GreaterThan; var epsilon = new IdentifierExpression ("EPSILON"); var compare = new BinaryOperatorExpression (abs, op, epsilon); script.Replace (binaryOperatorExpression, compare); script.Link (epsilon); }); } }
public override void VisitAssignmentExpression(AssignmentExpression expression) { base.VisitAssignmentExpression (expression); Identifier identifier = expression.FindIdentifier(); if (identifier == null) return; switch (expression.Operator) { case AssignmentOperatorType.BitwiseOr: case AssignmentOperatorType.BitwiseAnd: case AssignmentOperatorType.ExclusiveOr: case AssignmentOperatorType.Add: case AssignmentOperatorType.Subtract: case AssignmentOperatorType.Divide: case AssignmentOperatorType.Modulus: case AssignmentOperatorType.Multiply: case AssignmentOperatorType.ShiftLeft: case AssignmentOperatorType.ShiftRight: { BinaryOperatorType op = GetComplexAssignOperator (expression.Operator); Expression right = new BinaryOperatorExpression (new IdentifierExpression (identifier.Name), op, expression.Right.Clone()); expression.Operator = AssignmentOperatorType.Assign; expression.Right = GetAssignmentExpression (identifier, right); break; } case AssignmentOperatorType.Assign: expression.Right = GetAssignmentExpression (identifier, expression.Right); break; } }
public void OrIsShortcircuit() { IExpression trueexpr = new ConstantExpression(true); IExpression dividebyzero = new BinaryOperatorExpression(new ConstantExpression(1), new ConstantExpression(0), BinaryOperator.Divide); Assert.IsTrue((bool)(new BooleanExpression(trueexpr, dividebyzero, BooleanOperator.Or)).Evaluate(null)); }
Expression GenerateTarget(RefactoringContext context, BinaryOperatorExpression bOp) { var rr = context.Resolver.GetResolverStateBefore(bOp).LookupSimpleNameOrTypeName("Equals", emptyTypes, NameLookupMode.Expression) as MethodGroupResolveResult; if (rr == null || rr.IsError || HasDifferentEqualsMethod (rr.Methods)) { return new PrimitiveType ("object").Member("Equals"); } return new IdentifierExpression("Equals"); }
public void EvaluateSubtractExpression() { BinaryExpression expression = new BinaryOperatorExpression(new ConstantExpression(1), new ConstantExpression(2), BinaryOperator.Subtract); Assert.IsNotNull(expression); Assert.IsNotNull(expression.Left); Assert.IsNotNull(expression.Right); Assert.AreEqual(-1, expression.Evaluate(new BindingEnvironment())); }
public void EvaluateMultiplyExpressionWithLeftString() { BinaryExpression expression = new BinaryOperatorExpression(new ConstantExpression("spam"), new ConstantExpression(3), BinaryOperator.Multiply); Assert.IsNotNull(expression); Assert.IsNotNull(expression.Left); Assert.IsNotNull(expression.Right); Assert.AreEqual("spamspamspam", expression.Evaluate(new BindingEnvironment())); }
public void EvaluateDivideToFloatExpression() { BinaryExpression expression = new BinaryOperatorExpression(new ConstantExpression(4), new ConstantExpression(5), BinaryOperator.Divide); Assert.IsNotNull(expression); Assert.IsNotNull(expression.Left); Assert.IsNotNull(expression.Right); Assert.AreEqual(0.8, expression.Evaluate(new BindingEnvironment())); }
static VariableInitializer GetControlVariable(VariableDeclarationStatement variableDecl, BinaryOperatorExpression condition) { var controlVariables = variableDecl.Variables.Where ( v => { var identifier = new IdentifierExpression (v.Name); return condition.Left.Match (identifier).Success || condition.Right.Match (identifier).Success; }).ToList (); return controlVariables.Count == 1 ? controlVariables [0] : null; }
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { bool leftdangerous = false; bool rightdangerous = false; if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { if (binaryOperatorExpression.Left is PrimitiveExpression) { PrimitiveExpression prim = (PrimitiveExpression)binaryOperatorExpression.Left; if (prim.Value.GetType() == typeof(double) || prim.Value.GetType() == typeof(float) || prim.Value.GetType() == typeof(decimal)) { leftdangerous = true; } } else if (binaryOperatorExpression.Left is IdentifierExpression) { IdentifierExpression idexpr = (IdentifierExpression)binaryOperatorExpression.Left; if (doublefloatvariables.Contains(idexpr.Identifier)) { leftdangerous = true; } } if (binaryOperatorExpression.Right is PrimitiveExpression) { PrimitiveExpression prim = (PrimitiveExpression)binaryOperatorExpression.Right; if (prim.Value.GetType() == typeof(double) || prim.Value.GetType() == typeof(float) || prim.Value.GetType() == typeof(decimal)) { rightdangerous = true; } } else if (binaryOperatorExpression.Right is IdentifierExpression) { IdentifierExpression idexpr = (IdentifierExpression)binaryOperatorExpression.Right; if (doublefloatvariables.Contains(idexpr.Identifier)) { rightdangerous = true; } } if (leftdangerous || rightdangerous) { UnlockWith(binaryOperatorExpression); } } return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); }
internal static Expression GetRightSide(BinaryOperatorExpression expression) { var parent = expression.Parent as BinaryOperatorExpression; if (parent != null) { if (parent.Left == expression) { var parentClone = (BinaryOperatorExpression)parent.Clone(); parentClone.Left = expression.Right.Clone(); return parentClone; } } return expression.Right.Clone(); }
void AddIsNaNIssue(BinaryOperatorExpression binaryOperatorExpr, Expression argExpr, string floatType) { if (ctx.Resolve (argExpr).Type.ReflectionName != "System.Single") floatType = "double"; AddIssue (binaryOperatorExpr, string.Format(ctx.TranslateString ("Use {0}.IsNan()"), floatType), script => { Expression expr = new InvocationExpression (new MemberReferenceExpression ( new TypeReferenceExpression (new PrimitiveType (floatType)), "IsNaN"), argExpr.Clone ()); if (binaryOperatorExpr.Operator == BinaryOperatorType.InEquality) expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr); script.Replace (binaryOperatorExpr, expr); }); }
static CodeAction CreateAndSplit(RefactoringContext context, IfElseStatement ifStatement, BinaryOperatorExpression bOp) { return new CodeAction( context.TranslateString("Split if"), script => { var nestedIf = (IfElseStatement)ifStatement.Clone(); nestedIf.Condition = GetRightSide(bOp); script.Replace(ifStatement.Condition, GetLeftSide(bOp)); script.Replace(ifStatement.TrueStatement, new BlockStatement { nestedIf }); }, bOp.OperatorToken ); }
public override void VisitConditionalExpression(ConditionalExpression conditionalExpression) { Match m = pattern.Match(conditionalExpression); if (m.Success) { var a = m.Get<Expression>("a").Single(); var other = m.Get<Expression>("other").Single(); AddIssue(conditionalExpression, ctx.TranslateString("Convert to '??' expression"), script => { var expr = new BinaryOperatorExpression (a.Clone (), BinaryOperatorType.NullCoalescing, other.Clone ()); script.Replace (conditionalExpression, expr); }); } base.VisitConditionalExpression (conditionalExpression); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression(binaryOperatorExpression); var left = binaryOperatorExpression.Left; var right = binaryOperatorExpression.Right; if (left is IdentifierExpression && right is IdentifierExpression) { var leftIdent = (left as IdentifierExpression).Identifier; var rightIdent = (right as IdentifierExpression).Identifier; if (leftIdent == rightIdent) { if (binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { binaryOperatorExpression.ReplaceWith(new PrimitiveExpression(0)); return; } } } if (right is PrimitiveExpression && (right as PrimitiveExpression).Value is int && (int)(right as PrimitiveExpression).Value == 0) { if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { binaryOperatorExpression.ReplaceWith(left); return; } } if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd) { if (ReplaceConditionalAnd(binaryOperatorExpression, left, right) || ReplaceConditionalAnd(binaryOperatorExpression, right, left)) return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr) { if (ReplaceConditionalOr(binaryOperatorExpression, left, right) || ReplaceConditionalOr(binaryOperatorExpression, right, left)) return; } }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return true; } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable.lift("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] {binaryOperatorExpression.Left, binaryOperatorExpression.Right}, null).Emit(); this.WriteCloseParentheses(); return true; } } return false; }
static CodeAction CreateOrSplit(RefactoringContext context, IfElseStatement ifStatement, BinaryOperatorExpression bOp) { return new CodeAction( context.TranslateString("Split if"), script => { var newElse = (IfElseStatement)ifStatement.Clone(); newElse.Condition = GetRightSide(bOp); var newIf = (IfElseStatement)ifStatement.Clone(); newIf.Condition = GetLeftSide(bOp); newIf.FalseStatement = newElse; script.Replace(ifStatement, newIf); script.FormatText(newIf); }, bOp.OperatorToken ); }
// The following conversions are implemented: // a == null -> a Is Nothing // a != null -> a Is Not Nothing // i++ / ++i as statement: convert to i += 1 // i-- / --i as statement: convert to i -= 1 // ForStatement -> ForNextStatement when for-loop is simple // if (Event != null) Event(this, bla); -> RaiseEvent Event(this, bla) // Casts to value types are marked as conversions public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { if (binaryOperatorExpression.Op == BinaryOperatorType.Equality || binaryOperatorExpression.Op == BinaryOperatorType.InEquality) { if (IsNullLiteralExpression(binaryOperatorExpression.Left)) { Expression tmp = binaryOperatorExpression.Left; binaryOperatorExpression.Left = binaryOperatorExpression.Right; binaryOperatorExpression.Right = tmp; } if (IsNullLiteralExpression(binaryOperatorExpression.Right)) { if (binaryOperatorExpression.Op == BinaryOperatorType.Equality) { binaryOperatorExpression.Op = BinaryOperatorType.ReferenceEquality; } else { binaryOperatorExpression.Op = BinaryOperatorType.ReferenceInequality; } } } return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); }
public ArgumentsInfo(IEmitter emitter, BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult operatorResolveResult) { this.Emitter = emitter; this.Expression = binaryOperatorExpression; this.OperatorResolveResult = operatorResolveResult; if (operatorResolveResult.UserDefinedOperatorMethod != null) { this.BuildOperatorArgumentsList(new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }); this.BuildOperatorTypedArguments(); } else { this.ArgumentsExpressions = new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }; this.ArgumentsNames = new string[] { "left", "right" }; this.CreateNamedExpressions(this.ArgumentsNames, this.ArgumentsExpressions); } }
public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression (binaryOperatorExpression); var match = pattern.Match (binaryOperatorExpression); if (!match.Success) return; AddIssue (binaryOperatorExpression, ctx.TranslateString ("Simplify boolean comparison"), scrpit => { var expr = match.Get<Expression> ("expr").First ().Clone (); var boolConstant = (bool)match.Get<PrimitiveExpression> ("const").First ().Value; if ((binaryOperatorExpression.Operator == BinaryOperatorType.InEquality && boolConstant) || (binaryOperatorExpression.Operator == BinaryOperatorType.Equality && !boolConstant)) { expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr); expr.AcceptVisitor (insertParenthesesVisitor); } scrpit.Replace (binaryOperatorExpression, expr); }); }
public void AdditionWithConditional() { Expression expr = new BinaryOperatorExpression { Left = new IdentifierExpression("a"), Operator = BinaryOperatorType.Add, Right = new ConditionalExpression { Condition = new BinaryOperatorExpression { Left = new IdentifierExpression("b"), Operator = BinaryOperatorType.Equality, Right = new PrimitiveExpression(null) }, TrueExpression = new IdentifierExpression("c"), FalseExpression = new IdentifierExpression("d") } }; Assert.AreEqual("a + (b == null ? c : d)", InsertRequired(expr)); Assert.AreEqual("a + ((b == null) ? c : d)", InsertReadable(expr)); }
public override Expression Visit(BinaryOperatorExpression expression) { var left = expression.Left.Accept(this); var right = expression.Right.Accept(this); var leftNum = left as NumberExpression; var rightNum = right as NumberExpression; if (leftNum == null && rightNum == null) return new BinaryOperatorExpression(expression.Start, left, right); // n <op> n Func<int, int, int> simplifyOp; if (_simplifyMap.TryGetValue(expression.Operation, out simplifyOp) && leftNum != null && rightNum != null) { try { var result = simplifyOp(leftNum.Value, rightNum.Value); var token = new LoonyToken(expression.Start, LoonyTokenType.Number, null); return new NumberExpression(token, result); } catch (DivideByZeroException) { throw new CompilerException(expression.Start, CompilerError.DivisionByZero); } } // 0 + e || e + 0 if (expression.Operation == LoonyTokenType.Add) { if (leftNum != null && leftNum.Value == 0) return right; if (rightNum != null && rightNum.Value == 0) return left; } return new BinaryOperatorExpression(expression.Start, left, right); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression(binaryOperatorExpression); // Looking for patterns like: // // 2 - 2 var valueLeft = AstHelpers.GetValueFromExpression(binaryOperatorExpression.Left); var valueRight = AstHelpers.GetValueFromExpression(binaryOperatorExpression.Right); if (valueLeft == null || valueRight == null) return; try { dynamic valueResult; switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: valueResult = valueLeft + valueRight; break; case BinaryOperatorType.Subtract: valueResult = valueLeft - valueRight; break; case BinaryOperatorType.Divide: valueResult = valueLeft / valueRight; break; case BinaryOperatorType.Multiply: valueResult = valueLeft * valueRight; break; default: return; } binaryOperatorExpression.ReplaceWith(new PrimitiveExpression(valueResult)); } catch (Exception) { // Can't do anything with this value perhaps, so just ignore it and leave // the code as-is. } }
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { bool lhs = binaryOperatorExpression.Left.AcceptVisitor(this, data) == SymbolDefined; bool rhs = binaryOperatorExpression.Right.AcceptVisitor(this, data) == SymbolDefined; bool result; switch (binaryOperatorExpression.Op) { case BinaryOperatorType.LogicalAnd: result = lhs && rhs; break; case BinaryOperatorType.LogicalOr: result = lhs || rhs; break; case BinaryOperatorType.Equality: result = lhs == rhs; break; case BinaryOperatorType.InEquality: result = lhs != rhs; break; default: return null; } return result ? SymbolDefined : null; }
public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression (binaryOperatorExpression); var match = pattern.Match (binaryOperatorExpression); if (!match.Success) return; var expr = match.First<Expression>("expr"); // check if expr is of boolean type var exprType = ctx.Resolve (expr).Type.GetDefinition (); if (exprType == null || exprType.KnownTypeCode != KnownTypeCode.Boolean) return; AddIssue (binaryOperatorExpression, ctx.TranslateString ("Simplify boolean comparison"), scrpit => { var boolConstant = (bool)match.First<PrimitiveExpression>("const").Value; if ((binaryOperatorExpression.Operator == BinaryOperatorType.InEquality && boolConstant) || (binaryOperatorExpression.Operator == BinaryOperatorType.Equality && !boolConstant)) { expr = new UnaryOperatorExpression (UnaryOperatorType.Not, expr.Clone()); expr.AcceptVisitor (insertParenthesesVisitor); } scrpit.Replace (binaryOperatorExpression, expr); }); }
public ExpressionTree(ParseInfo parseInfo, Scope scope, BinaryOperatorExpression exprContext, bool usedAsValue) { _parseInfo = parseInfo; ExprContextTree = Flatten(parseInfo.Script, exprContext); // Setup var usageResolvers = new UsageResolver[ExprContextTree.Length]; for (int i = 0; i < ExprContextTree.Length; i++) { usageResolvers[i] = new UsageResolver(); ParseInfo partInfo = parseInfo.SetUsageResolver(usageResolvers[i], i == 0 ? null : usageResolvers[i - 1]); // If this is not the first expression, clear tail data and set the source expression. if (i != 0) { partInfo = partInfo.ClearTail().SetSourceExpression(ExprContextTree[i - 1]); } // If this is not the last expression, clear head data. if (i != ExprContextTree.Length - 1) { partInfo = partInfo.ClearHead(); } ExprContextTree[i].Setup(new TreeContextParseInfo() { ParseInfo = partInfo, Getter = scope, Scope = i == 0 ? scope : ExprContextTree[i - 1].GetScope() ?? new Scope(), Parent = i == 0 ? null : ExprContextTree[i - 1], UsedAsExpression = usedAsValue || i < ExprContextTree.Length - 1, IsLast = i == ExprContextTree.Length - 1 }); } for (int i = 0; i < usageResolvers.Length; i++) { usageResolvers[i].ResolveUnknownIfNotResolved(); } // Get expressions Tree = new IExpression[ExprContextTree.Length]; IExpression current = ExprContextTree[0].GetExpression(); Tree[0] = current; if (current != null) { for (int i = 1; i < ExprContextTree.Length; i++) { current = ExprContextTree[i].GetExpression(); Tree[i] = current; if (current == null) { Completed = false; break; } } } else { Completed = false; } if (Completed) { Result = Tree[Tree.Length - 1]; } // Get the completion items for each expression in the path. GetCompletion(parseInfo, scope); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { binaryOperatorExpression.Left.AcceptVisitor(this); binaryOperatorExpression.Right.AcceptVisitor(this); }
void ProcessInvocationExpression(InvocationExpression invocationExpression) { var method = invocationExpression.GetSymbol() as IMethod; if (method == null) { return; } var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" if (method.Name == "Concat" && method.DeclaringType.FullName == "System.String" && CheckArgumentsForStringConcat(arguments)) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression Expression expr = arguments[0]; for (int i = 1; i < arguments.Length; i++) { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]); } expr.CopyAnnotationsFrom(invocationExpression); invocationExpression.ReplaceWith(expr); return; } switch (method.FullName) { case "System.Type.GetTypeFromHandle": if (arguments.Length == 1) { if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) { Expression target = ((MemberReferenceExpression)arguments[0]).Target; target.CopyInstructionsFrom(invocationExpression); invocationExpression.ReplaceWith(target); return; } } break; /* * case "System.Reflection.FieldInfo.GetFieldFromHandle": * // TODO : This is dead code because LdTokenAnnotation is not added anywhere: * if (arguments.Length == 1) { * MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression; * if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation<LdTokenAnnotation>() != null) { * invocationExpression.ReplaceWith(mre.Target); * return; * } * } else if (arguments.Length == 2) { * MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression; * MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression; * if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation<LdTokenAnnotation>() != null) { * if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) { * Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single(); * FieldReference field = oldArg.Annotation<FieldReference>(); * if (field != null) { * AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach(); * oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg)); * invocationExpression.ReplaceWith(mre1.Target); * return; * } * } * } * } * break; */ case "System.Activator.CreateInstance": if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0])) { invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First()))); } break; } BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(method.Name); if (bop != null && arguments.Length == 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression invocationExpression.ReplaceWith( new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).CopyAnnotationsFrom(invocationExpression) ); return; } UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(method.Name); if (uop != null && arguments.Length == 1) { if (uop == UnaryOperatorType.Increment || uop == UnaryOperatorType.Decrement) { // `op_Increment(a)` is not equivalent to `++a`, // because it doesn't assign the incremented value to a. if (method.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) { // Legacy csc optimizes "d + 1m" to "op_Increment(d)", // so reverse that optimization here: invocationExpression.ReplaceWith( new BinaryOperatorExpression( arguments[0].Detach(), (uop == UnaryOperatorType.Increment ? BinaryOperatorType.Add : BinaryOperatorType.Subtract), new PrimitiveExpression(1m) ).CopyAnnotationsFrom(invocationExpression) ); } return; } arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new UnaryOperatorExpression(uop.Value, arguments[0]).CopyAnnotationsFrom(invocationExpression) ); return; } if (method.Name == "op_Explicit" && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.ReturnType), arguments[0]) .CopyAnnotationsFrom(invocationExpression) ); return; } if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) { invocationExpression.ReplaceWith(arguments[0]); return; } return; }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { new BinaryOperatorBlock(this, binaryOperatorExpression).Emit(); }
protected void VisitBinaryOperatorExpression() { BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression; if (this.Emitter.IsAsync && ( binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr || binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr || binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd ) && this.GetAwaiters(binaryOperatorExpression).Length > 0) { if (this.Emitter.AsyncBlock.WrittenAwaitExpressions.Contains(binaryOperatorExpression)) { var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, binaryOperatorExpression) + 1; this.Write(JS.Vars.ASYNC_TASK_RESULT + index); } else { var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, binaryOperatorExpression) + 1; this.WriteAsyncBinaryExpression(index); } return; } var resolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; var leftResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter); var charToString = -1; string variable = null; bool leftIsNull = this.BinaryOperatorExpression.Left is NullReferenceExpression; bool rightIsNull = this.BinaryOperatorExpression.Right is NullReferenceExpression; bool isUint = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64); var isFloatResult = Helpers.IsFloatType(resolveOperator.Type, this.Emitter.Resolver); var leftExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left); var rightExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right); var strictNullChecks = this.Emitter.AssemblyInfo.StrictNullChecks; if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } var resultIsString = expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String); var isStringConcat = resultIsString && binaryOperatorExpression.Operator == BinaryOperatorType.Add; var toStringForLeft = false; var toStringForRight = false; var parentBinary = binaryOperatorExpression.Parent as BinaryOperatorExpression; bool parentIsString = resultIsString && parentBinary != null && parentBinary.Operator == BinaryOperatorType.Add; if (parentIsString) { var parentResolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Parent, this.Emitter) as OperatorResolveResult; if (parentResolveOperator != null && parentResolveOperator.UserDefinedOperatorMethod != null) { parentIsString = false; } } bool isSimpleConcat = isStringConcat && BinaryOperatorBlock.IsOperatorSimple(binaryOperatorExpression, this.Emitter); if (charToString == -1 && isStringConcat && !leftResolverResult.Type.IsKnownType(KnownTypeCode.String)) { toStringForLeft = true; } if (charToString == -1 && isStringConcat && !rightResolverResult.Type.IsKnownType(KnownTypeCode.String)) { toStringForRight = true; } if (!isStringConcat && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver))) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { this.HandleDecimal(resolveOperator); return; } var isLeftLong = Helpers.Is64Type(leftExpected, this.Emitter.Resolver); var isRightLong = Helpers.Is64Type(rightExpected, this.Emitter.Resolver); if (!isLeftLong && !isRightLong) { if (leftExpected.Kind == TypeKind.Enum && Helpers.Is64Type(leftExpected.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver)) { isLeftLong = true; } if (rightExpected.Kind == TypeKind.Enum && Helpers.Is64Type(rightExpected.GetDefinition().EnumUnderlyingType, this.Emitter.Resolver)) { isRightLong = true; } } if (!(resultIsString && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (isLeftLong || isRightLong)) { isLong = true; isLongExpected = true; } if (isLong && isLongExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { if (!isFloatResult || binaryOperatorExpression.Operator == BinaryOperatorType.Divide && isLeftLong) { this.HandleLong(resolveOperator, isUint); return; } } var delegateOperator = false; if (this.ResolveOperator(binaryOperatorExpression, orr)) { return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality) { if (leftIsNull || rightIsNull) { this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { this.Write(strictNullChecks ? " === " : " == "); } else { this.Write(strictNullChecks ? " !== " : " != "); } this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); return; } } var insideOverflowContext = ConversionBlock.InsideOverflowContext(this.Emitter, binaryOperatorExpression); if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && !(this.Emitter.IsJavaScriptOverflowMode && !insideOverflowContext) && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) )) { this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "("); this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); this.Write(", "); this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Multiply && !(this.Emitter.IsJavaScriptOverflowMode && !insideOverflowContext) && ( (Helpers.IsInteger32Type(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(rightResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(resolveOperator.Type, this.Emitter.Resolver)) || (Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver) && Helpers.IsInteger32Type(resolveOperator.Type, this.Emitter.Resolver)) )) { isUint = NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.UInt32); this.Write(JS.Types.BRIDGE_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "("); this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); this.Write(", "); this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); if (ConversionBlock.IsInCheckedContext(this.Emitter, this.BinaryOperatorExpression)) { this.Write(", 1"); } this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add; if (expectedType.Kind == TypeKind.Delegate || this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult)) { delegateOperator = true; this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE); this.WriteOpenParentheses(); } } if (isStringConcat && !parentIsString && !isSimpleConcat) { this.Write(JS.Types.System.String.CONCAT); this.WriteOpenParentheses(); } bool nullable = orr != null && orr.IsLiftedOperator; bool isCoalescing = (this.Emitter.AssemblyInfo.StrictNullChecks || NullableType.IsNullable(leftResolverResult.Type) || leftResolverResult.Type.IsKnownType(KnownTypeCode.String) || leftResolverResult.Type.IsKnownType(KnownTypeCode.Object) ) && binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing; string root = JS.Types.SYSTEM_NULLABLE + "."; bool special = nullable; bool rootSpecial = nullable; bool isBool = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean); bool toBool = isBool && !rootSpecial && !delegateOperator && (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr); bool isRefEquals = !isCoalescing && !strictNullChecks && (binaryOperatorExpression.Operator == BinaryOperatorType.InEquality || binaryOperatorExpression.Operator == BinaryOperatorType.Equality) && leftExpected.IsReferenceType.HasValue && leftExpected.IsReferenceType.Value && rightExpected.IsReferenceType.HasValue && rightExpected.IsReferenceType.Value; if (rootSpecial) { this.Write(root); } else if (!isRefEquals) { if (isCoalescing) { this.Write("("); variable = this.GetTempVarName(); this.Write(variable); this.Write(" = "); } else if (charToString == 0) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } if (toBool) { this.Write("!!("); } this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult, isCoalescing); if (isCoalescing) { this.Write(", "); this.Write(variable); this.Write(strictNullChecks ? " !== null" : " != null"); this.Write(" ? "); ConversionBlock.expressionMap.Add(binaryOperatorExpression.Left, variable); //this.Write(variable); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); ConversionBlock.expressionMap.Remove(binaryOperatorExpression.Left); } else if (charToString == 0) { this.Write(")"); } } if (isRefEquals) { if (binaryOperatorExpression.Operator == BinaryOperatorType.InEquality) { this.Write("!"); } this.Write(JS.Funcs.BRIDGE_REFERENCEEQUALS); special = true; } if (!delegateOperator && (!isStringConcat || isSimpleConcat)) { if (!special) { this.WriteSpace(); } switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: this.Write(rootSpecial ? JS.Funcs.Math.ADD : "+"); break; case BinaryOperatorType.BitwiseAnd: if (isBool) { this.Write(rootSpecial ? JS.Funcs.Math.AND : "&"); } else { this.Write(rootSpecial ? JS.Funcs.Math.BAND : "&"); } break; case BinaryOperatorType.BitwiseOr: if (isBool) { this.Write(rootSpecial ? JS.Funcs.Math.OR : "|"); } else { this.Write(rootSpecial ? JS.Funcs.Math.BOR : "|"); } break; case BinaryOperatorType.ConditionalAnd: this.Write(rootSpecial ? JS.Funcs.Math.AND : "&&"); break; case BinaryOperatorType.NullCoalescing: this.Write(isCoalescing ? ":" : "||"); break; case BinaryOperatorType.ConditionalOr: this.Write(rootSpecial ? JS.Funcs.Math.OR : "||"); break; case BinaryOperatorType.Divide: this.Write(rootSpecial ? JS.Funcs.Math.DIV : "/"); break; case BinaryOperatorType.Equality: if (!isRefEquals) { this.Write(rootSpecial ? "eq" : "==="); } break; case BinaryOperatorType.ExclusiveOr: this.Write(rootSpecial ? JS.Funcs.Math.XOR : "^"); break; case BinaryOperatorType.GreaterThan: this.Write(rootSpecial ? JS.Funcs.Math.GT : ">"); break; case BinaryOperatorType.GreaterThanOrEqual: this.Write(rootSpecial ? JS.Funcs.Math.GTE : ">="); break; case BinaryOperatorType.InEquality: if (!isRefEquals) { this.Write(rootSpecial ? "neq" : "!=="); } break; case BinaryOperatorType.LessThan: this.Write(rootSpecial ? JS.Funcs.Math.LT : "<"); break; case BinaryOperatorType.LessThanOrEqual: this.Write(rootSpecial ? JS.Funcs.Math.LTE : "<="); break; case BinaryOperatorType.Modulus: this.Write(rootSpecial ? JS.Funcs.Math.MOD : "%"); break; case BinaryOperatorType.Multiply: this.Write(rootSpecial ? JS.Funcs.Math.MUL : "*"); break; case BinaryOperatorType.ShiftLeft: this.Write(rootSpecial ? JS.Funcs.Math.SL : "<<"); break; case BinaryOperatorType.ShiftRight: if (isUint) { this.Write(rootSpecial ? JS.Funcs.Math.SRR : ">>>"); } else { this.Write(rootSpecial ? JS.Funcs.Math.SR : ">>"); } break; case BinaryOperatorType.Subtract: this.Write(rootSpecial ? JS.Funcs.Math.SUB : "-"); break; default: throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString()); } } else { this.WriteComma(); } if (special) { this.WriteOpenParentheses(); if (charToString == 0) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } this.WritePart(binaryOperatorExpression.Left, toStringForLeft, leftResolverResult); if (charToString == 0) { this.Write(")"); } this.WriteComma(); } else if (!delegateOperator && (!isStringConcat || isSimpleConcat)) { this.WriteSpace(); } if (charToString == 1) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } this.WritePart(binaryOperatorExpression.Right, toStringForRight, rightResolverResult); if (toBool) { this.WriteCloseParentheses(); } if (charToString == 1 || isCoalescing) { this.WriteCloseParentheses(); } if (delegateOperator || special || isStringConcat && !parentIsString && !isSimpleConcat) { this.WriteCloseParentheses(); } }
public void ParseOrAndExpressionTest2() { Action <string> testExpression = delegate(string condition) { IConditionExpression expression = ConditionExpressionParser.Instance.Parse( condition); Assert.IsNotNull(expression, "Expected an expression instance."); BinaryOperatorExpression operatorExpression = expression as BinaryOperatorExpression; Assert.IsNotNull(operatorExpression, "Expected an operator expression."); Assert.AreEqual(BinaryExpressionOperator.Or, operatorExpression.Operator, "Unexpected operator."); // // Or left // BinaryOperatorExpression testExpression1 = operatorExpression.Left as BinaryOperatorExpression; Assert.IsNotNull(testExpression1, "Expected an operator expression."); Assert.AreEqual(BinaryExpressionOperator.Equal, testExpression1.Operator, "Unexpected operator."); ElementAttributeExpression test1AttributeExpression = testExpression1.Left as ElementAttributeExpression; Assert.IsNotNull(test1AttributeExpression, "Unexpected left node type."); Assert.AreEqual(ElementAttributeType.Name, test1AttributeExpression.ElementAttribute, "Attribute expression was not parsed correctly."); StringExpression test1StringExpression = testExpression1.Right as StringExpression; Assert.IsNotNull(test1StringExpression, "Unexpected right node type."); Assert.AreEqual("Test 1", test1StringExpression.Text, "String expression was not parsed correctly."); // // Or right // BinaryOperatorExpression andExpression = operatorExpression.Right as BinaryOperatorExpression; Assert.IsNotNull(andExpression, "Expected an operator expression."); Assert.AreEqual(BinaryExpressionOperator.And, andExpression.Operator, "Unexpected operator."); // // And Left // BinaryOperatorExpression testExpression2 = andExpression.Left as BinaryOperatorExpression; Assert.IsNotNull(testExpression2, "Expected an operator expression."); Assert.AreEqual(BinaryExpressionOperator.Equal, testExpression2.Operator, "Unexpected operator."); ElementAttributeExpression test2AttributeExpression = testExpression2.Left as ElementAttributeExpression; Assert.IsNotNull(test2AttributeExpression, "Unexpected left node type."); Assert.AreEqual(ElementAttributeType.Name, test2AttributeExpression.ElementAttribute, "Attribute expression was not parsed correctly."); StringExpression test2StringExpression = testExpression2.Right as StringExpression; Assert.IsNotNull(test2StringExpression, "Unexpected right node type."); Assert.AreEqual("Test 2", test2StringExpression.Text, "String expression was not parsed correctly."); // // And Right // BinaryOperatorExpression testExpression3 = andExpression.Right as BinaryOperatorExpression; Assert.IsNotNull(testExpression3, "Expected an operator expression."); Assert.AreEqual(BinaryExpressionOperator.Equal, testExpression3.Operator, "Unexpected operator."); ElementAttributeExpression test3AttributeExpression = testExpression3.Left as ElementAttributeExpression; Assert.IsNotNull(test3AttributeExpression, "Unexpected left node type."); Assert.AreEqual(ElementAttributeType.Name, test3AttributeExpression.ElementAttribute, "Attribute expression was not parsed correctly."); StringExpression test3StringExpression = testExpression3.Right as StringExpression; Assert.IsNotNull(test3StringExpression, "Unexpected right node type."); Assert.AreEqual("Test 3", test3StringExpression.Text, "String expression was not parsed correctly."); }; string expressionText; expressionText = "(($(Name) == 'Test 1') Or (($(Name) == 'Test 2') And ($(Name) == 'Test 3')))"; testExpression(expressionText); expressionText = "$(Name) == 'Test 1' Or $(Name) == 'Test 2' And $(Name) == 'Test 3'"; testExpression(expressionText); }
public int Visit(BinaryOperatorExpression expression) { if (expression.Operation == ScriptTokenType.EqualTo || expression.Operation == ScriptTokenType.NotEqualTo) { var leftString = expression.Left as StringExpression; var rightString = expression.Right as StringExpression; if ((leftString != null && !leftString.IsSingleQuote) || (rightString != null && !rightString.IsSingleQuote)) { if (expression.Operation == ScriptTokenType.NotEqualTo) { _writer.Write("!"); } expression.Left.Accept(this); _writer.Write(".equals("); expression.Right.Accept(this); _writer.Write(")"); return(0); } } if (expression.Operation == ScriptTokenType.Assign) { var leftIndexer = expression.Left as IndexerExpression; if (leftIndexer != null) { var leftIdentifier = leftIndexer.Left as IdentifierExpression; if (leftIdentifier != null) { var type = GetType(leftIdentifier.Name); if (type != null && type.IsResizable) { _writer.Write(leftIdentifier.Name); _writer.Write(".set("); leftIndexer.Index.Accept(this); _writer.Write(", "); expression.Right.Accept(this); _writer.Write(")"); return(0); } } } var leftIdent = expression.Left as IdentifierExpression; var rightIdent = expression.Right as IdentifierExpression; if (expression.Parent == null && leftIdent != null && rightIdent != null) { var leftType = GetType(leftIdent.Name); var rightType = GetType(rightIdent.Name); if (leftType != null && rightType != null) { if (leftType.IsResizable && (rightType.IsArray && !rightType.IsResizable)) { // <vector> = <array> var result = ArrayToResizable(rightIdent.Name); _writer.Write("{0} = {1}", leftIdent.Name, result); return(0); } if ((leftType.IsArray && !leftType.IsResizable) && rightType.IsResizable) { // <array> = <vector> var result = ResizableToArray(rightIdent.Name, leftType); _writer.Write("{0} = {1}", leftIdent.Name, result); return(0); } } } } var needParens = expression.Parent != null; if (needParens) { _writer.Write("("); } expression.Left.Accept(this); _writer.Write(" "); _writer.Write(BinaryOperatorMap[expression.Operation]); _writer.Write(" "); expression.Right.Accept(this); if (needParens) { _writer.Write(")"); } return(0); }
/// <inheritdoc/> public virtual void VisitBinaryOperatorExpression(BinaryOperatorExpression syntax) { VisitNode(syntax); }
bool ExtractExpression (Statement statement, out Expression leftSide, out Expression rightSide) { ExpressionStatement expression = statement as ExpressionStatement; if (expression != null) { AssignmentExpression assignment = expression.Expression as AssignmentExpression; if (assignment != null) { if (assignment.Operator == AssignmentOperatorType.Add) { leftSide = assignment.Left; rightSide = assignment.Right; return true; } if (assignment.Operator == AssignmentOperatorType.Subtract) { leftSide = assignment.Left; rightSide = new UnaryOperatorExpression(UnaryOperatorType.Minus, assignment.Right.Clone()); return true; } leftSide = null; rightSide = null; return false; } UnaryOperatorExpression unary = expression.Expression as UnaryOperatorExpression; if (unary != null) { leftSide = unary.Expression; if (unary.Operator == UnaryOperatorType.Increment || unary.Operator == UnaryOperatorType.PostIncrement) { rightSide = new PrimitiveExpression(1); return true; } else if (unary.Operator == UnaryOperatorType.Decrement || unary.Operator == UnaryOperatorType.PostDecrement) { rightSide = new PrimitiveExpression(-1); return true; } else { leftSide = null; rightSide = null; return false; } } } if (statement is EmptyStatement || statement.IsNull) { leftSide = null; rightSide = null; return true; } BlockStatement block = statement as BlockStatement; if (block != null) { leftSide = null; rightSide = null; foreach (Statement child in block.Statements) { Expression newLeft, newRight; if (!ExtractExpression(child, out newLeft, out newRight)) { leftSide = null; rightSide = null; return false; } if (newLeft == null) { continue; } if (leftSide == null) { leftSide = newLeft; rightSide = newRight; } else if (SameNode(leftSide, newLeft)) { rightSide = new BinaryOperatorExpression(ParenthesizeIfNeeded(rightSide).Clone(), BinaryOperatorType.Add, ParenthesizeIfNeeded(newRight).Clone()); } else { return false; } } return true; } IfElseStatement condition = statement as IfElseStatement; if (condition != null) { Expression ifLeft, ifRight; if (!ExtractExpression(condition.TrueStatement, out ifLeft, out ifRight)) { leftSide = null; rightSide = null; return false; } Expression elseLeft, elseRight; if (!ExtractExpression(condition.FalseStatement, out elseLeft, out elseRight)) { leftSide = null; rightSide = null; return false; } if (ifLeft == null && elseLeft == null) { leftSide = null; rightSide = null; return true; } if (ifLeft != null && elseLeft != null && !SameNode(ifLeft, elseLeft)) { leftSide = null; rightSide = null; return false; } ifRight = ifRight ?? new PrimitiveExpression(0); elseRight = elseRight ?? new PrimitiveExpression(0); leftSide = ifLeft ?? elseLeft; rightSide = new ConditionalExpression(condition.Condition.Clone(), ifRight.Clone(), elseRight.Clone()); return true; } leftSide = null; rightSide = null; return false; }
public override void GenerateCode(List <AbstractNode> nodes, IList items) { TypeReference intReference = new TypeReference("System.Int32", true); MethodDeclaration method = new MethodDeclaration { Name = "GetHashCode", Modifier = Modifiers.Public | Modifiers.Override, TypeReference = intReference, Body = new BlockStatement() }; VariableDeclaration var; var = new VariableDeclaration("hashCode", new PrimitiveExpression(0, "0"), intReference); method.Body.AddChild(new LocalVariableDeclaration(var)); bool usePrimeMultiplication = currentClass.ProjectContent.Language == LanguageProperties.CSharp; BlockStatement hashCalculationBlock; if (usePrimeMultiplication) { hashCalculationBlock = new BlockStatement(); method.Body.AddChild(new UncheckedStatement(hashCalculationBlock)); } else { hashCalculationBlock = method.Body; } int fieldIndex = 0; Expression expr; foreach (IField field in currentClass.Fields) { if (field.IsStatic) { continue; } expr = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(field.Name), "GetHashCode")); if (usePrimeMultiplication) { int prime = largePrimes[fieldIndex++ % largePrimes.Length]; expr = new AssignmentExpression( new IdentifierExpression(var.Name), AssignmentOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(prime, prime.ToString()), BinaryOperatorType.Multiply, expr)); } else { expr = new AssignmentExpression(new IdentifierExpression(var.Name), AssignmentOperatorType.ExclusiveOr, expr); } if (IsValueType(field.ReturnType)) { hashCalculationBlock.AddChild(new ExpressionStatement(expr)); } else { hashCalculationBlock.AddChild(new IfElseStatement( new BinaryOperatorExpression(new IdentifierExpression(field.Name), BinaryOperatorType.ReferenceInequality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr) )); } } method.Body.AddChild(new ReturnStatement(new IdentifierExpression(var.Name))); nodes.Add(method); TypeReference boolReference = new TypeReference("System.Boolean", true); TypeReference objectReference = new TypeReference("System.Object", true); method = new MethodDeclaration { Name = "Equals", Modifier = Modifiers.Public | Modifiers.Override, TypeReference = boolReference }; method.Parameters.Add(new ParameterDeclarationExpression(objectReference, "obj")); method.Body = new BlockStatement(); TypeReference currentType = ConvertType(currentClass.DefaultReturnType); if (currentClass.ClassType == Dom.ClassType.Struct) { // return obj is CurrentType && Equals((CurrentType)obj); expr = new TypeOfIsExpression(new IdentifierExpression("obj"), currentType); expr = new ParenthesizedExpression(expr); expr = new BinaryOperatorExpression( expr, BinaryOperatorType.LogicalAnd, new InvocationExpression( new IdentifierExpression("Equals"), new List <Expression> { new CastExpression(currentType, new IdentifierExpression("obj"), CastType.Cast) })); method.Body.AddChild(new ReturnStatement(expr)); nodes.Add(method); // IEquatable implementation: method = new MethodDeclaration { Name = "Equals", Modifier = Modifiers.Public | Modifiers.Override, TypeReference = boolReference }; method.Parameters.Add(new ParameterDeclarationExpression(currentType, "other")); method.Body = new BlockStatement(); } else { method.Body.AddChild(new LocalVariableDeclaration(new VariableDeclaration( "other", new CastExpression(currentType, new IdentifierExpression("obj"), CastType.TryCast), currentType))); method.Body.AddChild(new IfElseStatement( new BinaryOperatorExpression(new IdentifierExpression("other"), BinaryOperatorType.ReferenceEquality, new PrimitiveExpression(null, "null")), new ReturnStatement(new PrimitiveExpression(false, "false")))); // expr = new BinaryOperatorExpression(new ThisReferenceExpression(), // BinaryOperatorType.ReferenceEquality, // new IdentifierExpression("obj")); // method.Body.AddChild(new IfElseStatement(expr, new ReturnStatement(new PrimitiveExpression(true, "true")))); } expr = null; foreach (IField field in currentClass.Fields) { if (field.IsStatic) { continue; } if (expr == null) { expr = TestEquality("other", field); } else { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.LogicalAnd, TestEquality("other", field)); } } method.Body.AddChild(new ReturnStatement(expr ?? new PrimitiveExpression(true, "true"))); nodes.Add(method); }
Expression ConvertEnumValue(IType type, long val) { ITypeDefinition enumDefinition = type.GetDefinition(); TypeCode enumBaseTypeCode = ReflectionHelper.GetTypeCode(enumDefinition.EnumUnderlyingType); foreach (IField field in enumDefinition.Fields) { if (field.IsConst && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false), val)) { return(ConvertType(type).Member(field.Name)); } } if (IsFlagsEnum(enumDefinition)) { long enumValue = val; Expression expr = null; long negatedEnumValue = ~val; // limit negatedEnumValue to the appropriate range switch (enumBaseTypeCode) { case TypeCode.Byte: case TypeCode.SByte: negatedEnumValue &= byte.MaxValue; break; case TypeCode.Int16: case TypeCode.UInt16: negatedEnumValue &= ushort.MaxValue; break; case TypeCode.Int32: case TypeCode.UInt32: negatedEnumValue &= uint.MaxValue; break; } Expression negatedExpr = null; foreach (IField field in enumDefinition.Fields.Where(fld => fld.IsConst)) { long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); if (fieldValue == 0) { continue; // skip None enum value } if ((fieldValue & enumValue) == fieldValue) { var fieldExpression = ConvertType(type).Member(field.Name); if (expr == null) { expr = fieldExpression; } else { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression); } enumValue &= ~fieldValue; } if ((fieldValue & negatedEnumValue) == fieldValue) { var fieldExpression = ConvertType(type).Member(field.Name); if (negatedExpr == null) { negatedExpr = fieldExpression; } else { negatedExpr = new BinaryOperatorExpression(negatedExpr, BinaryOperatorType.BitwiseOr, fieldExpression); } negatedEnumValue &= ~fieldValue; } } if (enumValue == 0 && expr != null) { if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) { return(expr); } } if (negatedEnumValue == 0 && negatedExpr != null) { return(new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr)); } } return(new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type))); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression(binaryOperatorExpression); if (binaryOperatorExpression.Operator != BinaryOperatorType.Equality && binaryOperatorExpression.Operator != BinaryOperatorType.InEquality) { return; } string floatType = GetFloatType(binaryOperatorExpression.Left, binaryOperatorExpression.Right); if (IsNaN(binaryOperatorExpression.Left)) { AddIsNaNIssue(binaryOperatorExpression, binaryOperatorExpression.Right, floatType); } else if (IsNaN(binaryOperatorExpression.Right)) { AddIsNaNIssue(binaryOperatorExpression, binaryOperatorExpression.Left, floatType); } else if (IsPositiveInfinity(binaryOperatorExpression.Left)) { AddIsPositiveInfinityIssue(binaryOperatorExpression, binaryOperatorExpression.Right, floatType); } else if (IsPositiveInfinity(binaryOperatorExpression.Right)) { AddIsPositiveInfinityIssue(binaryOperatorExpression, binaryOperatorExpression.Left, floatType); } else if (IsNegativeInfinity(binaryOperatorExpression.Left)) { AddIsNegativeInfinityIssue(binaryOperatorExpression, binaryOperatorExpression.Right, floatType); } else if (IsNegativeInfinity(binaryOperatorExpression.Right)) { AddIsNegativeInfinityIssue(binaryOperatorExpression, binaryOperatorExpression.Left, floatType); } else if (IsFloatingPoint(binaryOperatorExpression.Left) || IsFloatingPoint(binaryOperatorExpression.Right)) { if (IsConstantInfinity(binaryOperatorExpression.Left) || IsConstantInfinity(binaryOperatorExpression.Right)) { return; } if (IsZero(binaryOperatorExpression.Left)) { AddIsZeroIssue(binaryOperatorExpression, binaryOperatorExpression.Right); return; } if (IsZero(binaryOperatorExpression.Right)) { AddIsZeroIssue(binaryOperatorExpression, binaryOperatorExpression.Left); return; } AddIssue( binaryOperatorExpression, ctx.TranslateString("Comparison of floating point numbers can be unequal due to the differing precision of the two values."), ctx.TranslateString("Fix floating point number comparing. Compare a difference with epsilon."), script => { // Math.Abs(diff) op EPSILON var builder = ctx.CreateTypeSystemAstBuilder(binaryOperatorExpression); var diff = new BinaryOperatorExpression(binaryOperatorExpression.Left.Clone(), BinaryOperatorType.Subtract, binaryOperatorExpression.Right.Clone()); var abs = builder.ConvertType(new TopLevelTypeName("System", "Math")).Invoke("Abs", diff); var op = binaryOperatorExpression.Operator == BinaryOperatorType.Equality ? BinaryOperatorType.LessThan : BinaryOperatorType.GreaterThan; var epsilon = new IdentifierExpression("EPSILON"); var compare = new BinaryOperatorExpression(abs, op, epsilon); script.Replace(binaryOperatorExpression, compare); script.Select(epsilon); } ); } }
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) { base.VisitInvocationExpression(invocationExpression, data); MethodReference methodRef = invocationExpression.Annotation <MethodReference>(); if (methodRef == null) { return(null); } var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" if (methodRef != null && methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression Expression expr = arguments[0]; for (int i = 1; i < arguments.Length; i++) { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]); } invocationExpression.ReplaceWith(expr); return(null); } switch (methodRef.FullName) { case "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)": if (arguments.Length == 1) { if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) { invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target); return(null); } } break; } BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name); if (bop != null && arguments.Length == 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression invocationExpression.ReplaceWith( new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef) ); return(null); } UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name); if (uop != null && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new UnaryOperatorExpression(uop.Value, arguments[0]).WithAnnotation(methodRef) ); return(null); } if (methodRef.Name == "op_Explicit" && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( arguments[0].CastTo(AstBuilder.ConvertType(methodRef.ReturnType, methodRef.MethodReturnType)) .WithAnnotation(methodRef) ); return(null); } if (methodRef.Name == "op_Implicit" && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith(arguments[0]); return(null); } return(null); }
public BinaryOperatorBlock(IEmitter emitter, BinaryOperatorExpression binaryOperatorExpression) : base(emitter, binaryOperatorExpression) { this.Emitter = emitter; this.BinaryOperatorExpression = binaryOperatorExpression; }
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { binaryOperatorExpression.Left.Parent = binaryOperatorExpression; binaryOperatorExpression.Right.Parent = binaryOperatorExpression; return(base.VisitBinaryOperatorExpression(binaryOperatorExpression, data)); }
bool ExtractExpression(Statement statement, out Expression leftSide, out Expression rightSide) { ExpressionStatement expression = statement as ExpressionStatement; if (expression != null) { AssignmentExpression assignment = expression.Expression as AssignmentExpression; if (assignment != null) { if (assignment.Operator == AssignmentOperatorType.Add) { leftSide = assignment.Left; rightSide = assignment.Right; return(true); } if (assignment.Operator == AssignmentOperatorType.Subtract) { leftSide = assignment.Left; rightSide = new UnaryOperatorExpression(UnaryOperatorType.Minus, assignment.Right.Clone()); return(true); } leftSide = null; rightSide = null; return(false); } UnaryOperatorExpression unary = expression.Expression as UnaryOperatorExpression; if (unary != null) { leftSide = unary.Expression; if (unary.Operator == UnaryOperatorType.Increment || unary.Operator == UnaryOperatorType.PostIncrement) { rightSide = new PrimitiveExpression(1); return(true); } else if (unary.Operator == UnaryOperatorType.Decrement || unary.Operator == UnaryOperatorType.PostDecrement) { rightSide = new PrimitiveExpression(-1); return(true); } else { leftSide = null; rightSide = null; return(false); } } } if (statement is EmptyStatement || statement.IsNull) { leftSide = null; rightSide = null; return(true); } BlockStatement block = statement as BlockStatement; if (block != null) { leftSide = null; rightSide = null; foreach (Statement child in block.Statements) { Expression newLeft, newRight; if (!ExtractExpression(child, out newLeft, out newRight)) { leftSide = null; rightSide = null; return(false); } if (newLeft == null) { continue; } if (leftSide == null) { leftSide = newLeft; rightSide = newRight; } else if (SameNode(leftSide, newLeft)) { rightSide = new BinaryOperatorExpression(ParenthesizeIfNeeded(rightSide).Clone(), BinaryOperatorType.Add, ParenthesizeIfNeeded(newRight).Clone()); } else { return(false); } } return(true); } IfElseStatement condition = statement as IfElseStatement; if (condition != null) { Expression ifLeft, ifRight; if (!ExtractExpression(condition.TrueStatement, out ifLeft, out ifRight)) { leftSide = null; rightSide = null; return(false); } Expression elseLeft, elseRight; if (!ExtractExpression(condition.FalseStatement, out elseLeft, out elseRight)) { leftSide = null; rightSide = null; return(false); } if (ifLeft == null && elseLeft == null) { leftSide = null; rightSide = null; return(true); } if (ifLeft != null && elseLeft != null && !SameNode(ifLeft, elseLeft)) { leftSide = null; rightSide = null; return(false); } ifRight = ifRight ?? new PrimitiveExpression(0); elseRight = elseRight ?? new PrimitiveExpression(0); leftSide = ifLeft ?? elseLeft; rightSide = new ConditionalExpression(condition.Condition.Clone(), ifRight.Clone(), elseRight.Clone()); return(true); } leftSide = null; rightSide = null; return(false); }
public override object Visit(BinaryOperatorExpression expression, object data) { CodeBinaryOperatorType op = CodeBinaryOperatorType.Add; switch (expression.Op) { case BinaryOperatorType.Add: op = CodeBinaryOperatorType.Add; break; case BinaryOperatorType.BitwiseAnd: op = CodeBinaryOperatorType.BitwiseAnd; break; case BinaryOperatorType.BitwiseOr: op = CodeBinaryOperatorType.BitwiseOr; break; case BinaryOperatorType.LogicalAnd: op = CodeBinaryOperatorType.BooleanAnd; break; case BinaryOperatorType.LogicalOr: op = CodeBinaryOperatorType.BooleanOr; break; case BinaryOperatorType.Divide: case BinaryOperatorType.DivideInteger: op = CodeBinaryOperatorType.Divide; break; case BinaryOperatorType.GreaterThan: op = CodeBinaryOperatorType.GreaterThan; break; case BinaryOperatorType.GreaterThanOrEqual: op = CodeBinaryOperatorType.GreaterThanOrEqual; break; case BinaryOperatorType.Equality: op = CodeBinaryOperatorType.IdentityEquality; break; case BinaryOperatorType.InEquality: op = CodeBinaryOperatorType.IdentityInequality; break; case BinaryOperatorType.LessThan: op = CodeBinaryOperatorType.LessThan; break; case BinaryOperatorType.LessThanOrEqual: op = CodeBinaryOperatorType.LessThanOrEqual; break; case BinaryOperatorType.Modulus: op = CodeBinaryOperatorType.Modulus; break; case BinaryOperatorType.Multiply: op = CodeBinaryOperatorType.Multiply; break; case BinaryOperatorType.Subtract: op = CodeBinaryOperatorType.Subtract; break; //case BinaryOperatorType.ValueEquality: // op = CodeBinaryOperatorType.ValueEquality; // break; case BinaryOperatorType.ShiftLeft: case BinaryOperatorType.ShiftRight: // CodeDOM suxx op = CodeBinaryOperatorType.Multiply; break; case BinaryOperatorType.ReferenceEquality: op = CodeBinaryOperatorType.IdentityEquality; break; case BinaryOperatorType.ReferenceInequality: op = CodeBinaryOperatorType.IdentityInequality; break; case BinaryOperatorType.ExclusiveOr: // TODO ExclusiveOr op = CodeBinaryOperatorType.BitwiseAnd; break; } return(new CodeBinaryOperatorExpression((CodeExpression)expression.Left.AcceptVisitor(this, data), op, (CodeExpression)expression.Right.AcceptVisitor(this, data))); }
public override object Visit(BinaryOperatorExpression node) { switch (node.Operator) { case BinaryOperatorExpression.Operators.Multiply: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) * Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.Divide: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) / Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.Modulus: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) % Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.Add: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) + Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.Subtract: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) - Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.ShiftLeft: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) << Convert.ToInt32(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.ShiftRight: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) >> Convert.ToInt32(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.LessThan: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) < Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.GreaterThan: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) > Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.LessThanOrEqual: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) <= Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.GreaterThanOrEqual: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) >= Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.Equality: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) == Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.Inequality: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) != Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.BitwiseAnd: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) & Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.ExclusiveOr: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) ^ Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.BitwiseOr: return(Convert.ToInt64(node.Left.AcceptVisitor(this)) | Convert.ToInt64(node.Right.AcceptVisitor(this))); case BinaryOperatorExpression.Operators.LogicalAnd: return((Convert.ToInt64(node.Left.AcceptVisitor(this)) & Convert.ToInt64(node.Right.AcceptVisitor(this))) == 0 ? 0L : 1L); case BinaryOperatorExpression.Operators.LogicalOr: return((Convert.ToInt64(node.Left.AcceptVisitor(this)) | Convert.ToInt64(node.Right.AcceptVisitor(this))) == 0 ? 0L : 1L); case BinaryOperatorExpression.Operators.Invalid: default: break; } return(null); }
public RestoreOriginalAssignOperatorAnnotation(BinaryOperatorExpression binaryOperatorExpression) { this.binaryOperatorExpression = binaryOperatorExpression; }
Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool?isChecked = null) { if (invocation.Arguments.Count < 2) { return(NotSupported(invocation)); } Expression left = Convert(invocation.Arguments.ElementAt(0)); if (left == null) { return(null); } Expression right = Convert(invocation.Arguments.ElementAt(1)); if (right == null) { return(null); } BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right); if (isChecked != null) { boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation); } switch (invocation.Arguments.Count) { case 2: return(boe); case 3: Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2)); if (m.Success) { return(boe.WithAnnotation(m.Get <AstNode>("method").Single().Annotation <IMethod>())); } else { return(null); } case 4: if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2))) { return(null); } m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3)); if (m.Success) { return(boe.WithAnnotation(m.Get <AstNode>("method").Single().Annotation <IMethod>())); } else { return(null); } default: return(NotSupported(invocation)); } }
internal static void ProcessInvocationExpression(InvocationExpression invocationExpression) { MethodReference methodRef = invocationExpression.Annotation <MethodReference>(); if (methodRef == null) { return; } var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" if (methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression Expression expr = arguments[0]; for (int i = 1; i < arguments.Length; i++) { expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]); } invocationExpression.ReplaceWith(expr); return; } switch (methodRef.FullName) { case "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)": if (arguments.Length == 1) { if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) { invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target); return; } } break; case "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle)": if (arguments.Length == 1) { MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression; if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation <LdTokenAnnotation>() != null) { invocationExpression.ReplaceWith(mre.Target); return; } } break; case "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle,System.RuntimeTypeHandle)": if (arguments.Length == 2) { MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression; MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression; if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation <LdTokenAnnotation>() != null) { if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) { Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single(); FieldReference field = oldArg.Annotation <FieldReference>(); if (field != null) { AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach(); oldArg.ReplaceWith(declaringType.Member(field.Name).WithAnnotation(field)); invocationExpression.ReplaceWith(mre1.Target); return; } } } } break; } BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name); if (bop != null && arguments.Length == 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression invocationExpression.ReplaceWith( new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef) ); return; } UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name); if (uop != null && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new UnaryOperatorExpression(uop.Value, arguments[0]).WithAnnotation(methodRef) ); return; } if (methodRef.Name == "op_Explicit" && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( arguments[0].CastTo(AstBuilder.ConvertType(methodRef.ReturnType, methodRef.MethodReturnType)) .WithAnnotation(methodRef) ); return; } if (methodRef.Name == "op_Implicit" && arguments.Length == 1) { invocationExpression.ReplaceWith(arguments[0]); return; } if (methodRef.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) { invocationExpression.ReplaceWith(arguments[0]); return; } return; }
public override DefiniteAssignmentStatus VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, DefiniteAssignmentStatus data) { if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd) { // Handle constant left side of && expressions (not in the C# spec, but done by the MS compiler) bool?cond = analysis.EvaluateCondition(binaryOperatorExpression.Left); if (cond == true) { return(binaryOperatorExpression.Right.AcceptVisitor(this, data)); // right operand gets evaluated unconditionally } else if (cond == false) { return(data); // right operand never gets evaluated } // C# 4.0 spec: §5.3.3.24 Definite Assignment for && expressions DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data); DefiniteAssignmentStatus beforeRight; if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned; } else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned; } else { beforeRight = afterLeft; } DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight); if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned) { return(DefiniteAssignmentStatus.DefinitelyAssigned); } else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { return(DefiniteAssignmentStatus.DefinitelyAssigned); } else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { return(DefiniteAssignmentStatus.AssignedAfterTrueExpression); } else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { return(DefiniteAssignmentStatus.AssignedAfterFalseExpression); } else { return(DefiniteAssignmentStatus.PotentiallyAssigned); } } else if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr) { // C# 4.0 spec: §5.3.3.25 Definite Assignment for || expressions bool?cond = analysis.EvaluateCondition(binaryOperatorExpression.Left); if (cond == false) { return(binaryOperatorExpression.Right.AcceptVisitor(this, data)); // right operand gets evaluated unconditionally } else if (cond == true) { return(data); // right operand never gets evaluated } DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data); DefiniteAssignmentStatus beforeRight; if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned; } else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned; } else { beforeRight = afterLeft; } DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight); if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned) { return(DefiniteAssignmentStatus.DefinitelyAssigned); } else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { return(DefiniteAssignmentStatus.DefinitelyAssigned); } else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { return(DefiniteAssignmentStatus.AssignedAfterFalseExpression); } else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { return(DefiniteAssignmentStatus.AssignedAfterTrueExpression); } else { return(DefiniteAssignmentStatus.PotentiallyAssigned); } } else if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) { // C# 4.0 spec: §5.3.3.27 Definite assignment for ?? expressions ResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left); if (crr != null && crr.IsCompileTimeConstant && crr.ConstantValue == null) { return(binaryOperatorExpression.Right.AcceptVisitor(this, data)); } DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data)); binaryOperatorExpression.Right.AcceptVisitor(this, status); return(status); } else { // use default logic for other operators return(VisitChildren(binaryOperatorExpression, data)); } }
public override void VisitInvocationExpression(InvocationExpression invocationExpression) { InvocationExpression outerInvocationExpression = invocationExpression; //Note the invocations are in reverse order, so x.Foo().Bar() will have [0] be the Bar() and [1] be the Foo() List <InvocationExpression> invocations = new List <InvocationExpression>(); LinqMethod outerMethod = null; Expression target = null; for (;;) { var resolveResult = ctx.Resolve(invocationExpression) as MemberResolveResult; if (resolveResult == null || !(resolveResult.Member is IMethod)) { break; } var method = LinqMethods.FirstOrDefault(candidate => candidate.FullName == resolveResult.Member.FullName && candidate.ParameterCount == ((IMethod)resolveResult.Member.MemberDefinition).Parameters.Count); if (method == null || (invocations.Any() && method.IsLast)) { break; } var mre = invocationExpression.Target as MemberReferenceExpression; if (mre == null) { break; } if (outerMethod == null) { outerMethod = method; } invocations.Add(invocationExpression); target = mre.Target; var newInvocation = target as InvocationExpression; if (newInvocation == null) { break; } invocationExpression = newInvocation; } if (target == null) { base.VisitInvocationExpression(invocationExpression); return; } if (!outerMethod.IsPoorStyleAlone && invocations.Count == 1) { base.VisitInvocationExpression(invocationExpression); return; } var currentTypeDeclaration = outerInvocationExpression.GetParent <TypeDeclaration>(); var currentTypeResolveResult = ctx.Resolve(currentTypeDeclaration) as TypeResolveResult; if (currentTypeResolveResult == null) { base.VisitInvocationExpression(invocationExpression); return; } var currentTypeDefinition = currentTypeResolveResult.Type.GetDefinition(); var targetResolveResult = ctx.Resolve(target); if (!CanIndex(currentTypeDefinition, targetResolveResult)) { base.VisitInvocationExpression(invocationExpression); return; } string countPropertyName = GetCountProperty(currentTypeDefinition, targetResolveResult); string lastInvocationName = ((MemberReferenceExpression)invocations[0].Target).MemberName; bool endsReversed = invocations.Count(invocation => ((MemberReferenceExpression)invocation.Target).MemberName == "Reverse") % 2 != 0; bool requiresCount = lastInvocationName == "Count" || lastInvocationName == "Any" || (endsReversed ? lastInvocationName == "First" || lastInvocationName == "ElementAt" : lastInvocationName == "Last"); if (countPropertyName == null && requiresCount) { base.VisitInvocationExpression(invocationExpression); return; } AddIssue(new CodeIssue(invocations.Last().LParToken.StartLocation, invocations.First().RParToken.EndLocation, ctx.TranslateString("Use of Linq method when there's a better alternative"), ctx.TranslateString("Replace method by simpler version"), script => { Expression startOffset = null; Expression endOffset = null; Expression expression = null; bool reversed = false; foreach (var invocation in invocations.AsEnumerable().Reverse()) { string invocationName = ((MemberReferenceExpression)invocation.Target).MemberName; switch (invocationName) { case "Skip": Expression offset = reversed ? endOffset : startOffset; if (offset == null) { offset = invocation.Arguments.Last().Clone(); } else { offset = new BinaryOperatorExpression(offset, BinaryOperatorType.Add, invocation.Arguments.Last().Clone()); } if (reversed) { endOffset = offset; } else { startOffset = offset; } break; case "Reverse": reversed = !reversed; break; case "First": case "ElementAt": case "Last": { bool fromEnd = (invocationName == "Last") ^ reversed; Expression index = invocationName == "ElementAt" ? invocation.Arguments.Last().Clone() : null; Expression baseOffset = fromEnd ? endOffset : startOffset; //Our indexWithOffset is baseOffset + index //A baseOffset/index of null is considered "0". Expression indexWithOffset = baseOffset == null ? index : index == null ? baseOffset : new BinaryOperatorExpression(baseOffset, BinaryOperatorType.Add, index); Expression indexerExpression = indexWithOffset; if (fromEnd) { var endExpression = new BinaryOperatorExpression(new MemberReferenceExpression(target.Clone(), countPropertyName), BinaryOperatorType.Subtract, new PrimitiveExpression(1)); if (indexerExpression == null) { indexerExpression = endExpression; } else { indexerExpression = new BinaryOperatorExpression(endExpression, BinaryOperatorType.Subtract, new ParenthesizedExpression(indexerExpression)); } } indexerExpression = indexerExpression ?? new PrimitiveExpression(0); var newExpression = new IndexerExpression(target.Clone(), indexerExpression); script.Replace(outerInvocationExpression, newExpression); break; } case "Count": case "Any": { Expression takenMembers; if (startOffset == null) { takenMembers = endOffset; } else if (endOffset == null) { takenMembers = startOffset; } else { takenMembers = new BinaryOperatorExpression(startOffset, BinaryOperatorType.Add, endOffset); } var countExpression = new MemberReferenceExpression(target.Clone(), countPropertyName); Expression newExpression; if (invocationName == "Count") { if (takenMembers == null) { newExpression = countExpression; } else { newExpression = new BinaryOperatorExpression(countExpression, BinaryOperatorType.Subtract, new ParenthesizedExpression(takenMembers)); } } else { newExpression = new BinaryOperatorExpression(countExpression, BinaryOperatorType.GreaterThan, new ParenthesizedExpression(takenMembers)); } script.Replace(outerInvocationExpression, newExpression); break; } } } })); base.VisitInvocationExpression(invocationExpression); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { Check(binaryOperatorExpression.Left); Check(binaryOperatorExpression.Right); }
protected override IEnumerable <string> GenerateCode(List <object> includedMembers) { // Genereate Equals var methodDeclaration = new MethodDeclaration(); methodDeclaration.Name = "Equals"; methodDeclaration.ReturnType = new PrimitiveType("bool"); methodDeclaration.Modifiers = ICSharpCode.NRefactory.CSharp.Modifiers.Public | ICSharpCode.NRefactory.CSharp.Modifiers.Override; methodDeclaration.Body = new BlockStatement(); methodDeclaration.Parameters.Add(new ParameterDeclaration(new PrimitiveType("object"), "obj")); var paramId = new IdentifierExpression("obj"); IfElseStatement ifStatement = new IfElseStatement(); ifStatement.Condition = new BinaryOperatorExpression(paramId, BinaryOperatorType.Equality, new PrimitiveExpression(null)); ifStatement.TrueStatement = new ReturnStatement(new PrimitiveExpression(false)); methodDeclaration.Body.Statements.Add(ifStatement); ifStatement = new IfElseStatement(); var arguments = new List <Expression> (); arguments.Add(new ThisReferenceExpression()); arguments.Add(paramId.Clone()); ifStatement.Condition = new InvocationExpression(new IdentifierExpression("ReferenceEquals"), arguments); ifStatement.TrueStatement = new ReturnStatement(new PrimitiveExpression(true)); methodDeclaration.Body.Statements.Add(ifStatement); ifStatement = new IfElseStatement(); ifStatement.Condition = new BinaryOperatorExpression(new InvocationExpression(new MemberReferenceExpression(paramId.Clone(), "GetType")), BinaryOperatorType.InEquality, new TypeOfExpression(new SimpleType(Options.EnclosingType.Name))); ifStatement.TrueStatement = new ReturnStatement(new PrimitiveExpression(false)); methodDeclaration.Body.Statements.Add(ifStatement); var varType = new SimpleType(Options.EnclosingType.Name); var varDecl = new VariableDeclarationStatement(varType, "other", new CastExpression(varType.Clone(), paramId.Clone())); methodDeclaration.Body.Statements.Add(varDecl); var otherId = new IdentifierExpression("other"); Expression binOp = null; foreach (IMember member in includedMembers) { Expression right = new BinaryOperatorExpression(new IdentifierExpression(member.Name), BinaryOperatorType.Equality, new MemberReferenceExpression(otherId.Clone(), member.Name)); if (binOp == null) { binOp = right; } else { binOp = new BinaryOperatorExpression(binOp, BinaryOperatorType.ConditionalAnd, right); } } methodDeclaration.Body.Statements.Add(new ReturnStatement(binOp)); yield return(methodDeclaration.GetText(Options.FormattingOptions)); methodDeclaration = new MethodDeclaration(); methodDeclaration.Name = "GetHashCode"; methodDeclaration.ReturnType = new PrimitiveType("int"); methodDeclaration.Modifiers = ICSharpCode.NRefactory.CSharp.Modifiers.Public | ICSharpCode.NRefactory.CSharp.Modifiers.Override; methodDeclaration.Body = new BlockStatement(); binOp = null; foreach (IMember member in includedMembers) { Expression right; right = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(member.Name), "GetHashCode")); IType type = member.ReturnType; if (type != null && type.Kind != TypeKind.Struct && type.Kind != TypeKind.Enum) { right = new ParenthesizedExpression(new ConditionalExpression(new BinaryOperatorExpression(new IdentifierExpression(member.Name), BinaryOperatorType.InEquality, new PrimitiveExpression(null)), right, new PrimitiveExpression(0))); } if (binOp == null) { binOp = right; } else { binOp = new BinaryOperatorExpression(binOp, BinaryOperatorType.ExclusiveOr, right); } } var uncheckedBlock = new BlockStatement(); uncheckedBlock.Statements.Add(new ReturnStatement(binOp)); methodDeclaration.Body.Statements.Add(new UncheckedStatement(uncheckedBlock)); yield return(methodDeclaration.GetText(Options.FormattingOptions)); }
public void RaiseIfRightIsNull() { BinaryExpression expression = new BinaryOperatorExpression(new ConstantExpression(3), null, BinaryOperator.Divide); }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { bool addClose = false; string leftInterfaceTempVar = null; if (orr.OperatorType == ExpressionType.OrElse || orr.OperatorType == ExpressionType.AndAlso) { var orElse = orr.OperatorType == ExpressionType.OrElse; var left = orr.Operands[0]; var memberTargetrr = left as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(left is ThisResolveResult || left is TypeResolveResult || left is LocalResolveResult || left is ConstantResolveResult || isField)) { this.WriteOpenParentheses(); leftInterfaceTempVar = this.GetTempVarName(); this.Write(leftInterfaceTempVar); this.Write(" = "); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.WriteComma(); addClose = true; } var m = FindOperatorTrueOrFalse(left.Type, orElse); this.Write(BridgeTypes.ToJsName(m.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, m).GetOverloadName()); this.WriteOpenParentheses(); if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); this.Write(" ? "); if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.Write(" : "); } if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT; switch (this.BinaryOperatorExpression.Operator) { case BinaryOperatorType.GreaterThan: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.GreaterThanOrEqual: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.Equality: action = JS.Funcs.Math.LIFTEQ; break; case BinaryOperatorType.InEquality: action = JS.Funcs.Math.LIFTNE; break; case BinaryOperatorType.LessThan: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.LessThanOrEqual: action = JS.Funcs.Math.LIFTCMP; break; } this.Write(action + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); this.Write(", "); binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); } else { new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null, null, 0).Emit(); } this.WriteCloseParentheses(); if (addClose) { this.WriteCloseParentheses(); } return(true); } } return(false); }
protected void VisitBinaryOperatorExpression() { BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression; var resolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; var leftResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter); var charToString = -1; string variable = null; bool leftIsNull = this.BinaryOperatorExpression.Left is NullReferenceExpression; bool rightIsNull = this.BinaryOperatorExpression.Right is NullReferenceExpression; bool isUint = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64); if ((leftIsNull || rightIsNull) && (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality)) { if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { this.Write("!"); } this.Write("Bridge.hasValue"); this.WriteOpenParentheses(); if (leftIsNull) { binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); return; } if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver))) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { this.HandleDecimal(resolveOperator); return; } var isFloatResult = Helpers.IsFloatType(resolveOperator.Type, this.Emitter.Resolver); var leftExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left); var rightExpected = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right); var isLeftLong = Helpers.Is64Type(leftExpected, this.Emitter.Resolver); var isRightLong = Helpers.Is64Type(rightExpected, this.Emitter.Resolver); if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (isLeftLong || isRightLong)) { isLong = true; isLongExpected = true; } if (isLong && isLongExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { if (!isFloatResult || binaryOperatorExpression.Operator == BinaryOperatorType.Divide && isLeftLong) { this.HandleLong(resolveOperator, isUint); return; } } var delegateOperator = false; if (this.ResolveOperator(binaryOperatorExpression, orr)) { return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, binaryOperatorExpression)) && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) )) { this.Write("Bridge.Int.div("); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult)) { delegateOperator = true; this.Write(Bridge.Translator.Emitter.ROOT + "." + (add ? Bridge.Translator.Emitter.DELEGATE_COMBINE : Bridge.Translator.Emitter.DELEGATE_REMOVE)); this.WriteOpenParentheses(); } } bool nullable = orr != null && orr.IsLiftedOperator; bool isCoalescing = binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing; string root = Bridge.Translator.Emitter.ROOT + ".Nullable."; bool special = nullable; bool rootSpecial = nullable; bool isBool = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean); bool toBool = isBool && !rootSpecial && !delegateOperator && (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd || binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr); if (rootSpecial) { this.Write(root); } else { if (isCoalescing) { this.Write("("); variable = this.GetTempVarName(); this.Write(variable); this.Write(" = "); } else if (charToString == 0) { this.Write("String.fromCharCode("); } if (toBool) { this.Write("!!("); } binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); if (isCoalescing) { this.Write(", Bridge.hasValue("); this.Write(variable); this.Write(") ? "); this.Write(variable); } else if (charToString == 0) { this.Write(")"); } } if (!delegateOperator) { if (!special) { this.WriteSpace(); } switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: this.Write(rootSpecial ? "add" : "+"); break; case BinaryOperatorType.BitwiseAnd: if (isBool) { this.Write(rootSpecial ? "and" : "&"); } else { this.Write(rootSpecial ? "band" : "&"); } break; case BinaryOperatorType.BitwiseOr: if (isBool) { this.Write(rootSpecial ? "or" : "|"); } else { this.Write(rootSpecial ? "bor" : "|"); } break; case BinaryOperatorType.ConditionalAnd: this.Write(rootSpecial ? "and" : "&&"); break; case BinaryOperatorType.NullCoalescing: this.Write(":"); break; case BinaryOperatorType.ConditionalOr: this.Write(rootSpecial ? "or" : "||"); break; case BinaryOperatorType.Divide: this.Write(rootSpecial ? "div" : "/"); break; case BinaryOperatorType.Equality: this.Write(rootSpecial ? "eq" : "==="); break; case BinaryOperatorType.ExclusiveOr: this.Write(rootSpecial ? "xor" : "^"); break; case BinaryOperatorType.GreaterThan: this.Write(rootSpecial ? "gt" : ">"); break; case BinaryOperatorType.GreaterThanOrEqual: this.Write(rootSpecial ? "gte" : ">="); break; case BinaryOperatorType.InEquality: this.Write(rootSpecial ? "neq" : "!=="); break; case BinaryOperatorType.LessThan: this.Write(rootSpecial ? "lt" : "<"); break; case BinaryOperatorType.LessThanOrEqual: this.Write(rootSpecial ? "lte" : "<="); break; case BinaryOperatorType.Modulus: this.Write(rootSpecial ? "mod" : "%"); break; case BinaryOperatorType.Multiply: this.Write(rootSpecial ? "mul" : "*"); break; case BinaryOperatorType.ShiftLeft: this.Write(rootSpecial ? "sl" : "<<"); break; case BinaryOperatorType.ShiftRight: if (isUint) { this.Write(rootSpecial ? "srr" : ">>>"); } else { this.Write(rootSpecial ? "sr" : ">>"); } break; case BinaryOperatorType.Subtract: this.Write(rootSpecial ? "sub" : "-"); break; default: throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString()); } } else { this.WriteComma(); } if (special) { this.WriteOpenParentheses(); if (charToString == 0) { this.Write("String.fromCharCode("); } binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); if (charToString == 0) { this.Write(")"); } this.WriteComma(); } else { this.WriteSpace(); } if (charToString == 1) { this.Write("String.fromCharCode("); } binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); if (toBool) { this.WriteCloseParentheses(); } if (charToString == 1 || isCoalescing) { this.WriteCloseParentheses(); } if (delegateOperator || special) { this.WriteCloseParentheses(); } }
void ConvertForStatement(ForStatement forStatement) { // ForStatement -> ForNextStatement when for-loop is simple // only the following forms of the for-statement are allowed: // for (TypeReference name = start; name < oneAfterEnd; name += step) // for (name = start; name < oneAfterEnd; name += step) // for (TypeReference name = start; name <= end; name += step) // for (name = start; name <= end; name += step) // for (TypeReference name = start; name > oneAfterEnd; name -= step) // for (name = start; name > oneAfterEnd; name -= step) // for (TypeReference name = start; name >= end; name -= step) // for (name = start; name >= end; name -= step) // check if the form is valid and collect TypeReference, name, start, end and step if (forStatement.Initializers.Count != 1) { return; } if (forStatement.Iterator.Count != 1) { return; } ExpressionStatement statement = forStatement.Iterator[0] as ExpressionStatement; if (statement == null) { return; } AssignmentExpression iterator = statement.Expression as AssignmentExpression; if (iterator == null || (iterator.Op != AssignmentOperatorType.Add && iterator.Op != AssignmentOperatorType.Subtract)) { return; } IdentifierExpression iteratorIdentifier = iterator.Left as IdentifierExpression; if (iteratorIdentifier == null) { return; } PrimitiveExpression stepExpression = iterator.Right as PrimitiveExpression; if (stepExpression == null || !(stepExpression.Value is int)) { return; } int step = (int)stepExpression.Value; if (iterator.Op == AssignmentOperatorType.Subtract) { step = -step; } BinaryOperatorExpression condition = forStatement.Condition as BinaryOperatorExpression; if (condition == null || !(condition.Left is IdentifierExpression)) { return; } if ((condition.Left as IdentifierExpression).Identifier != iteratorIdentifier.Identifier) { return; } Expression end; if (iterator.Op == AssignmentOperatorType.Subtract) { if (condition.Op == BinaryOperatorType.GreaterThanOrEqual) { end = condition.Right; } else if (condition.Op == BinaryOperatorType.GreaterThan) { end = Expression.AddInteger(condition.Right, 1); } else { return; } } else { if (condition.Op == BinaryOperatorType.LessThanOrEqual) { end = condition.Right; } else if (condition.Op == BinaryOperatorType.LessThan) { end = Expression.AddInteger(condition.Right, -1); } else { return; } } Expression start; TypeReference typeReference = null; LocalVariableDeclaration varDecl = forStatement.Initializers[0] as LocalVariableDeclaration; if (varDecl != null) { if (varDecl.Variables.Count != 1 || varDecl.Variables[0].Name != iteratorIdentifier.Identifier || varDecl.Variables[0].Initializer == null) { return; } typeReference = varDecl.GetTypeForVariable(0); start = varDecl.Variables[0].Initializer; } else { statement = forStatement.Initializers[0] as ExpressionStatement; if (statement == null) { return; } AssignmentExpression assign = statement.Expression as AssignmentExpression; if (assign == null || assign.Op != AssignmentOperatorType.Assign) { return; } if (!(assign.Left is IdentifierExpression)) { return; } if ((assign.Left as IdentifierExpression).Identifier != iteratorIdentifier.Identifier) { return; } start = assign.Right; } ReplaceCurrentNode(new ForNextStatement(typeReference, iteratorIdentifier.Identifier, start, end, (step == 1) ? null : new PrimitiveExpression(step, step.ToString(System.Globalization.NumberFormatInfo.InvariantInfo)), forStatement.EmbeddedStatement, null)); }
public void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { StartNode(binaryOperatorExpression); binaryOperatorExpression.Left.AcceptVisitor(this); bool spacePolicy; switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.BitwiseAnd: case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: spacePolicy = policy.SpaceAroundBitwiseOperator; break; case BinaryOperatorType.ConditionalAnd: case BinaryOperatorType.ConditionalOr: spacePolicy = policy.SpaceAroundLogicalOperator; break; case BinaryOperatorType.GreaterThan: case BinaryOperatorType.GreaterThanOrEqual: case BinaryOperatorType.LessThanOrEqual: case BinaryOperatorType.LessThan: spacePolicy = policy.SpaceAroundRelationalOperator; break; case BinaryOperatorType.Equality: case BinaryOperatorType.InEquality: spacePolicy = policy.SpaceAroundEqualityOperator; break; case BinaryOperatorType.Add: case BinaryOperatorType.Subtract: spacePolicy = policy.SpaceAroundAdditiveOperator; break; case BinaryOperatorType.Multiply: case BinaryOperatorType.Divide: case BinaryOperatorType.Modulus: spacePolicy = policy.SpaceAroundMultiplicativeOperator; break; case BinaryOperatorType.ShiftLeft: case BinaryOperatorType.ShiftRight: spacePolicy = policy.SpaceAroundShiftOperator; break; case BinaryOperatorType.NullCoalescing: spacePolicy = true; break; default: throw new NotSupportedException ("Invalid value for BinaryOperatorType"); } Space(spacePolicy); WriteToken(BinaryOperatorExpression.GetOperatorRole(binaryOperatorExpression.Operator)); Space(spacePolicy); binaryOperatorExpression.Right.AcceptVisitor(this); EndNode(binaryOperatorExpression); }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable."); string action = "lift"; switch (this.BinaryOperatorExpression.Operator) { case BinaryOperatorType.GreaterThan: action = "liftcmp"; break; case BinaryOperatorType.GreaterThanOrEqual: action = "liftcmp"; break; case BinaryOperatorType.Equality: action = "lifteq"; break; case BinaryOperatorType.InEquality: action = "liftne"; break; case BinaryOperatorType.LessThan: action = "liftcmp"; break; case BinaryOperatorType.LessThanOrEqual: action = "liftcmp"; break; } this.Write(action + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null).Emit(); this.WriteCloseParentheses(); return(true); } } return(false); }
public override IEnumerable<CodeAction> GetActions(RefactoringContext context) { var loop = GetForeachStatement (context); if (loop == null) { yield break; } if (context.GetResolverStateBefore(loop) .LookupSimpleNameOrTypeName("Enumerable", new List<IType>(), NameLookupMode.Type) .Type.FullName != "System.Linq.Enumerable") { yield break; } var outputStatement = GetTransformedAssignmentExpression (context, loop); if (outputStatement == null) { yield break; } yield return new CodeAction(context.TranslateString("Convert foreach loop to LINQ expression"), script => { var prevSibling = loop.GetPrevSibling(node => node is Statement); Expression leftSide = outputStatement.Left; Expression rightSide = outputStatement.Right; Expression expressionToReplace = GetExpressionToReplace(prevSibling, leftSide); if (expressionToReplace != null) { Expression replacementExpression = rightSide.Clone(); if (!IsZeroPrimitive(expressionToReplace)) { replacementExpression = new BinaryOperatorExpression(ParenthesizeIfNeeded(expressionToReplace).Clone(), BinaryOperatorType.Add, replacementExpression); } script.Replace(expressionToReplace, replacementExpression); script.Remove(loop); } else { script.Replace(loop, new ExpressionStatement(outputStatement)); } }, loop); }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) { HandleExpressionNode(binaryOperatorExpression); }