Files
Nim/compiler/modules.nim
quantimnot d30c6419a0 Refactor and doc package handling, module name mangling (#19821)
* Refactor and doc package handling, module name mangling

* Consolidate, de-duplicate and extend package handling
* Alter how duplicate module names of a package are handled
* Alter how module names are mangled
* Fix crash when another package is named 'stdlib' (test case added)
* Doc what defines a package in the manual

Modules with duplicate names within a package used to be given 'fake'
packages to resolve conflicts. That prevented the ability to discern if
a module belonged to the current project package or a foreign package.
They now have the proper package owner and the names are mangled in a
consistent manner to prevent codegen clashes.

All module names are now mangled the same. Stdlib was treated special
before, but now it is same as any other package. This fixes a crash
when a foreign package is named 'stdlib'.

Module mangling is altered for both file paths and symbols used by the
backends.

Removed an unused module name to package mapping that may have been
intended for IC. The mapping was removed because it wasn't being used
and was complicating the issue of package modules with duplicate names
not having the proper package owner assigned.

* Fix some tests

* Refactor `packagehandling`

* Remove `packagehandling.withPackageName` and its uses
* Move module path mangling from `packagehandling` to `modulepaths`
* Move `options.toRodFile` to `ic` to break import cycle

* Changed import style to match preferred style

Co-authored-by: quantimnot <quantimnot@users.noreply.github.com>
2022-05-30 18:52:19 +02:00

146 lines
5.6 KiB
Nim

#
#
# The Nim Compiler
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Implements the module handling, including the caching of modules.
import
ast, astalgo, magicsys, msgs, options,
idents, lexer, passes, syntaxes, llstream, modulegraphs,
lineinfos, pathutils, tables, packages
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions]
import ic / replayer
proc resetSystemArtifacts*(g: ModuleGraph) =
magicsys.resetSysTypes(g)
template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
getIdent(graph.cache, splitFile(filename).name)
proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
let packSym = getPackage(graph, fileIdx)
result.owner = packSym
result.position = int fileIdx
proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
# We cannot call ``newSym`` here, because we have to circumvent the ID
# mechanism, which we do in order to assign each module a persistent ID.
result = PSym(kind: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32),
name: getModuleIdent(graph, filename),
info: newLineInfo(fileIdx, 1, 1))
if not isNimIdentifier(result.name.s):
rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
partialInitModule(result, graph, fileIdx, filename)
graph.registerModule(result)
proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fromModule: PSym = nil): PSym =
var flags = flags
if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule
result = graph.getModule(fileIdx)
template processModuleAux(moduleStatus) =
onProcessing(graph, fileIdx, moduleStatus, fromModule = fromModule)
var s: PLLStream
if sfMainModule in flags:
if graph.config.projectIsStdin: s = stdin.llStreamOpen
elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput)
discard processModule(graph, result, idGeneratorFromModule(result), s)
if result == nil:
var cachedModules: seq[FileIndex]
result = moduleFromRodFile(graph, fileIdx, cachedModules)
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
if result == nil:
result = newModule(graph, fileIdx)
result.flags.incl flags
registerModule(graph, result)
processModuleAux("import")
else:
if sfSystemModule in flags:
graph.systemModule = result
partialInitModule(result, graph, fileIdx, filename)
for m in cachedModules:
registerModuleById(graph, m)
replayStateChanges(graph.packed[m.int].module, graph)
replayGenericCacheInformation(graph, m.int)
elif graph.isDirty(result):
result.flags.excl sfDirty
# reset module fields:
initStrTables(graph, result)
result.ast = nil
processModuleAux("import(dirty)")
graph.markClientsDirty(fileIdx)
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
# this is called by the semantic checking phase
assert graph.config != nil
result = compileModule(graph, fileIdx, {}, s)
graph.addDep(s, fileIdx)
# keep track of import relationships
if graph.config.hcrOn:
graph.importDeps.mgetOrPut(FileIndex(s.position), @[]).add(fileIdx)
#if sfSystemModule in result.flags:
# localError(result.info, errAttemptToRedefine, result.name.s)
# restore the notes for outer module:
graph.config.notes =
if graph.config.belongsToProjectPackage(s) or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
result = syntaxes.parseFile(fileIdx, graph.cache, graph.config)
graph.addDep(s, fileIdx)
graph.addIncludeDep(s.position.FileIndex, fileIdx)
proc connectCallbacks*(graph: ModuleGraph) =
graph.includeFileCallback = includeModule
graph.importModuleCallback = importModule
proc compileSystemModule*(graph: ModuleGraph) =
if graph.systemModule == nil:
connectCallbacks(graph)
graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
graph.config.libpath / RelativeFile"system.nim")
discard graph.compileModule(graph.config.m.systemFileIdx, {sfSystemModule})
proc wantMainModule*(conf: ConfigRef) =
if conf.projectFull.isEmpty:
fatal(conf, gCmdLineInfo, "command expects a filename")
conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
connectCallbacks(graph)
let conf = graph.config
wantMainModule(conf)
configComplete(graph)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
conf.projectMainIdx2 = projectFile
let packSym = getPackage(graph, projectFile)
graph.config.mainPackageId = packSym.getPackageId
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})
else:
graph.compileSystemModule()
discard graph.compileModule(projectFile, {sfMainModule})
proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym =
result = graph.newModule(fileInfoIdx(graph.config, filename))
registerModule(graph, result)
proc makeModule*(graph: ModuleGraph; filename: string): PSym =
result = makeModule(graph, AbsoluteFile filename)
proc makeStdinModule*(graph: ModuleGraph): PSym = graph.makeModule(AbsoluteFile"stdin")