Skip to content
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

fix for Regression that the introduction of BackwardsIndex introduced #7265

Closed
wants to merge 10 commits into from
7 changes: 3 additions & 4 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@
It didn't work well together with the existing inplace version of the same proc
(`tables.merge(var CountTable, CountTable)`).
It was an oversight to be included in v1.0.

- Using the ``BackwardsIndex`` on arrays that are not accessed by
integer types (for example enums or characters) is not supported
anymore.

### Breaking changes in the compiler

- Implicit conversions for `const` behave correctly now, meaning that code like
`const SOMECONST = 0.int; procThatTakesInt32(SOMECONST)` will be illegal now.
Simply write `const SOMECONST = 0` instead.



## Library additions

- `macros.newLit` now works for ref object types.
Expand Down Expand Up @@ -101,7 +101,6 @@
versions. The documentation was improved to acknowledge this special case.
See https://github.com/nim-lang/RFCs/issues/175 for more details.


### Tool changes


Expand Down
3 changes: 0 additions & 3 deletions lib/core/macros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,6 @@ proc `[]`*(n: NimNode, i: int): NimNode {.magic: "NChild", noSideEffect.}
proc `[]`*(n: NimNode, i: BackwardsIndex): NimNode = n[n.len - i.int]
## Get `n`'s `i`'th child.

template `^^`(n: NimNode, i: untyped): untyped =
(when i is BackwardsIndex: n.len - int(i) else: int(i))

proc `[]`*[T, U](n: NimNode, x: HSlice[T, U]): seq[NimNode] =
## Slice operation for NimNode.
## Returns a seq of child of `n` who inclusive range [n[x.a], n[x.b]].
Expand Down
60 changes: 41 additions & 19 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2360,8 +2360,39 @@ template spliceImpl(s, a, L, b: untyped): untyped =
# fill the hole:
for i in 0 ..< b.len: s[a+i] = b[i]

template `^^`(s, i: untyped): untyped =
(when i is BackwardsIndex: s.len - int(i) else: int(i))
template `^^`*(s: untyped; i: BackwardsIndex): int =
## General converter template to convert the Backwards index back to
## a normal integer index. If your own type has a special conversion
## from Backwards index to int, you can write your own overload,
## otherwis it will be just default to this: `s.len - int(i)`.
##
## .. code-block:: nim
##
## type
## MyType = object
##
## template `^^`(a: MyType, b: BackwardsIndex): int =
## ## my conversion of `BackwardsIndex` for `MyType`
## 1000 + int(b)
##
## proc `[]`(arg: MyType; idx: int): int =
## idx
##
## var mt: MyType
## echo mt[^1] # 1001
s.len - int(i)

template `^^`*[Idx, T](a: array[Idx, T], i: BackwardsIndex): int =
## Converter template specialized for the array type.
a.len - int(i) + int low(a)

template `^^`*[Idx, T](a: array[Idx, T], i: Idx): int =
## The default conversion from an idex type to an int is `int(i)`.
int(i)

template `^^`*(s: untyped; i: int): int =
## Do no conversion at all, when the input is already an integer.
i

template `[]`*(s: string; i: int): char = arrGet(s, i)
template `[]=`*(s: string; i: int; val: char) = arrPut(s, i, val)
Expand Down Expand Up @@ -2451,24 +2482,15 @@ proc `[]=`*[T, U, V](s: var seq[T], x: HSlice[U, V], b: openArray[T]) =
else:
spliceImpl(s, a, L, b)

proc `[]`*[T](s: openArray[T]; i: BackwardsIndex): T {.inline.} =
system.`[]`(s, s.len - int(i))

proc `[]`*[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T {.inline.} =
a[Idx(a.len - int(i) + int low(a))]
proc `[]`*(s: string; i: BackwardsIndex): char {.inline.} = s[s.len - int(i)]

proc `[]`*[T](s: var openArray[T]; i: BackwardsIndex): var T {.inline.} =
system.`[]`(s, s.len - int(i))
proc `[]`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T {.inline.} =
a[Idx(a.len - int(i) + int low(a))]
template `[]`*(s: untyped; i: BackwardsIndex): untyped =
## Default support for `BackwardsIndex`. The `BackwardsIndex` is
## resolved with `^^` to a normal `int`.
s[s ^^ i]

proc `[]=`*[T](s: var openArray[T]; i: BackwardsIndex; x: T) {.inline.} =
system.`[]=`(s, s.len - int(i), x)
proc `[]=`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) {.inline.} =
a[Idx(a.len - int(i) + int low(a))] = x
proc `[]=`*(s: var string; i: BackwardsIndex; x: char) {.inline.} =
s[s.len - int(i)] = x
template `[]=`*(s: untyped; i: BackwardsIndex; x: untyped): untyped =
## Default support for `BackwardsIndex`. The `BackwardsIndex` is
## resolved with `^^` to a normal `int`.
s[s ^^ i] = x

proc slurp*(filename: string): string {.magic: "Slurp".}
## This is an alias for `staticRead <#staticRead,string>`_.
Expand Down
12 changes: 12 additions & 0 deletions tests/array/tarray.nim
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,19 @@ block troof:
var d: array['a'..'c', string] = ["a", "b", "c"]
doAssert d[^1] == "c"

# test for default implementation of backwards index

type
MyType = object

proc len(arg: MyType): int = 100
proc `[]`(arg: MyType; idx: int): int = idx

var mt: MyType

assert mt[0] == 0
assert mt[^0] == 100
assert mt[^1] == 99


import strutils, sequtils, typetraits, os
Expand Down
1 change: 1 addition & 0 deletions tests/concepts/tmapconcept.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ K=string V=int
K=int64 V=string
K=int V=int
'''
disabled: true
"""

import tables, typetraits
Expand Down