5050 id, parent: int
5151 active: int
5252 isSystem: bool
53+ plugin: string
5354
5455 Command * = enum
5556 DoCheck , # like `nim check`
6869 processedModules: HashSet [string ]
6970 moduleFlags: set [ModuleFlag ]
7071 isGeneratingFinal: bool
72+ foundPlugins: HashSet [string ]
7173
7274proc toPair (c: DepContext ; f: string ): FilePair =
7375 FilePair (nimFile: f, modname: moduleSuffix (f, c.config.paths))
@@ -88,6 +90,9 @@ proc processInclude(c: var DepContext; it: var Cursor; current: Node) =
8890 discard " ignore wrong `include` statement"
8991 else :
9092 for f1 in items (files):
93+ if f1.plugin.len > 0 :
94+ discard " ignore plugin include file, will cause an error in sem.nim"
95+ continue
9196 let f2 = resolveFileWrapper (c.config.paths, current.files[current.active].nimFile, f1.path)
9297 # check for recursive include files:
9398 var isRecursive = false
@@ -133,6 +138,16 @@ proc importSingleFile(c: var DepContext; f1: string; info: PackedLineInfo;
133138 else :
134139 current.deps.add p
135140
141+ proc processPluginImport (c: var DepContext ; f: ImportedFilename ; info: PackedLineInfo ; current: Node ) =
142+ let f2 = resolveFileWrapper (c.config.paths, current.files[current.active].nimFile, f.path)
143+ if not semos.fileExists (f2): return
144+ 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)
149+ c.foundPlugins.incl f.plugin
150+
136151proc processImport (c: var DepContext ; it: var Cursor ; current: Node ) =
137152 let info = it.info
138153 var x = it
@@ -142,8 +157,8 @@ proc processImport(c: var DepContext; it: var Cursor; current: Node) =
142157 if x.stmtKind == WhenS : return
143158 while x.kind != ParRi :
144159 if x.kind == ParLe and x.exprKind == PragmaxX :
145- inc x
146160 var y = x
161+ inc y
147162 skip y
148163 if y.substructureKind == PragmasU :
149164 inc y
@@ -157,7 +172,10 @@ proc processImport(c: var DepContext; it: var Cursor; current: Node) =
157172 discard " ignore wrong `import` statement"
158173 else :
159174 for f in files:
160- importSingleFile c, f.path, info, current, false
175+ if f.plugin.len == 0 :
176+ importSingleFile c, f.path, info, current, false
177+ else :
178+ processPluginImport c, f, info, current
161179
162180proc processSingleImport (c: var DepContext ; it: var Cursor ; current: Node ) =
163181 # process `from import` and `import except` which have a single module expression
@@ -174,7 +192,10 @@ proc processSingleImport(c: var DepContext; it: var Cursor; current: Node) =
174192 discard " ignore wrong `from` statement"
175193 else :
176194 for f in files:
177- importSingleFile c, f.path, info, current, false
195+ if f.plugin.len == 0 :
196+ importSingleFile c, f.path, info, current, false
197+ else :
198+ processPluginImport c, f, info, current
178199 break
179200
180201proc processDep (c: var DepContext ; n: var Cursor ; current: Node ) =
@@ -237,7 +258,7 @@ proc parseDeps(c: var DepContext; p: FilePair; current: Node) =
237258 nifstreams.close (stream)
238259
239260type
240- CFile = tuple
261+ CFile = object
241262 name, obj, customArgs: string
242263
243264proc rootPath (c: DepContext ): string =
@@ -253,7 +274,7 @@ proc toBuildList(c: DepContext): seq[CFile] =
253274 let path = i[1 ]
254275 let obj = splitFile (path).name & " .o"
255276 let customArgs = i[2 ]
256- result .add ( path, obj, customArgs)
277+ result .add CFile (name: path, obj: obj, customArgs: customArgs)
257278
258279proc generateFinalBuildFile (c: DepContext ; commandLineArgsNifc: string ; passC, passL: string ): string =
259280 result = c.config.nifcachePath / c.rootNode.files[0 ].modname & " .final.build.nif"
@@ -387,6 +408,46 @@ proc generateFinalBuildFile(c: DepContext; commandLineArgsNifc: string; passC, p
387408proc cachedConfigFile (config: NifConfig ): string =
388409 config.nifcachePath / " cachedconfigfile.txt"
389410
411+ proc generateSemInstructions (c: DepContext ; v: Node ; b: var Builder ; isMain: bool ) =
412+ b.withTree " do" :
413+ b.addIdent " nimsem"
414+ b.withTree " args" :
415+ if v.isSystem:
416+ b.addStrLit " --isSystem"
417+ elif isMain:
418+ b.addStrLit " --isMain"
419+ # Input: parsed file
420+ var seenDeps = initHashSet [string ]()
421+ for f in v.files:
422+ let pf = c.config.parsedFile (f)
423+ if not seenDeps.containsOrIncl (pf):
424+ b.withTree " input" :
425+ b.addStrLit pf
426+ # Input: dependencies
427+ for f in v.deps:
428+ let idxFile = c.config.indexFile (f)
429+ if not seenDeps.containsOrIncl (idxFile):
430+ b.withTree " input" :
431+ b.addStrLit idxFile
432+ # Input: cached config file
433+ b.withTree " input" :
434+ b.addStrLit c.config.cachedConfigFile ()
435+ # Outputs: semmed file and index file
436+ b.withTree " output" :
437+ b.addStrLit c.config.semmedFile (v.files[0 ])
438+ b.withTree " output" :
439+ b.addStrLit c.config.indexFile (v.files[0 ])
440+
441+ proc generatePluginSemInstructions (c: DepContext ; v: Node ; b: var Builder ) =
442+ b.withTree " do" :
443+ b.addIdent v.plugin
444+ b.withTree " input" :
445+ b.addStrLit v.files[0 ].nimFile
446+ b.withTree " output" :
447+ b.addStrLit c.config.semmedFile (v.files[0 ])
448+ b.withTree " output" :
449+ b.addStrLit c.config.indexFile (v.files[0 ])
450+
390451proc generateFrontendBuildFile (c: DepContext ; commandLineArgs: string ): string =
391452 result = c.config.nifcachePath / c.rootNode.files[0 ].modname & " .build.nif"
392453 var b = nifbuilder.open (result )
@@ -420,44 +481,32 @@ proc generateFrontendBuildFile(c: DepContext; commandLineArgs: string): string =
420481 b.withTree " output" :
421482 b.addIntLit 1 # index file output
422483
423- # Build rules for semantic checking
424- var i = 0
425- for v in c.nodes:
426- b.withTree " do" :
427- # Choose the right command based on flags
428- b.addIdent " nimsem"
429- b.withTree " args" :
430- if v.isSystem:
431- b.addStrLit " --isSystem"
432- elif i == 0 : # first node is main
433- b.addStrLit " --isMain"
434-
435- # Input: parsed file
436- var seenDeps = initHashSet [string ]()
437- for f in v.files:
438- let pf = c.config.parsedFile (f)
439- if not seenDeps.containsOrIncl (pf):
440- b.withTree " input" :
441- b.addStrLit pf
442- # Input: dependencies
443- for f in v.deps:
444- let idxFile = c.config.indexFile (f)
445- if not seenDeps.containsOrIncl (idxFile):
446- b.withTree " input" :
447- b.addStrLit idxFile
448- # Input: cached config file
484+ for plugin in c.foundPlugins:
485+ b.withTree " cmd" :
486+ b.addSymbolDef plugin
487+ b.addStrLit plugin
488+ b.addKeyw " args"
449489 b.withTree " input" :
450- b.addStrLit c.config.cachedConfigFile ()
451- # Outputs: semmed file and index file
490+ b.addIntLit 0 # main parsed file
452491 b.withTree " output" :
453- b.addStrLit c.config. semmedFile (v.files[ 0 ])
492+ b.addIntLit 0 # semmed file output
454493 b.withTree " output" :
455- b.addStrLit c.config.indexFile (v.files[0 ])
494+ b.addIntLit 1 # index file output
495+
496+ # Build rules for semantic checking
497+ var i = 0
498+ for v in c.nodes:
499+ if v.plugin.len == 0 :
500+ generateSemInstructions c, v, b, i == 0
501+ else :
502+ generatePluginSemInstructions c, v, b
456503 inc i
457504
458505 # Build rules for parsing
459506 var seenFiles = initHashSet [string ]()
460507 for v in c.nodes:
508+ if v.plugin.len > 0 :
509+ continue
461510 for i in 0 ..< v.files.len:
462511 let f = c.config.parsedFile (v.files[i])
463512 if not seenFiles.containsOrIncl (f):
@@ -481,6 +530,16 @@ proc generateCachedConfigFile(c: DepContext; passC, passL: string) =
481530 if needUpdate:
482531 writeFile path, configStr
483532
533+ proc initDepContext (config: sink NifConfig ; project, nifler: string ; isFinal, forceRebuild: bool ; moduleFlags: set [ModuleFlag ]; cmd: Command ): DepContext =
534+ result = DepContext (nifler: nifler, config: config, rootNode: nil , includeStack: @ [],
535+ forceRebuild: forceRebuild, moduleFlags: moduleFlags, nimsem: findTool (" nimsem" ),
536+ cmd: cmd, isGeneratingFinal: isFinal)
537+ let p = result .toPair (project)
538+ result .rootNode = Node (files: @ [p], id: 0 , parent: - 1 , active: 0 , isSystem: IsSystem in moduleFlags)
539+ result .nodes.add result .rootNode
540+ result .processedModules.incl p.modname
541+ parseDeps result , p, result .rootNode
542+
484543proc buildGraph * (config: sink NifConfig ; project: string ; forceRebuild, silentMake: bool ;
485544 commandLineArgs, commandLineArgsNifc: string ; moduleFlags: set [ModuleFlag ]; cmd: Command ;
486545 passC, passL: string ) =
@@ -493,18 +552,7 @@ proc buildGraph*(config: sink NifConfig; project: string; forceRebuild, silentMa
493552 quoteShell (cfgNif)
494553 parseNifConfig cfgNif, config
495554
496- template initDepContext (isFinal: bool ): DepContext =
497- var c = DepContext (nifler: nifler, config: config, rootNode: nil , includeStack: @ [],
498- forceRebuild: forceRebuild, moduleFlags: moduleFlags, nimsem: findTool (" nimsem" ),
499- cmd: cmd, isGeneratingFinal: isFinal)
500- let p = c.toPair (project)
501- c.rootNode = Node (files: @ [p], id: 0 , parent: - 1 , active: 0 , isSystem: IsSystem in moduleFlags)
502- c.nodes.add c.rootNode
503- c.processedModules.incl p.modname
504- parseDeps c, p, c.rootNode
505- c
506-
507- var c = initDepContext (false )
555+ var c = initDepContext (config, project, nifler, false , forceRebuild, moduleFlags, cmd)
508556 generateCachedConfigFile c, passC, passL
509557 let buildFilename = generateFrontendBuildFile (c, commandLineArgs)
510558 # echo "run with: nifmake run ", buildFilename
@@ -519,7 +567,7 @@ proc buildGraph*(config: sink NifConfig; project: string; forceRebuild, silentMa
519567 # Parse `.2.deps.nif`.
520568 # It is generated by nimsem and doesn't contains modules imported under `when false:`.
521569 # https://github.com/nim-lang/nimony/issues/985
522- c = initDepContext (true )
570+ c = initDepContext (config, project, nifler, true , forceRebuild, moduleFlags, cmd )
523571 let buildFinalFilename = generateFinalBuildFile (c, commandLineArgsNifc, passC, passL)
524572 exec nifmakeCommand & quoteShell (buildFinalFilename)
525573 if cmd == DoRun :
0 commit comments