tvmmisc.nim 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. import macros
  2. import os
  3. # bug #4462
  4. block:
  5. proc foo(t: typedesc) {.compileTime.} =
  6. assert sameType(getType(t), getType(typedesc[int]))
  7. assert sameType(getType(t), getType(type int))
  8. static:
  9. foo(int)
  10. # bug #4412
  11. block:
  12. proc default[T](t: typedesc[T]): T {.inline.} = discard
  13. static:
  14. var x = default(type(0))
  15. # #6379
  16. import algorithm
  17. static:
  18. var numArray = [1, 2, 3, 4, -1]
  19. numArray.sort(cmp)
  20. doAssert numArray == [-1, 1, 2, 3, 4]
  21. var str = "cba"
  22. str.sort(cmp)
  23. doAssert str == "abc"
  24. # #6086
  25. import math, sequtils, sugar
  26. block:
  27. proc f: int =
  28. toSeq(10..<10_000).filter(
  29. a => a == ($a).map(
  30. d => (d.ord-'0'.ord).int^4
  31. ).sum
  32. ).sum
  33. var a = f()
  34. const b = f()
  35. doAssert a == b
  36. block:
  37. proc f(): seq[char] =
  38. result = "hello".map(proc(x: char): char = x)
  39. var runTime = f()
  40. const compTime = f()
  41. doAssert runTime == compTime
  42. # #6083
  43. block:
  44. proc abc(): seq[int] =
  45. result = @[0]
  46. result.setLen(2)
  47. var tmp: int
  48. for i in 0 ..< 2:
  49. inc tmp
  50. result[i] = tmp
  51. const fact1000 = abc()
  52. doAssert fact1000 == @[1, 2]
  53. # Tests for VM ops
  54. block:
  55. static:
  56. # for joint test, the project path is different, so I disabled it:
  57. when false:
  58. doAssert "vm" in getProjectPath()
  59. let b = getEnv("UNSETENVVAR")
  60. doAssert b == ""
  61. doAssert existsEnv("UNSERENVVAR") == false
  62. putEnv("UNSETENVVAR", "VALUE")
  63. doAssert getEnv("UNSETENVVAR") == "VALUE"
  64. doAssert existsEnv("UNSETENVVAR") == true
  65. doAssert fileExists("MISSINGFILE") == false
  66. doAssert dirExists("MISSINGDIR") == false
  67. # #7210
  68. block:
  69. static:
  70. proc f(size: int): int =
  71. var some = newStringOfCap(size)
  72. result = size
  73. doAssert f(4) == 4
  74. # #6689
  75. block:
  76. static:
  77. proc foo(): int = 0
  78. var f: proc(): int
  79. doAssert f.isNil
  80. f = foo
  81. doAssert(not f.isNil)
  82. block:
  83. static:
  84. var x: ref ref int
  85. new(x)
  86. doAssert(not x.isNil)
  87. # #7871
  88. static:
  89. type Obj = object
  90. field: int
  91. var s = newSeq[Obj](1)
  92. var o = Obj()
  93. s[0] = o
  94. o.field = 2
  95. doAssert s[0].field == 0
  96. # #8125
  97. static:
  98. let def_iter_var = ident("it")
  99. # #8142
  100. static:
  101. type Obj = object
  102. names: string
  103. proc pushName(o: var Obj) =
  104. var s = ""
  105. s.add("FOOBAR")
  106. o.names.add(s)
  107. var o = Obj()
  108. o.names = ""
  109. o.pushName()
  110. o.pushName()
  111. doAssert o.names == "FOOBARFOOBAR"
  112. # #8154
  113. import parseutils
  114. static:
  115. type Obj = object
  116. i: int
  117. proc foo(): Obj =
  118. discard parseInt("1", result.i, 0)
  119. static:
  120. doAssert foo().i == 1
  121. # #10333
  122. block:
  123. const
  124. encoding: auto = [
  125. ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
  126. ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
  127. ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
  128. ["", "M", "MM", "MMM", "--", "-", "--", "---", "----", "--"],
  129. ]
  130. doAssert encoding.len == 4
  131. # #10886
  132. proc tor(): bool =
  133. result = true
  134. result = false or result
  135. proc tand(): bool =
  136. result = false
  137. result = true and result
  138. const
  139. ctor = tor()
  140. ctand = not tand()
  141. static:
  142. doAssert ctor
  143. doAssert ctand
  144. block: # bug #13081
  145. type Kind = enum
  146. k0, k1, k2, k3
  147. type Foo = object
  148. x0: float
  149. case kind: Kind
  150. of k0: discard
  151. of k1: x1: int
  152. of k2: x2: string
  153. of k3: x3: string
  154. const j1 = Foo(x0: 1.2, kind: k1, x1: 12)
  155. const j2 = Foo(x0: 1.3, kind: k2, x2: "abc")
  156. const j3 = Foo(x0: 1.3, kind: k3, x3: "abc2")
  157. static:
  158. doAssert $j1 == "(x0: 1.2, kind: k1, x1: 12)"
  159. doAssert $j2 == """(x0: 1.3, kind: k2, x2: "abc")"""
  160. doAssert $j3 == """(x0: 1.3, kind: k3, x3: "abc2")"""
  161. doAssert $j1 == "(x0: 1.2, kind: k1, x1: 12)"
  162. doAssert $j2 == """(x0: 1.3, kind: k2, x2: "abc")"""
  163. doAssert $j3 == """(x0: 1.3, kind: k3, x3: "abc2")"""
  164. doAssert j1.x1 == 12
  165. static:
  166. doAssert j1.x1 == 12
  167. block: # bug #15595
  168. proc fn0()=echo 0
  169. proc fn1()=discard
  170. proc main=
  171. var local = 0
  172. proc fn2()=echo local
  173. var a0 = fn0
  174. var a1 = fn1
  175. var a2 = fn2
  176. var a3: proc()
  177. var a4: proc()
  178. doAssert a0 == fn0 # bugfix
  179. doAssert a1 == fn1 # ditto
  180. doAssert a2 == fn2 # ditto
  181. doAssert fn0 != fn1
  182. doAssert a2 != nil
  183. doAssert a3 == nil # bugfix
  184. doAssert a3 == a4 # bugfix
  185. static: main()
  186. main()
  187. # bug #15363
  188. import sequtils
  189. block:
  190. func identity(a: bool): bool = a
  191. var a: seq[bool] = static:
  192. newSeq[bool](0).mapIt(it) # segfaults
  193. var b: seq[bool] = static:
  194. newSeq[bool](0).filterIt(it) # does not segfault
  195. var c: seq[bool] = static:
  196. newSeq[bool](0).map(identity) # does not segfault
  197. var d: seq[bool] = static:
  198. newSeq[bool](0).map(proc (a: bool): bool = false) # segfaults
  199. var e: seq[bool] = static:
  200. newSeq[bool](0).filter(identity) # does not segfault
  201. var f: seq[bool] = static:
  202. newSeq[bool](0).filter(proc (a: bool): bool = false) # segfaults
  203. doAssert a == @[]
  204. doAssert b == @[]
  205. doAssert c == @[]
  206. doAssert d == @[]
  207. doAssert e == @[]
  208. doAssert f == @[]
  209. block: # bug #18310
  210. macro t() : untyped =
  211. let
  212. x = nnkTupleConstr.newTree(newLit(1))
  213. y = nnkTupleConstr.newTree(newLit(2))
  214. doAssert not (x == y) # not using != intentionally
  215. doAssert not(cast[int](x) == cast[int](y))
  216. doAssert not(system.`==`(x, y))
  217. doAssert system.`==`(x, x)
  218. t()
  219. block: # bug #10815
  220. type
  221. Opcode = enum
  222. iChar, iSet
  223. Inst = object
  224. case code: Opcode
  225. of iChar:
  226. c: char
  227. of iSet:
  228. cs: set[char]
  229. Patt = seq[Inst]
  230. proc `$`(p: Patt): string =
  231. discard
  232. proc P(): Patt =
  233. result.add Inst(code: iSet)
  234. const a = P()
  235. doAssert $a == ""
  236. when defined osx: # xxx bug https://github.com/nim-lang/Nim/issues/10815#issuecomment-476380734
  237. block:
  238. type CharSet {.union.} = object
  239. cs: set[char]
  240. vs: array[4, uint64]
  241. const a = Charset(cs: {'a'..'z'})
  242. doAssert a.repr.len > 0
  243. import tables
  244. block: # bug #8007
  245. type
  246. CostKind = enum
  247. Fixed,
  248. Dynamic
  249. Cost = object
  250. case kind*: CostKind
  251. of Fixed:
  252. cost*: int
  253. of Dynamic:
  254. handler*: proc(value: int): int {.nimcall.}
  255. proc foo(value: int): int {.nimcall.} =
  256. sizeof(value)
  257. const a: array[2, Cost] =[
  258. Cost(kind: Fixed, cost: 999),
  259. Cost(kind: Dynamic, handler: foo)
  260. ]
  261. # OK with arrays & object variants
  262. doAssert $a == "[(kind: Fixed, cost: 999), (kind: Dynamic, handler: ...)]"
  263. const b: Table[int, Cost] = {
  264. 0: Cost(kind: Fixed, cost: 999),
  265. 1: Cost(kind: Dynamic, handler: foo)
  266. }.toTable
  267. # KO with Tables & object variants
  268. # echo b # {0: (kind: Fixed, cost: 0), 1: (kind: Dynamic, handler: ...)} # <----- wrong behaviour
  269. doAssert $b == "{0: (kind: Fixed, cost: 999), 1: (kind: Dynamic, handler: ...)}"
  270. const c: Table[int, int] = {
  271. 0: 100,
  272. 1: 999
  273. }.toTable
  274. # OK with Tables and primitive int
  275. doAssert $c == "{0: 100, 1: 999}"
  276. # For some reason the following gives
  277. # Error: invalid type for const: Cost
  278. const d0 = Cost(kind: Fixed, cost: 999)
  279. # OK with seq & object variants
  280. const d = @[Cost(kind: Fixed, cost: 999), Cost(kind: Dynamic, handler: foo)]
  281. doAssert $d == "@[(kind: Fixed, cost: 999), (kind: Dynamic, handler: ...)]"
  282. block: # bug #14340
  283. block:
  284. proc opl3EnvelopeCalcSin0() = discard
  285. type EnvelopeSinfunc = proc()
  286. # const EnvelopeCalcSin0 = opl3EnvelopeCalcSin0 # ok
  287. const EnvelopeCalcSin0: EnvelopeSinfunc = opl3EnvelopeCalcSin0 # was bug
  288. const envelopeSin = [EnvelopeCalcSin0]
  289. var a = 0
  290. envelopeSin[a]()
  291. block:
  292. type Mutator = proc() {.noSideEffect, gcsafe, locks: 0.}
  293. proc mutator0() = discard
  294. const mTable = [Mutator(mutator0)]
  295. var i=0
  296. mTable[i]()
  297. block: # VM wrong register free causes errors in unrelated code
  298. block: # bug #15597
  299. #[
  300. Error: unhandled exception: 'sym' is not accessible using discriminant 'kind' of type 'TNode' [FieldDefect]
  301. in /Users/timothee/git_clone/nim/Nim_prs/compiler/vm.nim(1176) rawExecute
  302. in opcIndCall
  303. in let prc = if not isClosure: bb.sym else: bb[0].sym
  304. ]#
  305. proc bar2(head: string): string = "asdf"
  306. proc zook(u1: int) = discard
  307. type PathEntry = object
  308. kind: int
  309. path: string
  310. iterator globOpt(): int =
  311. var u1: int
  312. zook(u1)
  313. zook(u1)
  314. zook(u1)
  315. zook(u1)
  316. zook(u1)
  317. zook(u1)
  318. zook(u1)
  319. zook(u1)
  320. zook(u1)
  321. zook(u1)
  322. zook(u1)
  323. zook(u1)
  324. zook(u1)
  325. zook(u1)
  326. var entry = PathEntry()
  327. entry.path = bar2("")
  328. if false:
  329. echo "here2"
  330. proc processAux(a: float) = discard
  331. template bar(iter: untyped): untyped =
  332. var ret: float
  333. for x in iter: break
  334. ret
  335. proc main() =
  336. processAux(bar(globOpt()))
  337. static: main()
  338. block: # ditto
  339. # D20201024T133245
  340. type Deque = object
  341. proc initDeque2(initialSize: int = 4): Deque = Deque()
  342. proc len2(a: Deque): int = 2
  343. proc baz(dir: string): bool = true
  344. proc bar2(head: string): string = "asdf"
  345. proc bar3(path: var string) = path = path
  346. type PathEntry = object
  347. kind: int
  348. path: string
  349. proc initGlobOpt(dir: string, a1=false,a2=false,a3=false,a4=false): string = dir
  350. iterator globOpt(dir: string): int =
  351. var stack = initDeque2()
  352. doAssert baz("")
  353. let z = stack.len2
  354. if stack.len2 >= 0:
  355. var entry = PathEntry()
  356. let current = if true: stack.len2 else: stack.len2
  357. entry.path = bar2("")
  358. bar3(entry.path)
  359. if false:
  360. echo "here2" # comment here => you get same error as https://github.com/nim-lang/Nim/issues/15704
  361. proc processAux(a: float) = discard
  362. template bar(iter: untyped): untyped =
  363. var ret: float
  364. for x in iter: break
  365. ret
  366. proc main() =
  367. processAux(bar(globOpt(initGlobOpt("."))))
  368. static: main()
  369. block: # bug #15704
  370. #[
  371. Error: attempt to access a nil address kind: rkFloat
  372. ]#
  373. type Deque = object
  374. proc initDeque2(initialSize: int = 4): Deque = Deque()
  375. proc len2(a: Deque): int = 2
  376. proc baz(dir: string): bool = true
  377. proc bar2(head: string): string = "asdf"
  378. proc bar3(path: var string) = path = path
  379. type PathEntry = object
  380. kind: int
  381. path: string
  382. depth: int
  383. proc initGlobOpt(dir: string, a1=false,a2=false,a3=false,a4=false): string =
  384. dir
  385. iterator globOpt(dir: string): int =
  386. var stack = initDeque2()
  387. doAssert baz("")
  388. let z = stack.len2
  389. var a5: int
  390. if stack.len2 >= 0:
  391. var entry = PathEntry()
  392. if false:
  393. echo "here"
  394. let current = if true: stack.len2 else: stack.len2
  395. entry.depth = 1
  396. entry.path = bar2("")
  397. bar3(entry.path)
  398. proc processAux(a: float) = discard
  399. template bar(iter: untyped): untyped =
  400. var ret: float
  401. for x in iter:
  402. break
  403. ret
  404. const dir = "."
  405. proc main() =
  406. processAux(bar(globOpt(initGlobOpt(dir))))
  407. static: main()
  408. block: # bug #8015
  409. block:
  410. type Foo = object
  411. case b: bool
  412. of false: v1: int
  413. of true: v2: int
  414. const t = [Foo(b: false, v1: 1), Foo(b: true, v2: 2)]
  415. doAssert $t == "[(b: false, v1: 1), (b: true, v2: 2)]"
  416. doAssert $t[0] == "(b: false, v1: 1)" # was failing
  417. block:
  418. type
  419. CostKind = enum
  420. Fixed,
  421. Dynamic
  422. Cost = object
  423. case kind*: CostKind
  424. of Fixed:
  425. cost*: int
  426. of Dynamic:
  427. handler*: proc(): int {.nimcall.}
  428. proc foo1(): int {.nimcall.} =
  429. 100
  430. proc foo2(): int {.nimcall.} =
  431. 200
  432. # Change to `let` and it doesn't crash
  433. const costTable = [
  434. 0: Cost(kind: Fixed, cost: 999),
  435. 1: Cost(kind: Dynamic, handler: foo1),
  436. 2: Cost(kind: Dynamic, handler: foo2)
  437. ]
  438. doAssert $costTable[0] == "(kind: Fixed, cost: 999)"
  439. doAssert costTable[1].handler() == 100
  440. doAssert costTable[2].handler() == 200
  441. # Now trying to carry the table as an object field
  442. type
  443. Wrapper = object
  444. table: array[3, Cost]
  445. proc procNewWrapper(): Wrapper =
  446. result.table = costTable
  447. # Alternatively, change to `const` and it doesn't crash
  448. let viaProc = procNewWrapper()
  449. doAssert viaProc.table[1].handler != nil
  450. doAssert viaProc.table[2].handler != nil
  451. doAssert $viaProc.table[0] == "(kind: Fixed, cost: 999)"
  452. doAssert viaProc.table[1].handler() == 100
  453. doAssert viaProc.table[2].handler() == 200
  454. # bug #19198
  455. block:
  456. type
  457. Foo[n: static int] = int
  458. block:
  459. static:
  460. let x = int 1
  461. doAssert $(x.type) == "Foo" # Foo
  462. block:
  463. static:
  464. let x = int 1
  465. let y = x + 1
  466. # Error: unhandled exception: value out of range: -8 notin 0 .. 65535 [RangeDefect]
  467. doAssert y == 2
  468. type Atom* = object
  469. bar: int
  470. proc main() = # bug #12994
  471. var s: seq[Atom]
  472. var atom: Atom
  473. var checked = 0
  474. for i in 0..<2:
  475. atom.bar = 5
  476. s.add atom
  477. atom.reset
  478. if i == 0:
  479. checked += 1
  480. doAssert $s == "@[(bar: 5)]"
  481. else:
  482. checked += 1
  483. doAssert $s == "@[(bar: 5), (bar: 5)]"
  484. doAssert checked == 2
  485. static: main()
  486. main()
  487. # bug #19201
  488. proc foo(s: sink string) = doAssert s.len == 3
  489. static:
  490. foo("abc")
  491. static:
  492. for i in '1' .. '2': # bug #10938
  493. var s: set[char]
  494. doAssert s == {}
  495. incl(s, i)
  496. for _ in 0 ..< 3: # bug #13312
  497. var s: string
  498. s.add("foo")
  499. doAssert s == "foo"
  500. for i in 1 .. 5: # bug #13918
  501. var arr: array[3, int]
  502. var val: int
  503. doAssert arr == [0, 0, 0] and val == 0
  504. for j in 0 ..< len(arr):
  505. arr[j] = i
  506. val = i
  507. # bug #20985
  508. let a = block:
  509. var groups: seq[seq[int]]
  510. for i in 0 ..< 3:
  511. var group: seq[int]
  512. for j in 0 ..< 3:
  513. group.add j
  514. groups.add group
  515. groups
  516. const b = block:
  517. var groups: seq[seq[int]]
  518. for i in 0 ..< 3:
  519. var group: seq[int]
  520. for j in 0 ..< 3:
  521. group.add j
  522. groups.add group
  523. groups
  524. doAssert a == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]]
  525. doAssert b == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]]
  526. macro m1(s: string): int =
  527. var ProcID {.global, compileTime.}: int
  528. inc(ProcID)
  529. result = newLit(ProcID)
  530. proc macroGlobal =
  531. doAssert m1("Macro argument") == 1
  532. doAssert m1("Macro argument") == 2
  533. doAssert m1("Macro argument") == 3
  534. static: macroGlobal()
  535. macroGlobal()
  536. block:
  537. proc swap[T](x: var T): T =
  538. result = x
  539. x = default(T)
  540. proc merge[T](a, b: var openArray[T]) =
  541. a[0] = swap b[0]
  542. static:
  543. var x = "abc"
  544. var y = "356"
  545. merge(x, y)
  546. doAssert x == "3bc"
  547. block: # issue #22524
  548. const cnst = cstring(nil)
  549. doAssert cnst.isNil
  550. doAssert cnst == nil
  551. let b = cnst
  552. doAssert b.isNil
  553. doAssert b == nil
  554. let a = static: cstring(nil)
  555. doAssert a.isNil
  556. static:
  557. var x: cstring
  558. doAssert x.isNil
  559. doAssert x == nil
  560. doAssert x != ""
  561. block: # issue #15730
  562. const s: cstring = ""
  563. doAssert s != nil
  564. static:
  565. let s: cstring = ""
  566. doAssert not s.isNil
  567. doAssert s != nil
  568. doAssert s == ""
  569. static: # more nil cstring issues
  570. let x = cstring(nil)
  571. doAssert x.len == 0