Skip to content

Add support for Index & Range #1369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: draft-v8
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .github/workflows/dependencies/GrammarTestingEnv.tgz
Binary file not shown.
4 changes: 4 additions & 0 deletions standard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,10 @@
- [§23.8.3](unsafe-code.md#2383-fixed-size-buffers-in-expressions) Fixed-size buffers in expressions
- [§23.8.4](unsafe-code.md#2384-definite-assignment-checking) Definite assignment checking
- [§23.9](unsafe-code.md#239-stack-allocation) Stack allocation
- [§24](ranges.md#24-ranges-and-slicing) Ranges and Slicing
- [§24.1](ranges.md#241-general) General
- [§24.2](ranges.md#242-the-index-type) The Index type
- [§24.3](ranges.md#243-the-range-type) The Range type
- [§A](grammar.md#annex-a-grammar) Grammar
- [§A.1](grammar.md#a1-general) General
- [§A.2](grammar.md#a2-lexical-grammar) Lexical grammar
Expand Down
4 changes: 3 additions & 1 deletion standard/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ Elements of arrays created by *array_creation_expression*s are always initialize

## 17.4 Array element access

Array elements are accessed using *element_access* expressions ([§12.8.12.2](expressions.md#128122-array-access)) of the form `A[I₁, I₂, ..., Iₓ]`, where `A` is an expression of an array type and each `Iₑ` is an expression of type `int`, `uint`, `long`, `ulong`, or can be implicitly converted to one or more of these types. The result of an array element access is a variable, namely the array element selected by the indices.
Array elements are accessed using the *array access* variant of *element_access* expressions ([§12.8.12.2](expressions.md#128122-array-access)) of the form `A[I₁, I₂, ..., Iₓ]`, where `A` is an expression of an array type and each `Iₑ` is an expression of type `int`, `uint`, `long`, `ulong`, or can be implicitly converted to one or more of these types. The result of an array access is a variable reference (§9.5) to the array element selected by the indices.

Array elements of single-dimensional arrays can also be accessed using an array access expression where the sole index, `I₁`, is an expression of type `Index`, `Range`, or can be implicitly converted to one or both of these types. If `I₁` is of type `Index`, or has been implicitly converted to it, then the result of the array access is a variable reference to the array element selected by the index value. If `I₁` is of type `Range`, or has been implicitly converted to it, then the result of the element access is a new array formed from a shallow copy of the array elements with indices in the `Range`, maintaining the element order.

The elements of an array can be enumerated using a `foreach` statement ([§13.9.5](statements.md#1395-the-foreach-statement)).

Expand Down
3 changes: 2 additions & 1 deletion standard/clauses.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"attributes.md"
],
"UnsafeClauses": [
"unsafe-code.md"
"unsafe-code.md",
"ranges.md"
],
"Annexes": [
"grammar.md",
Expand Down
216 changes: 174 additions & 42 deletions standard/expressions.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions standard/lexical-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -1010,11 +1010,11 @@ Punctuators are for grouping and separating.

```ANTLR
operator_or_punctuator
: '{' | '}' | '[' | ']' | '(' | ')' | '.' | ',' | ':' | ';'
| '+' | '-' | ASTERISK | SLASH | '%' | '&' | '|' | '^' | '!' | '~'
| '=' | '<' | '>' | '?' | '??' | '::' | '++' | '--' | '&&' | '||'
| '->' | '==' | '!=' | '<=' | '>=' | '+=' | '-=' | '*=' | '/=' | '%='
| '&=' | '|=' | '^=' | '<<' | '<<=' | '=>' | '??='
: '{' | '}' | '[' | ']' | '(' | ')' | '.' | ',' | ':' | ';'
| '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '!' | '~'
| '=' | '<' | '>' | '?' | '??' | '::' | '++' | '--' | '&&' | '||'
| '->' | '==' | '!=' | '<=' | '>=' | '+=' | '-=' | '*=' | '/=' | '%='
| '&=' | '|=' | '^=' | '<<' | '<<=' | '=>' | '??=' | '..'
;

right_shift
Expand Down
309 changes: 309 additions & 0 deletions standard/ranges.md

Large diffs are not rendered by default.

173 changes: 173 additions & 0 deletions standard/standard-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ namespace System
public ArgumentException(string? message, Exception? innerException);
}

public class ArgumentOutOfRangeException : ArgumentException
{
public ArgumentOutOfRangeException(string? paramName);
public ArgumentOutOfRangeException(string? paramName, string? message);
}

public class ArithmeticException : Exception
{
public ArithmeticException();
Expand Down Expand Up @@ -130,6 +136,11 @@ namespace System
void Dispose();
}

public interface IEquatable<T>
{
bool Equals(T? other);
}

public interface IFormattable { }

public sealed class IndexOutOfRangeException : Exception
Expand Down Expand Up @@ -396,6 +407,164 @@ namespace System
public OperationCanceledException(string? message, Exception? innerException);
}

/// <summary>
/// A read-only value type which represents an abstract
/// index to be used with collections.
/// - The Index can be relative to the start or end of a
/// collection.
/// - An Index can be converted to a zero-based concrete
/// from-start index to be used with a collection
/// of some specified length.
/// - Equality between Index values is provided, however
/// unlike concrete indices they are not ordered.
/// - Array and String element access support indexing
/// with Index values.
/// </summary>
public readonly struct Index : IEquatable<Index>
{
/// <summary>
/// Construct an Index from an integer value and a
/// boolean indicating whether the value is relative
/// to the end (true) or start (false).
/// </summary>
/// <param name="value">
/// The value, must be ≥ 0.
/// </param>
/// <param name="fromEnd">
/// Optional boolean indicating whether the Index is
/// relative to the end (true) or start (false).
/// The default value is false.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if value < 0.
/// </exception>
/// <remarks>
/// If the Index is relative to the start then:
/// - the value 0 refers to the first element.
/// If the Index is relative to the end then:
/// - the value 1 refers to the last element; and
/// - the value 0 refers to beyond last element.
/// </remarks>
public Index(int value, bool fromEnd = false);

/// <summary>
/// Implicit conversion from integer to a
/// from-start Index.
/// </summary>
/// <remarks>
/// The predefined operator:
/// <c>Index operator ^(int value);</c>
/// is provided to convert from integer to a
/// from-end Index.
/// </remarks>
public static implicit operator Index(int value);

/// <summary>
/// Return the value.
/// </summary>
public int Value { get; }

/// <summary>
/// Return whether the Index is relative to
/// the end (true) or start (false).
/// </summary>
public bool IsFromEnd { get; }

/// <summary>
/// Return a concrete from-start index for a
/// given collection length.
/// </summary>
/// <param name="length">
/// The length of the collection that the index
/// will be used with.
/// </param>
/// <remarks>
/// This method performs no sanity checking and
/// will never throw an IndexOutOfRangeException.
/// It is expected that the returned index will be
/// used with a collection which will do validation.
/// </remarks>
public int GetOffset(int length);

/// <summary>
/// Indicates whether the current Index value is
/// equal to another Index value.
/// </summary>
/// <param name="other">
/// The value to compare with this Index.
/// </param>
public bool Equals(Index other);
}

/// <summary>
/// A read-only value type which represents a range of
/// abstract indices to be used with collections.
/// - The Range has two Index properties, Start and End.
/// - A Range can be converted to a concrete index from
/// the start and a length value to be used with a
/// collection of some specified length.
/// - Equality between Range values is provided,
/// however they are not ordered.
/// - Array and String element access supports indexing
/// with Range values, returning a sub-array/substring
/// of the indexed value respectively.
/// </summary>
public readonly struct Range : IEquatable<Index>
{
/// <summary>
/// Construct a Range from two Index values.
/// </summary>
/// <param name="start">
/// The inclusive Index value for the start
/// of the range.
/// </param>
/// <param name="end">
/// The exclusive Index value for the end
/// of the range.</param>
/// <remarks>
/// As Index values represent unordered abstract
/// indices no sanity checking can be performed
/// on the resultant Range value,
/// <see cref="GetOffsetAndLength">".
///
/// The predefined operator:
/// <c>Range operator ..(Index start, Index end);</c>
/// also exists to create a Range value.
/// </remarks>
public Range(Index start, Index end);

/// <summary>Return the starting Index.</summary>
public Index Start { get; }

/// <summary>Return the ending Index.</summary>
public Index End { get; }

/// <summary>
/// Return a concrete from-start index and the
/// range length for a given collection length.
/// </summary>
/// <param name="length">
/// The length of the collection that the result
/// will be used with.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if the range is not valid wrt length.
/// </exception>
/// <returns>
/// A tuple consisting of an index value and range length
/// </returns>
public (int Offset, int Length) GetOffsetAndLength(int length);

/// <summary>
/// Indicates whether the current Range value is equal
/// to another Range value.
/// </summary>
/// <param name="other">
/// The value to compare with this Range.
/// </param>
public bool Equals(Range other);
}

public readonly ref struct ReadOnlySpan<T>
{
public int Length { get; }
Expand Down Expand Up @@ -1105,6 +1274,7 @@ The following library types are referenced in this specification. The full names

- `global::System.Action`
- `global::System.ArgumentException`
- `global::System.ArgumentOutOfRangeException`
- `global::System.ArithmeticException`
- `global::System.Array`
- `global::System.ArrayTypeMisMatchException`
Expand All @@ -1124,7 +1294,9 @@ The following library types are referenced in this specification. The full names
- `global::System.GC`
- `global::System.IAsyncDisposable`
- `global::System.IDisposable`
- `global::System.IEquatable<T>`
- `global::System.IFormattable`
- `global::System.Index`
- `global::System.IndexOutOfRangeException`
- `global::System.Int16`
- `global::System.Int32`
Expand All @@ -1140,6 +1312,7 @@ The following library types are referenced in this specification. The full names
- `global::System.OperationCanceledException`
- `global::System.OutOfMemoryException`
- `global::System.OverflowException`
- `global::System.Range`
- `global::System.ReadOnlySpan`
- `global::System.SByte`
- `global::System.Single`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ *
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ unary_expression
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ range_expression
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ identifier
⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ number
Expand Down
Loading