tconcepts.nim 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. discard """
  2. output: '''
  3. 10
  4. 20
  5. int
  6. 20
  7. 3
  8. x as ParameterizedType[T]
  9. x as ParameterizedType[T]
  10. x as ParameterizedType[T]
  11. x as ParameterizedType
  12. x as ParameterizedType
  13. x as CustomTypeClass
  14. 1
  15. 2
  16. 3
  17. 4
  18. 5
  19. 6
  20. a
  21. b
  22. t
  23. e
  24. s
  25. t
  26. z
  27. e
  28. 1
  29. 2
  30. 3
  31. 20
  32. 10
  33. 5
  34. 9
  35. '''
  36. """
  37. import typetraits, strutils
  38. block tcomparable:
  39. type
  40. Comparable = concept a
  41. (a < a) is bool
  42. proc myMax(a, b: Comparable): Comparable =
  43. if a < b:
  44. return b
  45. else:
  46. return a
  47. doAssert myMax(5, 10) == 10
  48. doAssert myMax(31.3, 1.23124) == 31.3
  49. block tconceptinclosure:
  50. type
  51. FonConcept = concept x
  52. x.x is int
  53. GenericConcept[T] = concept x
  54. x.x is T
  55. const L = T.name.len
  56. Implementation = object
  57. x: int
  58. Closure = object
  59. f: proc()
  60. proc f1(x: FonConcept): Closure =
  61. result.f = proc () =
  62. echo x.x
  63. proc f2(x: GenericConcept): Closure =
  64. result.f = proc () =
  65. echo x.x
  66. echo GenericConcept.T.name
  67. proc f3[T](x: GenericConcept[T]): Closure =
  68. result.f = proc () =
  69. echo x.x
  70. echo x.L
  71. let x = Implementation(x: 10)
  72. let y = Implementation(x: 20)
  73. let a = x.f1
  74. let b = x.f2
  75. let c = x.f1
  76. let d = y.f2
  77. let e = y.f3
  78. a.f()
  79. d.f()
  80. e.f()
  81. block overload_precedence:
  82. type ParameterizedType[T] = object
  83. type CustomTypeClass = concept c
  84. true
  85. # 3 competing procs
  86. proc a[T](x: ParameterizedType[T]) =
  87. echo "x as ParameterizedType[T]"
  88. proc a(x: ParameterizedType) =
  89. echo "x as ParameterizedType"
  90. proc a(x: CustomTypeClass) =
  91. echo "x as CustomTypeClass"
  92. # the same procs in different order
  93. proc b(x: ParameterizedType) =
  94. echo "x as ParameterizedType"
  95. proc b(x: CustomTypeClass) =
  96. echo "x as CustomTypeClass"
  97. proc b[T](x: ParameterizedType[T]) =
  98. echo "x as ParameterizedType[T]"
  99. # and yet another order
  100. proc c(x: CustomTypeClass) =
  101. echo "x as CustomTypeClass"
  102. proc c(x: ParameterizedType) =
  103. echo "x as ParameterizedType"
  104. proc c[T](x: ParameterizedType[T]) =
  105. echo "x as ParameterizedType[T]"
  106. # remove the most specific one
  107. proc d(x: ParameterizedType) =
  108. echo "x as ParameterizedType"
  109. proc d(x: CustomTypeClass) =
  110. echo "x as CustomTypeClass"
  111. # then shuffle the order again
  112. proc e(x: CustomTypeClass) =
  113. echo "x as CustomTypeClass"
  114. proc e(x: ParameterizedType) =
  115. echo "x as ParameterizedType"
  116. # the least specific one is a match
  117. proc f(x: CustomTypeClass) =
  118. echo "x as CustomTypeClass"
  119. a(ParameterizedType[int]())
  120. b(ParameterizedType[int]())
  121. c(ParameterizedType[int]())
  122. d(ParameterizedType[int]())
  123. e(ParameterizedType[int]())
  124. f(ParameterizedType[int]())
  125. block templates:
  126. template typeLen(x): int = x.type.name.len
  127. template bunchOfChecks(x) =
  128. x.typeLen > 3
  129. x != 10 is bool
  130. template stmtListExprTmpl(x: untyped): untyped =
  131. x is int
  132. x
  133. type
  134. Obj = object
  135. x: int
  136. Gen[T] = object
  137. x: T
  138. Eq = concept x, y
  139. (x == y) is bool
  140. NotEq = concept x, y
  141. (x != y) is bool
  142. ConceptUsingTemplate1 = concept x
  143. echo x
  144. sizeof(x) is int
  145. bunchOfChecks x
  146. ConceptUsingTemplate2 = concept x
  147. stmtListExprTmpl x
  148. template ok(x) =
  149. static: assert(x)
  150. template no(x) =
  151. static: assert(not(x))
  152. ok int is Eq
  153. ok int is NotEq
  154. ok string is Eq
  155. ok string is NotEq
  156. ok Obj is Eq
  157. ok Obj is NotEq
  158. ok Gen[string] is Eq
  159. ok Gen[int] is NotEq
  160. no int is ConceptUsingTemplate1
  161. ok float is ConceptUsingTemplate1
  162. no string is ConceptUsingTemplate1
  163. ok int is ConceptUsingTemplate2
  164. no float is ConceptUsingTemplate2
  165. no string is ConceptUsingTemplate2
  166. block titerable:
  167. type
  168. Iterable[T] = concept x
  169. for value in x:
  170. type(value) is T
  171. proc sum[T](iter: Iterable[T]): T =
  172. static: echo T.name
  173. for element in iter:
  174. static: echo element.type.name
  175. result += element
  176. doAssert sum([1, 2, 3, 4, 5]) == 15
  177. block tmanual:
  178. template accept(e) =
  179. static: assert compiles(e)
  180. template reject(e) =
  181. static: assert(not compiles(e))
  182. type
  183. Container[T] = concept c
  184. c.len is Ordinal
  185. items(c) is T
  186. for value in c:
  187. type(value) is T
  188. proc takesIntContainer(c: Container[int]) =
  189. for e in c: echo e
  190. takesIntContainer(@[1, 2, 3])
  191. reject takesIntContainer(@["x", "y"])
  192. proc takesContainer(c: Container) =
  193. for e in c: echo e
  194. takesContainer(@[4, 5, 6])
  195. takesContainer(@["a", "b"])
  196. takesContainer "test"
  197. reject takesContainer(10)
  198. block modifiers_in_place:
  199. type
  200. VarContainer[T] = concept c
  201. put(var c, T)
  202. AltVarContainer[T] = concept var c
  203. put(c, T)
  204. NonVarContainer[T] = concept c
  205. put(c, T)
  206. GoodContainer = object
  207. x: int
  208. BadContainer = object
  209. x: int
  210. proc put(x: BadContainer, y: int) = discard
  211. proc put(x: var GoodContainer, y: int) = discard
  212. template ok(x) = assert(x)
  213. template no(x) = assert(not(x))
  214. static:
  215. ok GoodContainer is VarContainer[int]
  216. ok GoodContainer is AltVarContainer[int]
  217. no BadContainer is VarContainer[int]
  218. no BadContainer is AltVarContainer[int]
  219. ok GoodContainer is NonVarContainer[int]
  220. ok BadContainer is NonVarContainer[int]
  221. block treversable:
  222. type
  223. Reversable[T] = concept a
  224. a[int] is T
  225. a.high is int
  226. a.len is int
  227. a.low is int
  228. proc get[T](s: Reversable[T], n: int): T =
  229. s[n]
  230. proc hi[T](s: Reversable[T]): int =
  231. s.high
  232. proc lo[T](s: Reversable[T]): int =
  233. s.low
  234. iterator reverse[T](s: Reversable[T]): T =
  235. assert hi(s) - lo(s) == len(s) - 1
  236. for z in hi(s).countdown(lo(s)):
  237. yield s.get(z)
  238. for s in @["e", "z"].reverse:
  239. echo s
  240. block tmonoid:
  241. type Monoid = concept x, y
  242. x + y is type(x)
  243. type(z(type(x))) is type(x)
  244. proc z(x: typedesc[int]): int = 0
  245. doAssert(int is Monoid)
  246. # https://github.com/nim-lang/Nim/issues/8126
  247. type AdditiveMonoid = concept x, y, type T
  248. x + y is T
  249. # some redundant checks to test an alternative approaches:
  250. type TT = type(x)
  251. x + y is type(x)
  252. x + y is TT
  253. doAssert(1 is AdditiveMonoid)
  254. block tesqofconcept:
  255. type
  256. MyConcept = concept x
  257. someProc(x)
  258. SomeSeq = seq[MyConcept]
  259. proc someProc(x:int) = echo x
  260. proc work (s: SomeSeq) =
  261. for item in s:
  262. someProc item
  263. var s = @[1, 2, 3]
  264. work s
  265. block tvectorspace:
  266. type VectorSpace[K] = concept x, y
  267. x + y is type(x)
  268. zero(type(x)) is type(x)
  269. -x is type(x)
  270. x - y is type(x)
  271. var k: K
  272. k * x is type(x)
  273. proc zero(T: typedesc): T = 0
  274. static:
  275. assert float is VectorSpace[float]
  276. # assert float is VectorSpace[int]
  277. # assert int is VectorSpace
  278. block tstack:
  279. template reject(e) =
  280. static: assert(not compiles(e))
  281. type
  282. ArrayStack = object
  283. data: seq[int]
  284. proc push(s: var ArrayStack, item: int) =
  285. s.data.add item
  286. proc pop(s: var ArrayStack): int =
  287. return s.data.pop()
  288. type
  289. Stack[T] = concept var s
  290. s.push(T)
  291. s.pop() is T
  292. type ValueType = T
  293. const ValueTypeName = T.name.toUpperAscii
  294. proc genericAlgorithm[T](s: var Stack[T], y: T) =
  295. static:
  296. echo "INFERRED ", T.name
  297. echo "VALUE TYPE ", s.ValueType.name
  298. echo "VALUE TYPE NAME ", s.ValueTypeName
  299. s.push(y)
  300. echo s.pop
  301. proc implicitGeneric(s: var Stack): auto =
  302. static:
  303. echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
  304. echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name
  305. echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", Stack.ValueTypeName
  306. return s.pop()
  307. var s = ArrayStack(data: @[])
  308. s.push 10
  309. s.genericAlgorithm 20
  310. echo s.implicitGeneric
  311. reject s.genericAlgorithm "x"
  312. reject s.genericAlgorithm 1.0
  313. reject "str".implicitGeneric
  314. reject implicitGeneric(10)
  315. import libs/[trie_database, trie]
  316. block ttrie:
  317. proc takeDb(d: TrieDatabase) = discard
  318. var mdb: MemDB
  319. takeDb(mdb)
  320. import mvarconcept
  321. block tvar:
  322. # bug #2346, bug #2404
  323. echo randomInt(5)
  324. block tcomment:
  325. type
  326. Foo = concept
  327. ## Some comment
  328. proc bar(x: Self)
  329. proc bar(x: int) = echo x
  330. proc foo(x: Foo) = x.bar
  331. foo(9)