tarray.nim 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. discard """
  2. output: '''
  3. [4, 5, 6]
  4. [16, 25, 36]
  5. [16, 25, 36]
  6. apple
  7. banana
  8. Fruit
  9. 2
  10. 4
  11. 3
  12. none
  13. skin
  14. paper
  15. @[2, 3, 4]321
  16. 9.0 4.0
  17. 3
  18. @[(1, 2), (3, 5)]
  19. 2
  20. @["a", "new one", "c"]
  21. @[1, 2, 3]
  22. 3
  23. dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajs
  24. dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf
  25. kgdchlfniambejop
  26. fjpmholcibdgeakn
  27. 2.0
  28. '''
  29. joinable: false
  30. """
  31. block tarray:
  32. type
  33. TMyArray = array[0..2, int]
  34. TMyRecord = tuple[x, y: int]
  35. TObj = object
  36. arr: TMyarray
  37. proc sum(a: openarray[int]): int =
  38. result = 0
  39. var i = 0
  40. while i < len(a):
  41. inc(result, a[i])
  42. inc(i)
  43. proc getPos(r: TMyRecord): int =
  44. result = r.x + r.y
  45. doAssert sum([1, 2, 3, 4]) == 10
  46. doAssert sum([]) == 0
  47. doAssert getPos( (x: 5, y: 7) ) == 12
  48. # bug #1669
  49. let filesToCreate = ["tempdir/fl1.a", "tempdir/fl2.b",
  50. "tempdir/tempdir2/fl3.e", "tempdir/tempdir2/tempdir3/fl4.f"]
  51. var found: array[0..filesToCreate.high, bool]
  52. doAssert found.len == 4
  53. # make sure empty arrays are assignable (bug #6853)
  54. const arr1: array[0, int] = []
  55. const arr2 = []
  56. let arr3: array[0, string] = []
  57. doAssert(arr1.len == 0)
  58. doAssert(arr2.len == 0)
  59. doAssert(arr3.len == 0)
  60. # Negative array length is not allowed (#6852)
  61. doAssert(not compiles(block:
  62. var arr: array[-1, int]))
  63. proc mul(a, b: TMyarray): TMyArray =
  64. result = a
  65. for i in 0..len(a)-1:
  66. result[i] = a[i] * b[i]
  67. var
  68. x, y: TMyArray
  69. o: TObj
  70. proc varArr1(x: var TMyArray): var TMyArray = x
  71. proc varArr2(x: var TObj): var TMyArray = x.arr
  72. x = [4, 5, 6]
  73. echo repr(varArr1(x))
  74. y = x
  75. echo repr(mul(x, y))
  76. o.arr = mul(x, y)
  77. echo repr(varArr2(o))
  78. const
  79. myData = [[1,2,3], [4, 5, 6]]
  80. doAssert myData[0][2] == 3
  81. block tarraycons:
  82. type
  83. TEnum = enum
  84. eA, eB, eC, eD, eE, eF
  85. const
  86. myMapping: array[TEnum, array[0..1, int]] = [
  87. eA: [1, 2],
  88. eB: [3, 4],
  89. [5, 6],
  90. eD: [0: 8, 1: 9],
  91. eE: [0: 8, 9],
  92. eF: [2, 1: 9]
  93. ]
  94. doAssert myMapping[eC][1] == 6
  95. block tarraycons_ptr_generic:
  96. type
  97. Fruit = object of RootObj
  98. name: string
  99. Apple = object of Fruit
  100. Banana = object of Fruit
  101. var
  102. ir = Fruit(name: "Fruit")
  103. ia = Apple(name: "apple")
  104. ib = Banana(name: "banana")
  105. let x = [ia.addr, ib.addr, ir.addr]
  106. for c in x: echo c.name
  107. type
  108. Vehicle[T] = object of RootObj
  109. tire: T
  110. Car[T] = object of Vehicle[T]
  111. Bike[T] = object of Vehicle[T]
  112. var v = Vehicle[int](tire: 3)
  113. var c = Car[int](tire: 4)
  114. var b = Bike[int](tire: 2)
  115. let y = [b.addr, c.addr, v.addr]
  116. for c in y: echo c.tire
  117. type
  118. Book[T] = ref object of RootObj
  119. cover: T
  120. Hard[T] = ref object of Book[T]
  121. Soft[T] = ref object of Book[T]
  122. var bn = Book[string](cover: "none")
  123. var hs = Hard[string](cover: "skin")
  124. var bp = Soft[string](cover: "paper")
  125. let z = [bn, hs, bp]
  126. for c in z: echo c.cover
  127. block tarraylen:
  128. var a: array[0, int]
  129. doAssert a.len == 0
  130. doAssert array[0..0, int].len == 1
  131. doAssert array[0..0, int]([1]).len == 1
  132. doAssert array[1..1, int].len == 1
  133. doAssert array[1..1, int]([1]).len == 1
  134. doAssert array[2, int].len == 2
  135. doAssert array[2, int]([1, 2]).len == 2
  136. doAssert array[1..3, int].len == 3
  137. doAssert array[1..3, int]([1, 2, 3]).len == 3
  138. doAssert array[0..2, int].len == 3
  139. doAssert array[0..2, int]([1, 2, 3]).len == 3
  140. doAssert array[-2 .. -2, int].len == 1
  141. doAssert([1, 2, 3].len == 3)
  142. doAssert([42].len == 1)
  143. type ustring = distinct string
  144. converter toUString(s: string): ustring = ustring(s)
  145. block tarrayindx:
  146. proc putEnv(key, val: string) =
  147. # XXX: we have to leak memory here, as we cannot
  148. # free it before the program ends (says Borland's
  149. # documentation)
  150. var
  151. env: ptr array[0..500000, char]
  152. env = cast[ptr array[0..500000, char]](alloc(len(key) + len(val) + 2))
  153. for i in 0..len(key)-1: env[i] = key[i]
  154. env[len(key)] = '='
  155. for i in 0..len(val)-1:
  156. env[len(key)+1+i] = val[i]
  157. # bug #7153
  158. const
  159. UnsignedConst = 1024'u
  160. type
  161. SomeObject = object
  162. s1: array[UnsignedConst, uint32]
  163. var
  164. obj: SomeObject
  165. doAssert obj.s1[0] == 0
  166. doAssert obj.s1[0u] == 0
  167. # bug #8049
  168. proc `[]`(s: ustring, i: int): ustring = s
  169. doAssert "abcdefgh"[1..2] == "bc"
  170. doAssert "abcdefgh"[1..^2] == "bcdefg"
  171. block troof:
  172. proc foo[T](x, y: T): T = x
  173. var a = @[1, 2, 3, 4]
  174. var b: array[3, array[2, float]] = [[1.0,2], [3.0,4], [8.0,9]]
  175. echo a[1.. ^1], a[^2], a[^3], a[^4]
  176. echo b[^1][^1], " ", (b[^2]).foo(b[^1])[^1]
  177. b[^1] = [8.8, 8.9]
  178. var c: seq[(int, int)] = @[(1,2), (3,4)]
  179. proc takeA(x: ptr int) = echo x[]
  180. takeA(addr c[^1][0])
  181. c[^1][1] = 5
  182. echo c
  183. proc useOpenarray(x: openArray[int]) =
  184. echo x[^2]
  185. proc mutOpenarray(x: var openArray[string]) =
  186. x[^2] = "new one"
  187. useOpenarray([1, 2, 3])
  188. var z = @["a", "b", "c"]
  189. mutOpenarray(z)
  190. echo z
  191. # bug #6675
  192. var y: array[1..5, int] = [1,2,3,4,5]
  193. y[3..5] = [1, 2, 3]
  194. echo y[3..5]
  195. var d: array['a'..'c', string] = ["a", "b", "c"]
  196. doAssert d[^1] == "c"
  197. import strutils, sequtils, typetraits, os
  198. type
  199. MetadataArray* = object
  200. data*: array[8, int]
  201. len*: int
  202. # Commenting the converter removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
  203. converter toMetadataArray*(se: varargs[int]): MetadataArray {.inline.} =
  204. result.len = se.len
  205. for i in 0..<se.len:
  206. result.data[i] = se[i]
  207. block troofregression:
  208. when NimVersion >= "0.17.3":
  209. type Index = int or BackwardsIndex
  210. template `^^`(s, i: untyped): untyped =
  211. when i is BackwardsIndex:
  212. s.len - int(i)
  213. else: i
  214. else:
  215. type Index = int
  216. template `^^`(s, i: untyped): untyped =
  217. i
  218. ## With Nim devel from the start of the week (~Oct30) I managed to trigger "lib/system.nim(3536, 4) Error: expression has no address"
  219. ## but I can't anymore after updating Nim (Nov5)
  220. ## Now commenting this plain compiles and removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
  221. proc `[]`(a: var MetadataArray, idx: Index): var int {.inline.} =
  222. a.data[a ^^ idx]
  223. ##############################
  224. ### Completely unrelated lib that triggers the issue
  225. type
  226. MySeq[T] = ref object
  227. data: seq[T]
  228. proc test[T](sx: MySeq[T]) =
  229. # Removing the backward index removes the error "lib/system.nim(3536, 3) Error: for a 'var' type a variable needs to be passed"
  230. echo sx.data[^1] # error here
  231. let s = MySeq[int](data: @[1, 2, 3])
  232. s.test()
  233. # bug #6989
  234. type Dist = distinct int
  235. proc mypred[T: Ordinal](x: T): T = T(int(x)-1)
  236. proc cons(x: int): Dist = Dist(x)
  237. var d: Dist
  238. template `^+`(s, i: untyped): untyped =
  239. (when i is BackwardsIndex: s.len - int(i) else: int(i))
  240. proc `...`[T, U](a: T, b: U): HSlice[T, U] =
  241. result.a = a
  242. result.b = b
  243. proc `...`[T](b: T): HSlice[int, T] =
  244. result.b = b
  245. template `...<`(a, b: untyped): untyped =
  246. ## a shortcut for 'a..pred(b)'.
  247. a ... pred(b)
  248. template check(a, b) =
  249. if $a != b:
  250. echo "Failure ", a, " != ", b
  251. check type(4 ...< 1), "HSlice[system.int, system.int]"
  252. check type(4 ...< ^1), "HSlice[system.int, system.BackwardsIndex]"
  253. check type(4 ... pred(^1)), "HSlice[system.int, system.BackwardsIndex]"
  254. check type(4 ... mypred(8)), "HSlice[system.int, system.int]"
  255. check type(4 ... mypred(^1)), "HSlice[system.int, system.BackwardsIndex]"
  256. var rot = 8
  257. proc bug(s: string): string =
  258. result = s
  259. result = result[result.len - rot .. ^1] & "__" & result[0 ..< ^rot]
  260. const testStr = "abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdflfdjkl"
  261. echo bug(testStr)
  262. echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)]
  263. var
  264. instructions = readFile(parentDir(currentSourcePath) / "troofregression2.txt").split(',')
  265. programs = "abcdefghijklmnop"
  266. proc dance(dancers: string): string =
  267. result = dancers
  268. for instr in instructions:
  269. let rem = instr[1 .. instr.high]
  270. case instr[0]
  271. of 's':
  272. let rot = rem.parseInt
  273. result = result[result.len - rot .. ^1] & result[0 ..< ^rot]
  274. of 'x':
  275. let
  276. x = rem.split('/')
  277. a = x[0].parseInt
  278. b = x[1].parseInt
  279. swap(result[a], result[b])
  280. of 'p':
  281. let
  282. a = result.find(rem[0])
  283. b = result.find(rem[^1])
  284. result[a] = rem[^1]
  285. result[b] = rem[0]
  286. else: discard
  287. proc longDance(dancers: string, iterations = 1_000_000_000): string =
  288. var
  289. dancers = dancers
  290. seen = @[dancers]
  291. for i in 1 .. iterations:
  292. dancers = dancers.dance()
  293. if dancers in seen:
  294. return seen[iterations mod i]
  295. seen.add(dancers)
  296. echo dance(programs)
  297. echo longDance(programs)
  298. block tunchecked:
  299. {.boundchecks: on.}
  300. type Unchecked = UncheckedArray[char]
  301. var x = cast[ptr Unchecked](alloc(100))
  302. x[5] = 'x'
  303. import macros
  304. block t7818:
  305. # bug #7818
  306. # this is not a macro bug, but array construction bug
  307. # I use macro to avoid object slicing
  308. # see #7712 and #7637
  309. type
  310. Vehicle[T] = object of RootObj
  311. tire: T
  312. Car[T] = object of Vehicle[T]
  313. Bike[T] = object of Vehicle[T]
  314. macro peek(n: typed): untyped =
  315. let val = getTypeImpl(n).treeRepr
  316. newLit(val)
  317. block test_t7818:
  318. var v = Vehicle[int](tire: 3)
  319. var c = Car[int](tire: 4)
  320. var b = Bike[int](tire: 2)
  321. let y = peek([c, b, v])
  322. let z = peek([v, c, b])
  323. doAssert(y == z)
  324. block test_t7906_1:
  325. proc init(x: typedesc, y: int): ref x =
  326. result = new(ref x)
  327. result.tire = y
  328. var v = init(Vehicle[int], 3)
  329. var c = init(Car[int], 4)
  330. var b = init(Bike[int], 2)
  331. let y = peek([c, b, v])
  332. let z = peek([v, c, b])
  333. doAssert(y == z)
  334. block test_t7906_2:
  335. var v = Vehicle[int](tire: 3)
  336. var c = Car[int](tire: 4)
  337. var b = Bike[int](tire: 2)
  338. let y = peek([c.addr, b.addr, v.addr])
  339. let z = peek([v.addr, c.addr, b.addr])
  340. doAssert(y == z)
  341. block test_t7906_3:
  342. type
  343. Animal[T] = object of RootObj
  344. hair: T
  345. Mammal[T] = object of Animal[T]
  346. Monkey[T] = object of Mammal[T]
  347. var v = Animal[int](hair: 3)
  348. var c = Mammal[int](hair: 4)
  349. var b = Monkey[int](hair: 2)
  350. let z = peek([c.addr, b.addr, v.addr])
  351. let y = peek([v.addr, c.addr, b.addr])
  352. doAssert(y == z)
  353. type
  354. Fruit[T] = ref object of RootObj
  355. color: T
  356. Apple[T] = ref object of Fruit[T]
  357. Banana[T] = ref object of Fruit[T]
  358. proc testArray[T](x: array[3, Fruit[T]]): string =
  359. result = ""
  360. for c in x:
  361. result.add $c.color
  362. proc testOpenArray[T](x: openArray[Fruit[T]]): string =
  363. result = ""
  364. for c in x:
  365. result.add $c.color
  366. block test_t7906_4:
  367. var v = Fruit[int](color: 3)
  368. var c = Apple[int](color: 4)
  369. var b = Banana[int](color: 2)
  370. let y = peek([c, b, v])
  371. let z = peek([v, c, b])
  372. doAssert(y == z)
  373. block test_t7906_5:
  374. var a = Fruit[int](color: 1)
  375. var b = Apple[int](color: 2)
  376. var c = Banana[int](color: 3)
  377. doAssert(testArray([a, b, c]) == "123")
  378. doAssert(testArray([b, c, a]) == "231")
  379. doAssert(testOpenArray([a, b, c]) == "123")
  380. doAssert(testOpenArray([b, c, a]) == "231")
  381. doAssert(testOpenArray(@[a, b, c]) == "123")
  382. doAssert(testOpenArray(@[b, c, a]) == "231")
  383. proc testArray[T](x: array[3, ptr Vehicle[T]]): string =
  384. result = ""
  385. for c in x:
  386. result.add $c.tire
  387. proc testOpenArray[T](x: openArray[ptr Vehicle[T]]): string =
  388. result = ""
  389. for c in x:
  390. result.add $c.tire
  391. block test_t7906_6:
  392. var u = Vehicle[int](tire: 1)
  393. var v = Bike[int](tire: 2)
  394. var w = Car[int](tire: 3)
  395. doAssert(testArray([u.addr, v.addr, w.addr]) == "123")
  396. doAssert(testArray([w.addr, u.addr, v.addr]) == "312")
  397. doAssert(testOpenArray([u.addr, v.addr, w.addr]) == "123")
  398. doAssert(testOpenArray([w.addr, u.addr, v.addr]) == "312")
  399. doAssert(testOpenArray(@[u.addr, v.addr, w.addr]) == "123")
  400. doAssert(testOpenArray(@[w.addr, u.addr, v.addr]) == "312")
  401. block trelaxedindextyp:
  402. # any integral type is allowed as index
  403. proc foo(x: ptr UncheckedArray[int]; idx: uint64) = echo x[idx]
  404. proc foo(x: seq[int]; idx: uint64) = echo x[idx]
  405. proc foo(x: string|cstring; idx: uint64) = echo x[idx]
  406. proc foo(x: openArray[int]; idx: uint64) = echo x[idx]
  407. block t3899:
  408. # https://github.com/nim-lang/Nim/issues/3899
  409. type O = object
  410. a: array[1..2,float]
  411. template `[]`(x: O, i: int): float =
  412. x.a[i]
  413. const c = O(a: [1.0,2.0])
  414. echo c[2]
  415. block arrayLiterals:
  416. type ABC = enum A, B, C
  417. template Idx[IdxT, ElemT](arr: array[IdxT, ElemT]): untyped = IdxT
  418. doAssert [A: 0, B: 1].Idx is range[A..B]
  419. doAssert [A: 0, 1, 3].Idx is ABC
  420. doAssert [1: 2][1] == 2
  421. doAssert [-1'i8: 2][-1] == 2
  422. doAssert [-1'i8: 2, 3, 4, 5].Idx is range[-1'i8..2'i8]