tarray.nim 14 KB

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