1717import std/ [os, tables, sets, syncio, assertions, strutils, times]
1818import semos, nifconfig, nimony_model, nifindexes
1919import " .." / gear2 / modnames, semdata
20+ import " .." / lib / tooldirs
2021
2122include nifprelude
2223
2526 nimFile: string
2627 modname: string
2728
28- proc indexFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .2.idx.nif"
29+ proc indexFile (config: NifConfig ; f: FilePair ; bundle: string ): string =
30+ config.nifcachePath / bundle / f.modname & " .2.idx.nif"
31+
2932proc parsedFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .1.nif"
3033proc depsFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .1.deps.nif"
3134proc deps2File (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .2.deps.nif"
32- proc semmedFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .2.nif"
35+ proc semmedFile (config: NifConfig ; f: FilePair ; bundle: string ): string =
36+ config.nifcachePath / bundle / f.modname & " .2.nif"
3337proc nifcFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .c.nif"
3438proc cFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .c"
3539proc objFile (config: NifConfig ; f: FilePair ): string = config.nifcachePath / f.modname & " .o"
@@ -46,7 +50,7 @@ proc resolveFileWrapper(paths: openArray[string]; origin: string; toResolve: str
4650type
4751 Node = ref object
4852 files: seq [FilePair ]
49- deps: seq [FilePair ]
53+ deps: seq [int ] # index into c.nodes
5054 id, parent: int
5155 active: int
5256 isSystem: bool
6670 nodes: seq [Node ]
6771 rootNode: Node
6872 includeStack: seq [string ]
69- processedModules: HashSet [string ]
73+ processedModules: Table [string , int ] # modname -> index to c.nodes
7074 moduleFlags: set [ModuleFlag ]
7175 isGeneratingFinal: bool
7276 foundPlugins: HashSet [string ]
@@ -125,9 +129,12 @@ proc importSingleFile(c: var DepContext; f1: string; info: PackedLineInfo;
125129 let f2 = resolveFileWrapper (c.config.paths, current.files[current.active].nimFile, f1)
126130 if not semos.fileExists (f2): return
127131 let p = c.toPair (f2)
128- if not c.processedModules.containsOrIncl (p.modname):
129- current.deps.add p
130- var imported = Node (files: @ [p], id: c.nodes.len, parent: current.id, isSystem: isSystem)
132+ let existingNode = c.processedModules.getOrDefault (p.modname, - 1 )
133+ if existingNode == - 1 :
134+ var imported = Node (files: @ [p], id: c.nodes.len, parent: current.id, isSystem: isSystem,
135+ plugin: current.plugin)
136+ current.deps.add imported.id
137+ c.processedModules[p.modname] = imported.id
131138 c.nodes.add imported
132139 parseDeps c, p, imported
133140 else :
@@ -136,17 +143,22 @@ proc importSingleFile(c: var DepContext; f1: string; info: PackedLineInfo;
136143 discard " ignore cycle"
137144 echo " cycle detected: " , current.files[0 ].nimFile, " <-> " , p.nimFile
138145 else :
139- current.deps.add p
146+ current.deps.add existingNode
140147
141148proc processPluginImport (c: var DepContext ; f: ImportedFilename ; info: PackedLineInfo ; current: Node ) =
142149 let f2 = resolveFileWrapper (c.config.paths, current.files[current.active].nimFile, f.path)
143150 if not semos.fileExists (f2): return
144151 let p = c.toPair (f2)
145- if not c.processedModules.containsOrIncl (p.modname):
146- current.deps.add p
147- c.nodes.add Node (files: @ [p], id: c.nodes.len,
148- parent: current.id, isSystem: false , plugin: f.plugin)
152+ let existingNode = c.processedModules.getOrDefault (p.modname, - 1 )
153+ if existingNode == - 1 :
154+ var imported = Node (files: @ [p], id: c.nodes.len,
155+ parent: current.id, isSystem: false , plugin: f.plugin)
156+ current.deps.add imported.id
157+ c.processedModules[p.modname] = imported.id
158+ c.nodes.add imported
149159 c.foundPlugins.incl f.plugin
160+ else :
161+ current.deps.add existingNode
150162
151163proc processImport (c: var DepContext ; it: var Cursor ; current: Node ) =
152164 let info = it.info
@@ -235,18 +247,25 @@ proc execNifler(c: var DepContext; f: FilePair) =
235247
236248proc importSystem (c: var DepContext ; current: Node ) =
237249 let p = c.toPair (stdlibFile (" std/system.nim" ))
238- current.deps. add p
239- if not c.processedModules. containsOrIncl (p.modname) :
250+ var existingNode = c.processedModules. getOrDefault (p.modname, - 1 )
251+ if existingNode == - 1 :
240252 # echo "NIFLING ", p.nimFile, " -> ", c.config.parsedFile(p)
241253 execNifler c, p
242254 var imported = Node (files: @ [p], id: c.nodes.len, parent: current.id, isSystem: true )
243255 c.nodes.add imported
256+ c.processedModules[p.modname] = imported.id
244257 parseDeps c, p, imported
258+ existingNode = imported.id
259+ current.deps.add existingNode
245260
246261proc parseDeps (c: var DepContext ; p: FilePair ; current: Node ) =
247- execNifler c, p
262+ let depsFile: string
263+ if not c.isGeneratingFinal:
264+ execNifler c, p
265+ depsFile = c.config.depsFile (p)
266+ else :
267+ depsFile = c.config.deps2File (p)
248268
249- let depsFile = if c.isGeneratingFinal: c.config.deps2File (p) else : c.config.depsFile (p)
250269 var stream = nifstreams.open (depsFile)
251270 try :
252271 discard processDirectives (stream.r)
@@ -269,7 +288,8 @@ proc rootPath(c: DepContext): string =
269288proc toBuildList (c: DepContext ): seq [CFile ] =
270289 result = @ []
271290 for v in c.nodes:
272- let index = readIndex (c.config.indexFile (v.files[0 ]))
291+ # if v.plugin.len > 0: continue
292+ let index = readIndex (c.config.indexFile (v.files[0 ], v.plugin))
273293 for i in index.toBuild:
274294 let path = i[1 ]
275295 let obj = splitFile (path).name & " .o"
@@ -399,9 +419,9 @@ proc generateFinalBuildFile(c: DepContext; commandLineArgsNifc: string; passC, p
399419 b.withTree " do" :
400420 b.addIdent " hexer"
401421 b.withTree " input" :
402- b.addStrLit c.config.semmedFile (v.files[0 ])
422+ b.addStrLit c.config.semmedFile (v.files[0 ], v.plugin )
403423 b.withTree " input" :
404- b.addStrLit c.config.indexFile (v.files[0 ])
424+ b.addStrLit c.config.indexFile (v.files[0 ], v.plugin )
405425 b.withTree " output" :
406426 b.addStrLit c.config.nifcFile (v.files[0 ])
407427
@@ -424,8 +444,8 @@ proc generateSemInstructions(c: DepContext; v: Node; b: var Builder; isMain: boo
424444 b.withTree " input" :
425445 b.addStrLit pf
426446 # Input: dependencies
427- for f in v.deps:
428- let idxFile = c.config.indexFile (f )
447+ for i in v.deps:
448+ let idxFile = c.config.indexFile (c.nodes[i].files[ 0 ], c.nodes[i].plugin )
429449 if not seenDeps.containsOrIncl (idxFile):
430450 b.withTree " input" :
431451 b.addStrLit idxFile
@@ -434,19 +454,26 @@ proc generateSemInstructions(c: DepContext; v: Node; b: var Builder; isMain: boo
434454 b.addStrLit c.config.cachedConfigFile ()
435455 # Outputs: semmed file and index file
436456 b.withTree " output" :
437- b.addStrLit c.config.semmedFile (v.files[0 ])
457+ b.addStrLit c.config.semmedFile (v.files[0 ], v.plugin )
438458 b.withTree " output" :
439- b.addStrLit c.config.indexFile (v.files[0 ])
459+ b.addStrLit c.config.indexFile (v.files[0 ], v.plugin )
440460
441461proc generatePluginSemInstructions (c: DepContext ; v: Node ; b: var Builder ) =
462+ #[ An import plugin fills `nimcache/<plugin>` for us. It is our job to
463+ generate index files for all `.nif` files in there. Both the frontend and
464+ the backend needs these files. But we want the index generation to happen
465+ in parallel. We cannot iterate over the files in the plugin directory as
466+ it is empty until the plugin has run. So unfortunately this logic lives in
467+ the v2 plugin.
468+ ]#
442469 b.withTree " do" :
443470 b.addIdent v.plugin
444471 b.withTree " input" :
445472 b.addStrLit v.files[0 ].nimFile
446473 b.withTree " output" :
447- b.addStrLit c.config.semmedFile (v.files[0 ])
474+ b.addStrLit c.config.semmedFile (v.files[0 ], v.plugin )
448475 b.withTree " output" :
449- b.addStrLit c.config.indexFile (v.files[0 ])
476+ b.addStrLit c.config.indexFile (v.files[0 ], v.plugin )
450477
451478proc generateFrontendBuildFile (c: DepContext ; commandLineArgs: string ): string =
452479 result = c.config.nifcachePath / c.rootNode.files[0 ].modname & " .build.nif"
@@ -490,8 +517,9 @@ proc generateFrontendBuildFile(c: DepContext; commandLineArgs: string): string =
490517 b.addIntLit 0 # main parsed file
491518 b.withTree " output" :
492519 b.addIntLit 0 # semmed file output
493- b.withTree " output" :
494- b.addIntLit 1 # index file output
520+ # index file output is not explicitly passed to the plugin!
521+ # b.withTree "output":
522+ # b.addIntLit 1 # index file output
495523
496524 # Build rules for semantic checking
497525 var i = 0
@@ -537,7 +565,7 @@ proc initDepContext(config: sink NifConfig; project, nifler: string; isFinal, fo
537565 let p = result .toPair (project)
538566 result .rootNode = Node (files: @ [p], id: 0 , parent: - 1 , active: 0 , isSystem: IsSystem in moduleFlags)
539567 result .nodes.add result .rootNode
540- result .processedModules. incl p.modname
568+ result .processedModules[ p.modname] = 0
541569 parseDeps result , p, result .rootNode
542570
543571proc buildGraph * (config: sink NifConfig ; project: string ; forceRebuild, silentMake: bool ;
0 commit comments