diff options
Diffstat (limited to 'compiler/reorder.nim')
-rw-r--r-- | compiler/reorder.nim | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/compiler/reorder.nim b/compiler/reorder.nim index 4fabf9041..2f7c04af1 100644 --- a/compiler/reorder.nim +++ b/compiler/reorder.nim @@ -1,9 +1,11 @@ import - intsets, ast, idents, algorithm, renderer, strutils, + ast, idents, renderer, msgs, modulegraphs, syntaxes, options, modulepaths, lineinfos +import std/[algorithm, strutils, intsets] + when defined(nimPreviewSlimSystem): import std/assertions @@ -25,17 +27,11 @@ when defined(nimDebugReorder): var idNames = newTable[int, string]() proc newDepN(id: int, pnode: PNode): DepN = - new(result) - result.id = id - result.pnode = pnode - result.idx = -1 - result.lowLink = -1 - result.onStack = false - result.kids = @[] - result.hAQ = -1 - result.hIS = -1 - result.hB = -1 - result.hCmd = -1 + result = DepN(id: id, pnode: pnode, idx: -1, + lowLink: -1, onStack: false, + kids: @[], hAQ: -1, hIS: -1, + hB: -1, hCmd: -1 + ) when defined(nimDebugReorder): result.expls = @[] @@ -106,6 +102,7 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev if a.kind == nkExprColonExpr and a[0].kind == nkIdent and a[0].ident.s == "pragma": # user defined pragma decl(a[1]) + for i in 1..<n.safeLen: deps(n[i]) else: for i in 0..<n.safeLen: deps(n[i]) of nkMixinStmt, nkBindStmt: discard @@ -113,7 +110,8 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev # XXX: for callables, this technically adds the return type dep before args for i in 0..<n.safeLen: deps(n[i]) -proc hasIncludes(n:PNode): bool = +proc hasIncludes(n: PNode): bool = + result = false for a in n: if a.kind == nkIncludeStmt: return true @@ -233,8 +231,9 @@ proc hasImportStmt(n: PNode): bool = # i it contains one case n.kind of nkImportStmt, nkFromStmt, nkImportExceptStmt: - return true + result = true of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt: + result = false for a in n: if a.hasImportStmt: return true @@ -255,6 +254,7 @@ proc hasCommand(n: PNode): bool = of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt, nkLetSection, nkConstSection, nkVarSection, nkIdentDefs: + result = false for a in n: if a.hasCommand: return true @@ -267,6 +267,7 @@ proc hasCommand(n: DepN): bool = result = bool(n.hCmd) proc hasAccQuoted(n: PNode): bool = + result = false if n.kind == nkAccQuoted: return true for a in n: @@ -282,6 +283,7 @@ proc hasAccQuotedDef(n: PNode): bool = of extendedProcDefs: result = n[0].hasAccQuoted of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt: + result = false for a in n: if hasAccQuotedDef(a): return true @@ -302,6 +304,7 @@ proc hasBody(n: PNode): bool = of extendedProcDefs: result = n[^1].kind == nkStmtList of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse, nkStaticStmt: + result = false for a in n: if a.hasBody: return true @@ -314,10 +317,19 @@ proc hasBody(n: DepN): bool = result = bool(n.hB) proc intersects(s1, s2: IntSet): bool = + result = false for a in s1: if s2.contains(a): return true +proc hasPushOrPopPragma(n: DepN): bool = + # Checks if the tree node has some pragmas that do not + # play well with reordering, like the push/pop pragma + # no crossing for push/pop barrier + let a = n.pnode + result = a.kind == nkPragma and a[0].kind == nkIdent and + (a[0].ident.s == "push" or a[0].ident.s == "pop") + proc buildGraph(n: PNode, deps: seq[(IntSet, IntSet)]): DepG = # Build a dependency graph result = newSeqOfCap[DepN](deps.len) @@ -359,6 +371,13 @@ proc buildGraph(n: PNode, deps: seq[(IntSet, IntSet)]): DepG = for dep in deps[i][0]: if dep in declares: ni.expls.add "one declares \"" & idNames[dep] & "\" and the other defines it" + elif hasPushOrPopPragma(nj): + # Every node that comes after a push/pop pragma must + # depend on it; vice versa + if j < i: + ni.kids.add nj + else: + nj.kids.add ni else: for d in declares: if uses.contains(d): @@ -392,23 +411,14 @@ proc strongConnect(v: var DepN, idx: var int, s: var seq[DepN], proc getStrongComponents(g: var DepG): seq[seq[DepN]] = ## Tarjan's algorithm. Performs a topological sort ## and detects strongly connected components. - var s: seq[DepN] + result = @[] + var s: seq[DepN] = @[] var idx = 0 for v in g.mitems: if v.idx < 0: strongConnect(v, idx, s, result) -proc hasForbiddenPragma(n: PNode): bool = - # Checks if the tree node has some pragmas that do not - # play well with reordering, like the push/pop pragma - for a in n: - if a.kind == nkPragma and a[0].kind == nkIdent and - a[0].ident.s == "push": - return true - proc reorder*(graph: ModuleGraph, n: PNode, module: PSym): PNode = - if n.hasForbiddenPragma: - return n var includedFiles = initIntSet() let mpath = toFullPath(graph.config, module.fileIdx) let n = expandIncludes(graph, module, n, mpath, |