toverloadable_enums.nim 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. discard """
  2. output: '''B
  3. 0
  4. E2-B'''
  5. joinable: false
  6. """
  7. {.experimental: "overloadableEnums".}
  8. type
  9. E1 = enum
  10. value1,
  11. value2
  12. E2 = enum
  13. value1,
  14. value2 = 4
  15. const
  16. Lookuptable = [
  17. E1.value1: "1",
  18. value2: "2"
  19. ]
  20. when false:
  21. const
  22. Lookuptable: array[E1, string] = [
  23. value1: "1",
  24. value2: "2"
  25. ]
  26. proc p(e: E1): int =
  27. # test that the 'case' statement is smart enough:
  28. case e
  29. of value1: echo "A"
  30. of value2: echo "B"
  31. let v = p value2 # ERROR: ambiguous!
  32. # (value2|value2) nkClosedSymChoice -> nkSym
  33. proc x(p: int) = discard
  34. proc x(p: string) = discard
  35. proc takeCallback(param: proc(p: int)) = discard
  36. takeCallback x
  37. echo ord v
  38. block: # https://github.com/nim-lang/RFCs/issues/8
  39. type
  40. Enum1 = enum
  41. A, B, C
  42. Enum2 = enum
  43. A, Z
  44. proc f(e: Enum1): int = ord(e)
  45. proc g(e: Enum2): int = ord(e)
  46. proc h(e: Enum1): int = ord(e)
  47. proc h(e: Enum2): int = ord(e)
  48. let fA = f(A) # Type of A is well defined
  49. let gA = g(A) # Same as above
  50. let hA1 = h(Enum1.A) # A requires disambiguation
  51. let hA2 = h(Enum2.A) # Similarly
  52. let hA3 = h(B)
  53. let hA4 = h(B)
  54. let x = ord(Enum1.A) # Also
  55. doAssert fA == 0
  56. doAssert gA == 0
  57. doAssert hA1 == 0
  58. doAssert hA2 == 0
  59. doAssert x == 0
  60. doAssert hA3 == 1
  61. doAssert hA4 == 1
  62. # bug #18769
  63. proc g3[T](x: T, e: E2): int =
  64. case e
  65. of value1: echo "E2-A" # Error: type mismatch: got 'E1' for 'value1' but expected 'E2 = enum'
  66. of value2: echo "E2-B"
  67. let v5 = g3(99, E2.value2)
  68. block: # only allow enums to overload enums
  69. # mirrors behavior without overloadableEnums
  70. proc foo() = discard
  71. block:
  72. type Foo = enum foo
  73. doAssert foo is Foo
  74. foo()
  75. import macros
  76. block: # test with macros/templates
  77. type
  78. Enum1 = enum
  79. value01, value02
  80. Enum2 = enum
  81. value01, value10
  82. macro isOneM(a: untyped): bool =
  83. result = newCall(bindSym"==", a, ident"value01")
  84. macro isOneMS(a: untyped): bool =
  85. result = newCall(bindSym"==", a, bindSym"value01")
  86. template isOneT(a: untyped): bool =
  87. a == value01
  88. let e1 = Enum1.value01
  89. let e2 = Enum2.value01
  90. doAssert isOneM(e1)
  91. doAssert isOneM(e2)
  92. doAssert isOneMS(e1)
  93. doAssert isOneMS(e2)
  94. doAssert isOneT(e1)
  95. doAssert isOneT(e2)