| File: Lowering\LocalRewriter\LocalRewriter_Index.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp { internal sealed partial class LocalRewriter { public override BoundNode VisitFromEndIndexExpression(BoundFromEndIndexExpression node) { Debug.Assert(node.MethodOpt != null); NamedTypeSymbol booleanType = _compilation.GetSpecialType(SpecialType.System_Boolean); BoundExpression fromEnd = MakeLiteral(node.Syntax, ConstantValue.Create(true), booleanType); BoundExpression operand = VisitExpression(node.Operand); if (NullableNeverHasValue(operand)) { operand = new BoundDefaultExpression(operand.Syntax, operand.Type!.GetNullableUnderlyingType()); } operand = NullableAlwaysHasValue(operand) ?? operand; if (!node.Type.IsNullableType()) { return new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, operand, fromEnd); } ArrayBuilder<BoundExpression> sideeffects = ArrayBuilder<BoundExpression>.GetInstance(); ArrayBuilder<LocalSymbol> locals = ArrayBuilder<LocalSymbol>.GetInstance(); // operand.HasValue operand = CaptureExpressionInTempIfNeeded(operand, sideeffects, locals); BoundExpression condition = MakeOptimizedHasValue(operand.Syntax, operand); // new Index(operand, fromEnd: true) BoundExpression boundOperandGetValueOrDefault = MakeOptimizedGetValueOrDefault(operand.Syntax, operand); BoundExpression indexCreation = new BoundObjectCreationExpression(node.Syntax, node.MethodOpt, boundOperandGetValueOrDefault, fromEnd); // new Nullable(new Index(operand, fromEnd: true)) BoundExpression consequence = ConvertToNullable(node.Syntax, node.Type, indexCreation); // default BoundExpression alternative = new BoundDefaultExpression(node.Syntax, node.Type); // operand.HasValue ? new Nullable(new Index(operand, fromEnd: true)) : 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); } private BoundExpression ConvertToNullable(SyntaxNode syntax, TypeSymbol targetNullableType, BoundExpression underlyingValue) { Debug.Assert(targetNullableType.IsNullableType()); Debug.Assert(TypeSymbol.Equals(targetNullableType.GetNullableUnderlyingType(), underlyingValue.Type, TypeCompareKind.AllIgnoreOptions)); if (!TryGetNullableMethod(syntax, targetNullableType, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor)) { return BadExpression(syntax, targetNullableType, underlyingValue); } return new BoundObjectCreationExpression(syntax, nullableCtor, underlyingValue); } } }