tsugar.nim 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. discard """
  2. output: '''
  3. x + y = 30
  4. '''
  5. """
  6. import std/[sugar, algorithm, random, sets, tables, strutils]
  7. template main() =
  8. block: # `=>`
  9. block:
  10. let f1 = () => 42
  11. doAssert f1() == 42
  12. let f2 = (x: int) => x + 1
  13. doAssert f2(42) == 43
  14. let f3 = (x, y: int) => x + y
  15. doAssert f3(1, 2) == 3
  16. var x = 0
  17. let f4 = () => (x = 12)
  18. f4()
  19. doAssert x == 12
  20. let f5 = () => (discard) # simplest proc that returns void
  21. f5()
  22. block:
  23. proc call1(f: () -> int): int = f()
  24. doAssert call1(() => 12) == 12
  25. proc call2(f: int -> int): int = f(42)
  26. doAssert call2(x => x) == 42
  27. doAssert call2((x) => x) == 42
  28. doAssert call2((x: int) => x) == 42
  29. proc call3(f: (int, int) -> int): int = f(1, 2)
  30. doAssert call3((x, y) => x + y) == 3
  31. doAssert call3((x, y: int) => x + y) == 3
  32. doAssert call3((x: int, y: int) => x + y) == 3
  33. var a = 0
  34. proc call4(f: int -> void) = f(42)
  35. call4((x: int) => (a = x))
  36. doAssert a == 42
  37. proc call5(f: (int {.noSideEffect.} -> int)): int = f(42)
  38. doAssert call5(x {.noSideEffect.} => x + 1) == 43
  39. block: # `->`
  40. doAssert $(() -> int) == "proc (): int{.closure.}"
  41. doAssert $(float -> int) == "proc (i0: float): int{.closure.}"
  42. doAssert $((float) -> int) == "proc (i0: float): int{.closure.}"
  43. doAssert $((float, bool) -> int) == "proc (i0: float, i1: bool): int{.closure.}"
  44. doAssert $(() -> void) == "proc (){.closure.}"
  45. doAssert $(float -> void) == "proc (i0: float){.closure.}"
  46. doAssert $((float) -> void) == "proc (i0: float){.closure.}"
  47. doAssert $((float, bool) -> void) == "proc (i0: float, i1: bool){.closure.}"
  48. doAssert $(() {.inline.} -> int) == "proc (): int{.inline.}"
  49. doAssert $(float {.inline.} -> int) == "proc (i0: float): int{.inline.}"
  50. doAssert $((float) {.inline.} -> int) == "proc (i0: float): int{.inline.}"
  51. doAssert $((float, bool) {.inline.} -> int) == "proc (i0: float, i1: bool): int{.inline.}"
  52. block: # capture
  53. var closure1: () -> int
  54. for i in 0 .. 10:
  55. if i == 5:
  56. capture i:
  57. closure1 = () => i
  58. doAssert closure1() == 5
  59. var closure2: () -> (int, int)
  60. for i in 0 .. 10:
  61. for j in 0 .. 10:
  62. if i == 5 and j == 3:
  63. capture i, j:
  64. closure2 = () => (i, j)
  65. doAssert closure2() == (5, 3)
  66. block: # bug #16967
  67. var s = newSeq[proc (): int](5)
  68. {.push exportc.}
  69. proc bar() =
  70. for i in 0 ..< s.len:
  71. let foo = i + 1
  72. capture foo:
  73. s[i] = proc(): int = foo
  74. {.pop.}
  75. bar()
  76. for i, p in s.pairs:
  77. let foo = i + 1
  78. doAssert p() == foo
  79. block: # dup
  80. block dup_with_field:
  81. type
  82. Foo = object
  83. col, pos: int
  84. name: string
  85. proc inc_col(foo: var Foo) = inc(foo.col)
  86. proc inc_pos(foo: var Foo) = inc(foo.pos)
  87. proc name_append(foo: var Foo, s: string) = foo.name &= s
  88. let a = Foo(col: 1, pos: 2, name: "foo")
  89. block:
  90. let b = a.dup(inc_col, inc_pos):
  91. _.pos = 3
  92. name_append("bar")
  93. inc_pos
  94. doAssert(b == Foo(col: 2, pos: 4, name: "foobar"))
  95. block:
  96. let b = a.dup(inc_col, pos = 3, name = "bar"):
  97. name_append("bar")
  98. inc_pos
  99. doAssert(b == Foo(col: 2, pos: 4, name: "barbar"))
  100. block:
  101. var a = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
  102. doAssert dup(a, sort(_)) == sorted(a)
  103. doAssert a.dup(sort) == sorted(a)
  104. # Chaining:
  105. var aCopy = a
  106. aCopy.insert(10)
  107. doAssert a.dup(insert(10)).dup(sort()) == sorted(aCopy)
  108. block:
  109. when nimvm: discard
  110. else:
  111. const b = @[0, 1, 2]
  112. discard b.dup shuffle()
  113. doAssert b[0] == 0
  114. doAssert b[1] == 1
  115. block: # collect
  116. let data = @["bird", "word"] # if this gets stuck in your head, its not my fault
  117. doAssert collect(newSeq, for (i, d) in data.pairs: (if i mod 2 == 0: d)) == @["bird"]
  118. doAssert collect(initTable(2), for (i, d) in data.pairs: {i: d}) ==
  119. {0: "bird", 1: "word"}.toTable
  120. doAssert collect(initHashSet(), for d in data.items: {d}) == data.toHashSet
  121. block:
  122. let x = collect(newSeqOfCap(4)):
  123. for (i, d) in data.pairs:
  124. if i mod 2 == 0: d
  125. doAssert x == @["bird"]
  126. block: # bug #12874
  127. let bug = collect(
  128. newSeq,
  129. for (i, d) in data.pairs:(
  130. block:
  131. if i mod 2 == 0:
  132. d
  133. else:
  134. d & d
  135. )
  136. )
  137. doAssert bug == @["bird", "wordword"]
  138. block:
  139. let y = collect(newSeq):
  140. for (i, d) in data.pairs:
  141. try: parseInt(d) except: 0
  142. doAssert y == @[0, 0]
  143. block:
  144. let z = collect(newSeq):
  145. for (i, d) in data.pairs:
  146. case d
  147. of "bird": "word"
  148. else: d
  149. doAssert z == @["word", "word"]
  150. block:
  151. proc tforum(): seq[int] =
  152. collect(newSeq):
  153. for y in 0..10:
  154. if y mod 5 == 2:
  155. for x in 0..y:
  156. x
  157. doAssert tforum() == @[0, 1, 2, 0, 1, 2, 3, 4, 5, 6, 7]
  158. block:
  159. let x = collect:
  160. for d in data.items:
  161. when d is int: "word"
  162. else: d
  163. doAssert x == @["bird", "word"]
  164. block:
  165. doAssert collect(for (i, d) in pairs(data): (i, d)) == @[(0, "bird"), (1, "word")]
  166. doAssert collect(for d in data.items: (try: parseInt(d) except: 0)) == @[0, 0]
  167. doAssert collect(for (i, d) in pairs(data): {i: d}) ==
  168. {1: "word", 0: "bird"}.toTable
  169. doAssert collect(for d in data.items: {d}) == data.toHashSet
  170. block: # bug #14332
  171. template foo =
  172. discard collect(newSeq, for i in 1..3: i)
  173. foo()
  174. proc mainProc() =
  175. block: # dump
  176. # symbols in templates are gensym'd
  177. let
  178. x = 10
  179. y = 20
  180. dump(x + y) # x + y = 30
  181. block: # dumpToString
  182. template square(x): untyped = x * x
  183. let x = 10
  184. doAssert dumpToString(square(x)) == "square(x): x * x = 100"
  185. let s = dumpToString(doAssert 1+1 == 2)
  186. doAssert "failedAssertImpl" in s
  187. let s2 = dumpToString:
  188. doAssertRaises(AssertionDefect): doAssert false
  189. doAssert "except AssertionDefect" in s2
  190. static:
  191. main()
  192. mainProc()
  193. main()
  194. mainProc()