From 8fa3e0cb25c7fec8ea727270dec7700a2ec271e5 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 5 Nov 2016 09:27:46 +0100 Subject: [PATCH] added missing module --- compiler/modulegraphs.nim | 92 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 compiler/modulegraphs.nim diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim new file mode 100644 index 0000000000..2c16717894 --- /dev/null +++ b/compiler/modulegraphs.nim @@ -0,0 +1,92 @@ +# +# +# The Nim Compiler +# (c) Copyright 2016 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements the module graph data structure. The module graph +## represents a complete Nim project. Single modules can either be kept in RAM +## or stored in a ROD file. The ROD file mechanism is not yet integrated here. +## +## The caching of modules is critical for 'nimsuggest' and is tricky to get +## right. If module E is being edited, we need autocompletion (and type +## checking) for E but we don't want to recompile depending +## modules right away for faster turnaround times. Instead we mark the module's +## dependencies as 'dirty'. Let D be a dependency of E. If D is dirty, we +## need to recompile it and all of its dependencies that are marked as 'dirty'. +## 'nimsuggest sug' actually is invoked for the file being edited so we know +## its content changed and there is no need to compute any checksums. +## Instead of a recursive algorithm, we use an iterative algorithm: +## +## - If a module gets recompiled, its dependencies need to be updated. +## - Its dependent module stays the same. +## + +import ast, intsets + +type + ModuleGraph* = ref object + modules*: seq[PSym] ## indexed by int32 fileIdx + packageSyms*: TStrTable + deps*: IntSet # the dependency graph or potentially its transitive closure. + suggestMode*: bool # whether we are in nimsuggest mode or not. + invalidTransitiveClosure: bool + +{.this: g.} + +proc newModuleGraph*(): ModuleGraph = + result = ModuleGraph() + initStrTable(result.packageSyms) + result.deps = initIntSet() + result.modules = @[] + +proc resetAllModules*(g: ModuleGraph) = + initStrTable(packageSyms) + deps = initIntSet() + modules = @[] + +proc getModule*(g: ModuleGraph; fileIdx: int32): PSym = + if fileIdx >= 0 and fileIdx < modules.len: + result = modules[fileIdx] + +proc dependsOn(a, b: int): int {.inline.} = (a shl 15) + b + +proc addDep*(g: ModuleGraph; m: PSym, dep: int32) = + if suggestMode: + deps.incl m.position.dependsOn(dep) + # we compute the transitive closure later when quering the graph lazily. + # this improve efficiency quite a lot: + invalidTransitiveClosure = true + +proc transitiveClosure(g: var IntSet; n: int) = + # warshall's algorithm + for k in 0..