summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/typetraits.nim11
-rw-r--r--lib/std/enumutils.nim19
-rw-r--r--lib/system/iterators.nim9
3 files changed, 35 insertions, 4 deletions
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index 7af78bf31..69c0329ef 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -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.
   ##
diff --git a/lib/std/enumutils.nim b/lib/std/enumutils.nim
index 704e42de5..56a6d82a7 100644
--- a/lib/std/enumutils.nim
+++ b/lib/std/enumutils.nim
@@ -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 =
@@ -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)
\ No newline at end of file
+    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
diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim
index 504695bf6..7f0076a44 100644
--- a/lib/system/iterators.nim
+++ b/lib/system/iterators.nim
@@ -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