topensym.nim 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. {.experimental: "templateOpenSym".}
  2. block: # issue #24002
  3. type Result[T, E] = object
  4. func value[T, E](self: Result[T, E]): T {.inline.} =
  5. discard
  6. func value[T: not void, E](self: var Result[T, E]): var T {.inline.} =
  7. discard
  8. template unrecognizedFieldWarning =
  9. doAssert value == 123
  10. let x = value
  11. doAssert value == x
  12. proc readValue(value: var int) =
  13. unrecognizedFieldWarning()
  14. var foo: int = 123
  15. readValue(foo)
  16. block: # issue #22605 for templates, normal call syntax
  17. const error = "bad"
  18. template valueOr(self: int, def: untyped): untyped =
  19. case false
  20. of true: ""
  21. of false:
  22. template error: untyped {.used, inject.} = "good"
  23. def
  24. template g(T: type): string =
  25. var res = "ok"
  26. let x = valueOr 123:
  27. res = $error
  28. "dummy"
  29. res
  30. doAssert g(int) == "good"
  31. template g2(T: type): string =
  32. bind error # use the bad version on purpose
  33. var res = "ok"
  34. let x = valueOr 123:
  35. res = $error
  36. "dummy"
  37. res
  38. doAssert g2(int) == "bad"
  39. block: # issue #22605 for templates, method call syntax
  40. const error = "bad"
  41. template valueOr(self: int, def: untyped): untyped =
  42. case false
  43. of true: ""
  44. of false:
  45. template error: untyped {.used, inject.} = "good"
  46. def
  47. template g(T: type): string =
  48. var res = "ok"
  49. let x = 123.valueOr:
  50. res = $error
  51. "dummy"
  52. res
  53. doAssert g(int) == "good"
  54. template g2(T: type): string =
  55. bind error # use the bad version on purpose
  56. var res = "ok"
  57. let x = 123.valueOr:
  58. res = $error
  59. "dummy"
  60. res
  61. doAssert g2(int) == "bad"
  62. block: # issue #22605 for templates, original complex example
  63. type Xxx = enum
  64. error
  65. value
  66. type
  67. Result[T, E] = object
  68. when T is void:
  69. when E is void:
  70. oResultPrivate*: bool
  71. else:
  72. case oResultPrivate*: bool
  73. of false:
  74. eResultPrivate*: E
  75. of true:
  76. discard
  77. else:
  78. when E is void:
  79. case oResultPrivate*: bool
  80. of false:
  81. discard
  82. of true:
  83. vResultPrivate*: T
  84. else:
  85. case oResultPrivate*: bool
  86. of false:
  87. eResultPrivate*: E
  88. of true:
  89. vResultPrivate*: T
  90. template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped =
  91. let s = (self) # TODO avoid copy
  92. case s.oResultPrivate
  93. of true:
  94. s.vResultPrivate
  95. of false:
  96. when E isnot void:
  97. template error: untyped {.used, inject.} = s.eResultPrivate
  98. def
  99. proc f(): Result[int, cstring] =
  100. Result[int, cstring](oResultPrivate: false, eResultPrivate: "f")
  101. template g(T: type): string =
  102. var res = "ok"
  103. let x = f().valueOr:
  104. res = $error
  105. 123
  106. res
  107. doAssert g(int) == "f"
  108. template g2(T: type): string =
  109. bind error # use the bad version on purpose
  110. var res = "ok"
  111. let x = f().valueOr:
  112. res = $error
  113. 123
  114. res
  115. doAssert g2(int) == "error"
  116. block: # issue #23865 for templates
  117. type Xxx = enum
  118. error
  119. value
  120. type
  121. Result[T, E] = object
  122. when T is void:
  123. when E is void:
  124. oResultPrivate: bool
  125. else:
  126. case oResultPrivate: bool
  127. of false:
  128. eResultPrivate: E
  129. of true:
  130. discard
  131. else:
  132. when E is void:
  133. case oResultPrivate: bool
  134. of false:
  135. discard
  136. of true:
  137. vResultPrivate: T
  138. else:
  139. case oResultPrivate: bool
  140. of false:
  141. eResultPrivate: E
  142. of true:
  143. vResultPrivate: T
  144. func error[T, E](self: Result[T, E]): E =
  145. ## Fetch error of result if set, or raise Defect
  146. case self.oResultPrivate
  147. of true:
  148. when T isnot void:
  149. raiseResultDefect("Trying to access error when value is set", self.vResultPrivate)
  150. else:
  151. raiseResultDefect("Trying to access error when value is set")
  152. of false:
  153. when E isnot void:
  154. self.eResultPrivate
  155. template valueOr[T: not void, E](self: Result[T, E], def: untyped): untyped =
  156. let s = (self) # TODO avoid copy
  157. case s.oResultPrivate
  158. of true:
  159. s.vResultPrivate
  160. of false:
  161. when E isnot void:
  162. template error: untyped {.used, inject.} = s.eResultPrivate
  163. def
  164. proc f(): Result[int, cstring] =
  165. Result[int, cstring](oResultPrivate: false, eResultPrivate: "f")
  166. template g(T: type): string =
  167. var res = "ok"
  168. let x = f().valueOr:
  169. res = $error
  170. 123
  171. res
  172. doAssert g(int) == "f"
  173. import std/sequtils
  174. block: # issue #15314
  175. var it: string
  176. var nums = @[1,2,3]
  177. template doubleNums() =
  178. nums.applyIt(it * 2)
  179. doubleNums()
  180. doAssert nums == @[2, 4, 6]