tconcepts.nim 7.8 KB

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