modules.nim 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Implements the module handling, including the caching of modules.
  10. import
  11. ast, astalgo, magicsys, msgs, options,
  12. idents, lexer, passes, syntaxes, llstream, modulegraphs,
  13. lineinfos, pathutils, tables, packages
  14. when defined(nimPreviewSlimSystem):
  15. import std/[syncio, assertions]
  16. import ic / replayer
  17. proc resetSystemArtifacts*(g: ModuleGraph) =
  18. magicsys.resetSysTypes(g)
  19. template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
  20. getIdent(graph.cache, splitFile(filename).name)
  21. proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
  22. let packSym = getPackage(graph, fileIdx)
  23. result.owner = packSym
  24. result.position = int fileIdx
  25. proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
  26. let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
  27. # We cannot call ``newSym`` here, because we have to circumvent the ID
  28. # mechanism, which we do in order to assign each module a persistent ID.
  29. result = PSym(kind: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32),
  30. name: getModuleIdent(graph, filename),
  31. info: newLineInfo(fileIdx, 1, 1))
  32. if not isNimIdentifier(result.name.s):
  33. rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
  34. partialInitModule(result, graph, fileIdx, filename)
  35. graph.registerModule(result)
  36. proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fromModule: PSym = nil): PSym =
  37. var flags = flags
  38. if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule
  39. result = graph.getModule(fileIdx)
  40. template processModuleAux(moduleStatus) =
  41. onProcessing(graph, fileIdx, moduleStatus, fromModule = fromModule)
  42. var s: PLLStream
  43. if sfMainModule in flags:
  44. if graph.config.projectIsStdin: s = stdin.llStreamOpen
  45. elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput)
  46. discard processModule(graph, result, idGeneratorFromModule(result), s)
  47. if result == nil:
  48. var cachedModules: seq[FileIndex]
  49. result = moduleFromRodFile(graph, fileIdx, cachedModules)
  50. let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
  51. if result == nil:
  52. result = newModule(graph, fileIdx)
  53. result.flags.incl flags
  54. registerModule(graph, result)
  55. processModuleAux("import")
  56. else:
  57. if sfSystemModule in flags:
  58. graph.systemModule = result
  59. partialInitModule(result, graph, fileIdx, filename)
  60. for m in cachedModules:
  61. registerModuleById(graph, m)
  62. replayStateChanges(graph.packed[m.int].module, graph)
  63. replayGenericCacheInformation(graph, m.int)
  64. elif graph.isDirty(result):
  65. result.flags.excl sfDirty
  66. # reset module fields:
  67. initStrTables(graph, result)
  68. result.ast = nil
  69. processModuleAux("import(dirty)")
  70. graph.markClientsDirty(fileIdx)
  71. proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
  72. # this is called by the semantic checking phase
  73. assert graph.config != nil
  74. result = compileModule(graph, fileIdx, {}, s)
  75. graph.addDep(s, fileIdx)
  76. # keep track of import relationships
  77. if graph.config.hcrOn:
  78. graph.importDeps.mgetOrPut(FileIndex(s.position), @[]).add(fileIdx)
  79. #if sfSystemModule in result.flags:
  80. # localError(result.info, errAttemptToRedefine, result.name.s)
  81. # restore the notes for outer module:
  82. graph.config.notes =
  83. if graph.config.belongsToProjectPackage(s) or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
  84. else: graph.config.foreignPackageNotes
  85. proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
  86. result = syntaxes.parseFile(fileIdx, graph.cache, graph.config)
  87. graph.addDep(s, fileIdx)
  88. graph.addIncludeDep(s.position.FileIndex, fileIdx)
  89. proc connectCallbacks*(graph: ModuleGraph) =
  90. graph.includeFileCallback = includeModule
  91. graph.importModuleCallback = importModule
  92. proc compileSystemModule*(graph: ModuleGraph) =
  93. if graph.systemModule == nil:
  94. connectCallbacks(graph)
  95. graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
  96. graph.config.libpath / RelativeFile"system.nim")
  97. discard graph.compileModule(graph.config.m.systemFileIdx, {sfSystemModule})
  98. proc wantMainModule*(conf: ConfigRef) =
  99. if conf.projectFull.isEmpty:
  100. fatal(conf, gCmdLineInfo, "command expects a filename")
  101. conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
  102. proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
  103. connectCallbacks(graph)
  104. let conf = graph.config
  105. wantMainModule(conf)
  106. configComplete(graph)
  107. let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
  108. let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
  109. conf.projectMainIdx2 = projectFile
  110. let packSym = getPackage(graph, projectFile)
  111. graph.config.mainPackageId = packSym.getPackageId
  112. graph.importStack.add projectFile
  113. if projectFile == systemFileIdx:
  114. discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})
  115. else:
  116. graph.compileSystemModule()
  117. discard graph.compileModule(projectFile, {sfMainModule})
  118. proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym =
  119. result = graph.newModule(fileInfoIdx(graph.config, filename))
  120. registerModule(graph, result)
  121. proc makeModule*(graph: ModuleGraph; filename: string): PSym =
  122. result = makeModule(graph, AbsoluteFile filename)
  123. proc makeStdinModule*(graph: ModuleGraph): PSym = graph.makeModule(AbsoluteFile"stdin")