summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorIvan Bobev <bobeff@protonmail.ch>2020-11-09 11:02:01 +0200
committerGitHub <noreply@github.com>2020-11-09 10:02:01 +0100
commitd03f24147a185091344c67a720a13ca0b3c98dc2 (patch)
treefdefb9206cb008c9067a64750608ab143dcce569
parent5db181f377e30f3a06e70b48e14337722d4dc114 (diff)
downloadNim-d03f24147a185091344c67a720a13ca0b3c98dc2.tar.gz
Add a macro returning enum items count (#15824)
Add a macro `enumLen` which is used to determine the number of items in
an enumeration type to the `typetraits.nim` module. Also, add unit tests
for it in the `ttypetraits.nim` module.

Related to nimlang/Nim#15824
-rw-r--r--changelog.md2
-rw-r--r--lib/pure/typetraits.nim13
-rw-r--r--tests/metatype/ttypetraits.nim40
3 files changed, 55 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index 53730ecc5..d00d07fa1 100644
--- a/changelog.md
+++ b/changelog.md
@@ -6,6 +6,8 @@
 
 - Make `{.requiresInit.}` pragma to work for `distinct` types.
 
+- Added a macros `enumLen` for returning the number of items in an enum to the `typetraits.nim` module.
+
 - `prelude` now works with the JavaScript target.
 
 - Added `ioutils` module containing `duplicate` and `duplicateTo` to duplicate `FileHandle` using C function `dup` and `dup2`.
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index 0a05b5ded..7b6c94cbd 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -107,6 +107,19 @@ since (1, 3, 5):
 
 import std/macros
 
+macro enumLen*(T: typedesc[enum]): int =
+  ## Returns the number of items in the enum `T`.
+
+  runnableExamples:
+    type Foo = enum fooItem1 fooItem2
+    doAssert Foo.enumLen == 2
+
+  let bracketExpr = getType(T)
+  expectKind(bracketExpr, nnkBracketExpr)
+  let enumTy = bracketExpr[1]
+  expectKind(enumTy, nnkEnumTy)
+  result = newLit(enumTy.len - 1)
+
 macro genericParamsImpl(T: typedesc): untyped =
   # auxiliary macro needed, can't do it directly in `genericParams`
   result = newNimNode(nnkTupleConstr)
diff --git a/tests/metatype/ttypetraits.nim b/tests/metatype/ttypetraits.nim
index 50c474fe9..326faac82 100644
--- a/tests/metatype/ttypetraits.nim
+++ b/tests/metatype/ttypetraits.nim
@@ -303,3 +303,43 @@ block: # elementType
   var a: seq[int]
   doAssert elementType(a) is int
   doAssert elementType(seq[char].default) is char
+
+block: # enum.len
+  type
+    Direction = enum
+      north, east, south, west
+    
+    Direction2 = Direction
+    Direction3 = Direction2
+
+    TokenType = enum
+      a = 2, b = 4, c = 89
+    
+    MyEnum = enum
+      ##[This is test of enum with a doc comment.
+
+         Which is also a multi line one.]##
+      valueA = (0, "my value A"),
+        ## The items are also commented. This has both integer and string
+        ## values.
+      valueB = "value B",
+        ## This item has only a string value,
+      valueC = 2,
+        ## and this one only an integer.
+      valueD = (3, "abc")
+        ## Both, integer and string values again.
+
+    OtherEnum {.pure.} = enum
+      valueX, valueY, valueZ
+
+    MyFlag {.size: sizeof(cint).} = enum
+      A, B, C, D
+
+  static:
+    doAssert Direction.enumLen == 4
+    doAssert Direction2.enumLen == 4
+    doAssert Direction3.enumLen == 4
+    doAssert TokenType.enumLen == 3
+    doAssert MyEnum.enumLen == 4
+    doAssert OtherEnum.enumLen == 3
+    doAssert MyFlag.enumLen == 4