Skip to content

Commit

Permalink
add enumutils.items for sparse enums, typetraits.SomeSparseEnum (nim-…
Browse files Browse the repository at this point in the history
…lang#17080)

* add enumutils.items for enum with holes
* changelog
* ref in lib.rst
* use `type SomeSparseEnum* = (not Ordinal) and enum` instead of concept
* address comment: rename back to enum with holes
  • Loading branch information
timotheecour authored and ardek66 committed Mar 26, 2021
1 parent f09bf1f commit f9c0dd4
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 6 deletions.
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

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()

0 comments on commit f9c0dd4

Please sign in to comment.