Skip to content

Commit 318e788

Browse files
authored
import plugins (#1165)
1 parent bf6dd8f commit 318e788

File tree

12 files changed

+290
-72
lines changed

12 files changed

+290
-72
lines changed

src/nimony/builtintypes.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# See the file "license.txt", included in this
55
# distribution, for details about the copyright.
66

7-
include nifprelude
7+
include ".." / lib / nifprelude
88
import nimony_model
99

1010
type

src/nimony/decls.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
## Helpers for declarative constructs like `let` statements or `proc` declarations.
88

99
import std / assertions
10-
import nifstreams, nifcursors, nimony_model, programs
10+
import ".." / lib / [nifstreams, nifcursors]
11+
import ".." / nimony / [nimony_model, programs]
1112

1213
proc isRoutine*(t: SymKind): bool {.inline.} =
1314
t in {ProcY, FuncY, IteratorY, MacroY, TemplateY, ConverterY, MethodY}

src/nimony/deps.nim

Lines changed: 96 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type
5050
id, parent: int
5151
active: int
5252
isSystem: bool
53+
plugin: string
5354

5455
Command* = enum
5556
DoCheck, # like `nim check`
@@ -68,6 +69,7 @@ type
6869
processedModules: HashSet[string]
6970
moduleFlags: set[ModuleFlag]
7071
isGeneratingFinal: bool
72+
foundPlugins: HashSet[string]
7173

7274
proc 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+
136151
proc 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

162180
proc 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

180201
proc 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

239260
type
240-
CFile = tuple
261+
CFile = object
241262
name, obj, customArgs: string
242263

243264
proc 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

258279
proc 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
387408
proc 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+
390451
proc 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+
484543
proc 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:

src/nimony/programs.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
# distribution, for details about the copyright.
66

77
import std / [syncio, os, tables, sequtils, times, sets]
8-
include nifprelude
9-
import nifindexes, symparser, reporters, builtintypes
8+
include ".." / lib / nifprelude
9+
import ".." / lib / [nifindexes, symparser]
10+
import reporters, builtintypes
1011
import ".." / models / [nifindex_tags]
1112

1213
type

src/nimony/reporters.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# distribution, for details about the copyright.
66

77
import std / [syncio, strutils, os, terminal, assertions, sets]
8-
import nifstreams, nifcursors, bitabs, lineinfos
8+
import ".." / lib / [nifstreams, nifcursors, bitabs, lineinfos]
99

1010
type
1111
MsgKind* = enum

src/nimony/sem.nim

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,6 +4592,32 @@ proc buildIndexExports(c: var SemContext): TokenBuf =
45924592
result.add identToken(s, NoLineInfo)
45934593
result.addParRi()
45944594

4595+
proc writeNewDepsFile(c: var SemContext; outfile: string) =
4596+
# Update .2.deps.nif file that doesn't contain modules imported under `when false:`
4597+
# so that Hexer and following phases doesn't read such modules.
4598+
var deps = createTokenBuf(16)
4599+
deps.buildTree StmtsS, NoLineInfo:
4600+
if c.importedModules.len != 0:
4601+
var usedPlugins = false
4602+
deps.buildTree ImportS, NoLineInfo:
4603+
for _, i in c.importedModules:
4604+
if not i.fromPlugin:
4605+
deps.addStrLit i.path.toAbsolutePath
4606+
else:
4607+
usedPlugins = true
4608+
if usedPlugins:
4609+
for _, i in c.importedModules:
4610+
if i.fromPlugin:
4611+
deps.buildTree ImportS, NoLineInfo:
4612+
deps.buildTree PragmaxX, NoLineInfo:
4613+
deps.addStrLit i.path.toAbsolutePath
4614+
deps.buildTree PragmasS, NoLineInfo:
4615+
deps.buildTree KvU, NoLineInfo:
4616+
deps.addIdent "plugin"
4617+
deps.addStrLit "unknown"
4618+
let depsFile = changeFileExt(outfile, ".deps.nif")
4619+
writeFile depsFile, "(.nif24)\n" & toString(deps)
4620+
45954621
proc writeOutput(c: var SemContext; outfile: string) =
45964622
#var b = nifbuilder.open(outfile)
45974623
#b.addHeader "nimony", "nim-sem"
@@ -4605,17 +4631,7 @@ proc writeOutput(c: var SemContext; outfile: string) =
46054631
classes: move c.classIndexMap,
46064632
toBuild: move c.toBuild,
46074633
exportBuf: buildIndexExports(c))
4608-
4609-
# Update .2.deps.nif file that doesn't contain modules imported under `when false:`
4610-
# so that Hexer and following phases doesn't read such modules.
4611-
var deps = createTokenBuf(16)
4612-
deps.buildTree StmtsS, NoLineInfo:
4613-
if c.importedModules.len != 0:
4614-
deps.buildTree ImportS, NoLineInfo:
4615-
for _, i in c.importedModules:
4616-
deps.addStrLit i.path.toAbsolutePath
4617-
let depsFile = changeFileExt(outfile, ".deps.nif")
4618-
writeFile depsFile, "(.nif24)\n" & toString(deps)
4634+
writeNewDepsFile c, outfile
46194635

46204636
proc phaseX(c: var SemContext; n: Cursor; x: SemPhase): TokenBuf =
46214637
assert n.stmtKind == StmtsS

src/nimony/semdata.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type
3434
path*: string
3535
iface*: Iface
3636
exports*: Table[SymId, ImportFilter]
37+
fromPlugin*: bool
3738

3839
InstRequest* = object
3940
origin*: SymId

src/nimony/semimport.nim

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ proc importSingleFile(c: var SemContext; f1: ImportedFilename; origin: string;
5151
result = SymId(0)
5252
if not c.processedModules.contains(suffix):
5353
c.meta.importedFiles.add f2
54-
if (c.canSelfExec or c.inWhen > 0) and needsRecompile(f2, suffixToNif suffix):
55-
selfExec c, f2, (if f1.isSystem: " --isSystem" else: "")
54+
if f1.plugin.len == 0:
55+
if (c.canSelfExec or c.inWhen > 0) and needsRecompile(f2, suffixToNif suffix):
56+
selfExec c, f2, (if f1.isSystem: " --isSystem" else: "")
5657

5758
let moduleName = pool.strings.getOrIncl(f1.name)
5859
result = identToSym(c, moduleName, ModuleY)
@@ -66,7 +67,7 @@ proc importSingleFile(c: var SemContext; f1: ImportedFilename; origin: string;
6667
publish result, moduleDecl
6768
else:
6869
result = c.processedModules[suffix]
69-
let module = addr c.importedModules.mgetOrPut(result, ImportedModule(path: f2))
70+
let module = addr c.importedModules.mgetOrPut(result, ImportedModule(path: f2, fromPlugin: f1.plugin.len != 0))
7071
loadInterface suffix, module.iface, result, c.importTab, c.converters, c.methods, exports, mode
7172

7273
proc importSingleFile(c: var SemContext; f1: ImportedFilename; origin: string;
@@ -99,8 +100,8 @@ proc doImports(c: var SemContext; files: seq[ImportedFilename]; mode: ImportFilt
99100

100101
template maybeCyclic(c: var SemContext; x: var Cursor) =
101102
if x.kind == ParLe and x.exprKind == PragmaxX:
102-
inc x
103103
var y = x
104+
inc y
104105
skip y
105106
if y.substructureKind == PragmasU:
106107
inc y

0 commit comments

Comments
 (0)