tconcepts_issues.nim 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. discard """
  2. output: '''
  3. 20.0 USD
  4. Printable
  5. true
  6. true
  7. true
  8. true
  9. true
  10. f
  11. 0
  12. 10
  13. 10
  14. 5
  15. ()
  16. false
  17. 10
  18. true
  19. true
  20. true
  21. true
  22. p has been called.
  23. p has been called.
  24. implicit generic
  25. generic
  26. false
  27. true
  28. -1
  29. Meow
  30. '''
  31. joinable: false
  32. """
  33. import macros, typetraits, os, posix
  34. block t5983:
  35. const currencies = ["USD", "EUR"] # in real code 120 currencies
  36. type USD = distinct float # in real code 120 types generates using macro
  37. type EUR = distinct float
  38. type CurrencyAmount = concept c
  39. type t = c.type
  40. const name = c.type.name
  41. name in currencies
  42. proc `$`(x: CurrencyAmount): string =
  43. $float(x) & " " & x.name
  44. let amount = 20.USD
  45. echo amount
  46. block t3414:
  47. type
  48. View[T] = concept v
  49. v.empty is bool
  50. v.front is T
  51. popFront v
  52. proc find(view: View; target: View.T): View =
  53. result = view
  54. while not result.empty:
  55. if view.front == target:
  56. return
  57. mixin popFront
  58. popFront result
  59. proc popFront[T](s: var seq[T]) = discard
  60. proc empty[T](s: seq[T]): bool = false
  61. var s1 = @[1, 2, 3]
  62. let s2 = s1.find(10)
  63. type
  64. Obj1[T] = object
  65. v: T
  66. converter toObj1[T](t: T): Obj1[T] =
  67. return Obj1[T](v: t)
  68. block t976:
  69. type
  70. int1 = distinct int
  71. int2 = distinct int
  72. int1g = concept x
  73. x is int1
  74. int2g = concept x
  75. x is int2
  76. proc take[T: int1g](value: int1) =
  77. when T is int2:
  78. static: error("killed in take(int1)")
  79. proc take[T: int2g](vale: int2) =
  80. when T is int1:
  81. static: error("killed in take(int2)")
  82. var i1: int1 = 1.int1
  83. var i2: int2 = 2.int2
  84. take[int1](i1)
  85. take[int2](i2)
  86. template reject(e) =
  87. static: assert(not compiles(e))
  88. reject take[string](i2)
  89. reject take[int1](i2)
  90. # bug #6249
  91. type
  92. Obj2 = ref object
  93. PrintAble = concept x
  94. $x is string
  95. proc `$`[T](nt: Obj1[T]): string =
  96. when T is PrintAble: result = "Printable"
  97. else: result = "Non Printable"
  98. echo Obj2()
  99. block t1128:
  100. type
  101. TFooContainer[T] = object
  102. TContainer[T] = concept var c
  103. foo(c, T)
  104. proc foo[T](c: var TFooContainer[T], val: T) =
  105. discard
  106. proc bar(c: var TContainer) =
  107. discard
  108. var fooContainer: TFooContainer[int]
  109. echo fooContainer is TFooContainer # true.
  110. echo fooContainer is TFooContainer[int] # true.
  111. fooContainer.bar()
  112. block t5642:
  113. type DataTable = concept x
  114. x is object
  115. for f in fields(x):
  116. f is seq
  117. type Students = object
  118. id : seq[int]
  119. name : seq[string]
  120. age: seq[int]
  121. proc nrow(dt: DataTable) : Natural =
  122. var totalLen = 0
  123. for f in fields(dt):
  124. totalLen += f.len
  125. return totalLen
  126. let
  127. stud = Students(id: @[1,2,3], name: @["Vas", "Pas", "NafNaf"], age: @[10,16,32])
  128. doAssert nrow(stud) == 9
  129. import t5888lib/ca, t5888lib/opt
  130. block t5888:
  131. type LocalCA = ca.CA
  132. proc f(c: CA) =
  133. echo "f"
  134. echo c.x
  135. var o = new(Opt)
  136. echo o is CA
  137. echo o is LocalCA
  138. echo o is ca.CA
  139. o.f()
  140. import json
  141. block t5968:
  142. type
  143. Enumerable[T] = concept e
  144. for it in e:
  145. it is T
  146. proc cmap[T, G](e: Enumerable[T], fn: proc(t: T): G): seq[G] =
  147. result = @[]
  148. for it in e: result.add(fn(it))
  149. var x = %["hello", "world"]
  150. var z = x.cmap(proc(it: JsonNode): string = it.getStr & "!")
  151. assert z == @["hello!", "world!"]
  152. import sugar
  153. block t6462:
  154. type
  155. FilterMixin[T] = ref object
  156. test: (T) -> bool
  157. trans: (T) -> T
  158. SeqGen[T] = ref object
  159. fil: FilterMixin[T]
  160. WithFilter[T] = concept a
  161. a.fil is FilterMixin[T]
  162. proc test[T](a: WithFilter[T]): (T) -> bool =
  163. a.fil.test
  164. var s = SeqGen[int](fil: FilterMixin[int](test: nil, trans: nil))
  165. doAssert s.test() == nil
  166. block t6770:
  167. type GA = concept c
  168. c.a is int
  169. type A = object
  170. a: int
  171. type AA = object
  172. case exists: bool
  173. of true:
  174. a: int
  175. else:
  176. discard
  177. proc print(inp: GA) =
  178. echo inp.a
  179. let failing = AA(exists: true, a: 10)
  180. let working = A(a:10)
  181. print(working)
  182. print(failing)
  183. block t7952:
  184. type
  185. HasLen = concept iter
  186. len(iter) is int
  187. proc echoLen(x: HasLen) =
  188. echo len(x)
  189. echoLen([1, 2, 3, 4, 5])
  190. block t8280:
  191. type
  192. Iterable[T] = concept x
  193. for elem in x:
  194. elem is T
  195. proc max[A](iter: Iterable[A]): A =
  196. discard
  197. type
  198. MyType = object
  199. echo max(@[MyType()])
  200. import math
  201. block t3452:
  202. type
  203. Node = concept n
  204. `==`(n, n) is bool
  205. Graph1 = concept g
  206. type N = Node
  207. distance(g, N, N) is float
  208. Graph2 = concept g
  209. distance(g, Node, Node) is float
  210. Graph3 = concept g
  211. var x: Node
  212. distance(g, x, x) is float
  213. XY = tuple[x, y: int]
  214. MyGraph = object
  215. points: seq[XY]
  216. static:
  217. assert XY is Node
  218. proc distance( g: MyGraph, a, b: XY): float =
  219. sqrt( pow(float(a.x - b.x), 2) + pow(float(a.y - b.y), 2) )
  220. static:
  221. assert MyGraph is Graph1
  222. assert MyGraph is Graph2
  223. assert MyGraph is Graph3
  224. block t6691:
  225. type
  226. ConceptA = concept c
  227. ConceptB = concept c
  228. c.myProc(ConceptA)
  229. Obj = object
  230. proc myProc(obj: Obj, x: ConceptA) = discard
  231. echo Obj is ConceptB
  232. block t6782:
  233. type
  234. Reader = concept c
  235. c.read(openArray[byte], int, int) is int
  236. Rdr = concept c
  237. c.rd(openArray[byte], int, int) is int
  238. type TestFile = object
  239. proc read(r: TestFile, dest: openArray[byte], offset: int, limit: int): int =
  240. result = 0
  241. proc rd(r: TestFile, dest: openArray[byte], offset: int, limit: int): int =
  242. result = 0
  243. doAssert TestFile is Reader
  244. doAssert TestFile is Rdr
  245. block t7114:
  246. type
  247. MyConcept = concept x
  248. x.close() # error, doesn't work
  249. MyConceptImplementer = object
  250. proc close(self: MyConceptImplementer) = discard
  251. proc takeConcept(window: MyConcept) =
  252. discard
  253. takeConcept(MyConceptImplementer())
  254. block t7510:
  255. type
  256. A[T] = concept a
  257. a.x is T
  258. B[T] = object
  259. x: T
  260. proc getx(v: A): v.T = v.x
  261. var v = B[int32](x: 10)
  262. echo v.getx
  263. block misc_issues:
  264. # https://github.com/nim-lang/Nim/issues/1147
  265. type TTest = object
  266. vals: seq[int]
  267. proc add(self: var TTest, val: int) =
  268. self.vals.add(val)
  269. type CAddable = concept x
  270. x[].add(int)
  271. echo((ref TTest) is CAddable) # true
  272. # https://github.com/nim-lang/Nim/issues/1570
  273. type ConcretePointOfFloat = object
  274. x, y: float
  275. type ConcretePoint[Value] = object
  276. x, y: Value
  277. type AbstractPointOfFloat = concept p
  278. p.x is float and p.y is float
  279. let p1 = ConcretePointOfFloat(x: 0, y: 0)
  280. let p2 = ConcretePoint[float](x: 0, y: 0)
  281. echo p1 is AbstractPointOfFloat # true
  282. echo p2 is AbstractPointOfFloat # true
  283. echo p2.x is float and p2.y is float # true
  284. # https://github.com/nim-lang/Nim/issues/2018
  285. type ProtocolFollower = concept c
  286. true # not a particularly involved protocol
  287. type ImplementorA = object
  288. type ImplementorB = object
  289. proc p[A: ProtocolFollower, B: ProtocolFollower](a: A, b: B) =
  290. echo "p has been called."
  291. p(ImplementorA(), ImplementorA())
  292. p(ImplementorA(), ImplementorB())
  293. # https://github.com/nim-lang/Nim/issues/2423
  294. proc put[T](c: seq[T], x: T) = echo "generic"
  295. proc put(c: seq) = echo "implicit generic"
  296. type
  297. Container[T] = concept c
  298. put(c)
  299. put(c, T)
  300. proc c1(x: Container) = echo "implicit generic"
  301. c1(@[1])
  302. proc c2[T](x: Container[T]) = echo "generic"
  303. c2(@[1])
  304. # https://github.com/nim-lang/Nim/issues/2882
  305. type
  306. Paper = object
  307. name: string
  308. Bendable = concept x
  309. bend(x is Bendable)
  310. proc bend(p: Paper): Paper = Paper(name: "bent-" & p.name)
  311. var paper = Paper(name: "red")
  312. echo paper is Bendable
  313. type
  314. A = concept self
  315. size(self) is int
  316. B = object
  317. proc size(self: B): int =
  318. return -1
  319. proc size(self: A): int =
  320. return 0
  321. let b = B()
  322. echo b is A
  323. echo b.size()
  324. # https://github.com/nim-lang/Nim/issues/7125
  325. type
  326. Thing = concept x
  327. x.hello is string
  328. Cat = object
  329. proc hello(d: Cat): string = "Meow"
  330. proc sayHello(c: Thing) = echo(c.hello)
  331. # used to be 'var a: Thing = Cat()' but that's not valid Nim code
  332. # anyway and will be an error soon.
  333. var a: Cat = Cat()
  334. a.sayHello()
  335. # bug #16897
  336. type
  337. Fp[N: static int, T] = object
  338. big: array[N, T]
  339. type
  340. QuadraticExt* = concept x
  341. ## Quadratic Extension concept (like complex)
  342. type BaseField = auto
  343. x.c0 is BaseField
  344. x.c1 is BaseField
  345. var address = pointer(nil)
  346. proc prod(r: var QuadraticExt, b: QuadraticExt) =
  347. if address == nil:
  348. address = addr b
  349. prod(r, b)
  350. else:
  351. assert address == addr b
  352. type
  353. Fp2[N: static int, T] {.byref.} = object
  354. c0, c1: Fp[N, T]
  355. # This should be passed by reference,
  356. # but concepts do not respect the 24 bytes rule
  357. # or `byref` pragma.
  358. var r, b: Fp2[6, uint64]
  359. prod(r, b)