bool BindNullableOperation(BinaryExpression node) { if (!IsNullableOperation(node)) return false; if (BinaryOperatorType.ReferenceEquality == node.Operator) { node.Operator = BinaryOperatorType.Equality; return BindNullableComparison(node); } else if (BinaryOperatorType.ReferenceInequality == node.Operator) { node.Operator = BinaryOperatorType.Inequality; return BindNullableComparison(node); } IType lhs = GetExpressionType(node.Left); IType rhs = GetExpressionType(node.Right); bool lhsIsNullable = TypeSystemServices.IsNullable(lhs); bool rhsIsNullable = TypeSystemServices.IsNullable(rhs); if (BinaryOperatorType.Assign == node.Operator) { if (lhsIsNullable) { if (rhsIsNullable) return false; BindNullableInitializer(node, node.Right, lhs); return false; } } if (lhsIsNullable) { MemberReferenceExpression mre = new MemberReferenceExpression(node.Left, "Value"); node.Replace(node.Left, mre); Visit(mre); mre.Annotate("nullableTarget", true); } if (rhsIsNullable) { MemberReferenceExpression mre = new MemberReferenceExpression(node.Right, "Value"); node.Replace(node.Right, mre); Visit(mre); mre.Annotate("nullableTarget", true); } return false; }
bool BindPointerArithmeticOperator(BinaryExpression node, IType left, IType right) { if (!left.IsPointer || !TypeSystemServices.IsPrimitiveNumber(right)) return false; switch (node.Operator) { case BinaryOperatorType.Addition: case BinaryOperatorType.Subtraction: if (node.ContainsAnnotation("pointerSizeNormalized")) return true; BindExpressionType(node, left); int size = TypeSystemServices.SizeOf(left); if (size == 1) return true; //no need for normalization //normalize RHS wrt size of pointer IntegerLiteralExpression literal = node.Right as IntegerLiteralExpression; Expression normalizedRhs = (null != literal) ? (Expression) new IntegerLiteralExpression(literal.Value * size) : (Expression) new BinaryExpression(BinaryOperatorType.Multiply, node.Right, new IntegerLiteralExpression(size)); node.Replace(node.Right, normalizedRhs); Visit(node.Right); node.Annotate("pointerSizeNormalized", size); return true; } return false; }
bool BindNullableComparison(BinaryExpression node) { if (!IsNullableOperation(node)) return false; if (IsNull(node.Left) || IsNull(node.Right)) { Expression nullable = IsNull(node.Left) ? node.Right : node.Left; Expression val = new MemberReferenceExpression(nullable, "HasValue"); node.Replace(node.Left, val); Visit(val); Expression nil = new BoolLiteralExpression(false); node.Replace(node.Right, nil); Visit(nil); BindExpressionType(node, TypeSystemServices.BoolType); return true; } BinaryExpression valueCheck = new BinaryExpression( (node.Operator == BinaryOperatorType.Inequality) ? BinaryOperatorType.BitwiseOr : BinaryOperatorType.BitwiseAnd, new BinaryExpression( GetCorrespondingHasValueOperator(node.Operator), CreateNullableHasValueOrTrueExpression(node.Left), CreateNullableHasValueOrTrueExpression(node.Right) ), new BinaryExpression( node.Operator, CreateNullableGetValueOrDefaultExpression(node.Left), CreateNullableGetValueOrDefaultExpression(node.Right) ) ); node.ParentNode.Replace(node, valueCheck); Visit(valueCheck); return true; }