reorder.nim 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import intsets, tables, ast, idents, renderer
  2. const
  3. nfTempMark = nfTransf
  4. nfPermMark = nfNoRewrite
  5. proc accQuoted(n: PNode): PIdent =
  6. var id = ""
  7. for i in 0 .. <n.len:
  8. let x = n[i]
  9. case x.kind
  10. of nkIdent: id.add(x.ident.s)
  11. of nkSym: id.add(x.sym.name.s)
  12. else: discard
  13. result = getIdent(id)
  14. proc addDecl(n: PNode; declares: var IntSet) =
  15. case n.kind
  16. of nkPostfix: addDecl(n[1], declares)
  17. of nkPragmaExpr: addDecl(n[0], declares)
  18. of nkIdent:
  19. declares.incl n.ident.id
  20. of nkSym:
  21. declares.incl n.sym.name.id
  22. of nkAccQuoted:
  23. declares.incl accQuoted(n).id
  24. else: discard
  25. proc computeDeps(n: PNode, declares, uses: var IntSet; topLevel: bool) =
  26. template deps(n) = computeDeps(n, declares, uses, false)
  27. template decl(n) =
  28. if topLevel: addDecl(n, declares)
  29. case n.kind
  30. of procDefs:
  31. decl(n[0])
  32. for i in 1..bodyPos: deps(n[i])
  33. of nkLetSection, nkVarSection, nkUsingStmt:
  34. for a in n:
  35. if a.kind in {nkIdentDefs, nkVarTuple}:
  36. for j in countup(0, a.len-3): decl(a[j])
  37. for j in a.len-2..a.len-1: deps(a[j])
  38. of nkConstSection, nkTypeSection:
  39. for a in n:
  40. if a.len >= 3:
  41. decl(a[0])
  42. for i in 1..<a.len: deps(a[i])
  43. of nkIdent: uses.incl n.ident.id
  44. of nkSym: uses.incl n.sym.name.id
  45. of nkAccQuoted: uses.incl accQuoted(n).id
  46. of nkOpenSymChoice, nkClosedSymChoice:
  47. uses.incl n.sons[0].sym.name.id
  48. of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse:
  49. for i in 0..<len(n): computeDeps(n[i], declares, uses, topLevel)
  50. else:
  51. for i in 0..<safeLen(n): deps(n[i])
  52. proc visit(i: int; all, res: PNode; deps: var seq[(IntSet, IntSet)]): bool =
  53. let n = all[i]
  54. if nfTempMark in n.flags:
  55. # not a DAG!
  56. return true
  57. if nfPermMark notin n.flags:
  58. incl n.flags, nfTempMark
  59. var uses = deps[i][1]
  60. for j in 0..<all.len:
  61. if j != i:
  62. let declares = deps[j][0]
  63. for d in declares:
  64. if uses.contains(d):
  65. let oldLen = res.len
  66. if visit(j, all, res, deps):
  67. result = true
  68. # rollback what we did, it turned out to be a dependency that caused
  69. # trouble:
  70. for k in oldLen..<res.len:
  71. res.sons[k].flags = res.sons[k].flags - {nfPermMark, nfTempMark}
  72. if oldLen != res.len: res.sons.setLen oldLen
  73. break
  74. n.flags = n.flags + {nfPermMark} - {nfTempMark}
  75. res.add n
  76. proc reorder*(n: PNode): PNode =
  77. result = newNodeI(nkStmtList, n.info)
  78. var deps = newSeq[(IntSet, IntSet)](n.len)
  79. for i in 0..<n.len:
  80. deps[i][0] = initIntSet()
  81. deps[i][1] = initIntSet()
  82. computeDeps(n[i], deps[i][0], deps[i][1], true)
  83. for i in 0 .. n.len-1:
  84. discard visit(i, n, result, deps)
  85. for i in 0..<result.len:
  86. result.sons[i].flags = result.sons[i].flags - {nfTempMark, nfPermMark}
  87. when false:
  88. # reverse the result:
  89. let L = result.len-1
  90. for i in 0 .. result.len div 2:
  91. result.sons[i].flags = result.sons[i].flags - {nfTempMark, nfPermMark}
  92. result.sons[L - i].flags = result.sons[L - i].flags - {nfTempMark, nfPermMark}
  93. swap(result.sons[i], result.sons[L - i])
  94. #echo result