trt_discrim.nim 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. template accept(x) =
  2. static: assert(compiles(x))
  3. template reject(x) =
  4. static: assert(not compiles(x))
  5. type
  6. Kind = enum k1 = 0, k2 = 33, k3 = 84, k4 = 278, k5 = 1000 # Holed enum work! #No they don't..
  7. KindObj = object
  8. case kind: Kind
  9. of k1, k2..k3: i32: int32
  10. of k4: f32: float32
  11. else: str: string
  12. IntObj = object
  13. case kind: uint8
  14. of low(uint8) .. 127: bad: string
  15. of 128'u8: neutral: string
  16. of 129 .. high(uint8): good: string
  17. OtherKind = enum ok1, ok2, ok3, ok4, ok5
  18. NestedKindObj = object
  19. case kind: Kind
  20. of k3, k5: discard
  21. of k2: str: string
  22. of k1, k4:
  23. case otherKind: OtherKind
  24. of ok1, ok2..ok3: i32: int32
  25. of ok4: f32: float32
  26. else: nestedStr: string
  27. let kind = k4 # actual value should have no impact on the analysis.
  28. accept: # Mimics the structure of the type. The optimial case.
  29. case kind
  30. of k1, k2, k3: discard KindObj(kind: kind, i32: 1)
  31. of k4: discard KindObj(kind: kind, f32: 2.0)
  32. else: discard KindObj(kind: kind, str: "3")
  33. accept: # Specifying the else explicitly is fine too.
  34. case kind
  35. of k1, k2, k3: discard KindObj(kind: kind, i32: 1)
  36. of k4: discard KindObj(kind: kind, f32: 2.0)
  37. of k5: discard KindObj(kind: kind, str: "3")
  38. accept:
  39. case kind
  40. of k1..k3, k5: discard
  41. else: discard KindObj(kind: kind, f32: 2.0)
  42. accept:
  43. case kind
  44. of k4, k5: discard
  45. else: discard KindObj(kind: kind, i32: 1)
  46. accept: # elif branches are ignored
  47. case kind
  48. of k1, k2, k3: discard KindObj(kind: kind, i32: 1)
  49. of k4: discard KindObj(kind: kind, f32: 2.0)
  50. elif kind in {k1..k5}: discard
  51. else: discard KindObj(kind: kind, str: "3")
  52. reject: # k4 conflicts with i32
  53. case kind
  54. of k1, k2, k3, k4: discard KindObj(kind: kind, i32: 1)
  55. else: discard KindObj(kind: kind, str: "3")
  56. reject: # k4 is not caught, conflicts with str in the else branch
  57. case kind
  58. of k1, k2, k3: discard KindObj(kind: kind, i32: 1)
  59. else: discard KindObj(kind: kind, str: "3")
  60. reject: # elif branches are ignored
  61. case kind
  62. of k1, k2, k3: discard KindObj(kind: kind, i32: 1)
  63. elif kind == k4: discard
  64. else: discard KindObj(kind: kind, str: "3")
  65. let intKind = 29'u8
  66. accept:
  67. case intKind
  68. of low(uint8) .. 127: discard IntObj(kind: intKind, bad: "bad")
  69. of 128'u8: discard IntObj(kind: intKind, neutral: "neutral")
  70. of 129 .. high(uint8): discard IntObj(kind: intKind, good: "good")
  71. reject: # 0 leaks to else
  72. case intKind
  73. of low(uint8) .. 127: discard IntObj(kind: intKind, bad: "bad")
  74. of 129 .. high(uint8): discard IntObj(kind: intKind, good: "good")
  75. accept:
  76. case intKind
  77. of low(uint8) .. 127: discard IntObj(kind: intKind, bad: "bad")
  78. of 128'u8: discard IntObj(kind: intKind, neutral: "neutral")
  79. of 139'u8, 140 .. high(uint8), 129'u8 .. 138'u8: discard IntObj(kind: intKind, good: "good")
  80. accept:
  81. case kind
  82. of {k1, k2}, [k3]: discard KindObj(kind: kind, i32: 1)
  83. of k4: discard KindObj(kind: kind, f32: 2.0)
  84. else: discard KindObj(kind: kind, str: "3")
  85. reject:
  86. case kind
  87. of {k1, k2, k3}, [k4]: discard KindObj(kind: kind, i32: 1)
  88. else: discard KindObj(kind: kind, str: "3")
  89. accept:
  90. case kind
  91. of k3, k5: discard NestedKindObj(kind: kind)
  92. of k2: discard NestedKindObj(kind: kind, str: "not nested")
  93. of k1, k4:
  94. let otherKind = ok5
  95. case otherKind
  96. of ok1..ok3: discard NestedKindObj(kind: kind, otherKind: otherKind, i32: 3)
  97. of ok4: discard NestedKindObj(kind: kind, otherKind: otherKind, f32: 5.0)
  98. else: discard NestedKindObj(kind: kind, otherKind: otherKind,
  99. nestedStr: "nested")
  100. reject:
  101. case kind
  102. of k3, k5: discard NestedKindObj(kind: kind)
  103. of k2: discard NestedKindObj(kind: kind, str: "not nested")
  104. of k1, k4:
  105. let otherKind = ok5
  106. case otherKind
  107. of ok1..ok3: discard NestedKindObj(kind: kind, otherKind: otherKind, i32: 3)
  108. else: discard NestedKindObj(kind: kind, otherKind: otherKind,
  109. nestedStr: "nested")
  110. var varkind = k4
  111. reject: # not immutable.
  112. case varkind
  113. of k1, k2, k3: discard KindObj(varkind: kind, i32: 1)
  114. of k4: discard KindObj(varkind: kind, f32: 2.0)
  115. else: discard KindObj(varkind: kind, str: "3")
  116. accept:
  117. proc kindProc(kind: Kind): KindObj =
  118. case kind:
  119. of k1: result = KindObj(kind: kind, i32: 1)
  120. else: discard
  121. reject:
  122. proc varKindProc(kind: var Kind): KindObj =
  123. case kind:
  124. of k1: result = KindObj(kind: kind, i32: 1)
  125. else: discard
  126. type
  127. Kind3 = enum
  128. A, B, C, E
  129. OkRange = range[B..C]
  130. NotOkRange = range[B..E]
  131. CaseObject = object
  132. case kind: Kind3
  133. of B, C:
  134. field: int
  135. else: discard
  136. accept:
  137. let rtDiscriminator: OkRange = B
  138. discard CaseObject(kind: rtDiscriminator, field: 1)
  139. accept:
  140. let rtDiscriminator = B
  141. discard CaseObject(kind: OkRange(rtDiscriminator), field: 1)
  142. accept:
  143. const rtDiscriminator: NotOkRange = B
  144. discard CaseObject(kind: rtDiscriminator, field: 1)
  145. accept:
  146. discard CaseObject(kind: NotOkRange(B), field: 1)
  147. reject:
  148. let rtDiscriminator: NotOkRange = B
  149. discard CaseObject(kind: rtDiscriminator, field: 1)
  150. reject:
  151. let rtDiscriminator = B
  152. discard CaseObject(kind: NotOkRange(rtDiscriminator), field: 1)
  153. reject:
  154. type Obj = object
  155. case x: int
  156. of 0 .. 1000:
  157. field: int
  158. else:
  159. discard
  160. let x: range[0..15] = 1
  161. let o = Obj(x: x, field: 1)