modules.nim 5.5 KB

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