astalgo.nim 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # Algorithms for the abstract syntax tree: hash tables, lists
  10. # and sets of nodes are supported. Efficiency is important as
  11. # the data structures here are used in various places of the compiler.
  12. import
  13. ast, hashes, intsets, options, lineinfos, ropes, idents, rodutils,
  14. msgs
  15. import strutils except addf
  16. when defined(nimPreviewSlimSystem):
  17. import std/assertions
  18. when not defined(nimHasCursor):
  19. {.pragma: cursor.}
  20. proc hashNode*(p: RootRef): Hash
  21. proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
  22. # Convert a tree into its YAML representation; this is used by the
  23. # YAML code generator and it is invaluable for debugging purposes.
  24. # If maxRecDepht <> -1 then it won't print the whole graph.
  25. proc typeToYaml*(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int = - 1): Rope
  26. proc symToYaml*(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope
  27. proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): Rope
  28. # these are for debugging only: They are not really deprecated, but I want
  29. # the warning so that release versions do not contain debugging statements:
  30. proc debug*(n: PSym; conf: ConfigRef = nil) {.exportc: "debugSym", deprecated.}
  31. proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.}
  32. proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.}
  33. proc typekinds*(t: PType) {.deprecated.} =
  34. var t = t
  35. var s = ""
  36. while t != nil and t.len > 0:
  37. s.add $t.kind
  38. s.add " "
  39. t = t.lastSon
  40. echo s
  41. template debug*(x: PSym|PType|PNode) {.deprecated.} =
  42. when compiles(c.config):
  43. debug(c.config, x)
  44. elif compiles(c.graph.config):
  45. debug(c.graph.config, x)
  46. else:
  47. error()
  48. template debug*(x: auto) {.deprecated.} =
  49. echo x
  50. template mdbg*: bool {.deprecated.} =
  51. when compiles(c.graph):
  52. c.module.fileIdx == c.graph.config.projectMainIdx
  53. elif compiles(c.module):
  54. c.module.fileIdx == c.config.projectMainIdx
  55. elif compiles(c.c.module):
  56. c.c.module.fileIdx == c.c.config.projectMainIdx
  57. elif compiles(m.c.module):
  58. m.c.module.fileIdx == m.c.config.projectMainIdx
  59. elif compiles(cl.c.module):
  60. cl.c.module.fileIdx == cl.c.config.projectMainIdx
  61. elif compiles(p):
  62. when compiles(p.lex):
  63. p.lex.fileIdx == p.lex.config.projectMainIdx
  64. else:
  65. p.module.module.fileIdx == p.config.projectMainIdx
  66. elif compiles(m.module.fileIdx):
  67. m.module.fileIdx == m.config.projectMainIdx
  68. elif compiles(L.fileIdx):
  69. L.fileIdx == L.config.projectMainIdx
  70. else:
  71. error()
  72. # --------------------------- ident tables ----------------------------------
  73. proc idTableGet*(t: TIdTable, key: PIdObj): RootRef
  74. proc idTableGet*(t: TIdTable, key: int): RootRef
  75. proc idTablePut*(t: var TIdTable, key: PIdObj, val: RootRef)
  76. proc idTableHasObjectAsKey*(t: TIdTable, key: PIdObj): bool
  77. # checks if `t` contains the `key` (compared by the pointer value, not only
  78. # `key`'s id)
  79. proc idNodeTableGet*(t: TIdNodeTable, key: PIdObj): PNode
  80. proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
  81. # ---------------------------------------------------------------------------
  82. proc lookupInRecord*(n: PNode, field: PIdent): PSym
  83. proc mustRehash*(length, counter: int): bool
  84. proc nextTry*(h, maxHash: Hash): Hash {.inline.}
  85. # ------------- table[int, int] ---------------------------------------------
  86. const
  87. InvalidKey* = low(int)
  88. type
  89. TIIPair*{.final.} = object
  90. key*, val*: int
  91. TIIPairSeq* = seq[TIIPair]
  92. TIITable*{.final.} = object # table[int, int]
  93. counter*: int
  94. data*: TIIPairSeq
  95. proc initIiTable*(x: var TIITable)
  96. proc iiTableGet*(t: TIITable, key: int): int
  97. proc iiTablePut*(t: var TIITable, key, val: int)
  98. # implementation
  99. proc skipConvCastAndClosure*(n: PNode): PNode =
  100. result = n
  101. while true:
  102. case result.kind
  103. of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64,
  104. nkClosure:
  105. result = result[0]
  106. of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
  107. result = result[1]
  108. else: break
  109. proc sameValue*(a, b: PNode): bool =
  110. result = false
  111. case a.kind
  112. of nkCharLit..nkUInt64Lit:
  113. if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) == getInt(b)
  114. of nkFloatLit..nkFloat64Lit:
  115. if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal
  116. of nkStrLit..nkTripleStrLit:
  117. if b.kind in {nkStrLit..nkTripleStrLit}: result = a.strVal == b.strVal
  118. else:
  119. # don't raise an internal error for 'nim check':
  120. #InternalError(a.info, "SameValue")
  121. discard
  122. proc leValue*(a, b: PNode): bool =
  123. # a <= b?
  124. result = false
  125. case a.kind
  126. of nkCharLit..nkUInt64Lit:
  127. if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) <= getInt(b)
  128. of nkFloatLit..nkFloat64Lit:
  129. if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal
  130. of nkStrLit..nkTripleStrLit:
  131. if b.kind in {nkStrLit..nkTripleStrLit}: result = a.strVal <= b.strVal
  132. else:
  133. # don't raise an internal error for 'nim check':
  134. #InternalError(a.info, "leValue")
  135. discard
  136. proc weakLeValue*(a, b: PNode): TImplication =
  137. if a.kind notin nkLiterals or b.kind notin nkLiterals:
  138. result = impUnknown
  139. else:
  140. result = if leValue(a, b): impYes else: impNo
  141. proc lookupInRecord(n: PNode, field: PIdent): PSym =
  142. result = nil
  143. case n.kind
  144. of nkRecList:
  145. for i in 0..<n.len:
  146. result = lookupInRecord(n[i], field)
  147. if result != nil: return
  148. of nkRecCase:
  149. if (n[0].kind != nkSym): return nil
  150. result = lookupInRecord(n[0], field)
  151. if result != nil: return
  152. for i in 1..<n.len:
  153. case n[i].kind
  154. of nkOfBranch, nkElse:
  155. result = lookupInRecord(lastSon(n[i]), field)
  156. if result != nil: return
  157. else: return nil
  158. of nkSym:
  159. if n.sym.name.id == field.id: result = n.sym
  160. else: return nil
  161. proc getModule*(s: PSym): PSym =
  162. result = s
  163. assert((result.kind == skModule) or (result.owner != result))
  164. while result != nil and result.kind != skModule: result = result.owner
  165. proc fromSystem*(op: PSym): bool {.inline.} = sfSystemModule in getModule(op).flags
  166. proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym =
  167. for i in start..<list.len:
  168. if list[i].kind == nkSym:
  169. result = list[i].sym
  170. if result.name.id == ident.id: return
  171. else: return nil
  172. result = nil
  173. proc sameIgnoreBacktickGensymInfo(a, b: string): bool =
  174. if a[0] != b[0]: return false
  175. var alen = a.len - 1
  176. while alen > 0 and a[alen] != '`': dec(alen)
  177. if alen <= 0: alen = a.len
  178. var i = 1
  179. var j = 1
  180. while true:
  181. while i < alen and a[i] == '_': inc i
  182. while j < b.len and b[j] == '_': inc j
  183. var aa = if i < alen: toLowerAscii(a[i]) else: '\0'
  184. var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
  185. if aa != bb: return false
  186. # the characters are identical:
  187. if i >= alen:
  188. # both cursors at the end:
  189. if j >= b.len: return true
  190. # not yet at the end of 'b':
  191. return false
  192. elif j >= b.len:
  193. return false
  194. inc i
  195. inc j
  196. proc getNamedParamFromList*(list: PNode, ident: PIdent): PSym =
  197. ## Named parameters are special because a named parameter can be
  198. ## gensym'ed and then they have '\`<number>' suffix that we need to
  199. ## ignore, see compiler / evaltempl.nim, snippet:
  200. ## ```
  201. ## result.add newIdentNode(getIdent(c.ic, x.name.s & "\`gensym" & $x.id),
  202. ## if c.instLines: actual.info else: templ.info)
  203. ## ```
  204. for i in 1..<list.len:
  205. let it = list[i].sym
  206. if it.name.id == ident.id or
  207. sameIgnoreBacktickGensymInfo(it.name.s, ident.s): return it
  208. proc hashNode(p: RootRef): Hash =
  209. result = hash(cast[pointer](p))
  210. proc mustRehash(length, counter: int): bool =
  211. assert(length > counter)
  212. result = (length * 2 < counter * 3) or (length - counter < 4)
  213. proc rspaces(x: int): Rope =
  214. # returns x spaces
  215. result = rope(spaces(x))
  216. proc toYamlChar(c: char): string =
  217. case c
  218. of '\0'..'\x1F', '\x7F'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4)
  219. of '\'', '\"', '\\': result = '\\' & c
  220. else: result = $c
  221. proc makeYamlString*(s: string): Rope =
  222. # We have to split long strings into many ropes. Otherwise
  223. # this could trigger InternalError(111). See the ropes module for
  224. # further information.
  225. const MaxLineLength = 64
  226. result = ""
  227. var res = "\""
  228. for i in 0..<s.len:
  229. if (i + 1) mod MaxLineLength == 0:
  230. res.add('\"')
  231. res.add("\n")
  232. result.add(rope(res))
  233. res = "\"" # reset
  234. res.add(toYamlChar(s[i]))
  235. res.add('\"')
  236. result.add(rope(res))
  237. proc flagsToStr[T](flags: set[T]): Rope =
  238. if flags == {}:
  239. result = rope("[]")
  240. else:
  241. result = ""
  242. for x in items(flags):
  243. if result != "": result.add(", ")
  244. result.add(makeYamlString($x))
  245. result = "[" & result & "]"
  246. proc lineInfoToStr(conf: ConfigRef; info: TLineInfo): Rope =
  247. result = "[$1, $2, $3]" % [makeYamlString(toFilename(conf, info)),
  248. rope(toLinenumber(info)),
  249. rope(toColumn(info))]
  250. proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet,
  251. indent, maxRecDepth: int): Rope
  252. proc symToYamlAux(conf: ConfigRef; n: PSym, marker: var IntSet,
  253. indent, maxRecDepth: int): Rope
  254. proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet,
  255. indent, maxRecDepth: int): Rope
  256. proc symToYamlAux(conf: ConfigRef; n: PSym, marker: var IntSet, indent: int,
  257. maxRecDepth: int): Rope =
  258. if n == nil:
  259. result = rope("null")
  260. elif containsOrIncl(marker, n.id):
  261. result = "\"$1\"" % [rope(n.name.s)]
  262. else:
  263. var ast = treeToYamlAux(conf, n.ast, marker, indent + 2, maxRecDepth - 1)
  264. #rope("typ"), typeToYamlAux(conf, n.typ, marker,
  265. # indent + 2, maxRecDepth - 1),
  266. let istr = rspaces(indent + 2)
  267. result = rope("{")
  268. result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
  269. result.addf("$N$1\"name\": $2", [istr, makeYamlString(n.name.s)])
  270. result.addf("$N$1\"typ\": $2", [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth - 1)])
  271. if conf != nil:
  272. # if we don't pass the config, we probably don't care about the line info
  273. result.addf("$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
  274. if card(n.flags) > 0:
  275. result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
  276. result.addf("$N$1\"magic\": $2", [istr, makeYamlString($n.magic)])
  277. result.addf("$N$1\"ast\": $2", [istr, ast])
  278. result.addf("$N$1\"options\": $2", [istr, flagsToStr(n.options)])
  279. result.addf("$N$1\"position\": $2", [istr, rope(n.position)])
  280. result.addf("$N$1\"k\": $2", [istr, makeYamlString($n.loc.k)])
  281. result.addf("$N$1\"storage\": $2", [istr, makeYamlString($n.loc.storage)])
  282. if card(n.loc.flags) > 0:
  283. result.addf("$N$1\"flags\": $2", [istr, makeYamlString($n.loc.flags)])
  284. result.addf("$N$1\"r\": $2", [istr, n.loc.r])
  285. result.addf("$N$1\"lode\": $2", [istr, treeToYamlAux(conf, n.loc.lode, marker, indent + 2, maxRecDepth - 1)])
  286. result.addf("$N$1}", [rspaces(indent)])
  287. proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
  288. maxRecDepth: int): Rope =
  289. var sonsRope: Rope
  290. if n == nil:
  291. sonsRope = rope("null")
  292. elif containsOrIncl(marker, n.id):
  293. sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope(
  294. strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
  295. else:
  296. if n.len > 0:
  297. sonsRope = rope("[")
  298. for i in 0..<n.len:
  299. if i > 0: sonsRope.add(",")
  300. sonsRope.addf("$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n[i],
  301. marker, indent + 4, maxRecDepth - 1)])
  302. sonsRope.addf("$N$1]", [rspaces(indent + 2)])
  303. else:
  304. sonsRope = rope("null")
  305. let istr = rspaces(indent + 2)
  306. result = rope("{")
  307. result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
  308. result.addf("$N$1\"sym\": $2", [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)])
  309. result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
  310. if card(n.flags) > 0:
  311. result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
  312. result.addf("$N$1\"callconv\": $2", [istr, makeYamlString($n.callConv)])
  313. result.addf("$N$1\"size\": $2", [istr, rope(n.size)])
  314. result.addf("$N$1\"align\": $2", [istr, rope(n.align)])
  315. result.addf("$N$1\"sons\": $2", [istr, sonsRope])
  316. proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
  317. maxRecDepth: int): Rope =
  318. if n == nil:
  319. result = rope("null")
  320. else:
  321. var istr = rspaces(indent + 2)
  322. result = "{$N$1\"kind\": $2" % [istr, makeYamlString($n.kind)]
  323. if maxRecDepth != 0:
  324. if conf != nil:
  325. result.addf(",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
  326. case n.kind
  327. of nkCharLit..nkInt64Lit:
  328. result.addf(",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
  329. of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
  330. result.addf(",$N$1\"floatVal\": $2",
  331. [istr, rope(n.floatVal.toStrMaxPrecision)])
  332. of nkStrLit..nkTripleStrLit:
  333. result.addf(",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
  334. of nkSym:
  335. result.addf(",$N$1\"sym\": $2",
  336. [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)])
  337. of nkIdent:
  338. if n.ident != nil:
  339. result.addf(",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
  340. else:
  341. result.addf(",$N$1\"ident\": null", [istr])
  342. else:
  343. if n.len > 0:
  344. result.addf(",$N$1\"sons\": [", [istr])
  345. for i in 0..<n.len:
  346. if i > 0: result.add(",")
  347. result.addf("$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n[i],
  348. marker, indent + 4, maxRecDepth - 1)])
  349. result.addf("$N$1]", [istr])
  350. result.addf(",$N$1\"typ\": $2",
  351. [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth)])
  352. result.addf("$N$1}", [rspaces(indent)])
  353. proc treeToYaml(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope =
  354. var marker = initIntSet()
  355. result = treeToYamlAux(conf, n, marker, indent, maxRecDepth)
  356. proc typeToYaml(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int = - 1): Rope =
  357. var marker = initIntSet()
  358. result = typeToYamlAux(conf, n, marker, indent, maxRecDepth)
  359. proc symToYaml(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope =
  360. var marker = initIntSet()
  361. result = symToYamlAux(conf, n, marker, indent, maxRecDepth)
  362. import tables
  363. const backrefStyle = "\e[90m"
  364. const enumStyle = "\e[34m"
  365. const numberStyle = "\e[33m"
  366. const stringStyle = "\e[32m"
  367. const resetStyle = "\e[0m"
  368. type
  369. DebugPrinter = object
  370. conf: ConfigRef
  371. visited: Table[pointer, int]
  372. renderSymType: bool
  373. indent: int
  374. currentLine: int
  375. firstItem: bool
  376. useColor: bool
  377. res: string
  378. proc indentMore(this: var DebugPrinter) =
  379. this.indent += 2
  380. proc indentLess(this: var DebugPrinter) =
  381. this.indent -= 2
  382. proc newlineAndIndent(this: var DebugPrinter) =
  383. this.res.add "\n"
  384. this.currentLine += 1
  385. for i in 0..<this.indent:
  386. this.res.add ' '
  387. proc openCurly(this: var DebugPrinter) =
  388. this.res.add "{"
  389. this.indentMore
  390. this.firstItem = true
  391. proc closeCurly(this: var DebugPrinter) =
  392. this.indentLess
  393. this.newlineAndIndent
  394. this.res.add "}"
  395. proc comma(this: var DebugPrinter) =
  396. this.res.add ", "
  397. proc openBracket(this: var DebugPrinter) =
  398. this.res.add "["
  399. #this.indentMore
  400. proc closeBracket(this: var DebugPrinter) =
  401. #this.indentLess
  402. this.res.add "]"
  403. proc key(this: var DebugPrinter; key: string) =
  404. if not this.firstItem:
  405. this.res.add ","
  406. this.firstItem = false
  407. this.newlineAndIndent
  408. this.res.add "\""
  409. this.res.add key
  410. this.res.add "\": "
  411. proc value(this: var DebugPrinter; value: string) =
  412. if this.useColor:
  413. this.res.add stringStyle
  414. this.res.add "\""
  415. this.res.add value
  416. this.res.add "\""
  417. if this.useColor:
  418. this.res.add resetStyle
  419. proc value(this: var DebugPrinter; value: BiggestInt) =
  420. if this.useColor:
  421. this.res.add numberStyle
  422. this.res.addInt value
  423. if this.useColor:
  424. this.res.add resetStyle
  425. proc value[T: enum](this: var DebugPrinter; value: T) =
  426. if this.useColor:
  427. this.res.add enumStyle
  428. this.res.add "\""
  429. this.res.add $value
  430. this.res.add "\""
  431. if this.useColor:
  432. this.res.add resetStyle
  433. proc value[T: enum](this: var DebugPrinter; value: set[T]) =
  434. this.openBracket
  435. let high = card(value)-1
  436. var i = 0
  437. for v in value:
  438. this.value v
  439. if i != high:
  440. this.comma
  441. inc i
  442. this.closeBracket
  443. template earlyExit(this: var DebugPrinter; n: PType | PNode | PSym) =
  444. if n == nil:
  445. this.res.add "null"
  446. return
  447. let index = this.visited.getOrDefault(cast[pointer](n), -1)
  448. if index < 0:
  449. this.visited[cast[pointer](n)] = this.currentLine
  450. else:
  451. if this.useColor:
  452. this.res.add backrefStyle
  453. this.res.add "<defined "
  454. this.res.addInt(this.currentLine - index)
  455. this.res.add " lines upwards>"
  456. if this.useColor:
  457. this.res.add resetStyle
  458. return
  459. proc value(this: var DebugPrinter; value: PType)
  460. proc value(this: var DebugPrinter; value: PNode)
  461. proc value(this: var DebugPrinter; value: PSym) =
  462. earlyExit(this, value)
  463. this.openCurly
  464. this.key("kind")
  465. this.value(value.kind)
  466. this.key("name")
  467. this.value(value.name.s)
  468. this.key("id")
  469. this.value(value.id)
  470. if value.kind in {skField, skEnumField, skParam}:
  471. this.key("position")
  472. this.value(value.position)
  473. if card(value.flags) > 0:
  474. this.key("flags")
  475. this.value(value.flags)
  476. if this.renderSymType and value.typ != nil:
  477. this.key "typ"
  478. this.value(value.typ)
  479. this.closeCurly
  480. proc value(this: var DebugPrinter; value: PType) =
  481. earlyExit(this, value)
  482. this.openCurly
  483. this.key "kind"
  484. this.value value.kind
  485. this.key "id"
  486. this.value value.id
  487. if value.sym != nil:
  488. this.key "sym"
  489. this.value value.sym
  490. #this.value value.sym.name.s
  491. if card(value.flags) > 0:
  492. this.key "flags"
  493. this.value value.flags
  494. if value.kind in IntegralTypes and value.n != nil:
  495. this.key "n"
  496. this.value value.n
  497. if value.len > 0:
  498. this.key "sons"
  499. this.openBracket
  500. for i in 0..<value.len:
  501. this.value value[i]
  502. if i != value.len - 1:
  503. this.comma
  504. this.closeBracket
  505. if value.n != nil:
  506. this.key "n"
  507. this.value value.n
  508. this.closeCurly
  509. proc value(this: var DebugPrinter; value: PNode) =
  510. earlyExit(this, value)
  511. this.openCurly
  512. this.key "kind"
  513. this.value value.kind
  514. if value.comment.len > 0:
  515. this.key "comment"
  516. this.value value.comment
  517. when defined(useNodeIds):
  518. this.key "id"
  519. this.value value.id
  520. if this.conf != nil:
  521. this.key "info"
  522. this.value $lineInfoToStr(this.conf, value.info)
  523. if value.flags != {}:
  524. this.key "flags"
  525. this.value value.flags
  526. if value.typ != nil:
  527. this.key "typ"
  528. this.value value.typ.kind
  529. else:
  530. this.key "typ"
  531. this.value "nil"
  532. case value.kind
  533. of nkCharLit..nkUInt64Lit:
  534. this.key "intVal"
  535. this.value value.intVal
  536. of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
  537. this.key "floatVal"
  538. this.value value.floatVal.toStrMaxPrecision
  539. of nkStrLit..nkTripleStrLit:
  540. this.key "strVal"
  541. this.value value.strVal
  542. of nkSym:
  543. this.key "sym"
  544. this.value value.sym
  545. #this.value value.sym.name.s
  546. of nkIdent:
  547. if value.ident != nil:
  548. this.key "ident"
  549. this.value value.ident.s
  550. else:
  551. if this.renderSymType and value.typ != nil:
  552. this.key "typ"
  553. this.value value.typ
  554. if value.len > 0:
  555. this.key "sons"
  556. this.openBracket
  557. for i in 0..<value.len:
  558. this.value value[i]
  559. if i != value.len - 1:
  560. this.comma
  561. this.closeBracket
  562. this.closeCurly
  563. proc debug(n: PSym; conf: ConfigRef) =
  564. var this: DebugPrinter
  565. this.visited = initTable[pointer, int]()
  566. this.renderSymType = true
  567. this.useColor = not defined(windows)
  568. this.value(n)
  569. echo($this.res)
  570. proc debug(n: PType; conf: ConfigRef) =
  571. var this: DebugPrinter
  572. this.visited = initTable[pointer, int]()
  573. this.renderSymType = true
  574. this.useColor = not defined(windows)
  575. this.value(n)
  576. echo($this.res)
  577. proc debug(n: PNode; conf: ConfigRef) =
  578. var this: DebugPrinter
  579. this.visited = initTable[pointer, int]()
  580. #this.renderSymType = true
  581. this.useColor = not defined(windows)
  582. this.value(n)
  583. echo($this.res)
  584. proc nextTry(h, maxHash: Hash): Hash =
  585. result = ((5 * h) + 1) and maxHash
  586. # For any initial h in range(maxHash), repeating that maxHash times
  587. # generates each int in range(maxHash) exactly once (see any text on
  588. # random-number generation for proof).
  589. proc objectSetContains*(t: TObjectSet, obj: RootRef): bool =
  590. # returns true whether n is in t
  591. var h: Hash = hashNode(obj) and high(t.data) # start with real hash value
  592. while t.data[h] != nil:
  593. if t.data[h] == obj:
  594. return true
  595. h = nextTry(h, high(t.data))
  596. result = false
  597. proc objectSetRawInsert(data: var TObjectSeq, obj: RootRef) =
  598. var h: Hash = hashNode(obj) and high(data)
  599. while data[h] != nil:
  600. assert(data[h] != obj)
  601. h = nextTry(h, high(data))
  602. assert(data[h] == nil)
  603. data[h] = obj
  604. proc objectSetEnlarge(t: var TObjectSet) =
  605. var n: TObjectSeq
  606. newSeq(n, t.data.len * GrowthFactor)
  607. for i in 0..high(t.data):
  608. if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
  609. swap(t.data, n)
  610. proc objectSetIncl*(t: var TObjectSet, obj: RootRef) =
  611. if mustRehash(t.data.len, t.counter): objectSetEnlarge(t)
  612. objectSetRawInsert(t.data, obj)
  613. inc(t.counter)
  614. proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool =
  615. # returns true if obj is already in the string table:
  616. var h: Hash = hashNode(obj) and high(t.data)
  617. while true:
  618. var it = t.data[h]
  619. if it == nil: break
  620. if it == obj:
  621. return true # found it
  622. h = nextTry(h, high(t.data))
  623. if mustRehash(t.data.len, t.counter):
  624. objectSetEnlarge(t)
  625. objectSetRawInsert(t.data, obj)
  626. else:
  627. assert(t.data[h] == nil)
  628. t.data[h] = obj
  629. inc(t.counter)
  630. result = false
  631. proc strTableContains*(t: TStrTable, n: PSym): bool =
  632. var h: Hash = n.name.h and high(t.data) # start with real hash value
  633. while t.data[h] != nil:
  634. if (t.data[h] == n):
  635. return true
  636. h = nextTry(h, high(t.data))
  637. result = false
  638. proc strTableRawInsert(data: var seq[PSym], n: PSym) =
  639. var h: Hash = n.name.h and high(data)
  640. while data[h] != nil:
  641. if data[h] == n:
  642. # allowed for 'export' feature:
  643. #InternalError(n.info, "StrTableRawInsert: " & n.name.s)
  644. return
  645. h = nextTry(h, high(data))
  646. assert(data[h] == nil)
  647. data[h] = n
  648. proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) =
  649. assert prevSym.name.h == newSym.name.h
  650. var h: Hash = prevSym.name.h and high(data)
  651. while data[h] != nil:
  652. if data[h] == prevSym:
  653. data[h] = newSym
  654. return
  655. h = nextTry(h, high(data))
  656. assert false
  657. proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
  658. symTabReplaceRaw(t.data, prevSym, newSym)
  659. proc strTableEnlarge(t: var TStrTable) =
  660. var n: seq[PSym]
  661. newSeq(n, t.data.len * GrowthFactor)
  662. for i in 0..high(t.data):
  663. if t.data[i] != nil: strTableRawInsert(n, t.data[i])
  664. swap(t.data, n)
  665. proc strTableAdd*(t: var TStrTable, n: PSym) =
  666. if mustRehash(t.data.len, t.counter): strTableEnlarge(t)
  667. strTableRawInsert(t.data, n)
  668. inc(t.counter)
  669. proc strTableInclReportConflict*(t: var TStrTable, n: PSym;
  670. onConflictKeepOld = false): PSym =
  671. # if `t` has a conflicting symbol (same identifier as `n`), return it
  672. # otherwise return `nil`. Incl `n` to `t` unless `onConflictKeepOld = true`
  673. # and a conflict was found.
  674. assert n.name != nil
  675. var h: Hash = n.name.h and high(t.data)
  676. var replaceSlot = -1
  677. while true:
  678. var it = t.data[h]
  679. if it == nil: break
  680. # Semantic checking can happen multiple times thanks to templates
  681. # and overloading: (var x=@[]; x).mapIt(it).
  682. # So it is possible the very same sym is added multiple
  683. # times to the symbol table which we allow here with the 'it == n' check.
  684. if it.name.id == n.name.id:
  685. if it == n: return nil
  686. replaceSlot = h
  687. h = nextTry(h, high(t.data))
  688. if replaceSlot >= 0:
  689. result = t.data[replaceSlot] # found it
  690. if not onConflictKeepOld:
  691. t.data[replaceSlot] = n # overwrite it with newer definition!
  692. return result # but return the old one
  693. elif mustRehash(t.data.len, t.counter):
  694. strTableEnlarge(t)
  695. strTableRawInsert(t.data, n)
  696. else:
  697. assert(t.data[h] == nil)
  698. t.data[h] = n
  699. inc(t.counter)
  700. result = nil
  701. proc strTableIncl*(t: var TStrTable, n: PSym;
  702. onConflictKeepOld = false): bool {.discardable.} =
  703. result = strTableInclReportConflict(t, n, onConflictKeepOld) != nil
  704. proc strTableGet*(t: TStrTable, name: PIdent): PSym =
  705. var h: Hash = name.h and high(t.data)
  706. while true:
  707. result = t.data[h]
  708. if result == nil: break
  709. if result.name.id == name.id: break
  710. h = nextTry(h, high(t.data))
  711. type
  712. TIdentIter* = object # iterator over all syms with same identifier
  713. h*: Hash # current hash
  714. name*: PIdent
  715. proc nextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym =
  716. # hot spots
  717. var h = ti.h and high(tab.data)
  718. var start = h
  719. var p {.cursor.} = tab.data[h]
  720. while p != nil:
  721. if p.name.id == ti.name.id: break
  722. h = nextTry(h, high(tab.data))
  723. if h == start:
  724. p = nil
  725. break
  726. p = tab.data[h]
  727. if p != nil:
  728. result = p # increase the count
  729. else:
  730. result = nil
  731. ti.h = nextTry(h, high(tab.data))
  732. proc initIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym =
  733. ti.h = s.h
  734. ti.name = s
  735. if tab.counter == 0: result = nil
  736. else: result = nextIdentIter(ti, tab)
  737. proc nextIdentExcluding*(ti: var TIdentIter, tab: TStrTable,
  738. excluding: IntSet): PSym =
  739. var h: Hash = ti.h and high(tab.data)
  740. var start = h
  741. result = tab.data[h]
  742. while result != nil:
  743. if result.name.id == ti.name.id and not contains(excluding, result.id):
  744. break
  745. h = nextTry(h, high(tab.data))
  746. if h == start:
  747. result = nil
  748. break
  749. result = tab.data[h]
  750. ti.h = nextTry(h, high(tab.data))
  751. if result != nil and contains(excluding, result.id): result = nil
  752. proc firstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
  753. excluding: IntSet): PSym =
  754. ti.h = s.h
  755. ti.name = s
  756. if tab.counter == 0: result = nil
  757. else: result = nextIdentExcluding(ti, tab, excluding)
  758. type
  759. TTabIter* = object
  760. h: Hash
  761. proc nextIter*(ti: var TTabIter, tab: TStrTable): PSym =
  762. # usage:
  763. # var
  764. # i: TTabIter
  765. # s: PSym
  766. # s = InitTabIter(i, table)
  767. # while s != nil:
  768. # ...
  769. # s = NextIter(i, table)
  770. #
  771. result = nil
  772. while (ti.h <= high(tab.data)):
  773. result = tab.data[ti.h]
  774. inc(ti.h) # ... and increment by one always
  775. if result != nil: break
  776. proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym =
  777. ti.h = 0
  778. if tab.counter == 0:
  779. result = nil
  780. else:
  781. result = nextIter(ti, tab)
  782. iterator items*(tab: TStrTable): PSym =
  783. var it: TTabIter
  784. var s = initTabIter(it, tab)
  785. while s != nil:
  786. yield s
  787. s = nextIter(it, tab)
  788. proc hasEmptySlot(data: TIdPairSeq): bool =
  789. for h in 0..high(data):
  790. if data[h].key == nil:
  791. return true
  792. result = false
  793. proc idTableRawGet(t: TIdTable, key: int): int =
  794. var h: Hash
  795. h = key and high(t.data) # start with real hash value
  796. while t.data[h].key != nil:
  797. if t.data[h].key.id == key:
  798. return h
  799. h = nextTry(h, high(t.data))
  800. result = - 1
  801. proc idTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool =
  802. var index = idTableRawGet(t, key.id)
  803. if index >= 0: result = t.data[index].key == key
  804. else: result = false
  805. proc idTableGet(t: TIdTable, key: PIdObj): RootRef =
  806. var index = idTableRawGet(t, key.id)
  807. if index >= 0: result = t.data[index].val
  808. else: result = nil
  809. proc idTableGet(t: TIdTable, key: int): RootRef =
  810. var index = idTableRawGet(t, key)
  811. if index >= 0: result = t.data[index].val
  812. else: result = nil
  813. iterator pairs*(t: TIdTable): tuple[key: int, value: RootRef] =
  814. for i in 0..high(t.data):
  815. if t.data[i].key != nil:
  816. yield (t.data[i].key.id, t.data[i].val)
  817. proc idTableRawInsert(data: var TIdPairSeq, key: PIdObj, val: RootRef) =
  818. var h: Hash
  819. h = key.id and high(data)
  820. while data[h].key != nil:
  821. assert(data[h].key.id != key.id)
  822. h = nextTry(h, high(data))
  823. assert(data[h].key == nil)
  824. data[h].key = key
  825. data[h].val = val
  826. proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) =
  827. var
  828. index: int
  829. n: TIdPairSeq
  830. index = idTableRawGet(t, key.id)
  831. if index >= 0:
  832. assert(t.data[index].key != nil)
  833. t.data[index].val = val
  834. else:
  835. if mustRehash(t.data.len, t.counter):
  836. newSeq(n, t.data.len * GrowthFactor)
  837. for i in 0..high(t.data):
  838. if t.data[i].key != nil:
  839. idTableRawInsert(n, t.data[i].key, t.data[i].val)
  840. assert(hasEmptySlot(n))
  841. swap(t.data, n)
  842. idTableRawInsert(t.data, key, val)
  843. inc(t.counter)
  844. iterator idTablePairs*(t: TIdTable): tuple[key: PIdObj, val: RootRef] =
  845. for i in 0..high(t.data):
  846. if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
  847. proc idNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int =
  848. var h: Hash
  849. h = key.id and high(t.data) # start with real hash value
  850. while t.data[h].key != nil:
  851. if t.data[h].key.id == key.id:
  852. return h
  853. h = nextTry(h, high(t.data))
  854. result = - 1
  855. proc idNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode =
  856. var index: int
  857. index = idNodeTableRawGet(t, key)
  858. if index >= 0: result = t.data[index].val
  859. else: result = nil
  860. proc idNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) =
  861. var h: Hash
  862. h = key.id and high(data)
  863. while data[h].key != nil:
  864. assert(data[h].key.id != key.id)
  865. h = nextTry(h, high(data))
  866. assert(data[h].key == nil)
  867. data[h].key = key
  868. data[h].val = val
  869. proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
  870. var index = idNodeTableRawGet(t, key)
  871. if index >= 0:
  872. assert(t.data[index].key != nil)
  873. t.data[index].val = val
  874. else:
  875. if mustRehash(t.data.len, t.counter):
  876. var n: TIdNodePairSeq
  877. newSeq(n, t.data.len * GrowthFactor)
  878. for i in 0..high(t.data):
  879. if t.data[i].key != nil:
  880. idNodeTableRawInsert(n, t.data[i].key, t.data[i].val)
  881. swap(t.data, n)
  882. idNodeTableRawInsert(t.data, key, val)
  883. inc(t.counter)
  884. iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
  885. for i in 0..high(t.data):
  886. if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
  887. proc initIITable(x: var TIITable) =
  888. x.counter = 0
  889. newSeq(x.data, StartSize)
  890. for i in 0..<StartSize: x.data[i].key = InvalidKey
  891. proc iiTableRawGet(t: TIITable, key: int): int =
  892. var h: Hash
  893. h = key and high(t.data) # start with real hash value
  894. while t.data[h].key != InvalidKey:
  895. if t.data[h].key == key: return h
  896. h = nextTry(h, high(t.data))
  897. result = -1
  898. proc iiTableGet(t: TIITable, key: int): int =
  899. var index = iiTableRawGet(t, key)
  900. if index >= 0: result = t.data[index].val
  901. else: result = InvalidKey
  902. proc iiTableRawInsert(data: var TIIPairSeq, key, val: int) =
  903. var h: Hash
  904. h = key and high(data)
  905. while data[h].key != InvalidKey:
  906. assert(data[h].key != key)
  907. h = nextTry(h, high(data))
  908. assert(data[h].key == InvalidKey)
  909. data[h].key = key
  910. data[h].val = val
  911. proc iiTablePut(t: var TIITable, key, val: int) =
  912. var index = iiTableRawGet(t, key)
  913. if index >= 0:
  914. assert(t.data[index].key != InvalidKey)
  915. t.data[index].val = val
  916. else:
  917. if mustRehash(t.data.len, t.counter):
  918. var n: TIIPairSeq
  919. newSeq(n, t.data.len * GrowthFactor)
  920. for i in 0..high(n): n[i].key = InvalidKey
  921. for i in 0..high(t.data):
  922. if t.data[i].key != InvalidKey:
  923. iiTableRawInsert(n, t.data[i].key, t.data[i].val)
  924. swap(t.data, n)
  925. iiTableRawInsert(t.data, key, val)
  926. inc(t.counter)
  927. proc isAddrNode*(n: PNode): bool =
  928. case n.kind
  929. of nkAddr, nkHiddenAddr: true
  930. of nkCallKinds:
  931. if n[0].kind == nkSym and n[0].sym.magic == mAddr: true
  932. else: false
  933. else: false
  934. proc listSymbolNames*(symbols: openArray[PSym]): string =
  935. for sym in symbols:
  936. if result.len > 0:
  937. result.add ", "
  938. result.add sym.name.s
  939. proc isDiscriminantField*(n: PNode): bool =
  940. if n.kind == nkCheckedFieldExpr: sfDiscriminant in n[0][1].sym.flags
  941. elif n.kind == nkDotExpr: sfDiscriminant in n[1].sym.flags
  942. else: false