public override BoundNode VisitRangeExpression(BoundRangeExpression node) { if (_inExpressionLambda) { Error(ErrorCode.ERR_ExpressionTreeContainsRangeExpression, node); } return(base.VisitRangeExpression(node)); }
public override BoundNode VisitRangeExpression(BoundRangeExpression node) { Debug.Assert(node != null && node.MethodOpt != null); bool needLifting = false; var F = _factory; var left = node.LeftOperandOpt; if (left != null) { left = tryOptimizeOperand(left); } var right = node.RightOperandOpt; if (right != null) { right = tryOptimizeOperand(right); } if (needLifting) { return(LiftRangeExpression(node, left, right)); } else { BoundExpression rangeCreation = MakeRangeExpression(node.MethodOpt, left, right); if (node.Type.IsNullableType()) { if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, node)); } return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation)); } return(rangeCreation); } BoundExpression tryOptimizeOperand(BoundExpression operand) { Debug.Assert(operand != null); operand = VisitExpression(operand); Debug.Assert(operand.Type is { }); if (NullableNeverHasValue(operand)) { operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType()); } else { operand = NullableAlwaysHasValue(operand) ?? operand; Debug.Assert(operand.Type is { });
public override BoundNode VisitRangeExpression(BoundRangeExpression node) { Debug.Assert(node != null && node.MethodOpt != null); bool needLifting = false; var F = _factory; var left = node.LeftOperandOpt; if (left != null) { left = tryOptimizeOperand(left); } var right = node.RightOperandOpt; if (right != null) { right = tryOptimizeOperand(right); } if (needLifting) { return(LiftRangeExpression(node, left, right)); } else { BoundExpression rangeCreation = MakeRangeExpression(node.MethodOpt, left, right); if (node.Type.IsNullableType()) { return(ConvertToNullable(node.Syntax, node.Type, rangeCreation)); } return(rangeCreation); } BoundExpression tryOptimizeOperand(BoundExpression operand) { Debug.Assert(operand != null); operand = VisitExpression(operand); Debug.Assert(operand.Type is { }); if (NullableNeverHasValue(operand)) { operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType()); } else { operand = NullableAlwaysHasValue(operand) ?? operand; Debug.Assert(operand.Type is { });
private BoundExpression LiftRangeExpression(BoundRangeExpression node, BoundExpression left, BoundExpression right) { Debug.Assert(node.Type.IsNullableType()); Debug.Assert(left?.Type.IsNullableType() == true || right?.Type.IsNullableType() == true); Debug.Assert(!(left is null && right is null)); var sideeffects = ArrayBuilder <BoundExpression> .GetInstance(); var locals = ArrayBuilder <LocalSymbol> .GetInstance(); // makeRange(left.GetValueOrDefault(), right.GetValueOrDefault()) BoundExpression condition = null; left = getIndexFromPossibleNullable(left); right = getIndexFromPossibleNullable(right); var rangeExpr = MakeRangeExpression(node.MethodOpt, left, right); Debug.Assert(condition != null); if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, node)); } // new Nullable(makeRange(left.GetValueOrDefault(), right.GetValueOrDefault())) BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeExpr); // default BoundExpression alternative = new BoundDefaultExpression(node.Syntax, node.Type); // left.HasValue && right.HasValue // ? new Nullable(makeRange(left.GetValueOrDefault(), right.GetValueOrDefault())) // : default BoundExpression conditionalExpression = RewriteConditionalOperator( syntax: node.Syntax, rewrittenCondition: condition, rewrittenConsequence: consequence, rewrittenAlternative: alternative, constantValueOpt: null, rewrittenType: node.Type, isRef: false); return(new BoundSequence( syntax: node.Syntax, locals: locals.ToImmutableAndFree(), sideEffects: sideeffects.ToImmutableAndFree(), value: conditionalExpression, type: node.Type)); BoundExpression getIndexFromPossibleNullable(BoundExpression arg) { if (arg is null) { return(null); } BoundExpression tempOperand = CaptureExpressionInTempIfNeeded(arg, sideeffects, locals); if (tempOperand.Type.IsNullableType()) { BoundExpression operandHasValue = MakeOptimizedHasValue(tempOperand.Syntax, tempOperand); if (condition is null) { condition = operandHasValue; } else { TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean); condition = MakeBinaryOperator(node.Syntax, BinaryOperatorKind.BoolAnd, condition, operandHasValue, boolType, method: null); } return(MakeOptimizedGetValueOrDefault(tempOperand.Syntax, tempOperand)); } else { return(tempOperand); } } }
private BoundExpression LiftRangeExpression(BoundRangeExpression node, ImmutableArray <BoundExpression> operands) { Debug.Assert(node.Type.IsNullableType()); Debug.Assert(operands.Any(operand => operand.Type.IsNullableType())); Debug.Assert(operands.Length == 1 || operands.Length == 2); ArrayBuilder <BoundExpression> sideeffects = ArrayBuilder <BoundExpression> .GetInstance(); ArrayBuilder <LocalSymbol> locals = ArrayBuilder <LocalSymbol> .GetInstance(); ArrayBuilder <BoundExpression> arguments = ArrayBuilder <BoundExpression> .GetInstance(); // left.HasValue && right.HasValue BoundExpression condition = null; foreach (var operand in operands) { BoundExpression tempOperand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals); if (tempOperand.Type.IsNullableType()) { BoundExpression operandHasValue = MakeOptimizedHasValue(tempOperand.Syntax, tempOperand); if (condition is null) { condition = operandHasValue; } else { TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean); condition = MakeBinaryOperator(node.Syntax, BinaryOperatorKind.BoolAnd, condition, operandHasValue, boolType, method: null); } arguments.Add(MakeOptimizedGetValueOrDefault(tempOperand.Syntax, tempOperand)); } else { arguments.Add(tempOperand); } } Debug.Assert(condition != null); // method(left.GetValueOrDefault(), right.GetValueOrDefault()) BoundExpression rangeCall = MakeCall( node.Syntax, rewrittenReceiver: null, node.MethodOpt, arguments.ToImmutableArray(), node.MethodOpt.ReturnType.TypeSymbol); if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, node)); } // new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault())) BoundExpression consequence = new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCall); // default BoundExpression alternative = new BoundDefaultExpression(node.Syntax, constantValueOpt: null, node.Type); // left.HasValue && right.HasValue ? new Nullable(method(left.GetValueOrDefault(), right.GetValueOrDefault())) : default BoundExpression conditionalExpression = RewriteConditionalOperator( syntax: node.Syntax, rewrittenCondition: condition, rewrittenConsequence: consequence, rewrittenAlternative: alternative, constantValueOpt: null, rewrittenType: node.Type, isRef: false); return(new BoundSequence( syntax: node.Syntax, locals: locals.ToImmutableAndFree(), sideEffects: sideeffects.ToImmutableAndFree(), value: conditionalExpression, type: node.Type)); }
public override BoundNode VisitRangeExpression(BoundRangeExpression node) { Debug.Assert(node != null && node.MethodOpt != null); bool needLifting = false; var operandsBuilder = new ArrayBuilder <BoundExpression>(); var left = node.LeftOperand; if (left != null) { operandsBuilder.Add(tryOptimizeOperand(left)); } var right = node.RightOperand; if (right != null) { operandsBuilder.Add(tryOptimizeOperand(right)); } ImmutableArray <BoundExpression> operands = operandsBuilder.ToImmutable(); if (needLifting) { return(LiftRangeExpression(node, operands)); } else { BoundExpression rangeCreation = MakeCall( node.Syntax, rewrittenReceiver: null, node.MethodOpt, operands, node.MethodOpt.ReturnType.TypeSymbol); if (node.Type.IsNullableType()) { if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, node)); } return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation)); } return(rangeCreation); } BoundExpression tryOptimizeOperand(BoundExpression operand) { Debug.Assert(operand != null); operand = VisitExpression(operand); if (NullableNeverHasValue(operand)) { operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType()); } else { operand = NullableAlwaysHasValue(operand) ?? operand; if (operand.Type.IsNullableType()) { needLifting = true; } } return(operand); } }
public override BoundNode VisitRangeExpression(BoundRangeExpression node) { Debug.Assert(node != null && node.MethodOpt != null); bool needLifting = false; var F = _factory; var left = node.LeftOperand; if (left != null) { left = tryOptimizeOperand(left); } else { left = newIndexZero(fromEnd: false); } var right = node.RightOperand; if (right != null) { right = tryOptimizeOperand(right); } else { right = newIndexZero(fromEnd: true); } var operands = ImmutableArray.Create(left, right); if (needLifting) { return(LiftRangeExpression(node, operands)); } else { BoundExpression rangeCreation = new BoundObjectCreationExpression( node.Syntax, node.MethodOpt, binderOpt: null, operands); if (node.Type.IsNullableType()) { if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return(BadExpression(node.Syntax, node.Type, node)); } return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation)); } return(rangeCreation); } BoundExpression newIndexZero(bool fromEnd) => // new Index(0, fromEnd: fromEnd) F.New( WellKnownMember.System_Index__ctor, ImmutableArray.Create <BoundExpression>(F.Literal(0), F.Literal(fromEnd))); BoundExpression tryOptimizeOperand(BoundExpression operand) { Debug.Assert(operand != null); operand = VisitExpression(operand); if (NullableNeverHasValue(operand)) { operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType()); } else { operand = NullableAlwaysHasValue(operand) ?? operand; if (operand.Type.IsNullableType()) { needLifting = true; } } return(operand); } }