tvmmisc.nim 13 KB

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