template_various.nim 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. discard """
  2. output: '''
  3. i2416
  4. 33
  5. foo55
  6. foo8.0
  7. fooaha
  8. bar7
  9. 10
  10. 4true
  11. 132
  12. 20
  13. 1
  14. -1
  15. 4
  16. 11
  17. 26
  18. 57
  19. -1-1-1
  20. 4
  21. 4
  22. 4
  23. 11
  24. 11
  25. 4
  26. 11
  27. 26
  28. 26
  29. 4
  30. 11
  31. 26
  32. 57
  33. 57
  34. -1-1-1
  35. '''
  36. """
  37. import macros
  38. import i2416
  39. i2416()
  40. import mcan_access_hidden_field
  41. var myfoo = createFoo(33, 44)
  42. echo myfoo.geta
  43. import mgensym_generic_cross_module
  44. foo(55)
  45. foo 8.0
  46. foo "aha"
  47. bar 7
  48. block generic_templates:
  49. type
  50. SomeObj = object of RootObj
  51. Foo[T, U] = object
  52. x: T
  53. y: U
  54. template someTemplate[T](): tuple[id: int32, obj: T] =
  55. var result: tuple[id: int32, obj: T] = (0'i32, T())
  56. result
  57. let ret = someTemplate[SomeObj]()
  58. # https://github.com/nim-lang/Nim/issues/7829
  59. proc inner[T](): int =
  60. discard
  61. template outer[A](): untyped =
  62. inner[A]()
  63. template outer[B](x: int): untyped =
  64. inner[B]()
  65. var i1 = outer[int]()
  66. var i2 = outer[int](i1)
  67. # https://github.com/nim-lang/Nim/issues/7883
  68. template t1[T: int|int64](s: string): T =
  69. var t: T
  70. t
  71. template t1[T: int|int64](x: int, s: string): T =
  72. var t: T
  73. t
  74. var i3: int = t1[int]("xx")
  75. from strutils import contains
  76. block tgetast_typeliar:
  77. proc error(s: string) = quit s
  78. macro assertOrReturn2(condition: bool; message: string) =
  79. var line = condition.lineInfo()
  80. result = quote do:
  81. block:
  82. if not likely(`condition`):
  83. error("Assertion failed: " & $(`message`) & "\n" & `line`)
  84. return
  85. macro assertOrReturn(condition: bool) =
  86. var message : NimNode = newLit(condition.repr)
  87. # echo message
  88. result = getAst assertOrReturn2(condition, message)
  89. # echo result.repr
  90. let s = result.repr
  91. doAssert """error("Assertion failed:""" in s
  92. proc point(size: int16): tuple[x, y: int16] =
  93. # returns random point in square area with given `size`
  94. assertOrReturn size > 0
  95. type
  96. MyFloat = object
  97. val: float
  98. converter to_myfloat(x: float): MyFloat {.inline.} =
  99. MyFloat(val: x)
  100. block pattern_with_converter:
  101. proc `+`(x1, x2: MyFloat): MyFloat =
  102. MyFloat(val: x1.val + x2.val)
  103. proc `*`(x1, x2: MyFloat): MyFloat =
  104. MyFloat(val: x1.val * x2.val)
  105. template optMul{`*`(a, 2.0)}(a: MyFloat): MyFloat =
  106. a + a
  107. func floatMyFloat(x: MyFloat): MyFloat =
  108. result = x * 2.0
  109. func floatDouble(x: float): float =
  110. result = x * 2.0
  111. doAssert floatDouble(5) == 10.0
  112. block procparshadow:
  113. template something(name: untyped) =
  114. proc name(x: int) =
  115. var x = x # this one should not be rejected by the compiler (#5225)
  116. echo x
  117. something(what)
  118. what(10)
  119. # bug #4750
  120. type
  121. O = object
  122. i: int
  123. OP = ptr O
  124. template alf(p: pointer): untyped =
  125. cast[OP](p)
  126. proc t1(al: pointer) =
  127. var o = alf(al)
  128. proc t2(alf: pointer) =
  129. var x = alf
  130. var o = alf(x)
  131. block symchoicefield:
  132. type Foo = object
  133. len: int
  134. var f = Foo(len: 40)
  135. template getLen(f: Foo): int = f.len
  136. doAssert f.getLen == 40
  137. # This fails, because `len` gets the nkOpenSymChoice
  138. # treatment inside the template early pass and then
  139. # it can't be recognized as a field anymore
  140. import os, times
  141. include "sunset.nimf"
  142. block ttempl:
  143. const
  144. tabs = [["home", "index"],
  145. ["news", "news"],
  146. ["documentation", "documentation"],
  147. ["download", "download"],
  148. ["FAQ", "question"],
  149. ["links", "links"]]
  150. var i = 0
  151. for item in items(tabs):
  152. var content = $i
  153. var file: File
  154. if open(file, changeFileExt(item[1], "html"), fmWrite):
  155. write(file, sunsetTemplate(current=item[1], ticker="", content=content,
  156. tabs=tabs))
  157. close(file)
  158. else:
  159. write(stdout, "cannot open file for writing")
  160. inc(i)
  161. block ttempl4:
  162. template `:=`(name, val: untyped) =
  163. var name = val
  164. ha := 1 * 4
  165. hu := "ta-da" == "ta-da"
  166. echo ha, hu
  167. import mtempl5
  168. block ttempl5:
  169. echo templ()
  170. #bug #892
  171. proc parse_to_close(value: string, index: int, open='(', close=')'): int =
  172. discard
  173. # Call parse_to_close
  174. template get_next_ident =
  175. discard "{something}".parse_to_close(0, open = '{', close = '}')
  176. get_next_ident()
  177. #identifier expected, but found '(open|open|open)'
  178. #bug #880 (also example in the manual!)
  179. template typedef(name: untyped, typ: typedesc) =
  180. type
  181. `T name` {.inject.} = typ
  182. `P name` {.inject.} = ref `T name`
  183. typedef(myint, int)
  184. var x: PMyInt
  185. block templreturntype:
  186. template `=~` (a: int, b: int): bool = false
  187. var foo = 2 =~ 3
  188. # bug #7117
  189. template parse9(body: untyped): untyped =
  190. template val9(arg: string): int {.inject.} =
  191. var b: bool
  192. if b: 10
  193. else: 20
  194. body
  195. parse9:
  196. echo val9("1")
  197. block gensym1:
  198. template x: untyped = -1
  199. template t1() =
  200. template x: untyped {.gensym, redefine.} = 1
  201. echo x() # 1
  202. template t2() =
  203. template x: untyped {.redefine.} = 1 # defaults to {.inject.}
  204. echo x() # -1 injected x not available during template definition
  205. t1()
  206. t2()
  207. block gensym2:
  208. let x,y,z = -1
  209. template `!`(xx,yy: typed): untyped =
  210. template x: untyped {.gensym.} = xx
  211. template y: untyped {.gensym.} = yy
  212. let z = x + x + y
  213. z
  214. var
  215. a = 1
  216. b = 2
  217. c = 3
  218. d = 4
  219. e = 5
  220. echo a ! b
  221. echo a ! b ! c
  222. echo a ! b ! c ! d
  223. echo a ! b ! c ! d ! e
  224. echo x,y,z
  225. block gensym3:
  226. macro liftStmts(body: untyped): auto =
  227. # convert
  228. # template x: untyped {.gensym.} =
  229. # let z = a + a + b
  230. # echo z
  231. # z
  232. # to
  233. # let z = a + a + b
  234. # echo z
  235. # template x: untyped {.gensym.} =
  236. # z
  237. #echo body.repr
  238. body.expectKind nnkStmtList
  239. result = newNimNode nnkStmtList
  240. for s in body:
  241. s.expectKind nnkTemplateDef
  242. var sle = s[6]
  243. while sle.kind == nnkStmtList:
  244. doAssert(sle.len==1)
  245. sle = sle[0]
  246. if sle.kind == nnkStmtListExpr:
  247. let n = sle.len
  248. for i in 0..(n-2):
  249. result.add sle[i]
  250. var td = newNimNode nnkTemplateDef
  251. for i in 0..5:
  252. td.add s[i]
  253. td.add sle[n-1]
  254. result.add td
  255. else:
  256. result.add s
  257. #echo result.repr
  258. let x,y,z = -1
  259. template `!`(xx,yy: typed): untyped =
  260. liftStmts:
  261. template x: untyped {.gensym.} = xx
  262. template y: untyped {.gensym.} = yy
  263. let z = x + x + y
  264. echo " ", z
  265. z
  266. var
  267. a = 1
  268. b = 2
  269. c = 3
  270. d = 4
  271. e = 5
  272. echo a ! b
  273. echo a ! b ! c
  274. echo a ! b ! c ! d
  275. echo a ! b ! c ! d ! e
  276. echo x,y,z
  277. block: # issue #2465
  278. template t() =
  279. template declX(str: string) {.gensym.} =
  280. var x {.inject.} : string = str
  281. t()
  282. doAssert not declared(declX)
  283. doAssert not compiles(declX("a string"))
  284. template t2() =
  285. template fooGensym() {.gensym.} =
  286. echo 42
  287. t2()
  288. doAssert not declared(fooGensym)
  289. doAssert not compiles(fooGensym())
  290. block identifier_construction_with_overridden_symbol:
  291. # could use add, but wanna make sure it's an override no matter what
  292. func examplefn = discard
  293. func examplefn(x: int) = discard
  294. # the function our template wants to use
  295. func examplefn1 = discard
  296. template exampletempl(n) =
  297. # attempt to build a name using the overridden symbol "examplefn"
  298. `examplefn n`()
  299. exampletempl(1)
  300. import typetraits
  301. block: # issue #4596
  302. type
  303. T0 = object
  304. T1 = object
  305. template printFuncsT() =
  306. proc getV[A](a: typedesc[A]): string =
  307. var s {. global .} = name(A)
  308. return s
  309. printFuncsT()
  310. doAssert getV(T1) == "T1"
  311. doAssert getV(T0) == "T0"
  312. doAssert getV(T0) == "T0"
  313. doAssert getV(T1) == "T1"