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

add enumutils.items for sparse enums, typetraits.SomeSparseEnum #17080

Merged
merged 14 commits into from
Feb 23, 2021
6 changes: 4 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
- Added `randState` template that exposes the default random number generator.
Useful for library authors.

- Added std/enumutils module containing `genEnumCaseStmt` macro that generates
case statement to parse string to enum.
- Added `std/enumutils` module. Added `genEnumCaseStmt` macro that generates case statement to parse string to enum.
Added `items` for enums with holes.

- Added `typetraits.SomeEnumWithHoles` for enums with holes.

- Removed deprecated `iup` module from stdlib, it has already moved to
[nimble](https://github.com/nim-lang/iup).
Expand Down
3 changes: 3 additions & 0 deletions doc/lib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ Algorithms
* `algorithm <algorithm.html>`_
This module implements some common generic algorithms like sort or binary search.

* `std/enumutils <enumutils.html>`_
This module adds functionality for the built-in ``enum`` type.

* `sequtils <sequtils.html>`_
This module implements operations for the built-in ``seq`` type
which were inspired by functional programming languages.
Expand Down
11 changes: 11 additions & 0 deletions lib/pure/typetraits.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@
import std/private/since
export system.`$` # for backward compatibility

type SomeEnumWithHoles* = (not Ordinal) and enum ## Enum with holes.

runnableExamples:
type A = enum a0 = 2, a1 = 4, a2
type B = enum b0 = 2, b1, b2
assert A is SomeEnumWithHoles
assert B isnot SomeEnumWithHoles
assert int isnot SomeEnumWithHoles
type C[T] = enum h0 = 2, h1 = 4
assert C[float] is SomeEnumWithHoles

proc name*(t: typedesc): string {.magic: "TypeTrait".} =
## Returns the name of the given type.
##
Expand Down
19 changes: 17 additions & 2 deletions lib/std/enumutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
# distribution, for details about the copyright.
#

import macros
import std/macros

# xxx `genEnumCaseStmt` needs tests and runnableExamples
Araq marked this conversation as resolved.
Show resolved Hide resolved

macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
userMin, userMax: static[int], normalizer: static[proc(s :string): string]): untyped =
Expand Down Expand Up @@ -61,4 +63,17 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
result.add nnkElse.newTree(raiseStmt)
else:
expectKind(default, nnkSym)
result.add nnkElse.newTree(default)
result.add nnkElse.newTree(default)

macro enumWithHolesFullRange(a: typed): untyped =
newNimNode(nnkCurly).add(a.getType[1][1..^1])

iterator items*[T: enum and not Ordinal](E: typedesc[T]): T =
## Iterates over an enum with holes.
runnableExamples:
type A = enum a0 = 2, a1 = 4, a2
type B[T] = enum b0 = 2, b1 = 4
from std/sequtils import toSeq
assert A.toSeq == [a0, a1, a2]
assert B[float].toSeq == [B[float].b0, B[float].b1]
for a in enumWithHolesFullRange(E): yield a
9 changes: 7 additions & 2 deletions lib/system/iterators.nim
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,13 @@ iterator mitems*(a: var cstring): var char {.inline.} =
yield a[i]
inc(i)

iterator items*[T: enum](E: typedesc[T]): T =
## Iterates over the values of the enum ``E``.
iterator items*[T: enum and Ordinal](E: typedesc[T]): T =
## Iterates over the values of `E`.
## See also `enumutils.items` for enums with holes.
runnableExamples:
type Goo = enum g0 = 2, g1, g2
from std/sequtils import toSeq
assert Goo.toSeq == [g0, g1, g2]
for v in low(E) .. high(E):
yield v

Expand Down
16 changes: 16 additions & 0 deletions tests/stdlib/tenumutils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
discard """
targets: "c js"
"""

import std/enumutils
from std/sequtils import toSeq

template main =
block: # items
type A = enum a0 = 2, a1 = 4, a2
type B[T] = enum b0 = 2, b1 = 4
doAssert A.toSeq == [a0, a1, a2]
doAssert B[float].toSeq == [B[float].b0, B[float].b1]

static: main()
main()