public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundSpillSequenceBuilder builder = null; var expression = VisitExpression(ref builder, node.Expression); BoundSpillSequenceBuilder indicesBuilder = null; var indices = this.VisitExpressionList(ref indicesBuilder, node.Indices); if (indicesBuilder != null) { // spill the array if there were await expressions in the indices if (builder == null) { builder = new BoundSpillSequenceBuilder(); } expression = Spill(builder, expression); } if (builder != null) { builder.Include(indicesBuilder); indicesBuilder = builder; builder = null; } return(UpdateExpression(indicesBuilder, node.Update(expression, indices, node.Type))); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundSpillSequence2 ssArray = null; var expression = VisitExpression(ref ssArray, node.Expression); BoundSpillSequence2 ssIndices = null; var indices = this.VisitExpressionList(ref ssIndices, node.Indices); if (ssIndices != null) { // spill the array if there were await expressions in the indices if (ssArray == null) { ssArray = new BoundSpillSequence2(); } expression = Spill(ssArray, expression); } if (ssArray != null) { ssArray.IncludeSequence(ssIndices); ssIndices = ssArray; ssArray = null; } return(UpdateExpression(ssIndices, node.Update(expression, indices, node.Type))); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { if (_inExpressionLambda && node.Indices.Length == 1 && node.Indices[0].Type !.SpecialType == SpecialType.None) { Error(ErrorCode.ERR_ExpressionTreeContainsPatternIndexOrRangeIndexer, node); } return(base.VisitArrayAccess(node)); }
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, FileLinePositionSpan span, SyntheticBoundNodeFactory statementFactory) { // Add an entry in the spans array. int spansIndex = _spansBuilder.Count; _spansBuilder.Add(new SourceSpan(GetSourceDocument(syntaxForSpan, span), span.StartLinePosition.Line, span.StartLinePosition.Character, span.EndLinePosition.Line, span.EndLinePosition.Character)); // Generate "_payload[pointIndex] = true". BoundArrayAccess payloadCell = statementFactory.ArrayAccess(statementFactory.Local(_methodPayload), statementFactory.Literal(spansIndex)); return(statementFactory.Assignment(payloadCell, statementFactory.Literal(true))); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundExpression expression = (BoundExpression)this.Visit(node.Expression); ReadOnlyArray <BoundExpression> indices = (ReadOnlyArray <BoundExpression>) this.VisitList(node.Indices); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence) { return(node.Update(expression, indices, type)); } var spillBuilder = new SpillBuilder(); var spillResult = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray <RefKind> .Empty); BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type); return(spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess)); }
private BoundExpression VisitArrayAccess(BoundArrayAccess node) { var array = Visit(node.Expression); if (node.Indices.Length == 1) { var arg = node.Indices[0]; var index = Visit(arg); if (index.Type != _int32Type) { index = ConvertIndex(index, arg.Type, _int32Type); } return(ExprFactory("ArrayIndex", array, index)); } else { return(ExprFactory("ArrayIndex", array, Indices(node.Indices))); } }
private BoundExpression VisitArrayAccess(BoundArrayAccess node) { var array = Visit(node.Expression); if (node.Indices.Length == 1) { var arg = node.Indices[0]; var index = Visit(arg); if (!TypeSymbol.Equals(index.Type, _int32Type, TypeCompareKind.ConsiderEverything2)) { index = ConvertIndex(index, arg.Type, _int32Type); } return(ExprFactory("ArrayIndex", array, index)); } else { return(ExprFactory("ArrayIndex", array, Indices(node.Indices))); } }
private BoundExpression VisitArrayAccess(BoundArrayAccess node) { var array = Visit(node.Expression); if (node.Indices.Length == 1) { var arg = node.Indices[0]; var index = Visit(arg); if (node.Type != _int32Type) { index = ConvertIndex(index, arg.Type, _int32Type); } return ExprFactory("ArrayIndex", array, index); } else { return ExprFactory("ArrayIndex", array, Indices(node.Indices)); } }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundSpillSequence2 ssArray = null; var expression = VisitExpression(ref ssArray, node.Expression); BoundSpillSequence2 ssIndices = null; var indices = this.VisitExpressionList(ref ssIndices, node.Indices); if (ssIndices != null) { // spill the array if there were await expressions in the indices if (ssArray == null) ssArray = new BoundSpillSequence2(); expression = Spill(ssArray, expression); } if (ssArray != null) { ssArray.IncludeSequence(ssIndices); ssIndices = ssArray; ssArray = null; } return UpdateExpression(ssIndices, node.Update(expression, indices, node.Type)); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { // https://github.com/dotnet/roslyn/issues/30620 // If the array access index is of type System.Index or System.Range // we need to emit code as if there were a real indexer, instead // of a simple array element access. if (node.Indices.Length != 1) { return(base.VisitArrayAccess(node)); } TypeSymbol rawIndexType = node.Indices[0].Type; if (!(TypeSymbol.Equals(rawIndexType, _compilation.GetWellKnownType(WellKnownType.System_Index), TypeCompareKind.ConsiderEverything) || TypeSymbol.Equals(rawIndexType, _compilation.GetWellKnownType(WellKnownType.System_Range), TypeCompareKind.ConsiderEverything))) { return(base.VisitArrayAccess(node)); } var syntax = node.Syntax; var F = _factory; var indexLocal = F.StoreToTemp( VisitExpression(node.Indices[0]), out BoundAssignmentOperator indexAssign); var arrayLocal = F.StoreToTemp( VisitExpression(node.Expression), out BoundAssignmentOperator arrayAssign); var indexType = VisitType(node.Indices[0].Type); var indexValueSymbol = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Index__Value); var indexFromEndSymbol = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Index__IsFromEnd); BoundExpression resultExpr; if (TypeSymbol.Equals(indexType, _compilation.GetWellKnownType(WellKnownType.System_Index), TypeCompareKind.ConsiderEverything)) { // array[Index] is translated to: // array[index.FromEnd ? array.Length - index.Value : index.Value] var indexValueExpr = F.Property(indexLocal, indexValueSymbol); resultExpr = F.Sequence( ImmutableArray.Create <LocalSymbol>( indexLocal.LocalSymbol, arrayLocal.LocalSymbol), ImmutableArray.Create <BoundExpression>( indexAssign, arrayAssign), F.ArrayAccess(arrayLocal, ImmutableArray.Create( F.Conditional( F.Property(indexLocal, indexFromEndSymbol), F.Binary( BinaryOperatorKind.Subtraction, F.SpecialType(SpecialType.System_Int32), F.ArrayLength(arrayLocal), indexValueExpr), indexValueExpr, node.Type)))); } else if (TypeSymbol.Equals(indexType, _compilation.GetWellKnownType(WellKnownType.System_Range), TypeCompareKind.ConsiderEverything)) { // array[Range] is translated to: // var start = range.Start.FromEnd ? array.Length - range.Start.Value : range.Start.Value; // var end = range.End.FromEnd ? array.Length - range.End.Value : range.End.Value; // var length = end - start; // var newArr = new T[length]; // Array.Copy(array, start, newArr, 0, length); // push newArray var rangeStartSymbol = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Range__Start); var rangeEndSymbol = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Range__End); var arrayCopySymbol = F.WellKnownMethod(WellKnownMember.System_Array__Copy); var startLocal = F.StoreToTemp( F.Conditional( F.Property(F.Property(indexLocal, rangeStartSymbol), indexFromEndSymbol), F.Binary( BinaryOperatorKind.Subtraction, F.SpecialType(SpecialType.System_Int32), F.ArrayLength(arrayLocal), F.Property(F.Property(indexLocal, rangeStartSymbol), indexValueSymbol)), F.Property(F.Property(indexLocal, rangeStartSymbol), indexValueSymbol), F.SpecialType(SpecialType.System_Int32)), out BoundAssignmentOperator startAssign); var endLocal = F.StoreToTemp( F.Conditional( F.Property(F.Property(indexLocal, rangeEndSymbol), indexFromEndSymbol), F.Binary( BinaryOperatorKind.Subtraction, F.SpecialType(SpecialType.System_Int32), F.ArrayLength(arrayLocal), F.Property(F.Property(indexLocal, rangeEndSymbol), indexValueSymbol)), F.Property(F.Property(indexLocal, rangeEndSymbol), indexValueSymbol), F.SpecialType(SpecialType.System_Int32)), out BoundAssignmentOperator endAssign); var lengthLocal = F.StoreToTemp( F.Binary(BinaryOperatorKind.Subtraction, F.SpecialType(SpecialType.System_Int32), endLocal, startLocal), out BoundAssignmentOperator lengthAssign); var elementType = ((ArrayTypeSymbol)node.Type).ElementType.TypeSymbol; var newArrLocal = F.StoreToTemp(F.Array(elementType, lengthLocal), out BoundAssignmentOperator newArrAssign); var copyExpr = F.Call(null, arrayCopySymbol, ImmutableArray.Create <BoundExpression>( arrayLocal, startLocal, newArrLocal, F.Literal(0), lengthLocal)); resultExpr = F.Sequence( ImmutableArray.Create( indexLocal.LocalSymbol, arrayLocal.LocalSymbol, startLocal.LocalSymbol, endLocal.LocalSymbol, lengthLocal.LocalSymbol, newArrLocal.LocalSymbol), ImmutableArray.Create <BoundExpression>( indexAssign, arrayAssign, startAssign, endAssign, lengthAssign, newArrAssign, copyExpr), newArrLocal); } else { throw ExceptionUtilities.Unreachable; } return(resultExpr); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { // An array access expression can be indexed using any of the following types: // * an integer primitive // * a System.Index // * a System.Range // The last two are only supported on SZArrays. For those cases we need to // lower into the appropriate helper methods. if (node.Indices.Length != 1) { return(base.VisitArrayAccess(node)); } var indexType = VisitType(node.Indices[0].Type); var F = _factory; BoundNode resultExpr; if (TypeSymbol.Equals( indexType, _compilation.GetWellKnownType(WellKnownType.System_Index), TypeCompareKind.ConsiderEverything)) { // array[Index] is compiled to: // array[Index.GetOffset(array.Length)] var arrayLocal = F.StoreToTemp( VisitExpression(node.Expression), out BoundAssignmentOperator arrayAssign); resultExpr = F.Sequence( ImmutableArray.Create(arrayLocal.LocalSymbol), ImmutableArray.Create <BoundExpression>(arrayAssign), F.ArrayAccess( arrayLocal, ImmutableArray.Create <BoundExpression>( F.Call( VisitExpression(node.Indices[0]), WellKnownMember.System_Index__GetOffset, F.ArrayLength(arrayLocal))))); } else if (TypeSymbol.Equals( indexType, _compilation.GetWellKnownType(WellKnownType.System_Range), TypeCompareKind.ConsiderEverything)) { // array[Range] is compiled to: // System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(array, Range) var elementType = ((ArrayTypeSymbol)node.Expression.Type).ElementTypeWithAnnotations; resultExpr = F.Call( receiver: null, F.WellKnownMethod(WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T) .Construct(ImmutableArray.Create(elementType)), ImmutableArray.Create( VisitExpression(node.Expression), VisitExpression(node.Indices[0]))); } else { resultExpr = base.VisitArrayAccess(node); } return(resultExpr); }
public override BoundNode VisitArrayAccess(BoundArrayAccess node) { BoundExpression expression = (BoundExpression)this.Visit(node.Expression); ReadOnlyArray<BoundExpression> indices = (ReadOnlyArray<BoundExpression>)this.VisitList(node.Indices); TypeSymbol type = this.VisitType(node.Type); if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence) { return node.Update(expression, indices, type); } var spillBuilder = new SpillBuilder(); var spillResult = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray<RefKind>.Empty); BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type); return spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess); }