astalgo.nim 32 KB

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