modules.nim 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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, idgen, passes, syntaxes, llstream, modulegraphs, rod,
  13. lineinfos, pathutils, tables
  14. proc resetSystemArtifacts*(g: ModuleGraph) =
  15. magicsys.resetSysTypes(g)
  16. proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
  17. let
  18. pck = getPackageName(graph.config, filename.string)
  19. pck2 = if pck.len > 0: pck else: "unknown"
  20. pack = getIdent(graph.cache, pck2)
  21. var packSym = graph.packageSyms.strTableGet(pack)
  22. if packSym == nil:
  23. packSym = newSym(skPackage, getIdent(graph.cache, pck2), nil, result.info)
  24. initStrTable(packSym.tab)
  25. graph.packageSyms.strTableAdd(packSym)
  26. else:
  27. let existing = strTableGet(packSym.tab, result.name)
  28. if existing != nil and existing.info.fileIndex != result.info.fileIndex:
  29. when false:
  30. # we used to produce an error:
  31. localError(graph.config, result.info,
  32. "module names need to be unique per Nimble package; module clashes with " &
  33. toFullPath(graph.config, existing.info.fileIndex))
  34. else:
  35. # but starting with version 0.20 we now produce a fake Nimble package instead
  36. # to resolve the conflicts:
  37. let pck3 = fakePackageName(graph.config, filename)
  38. packSym = newSym(skPackage, getIdent(graph.cache, pck3), nil, result.info)
  39. initStrTable(packSym.tab)
  40. graph.packageSyms.strTableAdd(packSym)
  41. result.owner = packSym
  42. result.position = int fileIdx
  43. if int(fileIdx) >= graph.modules.len:
  44. setLen(graph.modules, int(fileIdx) + 1)
  45. graph.modules[result.position] = result
  46. initStrTable(result.tab)
  47. strTableAdd(result.tab, result) # a module knows itself
  48. strTableAdd(packSym.tab, result)
  49. proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
  50. # We cannot call ``newSym`` here, because we have to circumvent the ID
  51. # mechanism, which we do in order to assign each module a persistent ID.
  52. new(result)
  53. result.id = -1 # for better error checking
  54. result.kind = skModule
  55. let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
  56. result.name = getIdent(graph.cache, splitFile(filename).name)
  57. if not isNimIdentifier(result.name.s):
  58. rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
  59. result.info = newLineInfo(fileIdx, 1, 1)
  60. partialInitModule(result, graph, fileIdx, filename)
  61. proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): PSym =
  62. result = graph.getModule(fileIdx)
  63. if result == nil:
  64. let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
  65. let (r, id) = loadModuleSym(graph, fileIdx, filename)
  66. result = r
  67. if result == nil:
  68. result = newModule(graph, fileIdx)
  69. result.flags = result.flags + flags
  70. result.id = id
  71. registerModule(graph, result)
  72. else:
  73. partialInitModule(result, graph, fileIdx, filename)
  74. result.id = id
  75. assert result.id < 0
  76. discard processModule(graph, result,
  77. if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil)
  78. elif graph.isDirty(result):
  79. result.flags.excl sfDirty
  80. # reset module fields:
  81. initStrTable(result.tab)
  82. result.ast = nil
  83. discard processModule(graph, result,
  84. if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil)
  85. graph.markClientsDirty(fileIdx)
  86. proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym {.procvar.} =
  87. # this is called by the semantic checking phase
  88. assert graph.config != nil
  89. result = compileModule(graph, fileIdx, {})
  90. graph.addDep(s, fileIdx)
  91. # keep track of import relationships
  92. if graph.config.hcrOn:
  93. graph.importDeps.mgetOrPut(FileIndex(s.position), @[]).add(fileIdx)
  94. #if sfSystemModule in result.flags:
  95. # localError(result.info, errAttemptToRedefine, result.name.s)
  96. # restore the notes for outer module:
  97. graph.config.notes =
  98. if s.owner.id == graph.config.mainPackageId or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
  99. else: graph.config.foreignPackageNotes
  100. proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode {.procvar.} =
  101. result = syntaxes.parseFile(fileIdx, graph.cache, graph.config)
  102. graph.addDep(s, fileIdx)
  103. graph.addIncludeDep(s.position.FileIndex, fileIdx)
  104. proc connectCallbacks*(graph: ModuleGraph) =
  105. graph.includeFileCallback = includeModule
  106. graph.importModuleCallback = importModule
  107. proc compileSystemModule*(graph: ModuleGraph) =
  108. if graph.systemModule == nil:
  109. connectCallbacks(graph)
  110. graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
  111. graph.config.libpath / RelativeFile"system.nim")
  112. discard graph.compileModule(graph.config.m.systemFileIdx, {sfSystemModule})
  113. proc wantMainModule*(conf: ConfigRef) =
  114. if conf.projectFull.isEmpty:
  115. fatal(conf, newLineInfo(conf, AbsoluteFile"command line", 1, 1), errGenerated,
  116. "command expects a filename")
  117. conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
  118. proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
  119. connectCallbacks(graph)
  120. let conf = graph.config
  121. wantMainModule(conf)
  122. let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
  123. let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
  124. graph.importStack.add projectFile
  125. if projectFile == systemFileIdx:
  126. discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})
  127. else:
  128. graph.compileSystemModule()
  129. discard graph.compileModule(projectFile, {sfMainModule})
  130. proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym =
  131. result = graph.newModule(fileInfoIdx(graph.config, filename))
  132. result.id = getID()
  133. registerModule(graph, result)
  134. proc makeModule*(graph: ModuleGraph; filename: string): PSym =
  135. result = makeModule(graph, AbsoluteFile filename)
  136. proc makeStdinModule*(graph: ModuleGraph): PSym = graph.makeModule(AbsoluteFile"stdin")