compiler refactoring; use typesafe path handing; docgen: render symbols between modules
This commit is contained in:
parent
b5730ec01f
commit
86556ebfdb
44 changed files with 817 additions and 505 deletions
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import
|
||||
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
|
||||
intsets, platform, llstream, tables, sighashes
|
||||
intsets, platform, llstream, tables, sighashes, pathutils
|
||||
|
||||
# Careful! Section marks need to contain a tabulator so that they cannot
|
||||
# be part of C string literals.
|
||||
|
|
@ -226,7 +226,7 @@ proc processMergeInfo(L: var TBaseLexer, m: BModule) =
|
|||
when not defined(nimhygiene):
|
||||
{.pragma: inject.}
|
||||
|
||||
template withCFile(cfilename: string, body: untyped) =
|
||||
template withCFile(cfilename: AbsoluteFile, body: untyped) =
|
||||
var s = llStreamOpen(cfilename, fmRead)
|
||||
if s == nil: return
|
||||
var L {.inject.}: TBaseLexer
|
||||
|
|
@ -238,7 +238,7 @@ template withCFile(cfilename: string, body: untyped) =
|
|||
body
|
||||
closeBaseLexer(L)
|
||||
|
||||
proc readMergeInfo*(cfilename: string, m: BModule) =
|
||||
proc readMergeInfo*(cfilename: AbsoluteFile, m: BModule) =
|
||||
## reads the merge meta information into `m`.
|
||||
withCFile(cfilename):
|
||||
readKey(L, k)
|
||||
|
|
@ -251,7 +251,7 @@ type
|
|||
f: TCFileSections
|
||||
p: TCProcSections
|
||||
|
||||
proc readMergeSections(cfilename: string, m: var TMergeSections) =
|
||||
proc readMergeSections(cfilename: AbsoluteFile, m: var TMergeSections) =
|
||||
## reads the merge sections into `m`.
|
||||
withCFile(cfilename):
|
||||
readKey(L, k)
|
||||
|
|
@ -285,7 +285,7 @@ proc mergeRequired*(m: BModule): bool =
|
|||
#echo "not empty: ", i, " ", m.initProc.s[i]
|
||||
return true
|
||||
|
||||
proc mergeFiles*(cfilename: string, m: BModule) =
|
||||
proc mergeFiles*(cfilename: AbsoluteFile, m: BModule) =
|
||||
## merges the C file with the old version on hard disc.
|
||||
var old: TMergeSections
|
||||
readMergeSections(cfilename, old)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import
|
|||
nversion, nimsets, msgs, std / sha1, bitsets, idents, types,
|
||||
ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth,
|
||||
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
||||
lowerings, semparallel, tables, sets, ndi, lineinfos
|
||||
lowerings, semparallel, tables, sets, ndi, lineinfos, pathutils
|
||||
|
||||
import strutils except `%` # collides with ropes.`%`
|
||||
|
||||
|
|
@ -1064,7 +1064,8 @@ proc genFilenames(m: BModule): Rope =
|
|||
discard cgsym(m, "dbgRegisterFilename")
|
||||
result = nil
|
||||
for i in 0..<m.config.m.fileInfos.len:
|
||||
result.addf("dbgRegisterFilename($1);$N", [m.config.m.fileInfos[i].projPath.makeCString])
|
||||
result.addf("dbgRegisterFilename($1);$N",
|
||||
[m.config.m.fileInfos[i].projPath.string.makeCString])
|
||||
|
||||
proc genMainProc(m: BModule) =
|
||||
const
|
||||
|
|
@ -1348,7 +1349,7 @@ proc initProcOptions(m: BModule): TOptions =
|
|||
let opts = m.config.options
|
||||
if sfSystemModule in m.module.flags: opts-{optStackTrace} else: opts
|
||||
|
||||
proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
|
||||
proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule =
|
||||
new(result)
|
||||
result.g = g
|
||||
result.tmpBase = rope("TM" & $hashOwner(module) & "_")
|
||||
|
|
@ -1376,7 +1377,7 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
|
|||
incl result.flags, preventStackTrace
|
||||
excl(result.preInitProc.options, optStackTrace)
|
||||
let ndiName = if optCDebug in g.config.globalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi")
|
||||
else: ""
|
||||
else: AbsoluteFile""
|
||||
open(result.ndi, ndiName, g.config)
|
||||
|
||||
proc nullify[T](arr: var T) =
|
||||
|
|
@ -1427,7 +1428,7 @@ proc resetCgenModules*(g: BModuleList) =
|
|||
for m in cgenModules(g): resetModule(m)
|
||||
|
||||
proc rawNewModule(g: BModuleList; module: PSym; conf: ConfigRef): BModule =
|
||||
result = rawNewModule(g, module, toFullPath(conf, module.position.FileIndex))
|
||||
result = rawNewModule(g, module, AbsoluteFile toFullPath(conf, module.position.FileIndex))
|
||||
|
||||
proc newModule(g: BModuleList; module: PSym; conf: ConfigRef): BModule =
|
||||
# we should create only one cgen module for each module sym
|
||||
|
|
@ -1446,7 +1447,7 @@ proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
|
|||
injectG()
|
||||
result = newModule(g, module, graph.config)
|
||||
if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil:
|
||||
let f = if graph.config.headerFile.len > 0: graph.config.headerFile
|
||||
let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile
|
||||
else: graph.config.projectFull
|
||||
g.generatedHeader = rawNewModule(g, module,
|
||||
changeFileExt(completeCFilePath(graph.config, f), hExt))
|
||||
|
|
@ -1477,9 +1478,9 @@ proc writeHeader(m: BModule) =
|
|||
if optUseNimNamespace in m.config.globalOptions: result.add closeNamespaceNim()
|
||||
result.addf("#endif /* $1 */$n", [guard])
|
||||
if not writeRope(result, m.filename):
|
||||
rawMessage(m.config, errCannotOpenFile, m.filename)
|
||||
rawMessage(m.config, errCannotOpenFile, m.filename.string)
|
||||
|
||||
proc getCFile(m: BModule): string =
|
||||
proc getCFile(m: BModule): AbsoluteFile =
|
||||
let ext =
|
||||
if m.compileToCpp: ".cpp"
|
||||
elif m.config.cmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m"
|
||||
|
|
@ -1523,18 +1524,18 @@ proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
|
|||
if not equalsFile(code, cfile.cname):
|
||||
if isDefined(m.config, "nimdiff"):
|
||||
if fileExists(cfile.cname):
|
||||
copyFile(cfile.cname, cfile.cname & ".backup")
|
||||
echo "diff ", cfile.cname, ".backup ", cfile.cname
|
||||
copyFile(cfile.cname.string, cfile.cname.string & ".backup")
|
||||
echo "diff ", cfile.cname.string, ".backup ", cfile.cname.string
|
||||
else:
|
||||
echo "new file ", cfile.cname
|
||||
echo "new file ", cfile.cname.string
|
||||
if not writeRope(code, cfile.cname):
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.cname)
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.cname.string)
|
||||
return
|
||||
if existsFile(cfile.obj) and os.fileNewer(cfile.obj, cfile.cname):
|
||||
if fileExists(cfile.obj) and os.fileNewer(cfile.obj.string, cfile.cname.string):
|
||||
result = false
|
||||
else:
|
||||
if not writeRope(code, cfile.cname):
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.cname)
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.cname.string)
|
||||
|
||||
# We need 2 different logics here: pending modules (including
|
||||
# 'nim__dat') may require file merging for the combination of dead code
|
||||
|
|
@ -1570,14 +1571,14 @@ proc writeModule(m: BModule, pending: bool) =
|
|||
finishTypeDescriptions(m)
|
||||
var code = genModule(m, cf)
|
||||
if not writeRope(code, cfile):
|
||||
rawMessage(m.config, errCannotOpenFile, cfile)
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.string)
|
||||
addFileToCompile(m.config, cf)
|
||||
else:
|
||||
# Consider: first compilation compiles ``system.nim`` and produces
|
||||
# ``system.c`` but then compilation fails due to an error. This means
|
||||
# that ``system.o`` is missing, so we need to call the C compiler for it:
|
||||
var cf = Cfile(cname: cfile, obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {})
|
||||
if not existsFile(cf.obj): cf.flags = {CfileFlag.Cached}
|
||||
if not fileExists(cf.obj): cf.flags = {CfileFlag.Cached}
|
||||
addFileToCompile(m.config, cf)
|
||||
close(m.ndi)
|
||||
|
||||
|
|
@ -1592,7 +1593,7 @@ proc updateCachedModule(m: BModule) =
|
|||
|
||||
var code = genModule(m, cf)
|
||||
if not writeRope(code, cfile):
|
||||
rawMessage(m.config, errCannotOpenFile, cfile)
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.string)
|
||||
else:
|
||||
cf.flags = {CfileFlag.Cached}
|
||||
addFileToCompile(m.config, cf)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
import
|
||||
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
|
||||
tables, ndi, lineinfos
|
||||
tables, ndi, lineinfos, pathutils
|
||||
|
||||
from modulegraphs import ModuleGraph
|
||||
|
||||
|
|
@ -136,8 +136,8 @@ type
|
|||
s*: TCFileSections # sections of the C file
|
||||
flags*: set[Codegenflag]
|
||||
module*: PSym
|
||||
filename*: string
|
||||
cfilename*: string # filename of the module (including path,
|
||||
filename*: AbsoluteFile
|
||||
cfilename*: AbsoluteFile # filename of the module (including path,
|
||||
# without extension)
|
||||
tmpBase*: Rope # base for temp identifier generation
|
||||
typeCache*: TypeCache # cache the generated types
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2018 Nim contributors
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
|
||||
|
||||
# TODO: nimfix should use this; currently out of sync
|
||||
|
||||
import
|
||||
compiler/[options, idents, nimconf, scriptconfig, extccomp, commands, msgs, lineinfos, modulegraphs, condsyms],
|
||||
std/os
|
||||
options, idents, nimconf, scriptconfig, extccomp, commands, msgs,
|
||||
lineinfos, modulegraphs, condsyms, os, pathutils
|
||||
|
||||
type
|
||||
NimProg* = ref object
|
||||
|
|
@ -21,27 +28,27 @@ proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
|
|||
self.processCmdLine(passCmd1, "", conf)
|
||||
if self.supportsStdinFile and conf.projectName == "-":
|
||||
conf.projectName = "stdinfile"
|
||||
conf.projectFull = "stdinfile"
|
||||
conf.projectPath = canonicalizePath(conf, getCurrentDir())
|
||||
conf.projectFull = AbsoluteFile "stdinfile"
|
||||
conf.projectPath = AbsoluteDir getCurrentDir()
|
||||
conf.projectIsStdin = true
|
||||
elif conf.projectName != "":
|
||||
try:
|
||||
conf.projectFull = canonicalizePath(conf, conf.projectName)
|
||||
conf.projectFull = canonicalizePath(conf, AbsoluteFile conf.projectName)
|
||||
except OSError:
|
||||
conf.projectFull = conf.projectName
|
||||
conf.projectFull = AbsoluteFile conf.projectName
|
||||
let p = splitFile(conf.projectFull)
|
||||
let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
|
||||
conf.projectPath = canonicalizePath(conf, dir)
|
||||
let dir = if p.dir.isEmpty: AbsoluteDir getCurrentDir() else: p.dir
|
||||
conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile dir)
|
||||
conf.projectName = p.name
|
||||
else:
|
||||
conf.projectPath = canonicalizePath(conf, getCurrentDir())
|
||||
conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile getCurrentDir())
|
||||
|
||||
proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef): bool =
|
||||
loadConfigs(DefaultConfig, cache, conf) # load all config files
|
||||
if self.suggestMode:
|
||||
conf.command = "nimsuggest"
|
||||
|
||||
proc runNimScriptIfExists(path: string)=
|
||||
proc runNimScriptIfExists(path: AbsoluteFile)=
|
||||
if fileExists(path):
|
||||
runNimScript(cache, path, freshDefines = false, conf)
|
||||
|
||||
|
|
@ -53,8 +60,8 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
|||
runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
|
||||
|
||||
if optSkipParentConfigFiles notin conf.globalOptions:
|
||||
for dir in parentDirs(conf.projectPath, fromRoot = true, inclusive = false):
|
||||
runNimScriptIfExists(dir / DefaultConfigNims)
|
||||
for dir in parentDirs(conf.projectPath.string, fromRoot = true, inclusive = false):
|
||||
runNimScriptIfExists(AbsoluteDir(dir) / DefaultConfigNims)
|
||||
|
||||
if optSkipProjConfigFile notin conf.globalOptions:
|
||||
runNimScriptIfExists(conf.projectPath / DefaultConfigNims)
|
||||
|
|
@ -63,10 +70,10 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
|||
if not self.suggestMode:
|
||||
runNimScriptIfExists(scriptFile)
|
||||
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
|
||||
if fileExists(scriptFile) and scriptFile.cmpPaths(conf.projectFull) == 0:
|
||||
if fileExists(scriptFile) and scriptFile == conf.projectFull:
|
||||
return false
|
||||
else:
|
||||
if scriptFile.cmpPaths(conf.projectFull) != 0:
|
||||
if scriptFile != conf.projectFull:
|
||||
runNimScriptIfExists(scriptFile)
|
||||
else:
|
||||
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
|
|||
|
||||
import
|
||||
os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
|
||||
wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos
|
||||
wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos,
|
||||
pathutils
|
||||
|
||||
# but some have deps to imported modules. Yay.
|
||||
bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
|
||||
|
|
@ -208,7 +209,7 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
|
|||
|
||||
proc processCompile(conf: ConfigRef; filename: string) =
|
||||
var found = findFile(conf, filename)
|
||||
if found == "": found = filename
|
||||
if found.isEmpty: found = AbsoluteFile filename
|
||||
extccomp.addExternalFileToCompile(conf, found)
|
||||
|
||||
const
|
||||
|
|
@ -292,31 +293,32 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
|||
else: invalidCmdLineOption(conf, passCmd1, switch, info)
|
||||
|
||||
proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
|
||||
notRelativeToProj = false): string =
|
||||
notRelativeToProj = false): AbsoluteDir =
|
||||
let p = if os.isAbsolute(path) or '$' in path:
|
||||
path
|
||||
elif notRelativeToProj:
|
||||
getCurrentDir() / path
|
||||
else:
|
||||
conf.projectPath / path
|
||||
conf.projectPath.string / path
|
||||
try:
|
||||
result = pathSubs(conf, p, toFullPath(conf, info).splitFile().dir)
|
||||
result = AbsoluteDir pathSubs(conf, p, toFullPath(conf, info).splitFile().dir)
|
||||
except ValueError:
|
||||
localError(conf, info, "invalid path: " & p)
|
||||
result = p
|
||||
result = AbsoluteDir p
|
||||
|
||||
proc processCfgPath(conf: ConfigRef; path: string, info: TLineInfo): string =
|
||||
let path = if path[0] == '"': strutils.unescape(path) else: path
|
||||
proc processCfgPath(conf: ConfigRef; path: string, info: TLineInfo): AbsoluteDir =
|
||||
let path = if path.len > 0 and path[0] == '"': strutils.unescape(path)
|
||||
else: path
|
||||
let basedir = toFullPath(conf, info).splitFile().dir
|
||||
let p = if os.isAbsolute(path) or '$' in path:
|
||||
path
|
||||
else:
|
||||
basedir / path
|
||||
try:
|
||||
result = pathSubs(conf, p, basedir)
|
||||
result = AbsoluteDir pathSubs(conf, p, basedir)
|
||||
except ValueError:
|
||||
localError(conf, info, "invalid path: " & p)
|
||||
result = p
|
||||
result = AbsoluteDir p
|
||||
|
||||
const
|
||||
errInvalidNumber = "$1 is not a valid number"
|
||||
|
|
@ -331,9 +333,9 @@ proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) =
|
|||
if parseUtils.parseInt(a[3], column) <= 0:
|
||||
localError(conf, info, errInvalidNumber % a[2])
|
||||
|
||||
let dirtyOriginalIdx = fileInfoIdx(conf, a[1])
|
||||
let dirtyOriginalIdx = fileInfoIdx(conf, AbsoluteFile a[1])
|
||||
if dirtyOriginalIdx.int32 >= 0:
|
||||
msgs.setDirtyFile(conf, dirtyOriginalIdx, a[0])
|
||||
msgs.setDirtyFile(conf, dirtyOriginalIdx, AbsoluteFile a[0])
|
||||
|
||||
conf.m.trackPos = newLineInfo(dirtyOriginalIdx, line, column)
|
||||
|
||||
|
|
@ -345,7 +347,7 @@ proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
|
|||
localError(conf, info, errInvalidNumber % a[1])
|
||||
if parseUtils.parseInt(a[2], column) <= 0:
|
||||
localError(conf, info, errInvalidNumber % a[2])
|
||||
conf.m.trackPos = newLineInfo(conf, a[0], line, column)
|
||||
conf.m.trackPos = newLineInfo(conf, AbsoluteFile a[0], line, column)
|
||||
|
||||
proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
if pass in {passCmd2, passPP}:
|
||||
|
|
@ -359,14 +361,16 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
case switch.normalize
|
||||
of "path", "p":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
addPath(conf, if pass == passPP: processCfgPath(conf, arg, info) else: processPath(conf, arg, info), info)
|
||||
addPath(conf, if pass == passPP: processCfgPath(conf, arg, info)
|
||||
else: processPath(conf, arg, info), info)
|
||||
of "nimblepath", "babelpath":
|
||||
# keep the old name for compat
|
||||
if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
var path = processPath(conf, arg, info, notRelativeToProj=true)
|
||||
let nimbleDir = getEnv("NIMBLE_DIR")
|
||||
if nimbleDir.len > 0 and pass == passPP: path = nimbleDir / "pkgs"
|
||||
let nimbleDir = AbsoluteDir getEnv("NIMBLE_DIR")
|
||||
if not nimbleDir.isEmpty and pass == passPP:
|
||||
path = nimbleDir / RelativeDir"pkgs"
|
||||
nimblePath(conf, path, info)
|
||||
of "nonimblepath", "nobabelpath":
|
||||
expectNoArg(conf, switch, arg, pass, info)
|
||||
|
|
@ -374,20 +378,14 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
of "excludepath":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
let path = processPath(conf, arg, info)
|
||||
|
||||
conf.searchPaths.keepItIf(cmpPaths(it, path) != 0)
|
||||
conf.lazyPaths.keepItIf(cmpPaths(it, path) != 0)
|
||||
|
||||
if (len(path) > 0) and (path[len(path) - 1] == DirSep):
|
||||
let strippedPath = path[0 .. (len(path) - 2)]
|
||||
conf.searchPaths.keepItIf(cmpPaths(it, strippedPath) != 0)
|
||||
conf.lazyPaths.keepItIf(cmpPaths(it, strippedPath) != 0)
|
||||
conf.searchPaths.keepItIf(it != path)
|
||||
conf.lazyPaths.keepItIf(it != path)
|
||||
of "nimcache":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.nimcacheDir = processPath(conf, arg, info, true)
|
||||
of "out", "o":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.outFile = arg
|
||||
conf.outFile = AbsoluteFile arg
|
||||
of "docseesrcurl":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.docSeeSrcUrl = arg
|
||||
|
|
@ -411,7 +409,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
if pass in {passCmd2, passPP}: processCompile(conf, arg)
|
||||
of "link":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: addExternalFileToLink(conf, arg)
|
||||
if pass in {passCmd2, passPP}:
|
||||
addExternalFileToLink(conf, AbsoluteFile arg)
|
||||
of "debuginfo":
|
||||
expectNoArg(conf, switch, arg, pass, info)
|
||||
incl(conf.globalOptions, optCDebug)
|
||||
|
|
@ -581,7 +580,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
if pass in {passCmd2, passPP}: conf.cLibs.add processPath(conf, arg, info)
|
||||
of "clib":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: conf.cLinkedLibs.add processPath(conf, arg, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
conf.cLinkedLibs.add processPath(conf, arg, info).string
|
||||
of "header":
|
||||
if conf != nil: conf.headerFile = arg
|
||||
incl(conf.globalOptions, optGenIndex)
|
||||
|
|
@ -742,7 +742,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
|
||||
else: invalidCmdLineOption(conf, pass, switch, info)
|
||||
|
||||
template gCmdLineInfo*(): untyped = newLineInfo(config, "command line", 1, 1)
|
||||
template gCmdLineInfo*(): untyped = newLineInfo(config, AbsoluteFile"command line", 1, 1)
|
||||
|
||||
proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
|
||||
var cmd, arg: string
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
# This module implements a dependency file generator.
|
||||
|
||||
import
|
||||
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths
|
||||
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
|
||||
pathutils
|
||||
|
||||
from modulegraphs import ModuleGraph
|
||||
|
||||
|
|
@ -45,10 +46,10 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
|||
else:
|
||||
discard
|
||||
|
||||
proc generateDot*(graph: ModuleGraph; project: string) =
|
||||
proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) =
|
||||
let b = Backend(graph.backend)
|
||||
discard writeRope("digraph $1 {$n$2}$n" % [
|
||||
rope(changeFileExt(extractFilename(project), "")), b.dotGraph],
|
||||
rope(project.splitFile.name), b.dotGraph],
|
||||
changeFileExt(project, "dot"))
|
||||
|
||||
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ import
|
|||
wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast,
|
||||
packages/docutils/rst, packages/docutils/rstgen,
|
||||
packages/docutils/highlite, sempass2, json, xmltree, cgi,
|
||||
typesrenderer, astalgo, modulepaths, lineinfos, sequtils, intsets
|
||||
typesrenderer, astalgo, modulepaths, lineinfos, sequtils, intsets,
|
||||
pathutils
|
||||
|
||||
type
|
||||
TSections = array[TSymKind, Rope]
|
||||
|
|
@ -34,6 +35,8 @@ type
|
|||
exampleCounter: int
|
||||
emitted: IntSet # we need to track which symbols have been emitted
|
||||
# already. See bug #3655
|
||||
destFile*: AbsoluteFile
|
||||
thisDir*: AbsoluteDir
|
||||
|
||||
PDoc* = ref TDocumentor ## Alias to type less.
|
||||
|
||||
|
|
@ -48,12 +51,12 @@ proc whichType(d: PDoc; n: PNode): PSym =
|
|||
|
||||
proc attachToType(d: PDoc; p: PSym): PSym =
|
||||
let params = p.ast.sons[paramsPos]
|
||||
# first check the first parameter, then the return type,
|
||||
# then the other parameter:
|
||||
template check(i) =
|
||||
result = whichType(d, params[i])
|
||||
if result != nil: return result
|
||||
|
||||
# first check the first parameter, then the return type,
|
||||
# then the other parameter:
|
||||
if params.len > 1: check(1)
|
||||
if params.len > 0: check(0)
|
||||
for i in 2..<params.len: check(i)
|
||||
|
|
@ -74,10 +77,10 @@ template declareClosures =
|
|||
of mwUnknownSubstitution: k = warnUnknownSubstitutionX
|
||||
of mwUnsupportedLanguage: k = warnLanguageXNotSupported
|
||||
of mwUnsupportedField: k = warnFieldXNotSupported
|
||||
globalError(conf, newLineInfo(conf, filename, line, col), k, arg)
|
||||
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
|
||||
|
||||
proc docgenFindFile(s: string): string {.procvar.} =
|
||||
result = options.findFile(conf, s)
|
||||
result = options.findFile(conf, s).string
|
||||
if result.len == 0:
|
||||
result = getCurrentDir() / s
|
||||
if not existsFile(result): result = ""
|
||||
|
|
@ -90,13 +93,24 @@ proc parseRst(text, filename: string,
|
|||
result = rstParse(text, filename, line, column, hasToc, rstOptions,
|
||||
docgenFindFile, compilerMsgHandler)
|
||||
|
||||
proc newDocumentor*(filename: string; cache: IdentCache; conf: ConfigRef): PDoc =
|
||||
proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
|
||||
ext: string, dir: RelativeDir): AbsoluteFile =
|
||||
if optWholeProject in conf.globalOptions:
|
||||
# This is correct, for 'nim doc --project' we interpret the '--out' option as an
|
||||
# absolute directory, not as a filename!
|
||||
let d = if conf.outFile.isEmpty: conf.projectPath / dir else: AbsoluteDir(conf.outFile)
|
||||
createDir(d)
|
||||
result = d / changeFileExt(filename, ext)
|
||||
else:
|
||||
result = getOutFile(conf, filename, ext)
|
||||
|
||||
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef): PDoc =
|
||||
declareClosures()
|
||||
new(result)
|
||||
result.conf = conf
|
||||
result.cache = cache
|
||||
initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
|
||||
conf.configVars, filename, {roSupportRawDirective},
|
||||
conf.configVars, filename.string, {roSupportRawDirective},
|
||||
docgenFindFile, compilerMsgHandler)
|
||||
|
||||
if conf.configVars.hasKey("doc.googleAnalytics"):
|
||||
|
|
@ -120,8 +134,12 @@ proc newDocumentor*(filename: string; cache: IdentCache; conf: ConfigRef): PDoc
|
|||
result.jArray = newJArray()
|
||||
initStrTable result.types
|
||||
result.onTestSnippet = proc (d: var RstGenerator; filename, cmd: string; status: int; content: string) =
|
||||
localError(conf, newLineInfo(conf, d.filename, -1, -1), warnUser, "only 'rst2html' supports the ':test:' attribute")
|
||||
localError(conf, newLineInfo(conf, AbsoluteFile d.filename, -1, -1),
|
||||
warnUser, "only 'rst2html' supports the ':test:' attribute")
|
||||
result.emitted = initIntSet()
|
||||
result.destFile = getOutFile2(conf, relativeTo(filename, conf.projectPath),
|
||||
HtmlExt, RelativeDir"htmldocs")
|
||||
result.thisDir = result.destFile.splitFile.dir
|
||||
|
||||
proc dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
|
||||
if conf.cmd != cmdRst2tex: addf(dest, xml, args)
|
||||
|
|
@ -227,6 +245,10 @@ proc getPlainDocstring(n: PNode): string =
|
|||
result = getPlainDocstring(n.sons[i])
|
||||
if result.len > 0: return
|
||||
|
||||
proc belongsToPackage(conf: ConfigRef; module: PSym): bool =
|
||||
result = module.kind == skModule and module.owner != nil and
|
||||
module.owner.id == conf.mainPackageId
|
||||
|
||||
proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRenderFlags = {}) =
|
||||
var r: TSrcGen
|
||||
var literal = ""
|
||||
|
|
@ -259,8 +281,22 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
|
|||
dispA(d.conf, result, "<span class=\"FloatNumber\">$1</span>",
|
||||
"\\spanFloatNumber{$1}", [rope(esc(d.target, literal))])
|
||||
of tkSymbol:
|
||||
dispA(d.conf, result, "<span class=\"Identifier\">$1</span>",
|
||||
"\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
|
||||
let s = getTokSym(r)
|
||||
if s != nil and s.kind == skType and sfExported in s.flags and
|
||||
s.owner != nil and belongsToPackage(d.conf, s.owner) and
|
||||
d.target == outHtml:
|
||||
|
||||
let full = AbsoluteFile toFullPath(d.conf, FileIndex s.owner.position)
|
||||
let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath),
|
||||
HtmlExt, RelativeDir"htmldocs")
|
||||
|
||||
let external = tmp.relativeTo(d.thisDir, '/')
|
||||
result.addf "<a href=\"$1#$2\"><span class=\"Identifier\">$3</span></a>",
|
||||
[rope changeFileExt(external, "html").string, rope literal,
|
||||
rope(esc(d.target, literal))]
|
||||
else:
|
||||
dispA(d.conf, result, "<span class=\"Identifier\">$1</span>",
|
||||
"\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
|
||||
of tkSpaces, tkInvalid:
|
||||
add(result, literal)
|
||||
of tkCurlyDotLe:
|
||||
|
|
@ -290,23 +326,24 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
|
|||
|
||||
proc testExample(d: PDoc; ex: PNode) =
|
||||
if d.conf.errorCounter > 0: return
|
||||
let outputDir = d.conf.getNimcacheDir / "runnableExamples"
|
||||
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
|
||||
createDir(outputDir)
|
||||
inc d.exampleCounter
|
||||
let outp = outputDir / extractFilename(d.filename.changeFileExt"" &
|
||||
"_examples" & $d.exampleCounter & ".nim")
|
||||
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
|
||||
"_examples" & $d.exampleCounter & ".nim"))
|
||||
#let nimcache = outp.changeFileExt"" & "_nimcache"
|
||||
renderModule(ex, d.filename, outp, conf = d.conf)
|
||||
renderModule(ex, d.filename, outp.string, conf = d.conf)
|
||||
let backend = if isDefined(d.conf, "js"): "js"
|
||||
elif isDefined(d.conf, "cpp"): "cpp"
|
||||
elif isDefined(d.conf, "objc"): "objc"
|
||||
else: "c"
|
||||
if os.execShellCmd(os.getAppFilename() & " " & backend &
|
||||
" --nimcache:" & outputDir & " -r " & outp) != 0:
|
||||
quit "[Examples] failed: see " & outp
|
||||
" --nimcache:" & quoteShell(outputDir) &
|
||||
" -r " & quoteShell(outp)) != 0:
|
||||
quit "[Examples] failed: see " & outp.string
|
||||
else:
|
||||
# keep generated source file `outp` to allow inspection.
|
||||
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp])
|
||||
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
|
||||
removeFile(outp.changeFileExt(ExeExt))
|
||||
|
||||
proc extractImports(n: PNode; result: PNode) =
|
||||
|
|
@ -449,10 +486,8 @@ proc newUniquePlainSymbol(d: PDoc, original: string): string =
|
|||
result = original
|
||||
d.seenSymbols[original] = ""
|
||||
return
|
||||
|
||||
# Iterate over possible numeric variants of the original name.
|
||||
var count = 2
|
||||
|
||||
while true:
|
||||
result = original & "_" & $count
|
||||
if not d.seenSymbols.hasKey(result):
|
||||
|
|
@ -460,7 +495,6 @@ proc newUniquePlainSymbol(d: PDoc, original: string): string =
|
|||
break
|
||||
count += 1
|
||||
|
||||
|
||||
proc complexName(k: TSymKind, n: PNode, baseName: string): string =
|
||||
## Builds a complex unique href name for the node.
|
||||
##
|
||||
|
|
@ -482,11 +516,9 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
|
|||
of skTemplate: result.add(".t" & defaultParamSeparator)
|
||||
of skConverter: result.add(".c" & defaultParamSeparator)
|
||||
else: discard
|
||||
|
||||
if len(n) > paramsPos and n[paramsPos].kind == nkFormalParams:
|
||||
result.add(renderParamTypes(n[paramsPos]))
|
||||
|
||||
|
||||
proc isCallable(n: PNode): bool =
|
||||
## Returns true if `n` contains a callable node.
|
||||
case n.kind
|
||||
|
|
@ -495,7 +527,6 @@ proc isCallable(n: PNode): bool =
|
|||
else:
|
||||
result = false
|
||||
|
||||
|
||||
proc docstringSummary(rstText: string): string =
|
||||
## Returns just the first line or a brief chunk of text from a rst string.
|
||||
##
|
||||
|
|
@ -523,7 +554,6 @@ proc docstringSummary(rstText: string): string =
|
|||
result.delete(pos, last)
|
||||
result.add("…")
|
||||
|
||||
|
||||
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||
if not isVisible(d, nameNode): return
|
||||
let
|
||||
|
|
@ -545,8 +575,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
|||
break
|
||||
plainName.add(literal)
|
||||
|
||||
# Render the HTML hyperlink.
|
||||
nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments, renderDocComments})
|
||||
nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments,
|
||||
renderDocComments, renderSyms})
|
||||
|
||||
inc(d.id)
|
||||
let
|
||||
|
|
@ -563,16 +593,18 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
|||
var seeSrcRope: Rope = nil
|
||||
let docItemSeeSrc = getConfigVar(d.conf, "doc.item.seesrc")
|
||||
if docItemSeeSrc.len > 0:
|
||||
let cwd = canonicalizePath(d.conf, getCurrentDir())
|
||||
var path = toFullPath(d.conf, n.info)
|
||||
if path.startsWith(cwd):
|
||||
path = path[cwd.len+1 .. ^1].replace('\\', '/')
|
||||
let path = relativeTo(AbsoluteFile toFullPath(d.conf, n.info), d.conf.projectPath, '/')
|
||||
when false:
|
||||
let cwd = canonicalizePath(d.conf, getCurrentDir())
|
||||
var path = toFullPath(d.conf, n.info)
|
||||
if path.startsWith(cwd):
|
||||
path = path[cwd.len+1 .. ^1].replace('\\', '/')
|
||||
let gitUrl = getConfigVar(d.conf, "git.url")
|
||||
if gitUrl.len > 0:
|
||||
let commit = getConfigVar(d.conf, "git.commit", "master")
|
||||
let develBranch = getConfigVar(d.conf, "git.devel", "devel")
|
||||
dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc,
|
||||
["path", "line", "url", "commit", "devel"], [rope path,
|
||||
["path", "line", "url", "commit", "devel"], [rope path.string,
|
||||
rope($n.info.line), rope gitUrl, rope commit, rope develBranch])])
|
||||
|
||||
add(d.section[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"),
|
||||
|
|
@ -611,9 +643,7 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode =
|
|||
name = getName(d, nameNode)
|
||||
comm = $genRecComment(d, n)
|
||||
r: TSrcGen
|
||||
|
||||
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments})
|
||||
|
||||
result = %{ "name": %name, "type": %($k), "line": %n.info.line.int,
|
||||
"col": %n.info.col}
|
||||
if comm.len > 0:
|
||||
|
|
@ -626,7 +656,6 @@ proc checkForFalse(n: PNode): bool =
|
|||
|
||||
proc traceDeps(d: PDoc, it: PNode) =
|
||||
const k = skModule
|
||||
|
||||
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
|
||||
let sep = it[0]
|
||||
let dir = it[1]
|
||||
|
|
@ -637,11 +666,16 @@ proc traceDeps(d: PDoc, it: PNode) =
|
|||
for x in it[2]:
|
||||
a.sons[2] = x
|
||||
traceDeps(d, a)
|
||||
else:
|
||||
elif it.kind == nkSym and belongsToPackage(d.conf, it.sym):
|
||||
let full = AbsoluteFile toFullPath(d.conf, FileIndex it.sym.position)
|
||||
let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath), HtmlExt,
|
||||
RelativeDir"htmldocs")
|
||||
let external = relativeTo(tmp, d.thisDir, '/')
|
||||
if d.section[k] != nil: add(d.section[k], ", ")
|
||||
dispA(d.conf, d.section[k],
|
||||
"<a class=\"reference external\" href=\"$1.html\">$1</a>",
|
||||
"$1", [rope(splitFile(getModuleName(d.conf, it)).name)])
|
||||
"<a class=\"reference external\" href=\"$2\">$1</a>",
|
||||
"$1", [rope esc(d.target, it.sym.name.s),
|
||||
rope changeFileExt(external, "html").string])
|
||||
|
||||
proc generateDoc*(d: PDoc, n: PNode) =
|
||||
case n.kind
|
||||
|
|
@ -829,29 +863,23 @@ proc genOutFile(d: PDoc): Rope =
|
|||
|
||||
proc generateIndex*(d: PDoc) =
|
||||
if optGenIndex in d.conf.globalOptions:
|
||||
writeIndexFile(d[], splitFile(d.conf.outFile).dir /
|
||||
splitFile(d.filename).name & IndexExt)
|
||||
let dest = getOutFile2(d.conf, relativeTo(AbsoluteFile d.filename, d.conf.projectPath),
|
||||
IndexExt, RelativeDir"index")
|
||||
writeIndexFile(d[], dest.string)
|
||||
|
||||
proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string =
|
||||
if optWholeProject in conf.globalOptions:
|
||||
let d = if conf.outFile != "": conf.outFile else: dir
|
||||
createDir(d)
|
||||
result = d / changeFileExt(filename, ext)
|
||||
else:
|
||||
result = getOutFile(conf, filename, ext)
|
||||
|
||||
proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
|
||||
proc writeOutput*(d: PDoc, useWarning = false) =
|
||||
var content = genOutFile(d)
|
||||
if optStdout in d.conf.globalOptions:
|
||||
writeRope(stdout, content)
|
||||
else:
|
||||
let outfile = getOutFile2(d.conf, filename, outExt, "htmldocs")
|
||||
createDir(outfile.parentDir)
|
||||
template outfile: untyped = d.destFile
|
||||
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt, "htmldocs")
|
||||
createDir(outfile.splitFile.dir)
|
||||
if not writeRope(content, outfile):
|
||||
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile, outfile)
|
||||
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile,
|
||||
outfile.string)
|
||||
|
||||
proc writeOutputJson*(d: PDoc, filename, outExt: string,
|
||||
useWarning = false) =
|
||||
proc writeOutputJson*(d: PDoc, useWarning = false) =
|
||||
let content = %*{"orig": d.filename,
|
||||
"nimble": getPackageName(d.conf, d.filename),
|
||||
"entries": d.jArray}
|
||||
|
|
@ -859,8 +887,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string,
|
|||
write(stdout, $content)
|
||||
else:
|
||||
var f: File
|
||||
if open(f, getOutFile2(d.conf, splitFile(filename).name,
|
||||
outExt, "jsondocs"), fmWrite):
|
||||
if open(f, d.destFile.string, fmWrite):
|
||||
write(f, $content)
|
||||
close(f)
|
||||
else:
|
||||
|
|
@ -872,26 +899,27 @@ proc commandDoc*(cache: IdentCache, conf: ConfigRef) =
|
|||
var d = newDocumentor(conf.projectFull, cache, conf)
|
||||
d.hasToc = true
|
||||
generateDoc(d, ast)
|
||||
writeOutput(d, conf.projectFull, HtmlExt)
|
||||
writeOutput(d)
|
||||
generateIndex(d)
|
||||
|
||||
proc commandRstAux(cache: IdentCache, conf: ConfigRef; filename, outExt: string) =
|
||||
proc commandRstAux(cache: IdentCache, conf: ConfigRef;
|
||||
filename: AbsoluteFile, outExt: string) =
|
||||
var filen = addFileExt(filename, "txt")
|
||||
var d = newDocumentor(filen, cache, conf)
|
||||
d.onTestSnippet = proc (d: var RstGenerator; filename, cmd: string;
|
||||
status: int; content: string) =
|
||||
var outp: string
|
||||
var outp: AbsoluteFile
|
||||
if filename.len == 0:
|
||||
inc(d.id)
|
||||
let nameOnly = splitFile(d.filename).name
|
||||
let subdir = getNimcacheDir(conf) / nameOnly
|
||||
let subdir = getNimcacheDir(conf) / RelativeDir(nameOnly)
|
||||
createDir(subdir)
|
||||
outp = subdir / (nameOnly & "_snippet_" & $d.id & ".nim")
|
||||
outp = subdir / RelativeFile(nameOnly & "_snippet_" & $d.id & ".nim")
|
||||
elif isAbsolute(filename):
|
||||
outp = filename
|
||||
outp = AbsoluteFile filename
|
||||
else:
|
||||
# Nim's convention: every path is relative to the file it was written in:
|
||||
outp = splitFile(d.filename).dir / filename
|
||||
outp = splitFile(d.filename).dir.AbsoluteDir / RelativeFile(filename)
|
||||
writeFile(outp, content)
|
||||
let cmd = cmd % quoteShell(outp)
|
||||
rawMessage(conf, hintExecuting, cmd)
|
||||
|
|
@ -899,14 +927,12 @@ proc commandRstAux(cache: IdentCache, conf: ConfigRef; filename, outExt: string)
|
|||
rawMessage(conf, errGenerated, "executing of external program failed: " & cmd)
|
||||
|
||||
d.isPureRst = true
|
||||
var rst = parseRst(readFile(filen), filen, 0, 1, d.hasToc,
|
||||
var rst = parseRst(readFile(filen.string), filen.string, 0, 1, d.hasToc,
|
||||
{roSupportRawDirective}, conf)
|
||||
var modDesc = newStringOfCap(30_000)
|
||||
#d.modDesc = newMutableRope(30_000)
|
||||
renderRstToOut(d[], rst, modDesc)
|
||||
#freezeMutableRope(d.modDesc)
|
||||
d.modDesc = rope(modDesc)
|
||||
writeOutput(d, filename, outExt)
|
||||
writeOutput(d)
|
||||
generateIndex(d)
|
||||
|
||||
proc commandRst2Html*(cache: IdentCache, conf: ConfigRef) =
|
||||
|
|
@ -928,9 +954,9 @@ proc commandJson*(cache: IdentCache, conf: ConfigRef) =
|
|||
writeRope(stdout, content)
|
||||
else:
|
||||
#echo getOutFile(gProjectFull, JsonExt)
|
||||
let filename = getOutFile(conf, conf.projectFull, JsonExt)
|
||||
let filename = getOutFile(conf, RelativeFile conf.projectName, JsonExt)
|
||||
if not writeRope(content, filename):
|
||||
rawMessage(conf, errCannotOpenFile, filename)
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
||||
proc commandTags*(cache: IdentCache, conf: ConfigRef) =
|
||||
var ast = parseFile(conf.projectMainIdx, cache, conf)
|
||||
|
|
@ -945,12 +971,12 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
|
|||
writeRope(stdout, content)
|
||||
else:
|
||||
#echo getOutFile(gProjectFull, TagsExt)
|
||||
let filename = getOutFile(conf, conf.projectFull, TagsExt)
|
||||
let filename = getOutFile(conf, RelativeFile conf.projectName, TagsExt)
|
||||
if not writeRope(content, filename):
|
||||
rawMessage(conf, errCannotOpenFile, filename)
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
||||
proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
|
||||
var content = mergeIndexes(conf.projectFull).rope
|
||||
var content = mergeIndexes(conf.projectFull.string).rope
|
||||
|
||||
let code = ropeFormatNamedVars(conf, getConfigVar(conf, "doc.file"), ["title",
|
||||
"tableofcontents", "moduledesc", "date", "time",
|
||||
|
|
@ -958,6 +984,6 @@ proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
|
|||
["Index".rope, nil, nil, rope(getDateStr()),
|
||||
rope(getClockStr()), content, nil, nil, nil])
|
||||
# no analytics because context is not available
|
||||
let filename = getOutFile(conf, "theindex", HtmlExt)
|
||||
let filename = getOutFile(conf, RelativeFile"theindex", HtmlExt)
|
||||
if not writeRope(code, filename):
|
||||
rawMessage(conf, errCannotOpenFile, filename)
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
# semantic checking.
|
||||
|
||||
import
|
||||
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos
|
||||
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
|
||||
pathutils
|
||||
|
||||
from modulegraphs import ModuleGraph
|
||||
|
||||
|
|
@ -38,11 +39,11 @@ template closeImpl(body: untyped) {.dirty.} =
|
|||
|
||||
proc close(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
|
||||
closeImpl:
|
||||
writeOutput(g.doc, toFullPath(graph.config, FileIndex g.module.position), HtmlExt, useWarning)
|
||||
writeOutput(g.doc, useWarning)
|
||||
|
||||
proc closeJson(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
|
||||
closeImpl:
|
||||
writeOutputJson(g.doc, toFullPath(graph.config, FileIndex g.module.position), ".json", useWarning)
|
||||
writeOutputJson(g.doc, useWarning)
|
||||
|
||||
proc processNode(c: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
|
|
@ -60,7 +61,8 @@ proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
|
|||
var g: PGen
|
||||
new(g)
|
||||
g.module = module
|
||||
var d = newDocumentor(toFullPath(graph.config, FileIndex module.position), graph.cache, graph.config)
|
||||
var d = newDocumentor(AbsoluteFile toFullPath(graph.config, FileIndex module.position),
|
||||
graph.cache, graph.config)
|
||||
d.hasToc = true
|
||||
g.doc = d
|
||||
result = g
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import
|
||||
ropes, os, strutils, osproc, platform, condsyms, options, msgs,
|
||||
lineinfos, std / sha1, streams
|
||||
lineinfos, std / sha1, streams, pathutils
|
||||
|
||||
type
|
||||
TInfoCCProp* = enum # properties of the C compiler:
|
||||
|
|
@ -429,12 +429,13 @@ proc initVars*(conf: ConfigRef) =
|
|||
if len(conf.ccompilerpath) == 0:
|
||||
conf.ccompilerpath = getConfigVar(conf, conf.cCompiler, ".path")
|
||||
|
||||
proc completeCFilePath*(conf: ConfigRef; cfile: string, createSubDir: bool = true): string =
|
||||
proc completeCFilePath*(conf: ConfigRef; cfile: AbsoluteFile,
|
||||
createSubDir: bool = true): AbsoluteFile =
|
||||
result = completeGeneratedFilePath(conf, cfile, createSubDir)
|
||||
|
||||
proc toObjFile*(conf: ConfigRef; filename: string): string =
|
||||
proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
|
||||
# Object file for compilation
|
||||
result = filename & "." & CC[conf.cCompiler].objExt
|
||||
result = AbsoluteFile(filename.string & "." & CC[conf.cCompiler].objExt)
|
||||
|
||||
proc addFileToCompile*(conf: ConfigRef; cf: Cfile) =
|
||||
conf.toCompile.add(cf)
|
||||
|
|
@ -447,8 +448,8 @@ proc resetCompilationLists*(conf: ConfigRef) =
|
|||
# Maybe we can do that in checkDep on the other hand?
|
||||
conf.externalToLink.setLen 0
|
||||
|
||||
proc addExternalFileToLink*(conf: ConfigRef; filename: string) =
|
||||
conf.externalToLink.insert(filename, 0)
|
||||
proc addExternalFileToLink*(conf: ConfigRef; filename: AbsoluteFile) =
|
||||
conf.externalToLink.insert(filename.string, 0)
|
||||
|
||||
proc execWithEcho(conf: ConfigRef; cmd: string, msg = hintExecuting): int =
|
||||
rawMessage(conf, msg, cmd)
|
||||
|
|
@ -459,14 +460,15 @@ proc execExternalProgram*(conf: ConfigRef; cmd: string, msg = hintExecuting) =
|
|||
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
|
||||
cmd)
|
||||
|
||||
proc generateScript(conf: ConfigRef; projectFile: string, script: Rope) =
|
||||
let (dir, name, ext) = splitFile(projectFile)
|
||||
let filename = getNimcacheDir(conf) / addFileExt("compile_" & name,
|
||||
platform.OS[conf.target.targetOS].scriptExt)
|
||||
proc generateScript(conf: ConfigRef; projectFile: AbsoluteFile, script: Rope) =
|
||||
let (_, name, _) = splitFile(projectFile)
|
||||
let filename = getNimcacheDir(conf) / RelativeFile(addFileExt("compile_" & name,
|
||||
platform.OS[conf.target.targetOS].scriptExt))
|
||||
if writeRope(script, filename):
|
||||
copyFile(conf.libpath / "nimbase.h", getNimcacheDir(conf) / "nimbase.h")
|
||||
copyFile(conf.libpath / RelativeFile"nimbase.h",
|
||||
getNimcacheDir(conf) / RelativeFile"nimbase.h")
|
||||
else:
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename)
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)
|
||||
|
||||
proc getOptSpeed(conf: ConfigRef; c: TSystemCC): string =
|
||||
result = getConfigVar(conf, c, ".options.speed")
|
||||
|
|
@ -490,7 +492,7 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
|
|||
# `optGenMapping` is included here for niminst.
|
||||
result = conf.globalOptions * {optGenScript, optGenMapping} != {}
|
||||
|
||||
proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string =
|
||||
proc cFileSpecificOptions(conf: ConfigRef; cfilename: AbsoluteFile): string =
|
||||
result = conf.compileOptions
|
||||
for option in conf.compileOptionsCmd:
|
||||
if strutils.find(result, option, 0) < 0:
|
||||
|
|
@ -513,7 +515,7 @@ proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string =
|
|||
if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
|
||||
|
||||
proc getCompileOptions(conf: ConfigRef): string =
|
||||
result = cFileSpecificOptions(conf, "__dummy__")
|
||||
result = cFileSpecificOptions(conf, AbsoluteFile"__dummy__")
|
||||
|
||||
proc getLinkOptions(conf: ConfigRef): string =
|
||||
result = conf.linkOptions & " " & conf.linkOptionsCmd & " "
|
||||
|
|
@ -526,8 +528,8 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
|
|||
result = (optGenScript in conf.globalOptions and conf.target.targetOS == osWindows) or
|
||||
(conf.target.hostOS == osWindows)
|
||||
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: string): string =
|
||||
result = if conf.cmd == cmdCompileToCpp and not cfile.endsWith(".c"):
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
|
||||
result = if conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c"):
|
||||
CC[compiler].cppCompiler
|
||||
else:
|
||||
CC[compiler].compilerExe
|
||||
|
|
@ -539,7 +541,7 @@ proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: string): string
|
|||
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
|
||||
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
||||
elif optMixedMode in conf.globalOptions and conf.cmd != cmdCompileToCpp: CC[compiler].cppCompiler
|
||||
else: getCompilerExe(conf, compiler, "")
|
||||
else: getCompilerExe(conf, compiler, AbsoluteFile"")
|
||||
|
||||
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string =
|
||||
var c = conf.cCompiler
|
||||
|
|
@ -565,43 +567,42 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string =
|
|||
includeCmd = ""
|
||||
compilePattern = getCompilerExe(conf, c, cfile.cname)
|
||||
|
||||
var cf = if noAbsolutePaths(conf): extractFilename(cfile.cname)
|
||||
var cf = if noAbsolutePaths(conf): AbsoluteFile extractFilename(cfile.cname.string)
|
||||
else: cfile.cname
|
||||
|
||||
var objfile =
|
||||
if cfile.obj.len == 0:
|
||||
if cfile.obj.isEmpty:
|
||||
if not cfile.flags.contains(CfileFlag.External) or noAbsolutePaths(conf):
|
||||
toObjFile(conf, cf)
|
||||
toObjFile(conf, cf).string
|
||||
else:
|
||||
completeCFilePath(conf, toObjFile(conf, cf))
|
||||
completeCFilePath(conf, toObjFile(conf, cf)).string
|
||||
elif noAbsolutePaths(conf):
|
||||
extractFilename(cfile.obj)
|
||||
extractFilename(cfile.obj.string)
|
||||
else:
|
||||
cfile.obj
|
||||
cfile.obj.string
|
||||
|
||||
# D files are required by nintendo switch libs for
|
||||
# compilation. They are basically a list of all includes.
|
||||
let dfile = objfile.changeFileExt(".d").quoteShell()
|
||||
|
||||
objfile = quoteShell(objfile)
|
||||
cf = quoteShell(cf)
|
||||
let cfsh = quoteShell(cf)
|
||||
result = quoteShell(compilePattern % [
|
||||
"dfile", dfile,
|
||||
"file", cf, "objfile", objfile, "options", options,
|
||||
"include", includeCmd, "nim", getPrefixDir(conf),
|
||||
"nim", getPrefixDir(conf), "lib", conf.libpath])
|
||||
"file", cfsh, "objfile", objfile, "options", options,
|
||||
"include", includeCmd, "nim", getPrefixDir(conf).string,
|
||||
"lib", conf.libpath.string])
|
||||
add(result, ' ')
|
||||
addf(result, CC[c].compileTmpl, [
|
||||
"dfile", dfile,
|
||||
"file", cf, "objfile", objfile,
|
||||
"file", cfsh, "objfile", objfile,
|
||||
"options", options, "include", includeCmd,
|
||||
"nim", quoteShell(getPrefixDir(conf)),
|
||||
"nim", quoteShell(getPrefixDir(conf)),
|
||||
"lib", quoteShell(conf.libpath)])
|
||||
|
||||
proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
|
||||
result = secureHash(
|
||||
$secureHashFile(cfile.cname) &
|
||||
$secureHashFile(cfile.cname.string) &
|
||||
platform.OS[conf.target.targetOS].name &
|
||||
platform.CPU[conf.target.targetCPU].name &
|
||||
extccomp.CC[conf.cCompiler].name &
|
||||
|
|
@ -614,14 +615,14 @@ proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
|||
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
|
||||
var currentHash = footprint(conf, cfile)
|
||||
var f: File
|
||||
if open(f, hashFile, fmRead):
|
||||
if open(f, hashFile.string, fmRead):
|
||||
let oldHash = parseSecureHash(f.readLine())
|
||||
close(f)
|
||||
result = oldHash != currentHash
|
||||
else:
|
||||
result = true
|
||||
if result:
|
||||
if open(f, hashFile, fmWrite):
|
||||
if open(f, hashFile.string, fmWrite):
|
||||
f.writeLine($currentHash)
|
||||
close(f)
|
||||
|
||||
|
|
@ -630,7 +631,7 @@ proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
|
|||
c.flags.incl CfileFlag.Cached
|
||||
conf.toCompile.add(c)
|
||||
|
||||
proc addExternalFileToCompile*(conf: ConfigRef; filename: string) =
|
||||
proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
|
||||
var c = Cfile(cname: filename,
|
||||
obj: toObjFile(conf, completeCFilePath(conf, filename, false)),
|
||||
flags: {CfileFlag.External})
|
||||
|
|
@ -650,11 +651,11 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var
|
|||
add(script, compileCmd)
|
||||
add(script, "\n")
|
||||
|
||||
proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
||||
proc getLinkCmd(conf: ConfigRef; projectfile: AbsoluteFile, objfiles: string): string =
|
||||
if optGenStaticLib in conf.globalOptions:
|
||||
var libname: string
|
||||
if conf.outFile.len > 0:
|
||||
libname = conf.outFile.expandTilde
|
||||
if not conf.outFile.isEmpty:
|
||||
libname = conf.outFile.string.expandTilde
|
||||
if not libname.isAbsolute():
|
||||
libname = getCurrentDir() / libname
|
||||
else:
|
||||
|
|
@ -679,13 +680,13 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
|||
else:
|
||||
exefile = splitFile(projectfile).name & platform.OS[conf.target.targetOS].exeExt
|
||||
builddll = ""
|
||||
if conf.outFile.len > 0:
|
||||
exefile = conf.outFile.expandTilde
|
||||
if not conf.outFile.isEmpty:
|
||||
exefile = conf.outFile.string.expandTilde
|
||||
if not exefile.isAbsolute():
|
||||
exefile = getCurrentDir() / exefile
|
||||
if not noAbsolutePaths(conf):
|
||||
if not exefile.isAbsolute():
|
||||
exefile = joinPath(splitFile(projectfile).dir, exefile)
|
||||
exefile = string(splitFile(projectfile).dir / RelativeFile(exefile))
|
||||
when false:
|
||||
if optCDebug in conf.globalOptions:
|
||||
writeDebugInfo(exefile.changeFileExt("ndb"))
|
||||
|
|
@ -693,7 +694,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
|||
|
||||
# Map files are required by Nintendo Switch compilation. They are a list
|
||||
# of all function calls in the library and where they come from.
|
||||
let mapfile = quoteShell(getNimcacheDir(conf) / splitFile(projectFile).name & ".map")
|
||||
let mapfile = quoteShell(getNimcacheDir(conf) / RelativeFile(splitFile(projectFile).name & ".map"))
|
||||
|
||||
let linkOptions = getLinkOptions(conf) & " " &
|
||||
getConfigVar(conf, conf.cCompiler, ".options.linker")
|
||||
|
|
@ -703,7 +704,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
|
|||
result = quoteShell(result % ["builddll", builddll,
|
||||
"mapfile", mapfile,
|
||||
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
|
||||
"exefile", exefile, "nim", getPrefixDir(conf), "lib", conf.libpath])
|
||||
"exefile", exefile, "nim", getPrefixDir(conf).string, "lib", conf.libpath.string])
|
||||
result.add ' '
|
||||
addf(result, linkTmpl, ["builddll", builddll,
|
||||
"mapfile", mapfile,
|
||||
|
|
@ -761,7 +762,7 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
|
|||
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
|
||||
cmds.join())
|
||||
|
||||
proc callCCompiler*(conf: ConfigRef; projectfile: string) =
|
||||
proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
var
|
||||
linkCmd: string
|
||||
if conf.globalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
|
||||
|
|
@ -787,7 +788,7 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
|
|||
add(objfiles, quoteShell(
|
||||
addFileExt(objFile, CC[conf.cCompiler].objExt)))
|
||||
for x in conf.toCompile:
|
||||
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj
|
||||
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string
|
||||
add(objfiles, ' ')
|
||||
add(objfiles, quoteShell(objFile))
|
||||
|
||||
|
|
@ -804,7 +805,7 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
|
|||
#from json import escapeJson
|
||||
import json
|
||||
|
||||
proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
||||
proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
template lit(x: untyped) = f.write x
|
||||
template str(x: untyped) =
|
||||
when compiles(escapeJson(x, buf)):
|
||||
|
|
@ -821,7 +822,7 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
let compileCmd = getCompileCFileCmd(conf, it)
|
||||
if pastStart: lit "],\L"
|
||||
lit "["
|
||||
str it.cname
|
||||
str it.cname.string
|
||||
lit ", "
|
||||
str compileCmd
|
||||
pastStart = true
|
||||
|
|
@ -851,11 +852,10 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
|
||||
var buf = newStringOfCap(50)
|
||||
|
||||
let file = projectfile.splitFile.name
|
||||
let jsonFile = toGeneratedFile(conf, file, "json")
|
||||
let jsonFile = toGeneratedFile(conf, projectfile, "json")
|
||||
|
||||
var f: File
|
||||
if open(f, jsonFile, fmWrite):
|
||||
if open(f, jsonFile.string, fmWrite):
|
||||
lit "{\"compile\":[\L"
|
||||
cfiles(conf, f, buf, conf.toCompile, false)
|
||||
lit "],\L\"link\":[\L"
|
||||
|
|
@ -868,11 +868,10 @@ proc writeJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
lit "\L}\L"
|
||||
close(f)
|
||||
|
||||
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
||||
let file = projectfile.splitFile.name
|
||||
let jsonFile = toGeneratedFile(conf, file, "json")
|
||||
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
let jsonFile = toGeneratedFile(conf, projectfile, "json")
|
||||
try:
|
||||
let data = json.parseFile(jsonFile)
|
||||
let data = json.parseFile(jsonFile.string)
|
||||
let toCompile = data["compile"]
|
||||
doAssert toCompile.kind == JArray
|
||||
var cmds: TStringSeq = @[]
|
||||
|
|
@ -896,11 +895,11 @@ proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: string) =
|
|||
except:
|
||||
when declared(echo):
|
||||
echo getCurrentException().getStackTrace()
|
||||
quit "error evaluating JSON file: " & jsonFile
|
||||
quit "error evaluating JSON file: " & jsonFile.string
|
||||
|
||||
proc genMappingFiles(conf: ConfigRef; list: CFileList): Rope =
|
||||
for it in list:
|
||||
addf(result, "--file:r\"$1\"$N", [rope(it.cname)])
|
||||
addf(result, "--file:r\"$1\"$N", [rope(it.cname.string)])
|
||||
|
||||
proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
|
||||
if optGenMapping notin conf.globalOptions: return
|
||||
|
|
@ -914,9 +913,9 @@ proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
|
|||
getConfigVar(conf, conf.cCompiler, ".options.linker")))
|
||||
|
||||
add(code, "\n[Environment]\nlibpath=")
|
||||
add(code, strutils.escape(conf.libpath))
|
||||
add(code, strutils.escape(conf.libpath.string))
|
||||
|
||||
addf(code, "\n[Symbols]$n$1", [symbolMapping])
|
||||
let filename = joinPath(conf.projectPath, "mapping.txt")
|
||||
let filename = conf.projectPath / RelativeFile"mapping.txt"
|
||||
if not writeRope(code, filename):
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename)
|
||||
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
import
|
||||
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
|
||||
renderer, filters, lineinfos
|
||||
renderer, filters, lineinfos, pathutils
|
||||
|
||||
type
|
||||
TParseState = enum
|
||||
|
|
@ -199,7 +199,8 @@ proc parseLine(p: var TTmplParser) =
|
|||
inc(j)
|
||||
llStreamWrite(p.outp, "\\n\"")
|
||||
|
||||
proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode; conf: ConfigRef): PLLStream =
|
||||
proc filterTmpl*(stdin: PLLStream, filename: AbsoluteFile,
|
||||
call: PNode; conf: ConfigRef): PLLStream =
|
||||
var p: TTmplParser
|
||||
p.config = conf
|
||||
p.info = newLineInfo(conf, filename, 0, 0)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
import
|
||||
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
|
||||
renderer
|
||||
renderer, pathutils
|
||||
|
||||
proc invalidPragma(conf: ConfigRef; n: PNode) =
|
||||
localError(conf, n.info,
|
||||
|
|
@ -47,7 +47,7 @@ proc boolArg*(conf: ConfigRef; n: PNode, name: string, pos: int, default: bool):
|
|||
elif x.kind == nkIdent and cmpIgnoreStyle(x.ident.s, "false") == 0: result = false
|
||||
else: invalidPragma(conf, n)
|
||||
|
||||
proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
||||
proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, call: PNode): PLLStream =
|
||||
var pattern = strArg(conf, call, "startswith", 1, "")
|
||||
var leading = boolArg(conf, call, "leading", 2, true)
|
||||
var trailing = boolArg(conf, call, "trailing", 3, true)
|
||||
|
|
@ -61,7 +61,7 @@ proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: string, call: PNo
|
|||
llStreamWriteln(result, line)
|
||||
llStreamClose(stdin)
|
||||
|
||||
proc filterReplace*(conf: ConfigRef; stdin: PLLStream, filename: string, call: PNode): PLLStream =
|
||||
proc filterReplace*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, call: PNode): PLLStream =
|
||||
var sub = strArg(conf, call, "sub", 1, "")
|
||||
if len(sub) == 0: invalidPragma(conf, call)
|
||||
var by = strArg(conf, call, "by", 2, "")
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
## Module that implements ``gorge`` for the compiler.
|
||||
|
||||
import msgs, std / sha1, os, osproc, streams, strutils, options,
|
||||
lineinfos
|
||||
lineinfos, pathutils
|
||||
|
||||
proc readOutput(p: Process): (string, int) =
|
||||
result[0] = ""
|
||||
|
|
@ -26,7 +26,7 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
|
|||
let workingDir = parentDir(toFullPath(conf, info))
|
||||
if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
|
||||
let h = secureHash(cmd & "\t" & input & "\t" & cache)
|
||||
let filename = options.toGeneratedFile(conf, "gorge_" & $h, "txt")
|
||||
let filename = toGeneratedFile(conf, AbsoluteFile("gorge_" & $h), "txt").string
|
||||
var f: File
|
||||
if open(f, filename):
|
||||
result = (f.readAll, 0)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
## This module contains a simple persistent id generator.
|
||||
|
||||
import idents, strutils, os, options
|
||||
import idents, strutils, os, options, pathutils
|
||||
|
||||
var gFrontEndId*: int
|
||||
|
||||
|
|
@ -36,18 +36,18 @@ proc setId*(id: int) {.inline.} =
|
|||
proc idSynchronizationPoint*(idRange: int) =
|
||||
gFrontEndId = (gFrontEndId div idRange + 1) * idRange + 1
|
||||
|
||||
proc toGid(conf: ConfigRef; f: string): string =
|
||||
proc toGid(conf: ConfigRef; f: AbsoluteFile): string =
|
||||
# we used to use ``f.addFileExt("gid")`` (aka ``$project.gid``), but this
|
||||
# will cause strange bugs if multiple projects are in the same folder, so
|
||||
# we simply use a project independent name:
|
||||
result = options.completeGeneratedFilePath(conf, "nim.gid")
|
||||
result = options.completeGeneratedFilePath(conf, AbsoluteFile"nim.gid").string
|
||||
|
||||
proc saveMaxIds*(conf: ConfigRef; project: string) =
|
||||
proc saveMaxIds*(conf: ConfigRef; project: AbsoluteFile) =
|
||||
var f = open(toGid(conf, project), fmWrite)
|
||||
f.writeLine($gFrontEndId)
|
||||
f.close()
|
||||
|
||||
proc loadMaxIds*(conf: ConfigRef; project: string) =
|
||||
proc loadMaxIds*(conf: ConfigRef; project: AbsoluteFile) =
|
||||
var f: File
|
||||
if open(f, toGid(conf, project), fmRead):
|
||||
var line = newStringOfCap(20)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,12 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This module implements the symbol importing mechanism.
|
||||
## This module implements the symbol importing mechanism.
|
||||
|
||||
import
|
||||
intsets, strutils, os, ast, astalgo, msgs, options, idents, lookups,
|
||||
semdata, passes, renderer, modulepaths, sigmatch, lineinfos
|
||||
|
||||
proc evalImport*(c: PContext, n: PNode): PNode
|
||||
proc evalFrom*(c: PContext, n: PNode): PNode
|
||||
|
||||
proc readExceptSet*(c: PContext, n: PNode): IntSet =
|
||||
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
|
||||
result = initIntSet()
|
||||
|
|
@ -140,7 +137,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
|
|||
c.config.options)
|
||||
|
||||
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
|
||||
var f = checkModuleName(c.config, n)
|
||||
let f = checkModuleName(c.config, n)
|
||||
if f != InvalidFileIDX:
|
||||
let L = c.graph.importStack.len
|
||||
let recursion = c.graph.importStack.find(f)
|
||||
|
|
@ -168,7 +165,8 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
|
|||
else:
|
||||
message(c.config, n.info, warnDeprecated, result.name.s)
|
||||
suggestSym(c.config, n.info, result, c.graph.usageSym, false)
|
||||
importStmtResult.add newStrNode(toFullPath(c.config, f), n.info)
|
||||
importStmtResult.add newSymNode(result, n.info)
|
||||
#newStrNode(toFullPath(c.config, f), n.info)
|
||||
|
||||
proc transformImportAs(c: PContext; n: PNode): PNode =
|
||||
if n.kind == nkInfix and considerQuotedIdent(c, n[0]).s == "as":
|
||||
|
|
@ -188,7 +186,7 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
|
|||
importAllSymbolsExcept(c, m, emptySet)
|
||||
#importForwarded(c, m.ast, emptySet)
|
||||
|
||||
proc evalImport(c: PContext, n: PNode): PNode =
|
||||
proc evalImport*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkImportStmt, n.info)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
let it = n.sons[i]
|
||||
|
|
@ -212,7 +210,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
|
|||
else:
|
||||
impMod(c, it, result)
|
||||
|
||||
proc evalFrom(c: PContext, n: PNode): PNode =
|
||||
proc evalFrom*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkImportStmt, n.info)
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
n.sons[0] = transformImportAs(c, n.sons[0])
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import
|
|||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
|
||||
nversion, nimsets, msgs, std / sha1, bitsets, idents, types, os, tables,
|
||||
times, ropes, math, passes, ccgutils, wordrecg, renderer,
|
||||
intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils
|
||||
intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils
|
||||
|
||||
from modulegraphs import ModuleGraph
|
||||
|
||||
|
|
@ -2265,7 +2265,7 @@ proc genClass(conf: ConfigRef; obj: PType; content: Rope; ext: string) =
|
|||
"class $#$# {$n$#$n}$n") %
|
||||
[rope(VersionAsString), cls, extends, content]
|
||||
|
||||
let outfile = changeFileExt(completeCFilePath(conf, $cls), ext)
|
||||
let outfile = changeFileExt(completeCFilePath(conf, AbsoluteFile $cls), ext)
|
||||
discard writeRopeIfNotEqual(result, outfile)
|
||||
|
||||
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||
|
|
@ -2279,11 +2279,11 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
|||
else: "nimsystem"
|
||||
let code = wholeCode(graph, m)
|
||||
let outfile =
|
||||
if m.config.outFile.len > 0:
|
||||
if m.config.outFile.isAbsolute: m.config.outFile
|
||||
else: getCurrentDir() / m.config.outFile
|
||||
if not m.config.outFile.isEmpty:
|
||||
if m.config.outFile.string.isAbsolute: m.config.outFile
|
||||
else: AbsoluteFile(getCurrentDir() / m.config.outFile.string)
|
||||
else:
|
||||
changeFileExt(completeCFilePath(m.config, f), ext)
|
||||
changeFileExt(completeCFilePath(m.config, AbsoluteFile f), ext)
|
||||
discard writeRopeIfNotEqual(genHeader() & code, outfile)
|
||||
for obj, content in items(globals.classes):
|
||||
genClass(m.config, obj, content, ext)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
import
|
||||
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream,
|
||||
wordrecg, lineinfos
|
||||
wordrecg, lineinfos, pathutils
|
||||
|
||||
const
|
||||
MaxLineLength* = 80 # lines longer than this lead to a warning
|
||||
|
|
@ -232,7 +232,7 @@ proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
|
|||
lex.previousToken.fileIndex = fileIdx
|
||||
lex.config = config
|
||||
|
||||
proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream;
|
||||
proc openLexer*(lex: var TLexer, filename: AbsoluteFile, inputstream: PLLStream;
|
||||
cache: IdentCache; config: ConfigRef) =
|
||||
openLexer(lex, fileInfoIdx(config, filename), inputstream, cache, config)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
## This module contains the ``TMsgKind`` enum as well as the
|
||||
## ``TLineInfo`` object.
|
||||
|
||||
import ropes, tables
|
||||
import ropes, tables, pathutils
|
||||
|
||||
const
|
||||
explanationsBaseUrl* = "https://nim-lang.org/docs/manual"
|
||||
|
|
@ -179,8 +179,8 @@ const
|
|||
|
||||
type
|
||||
TFileInfo* = object
|
||||
fullPath*: string # This is a canonical full filesystem path
|
||||
projPath*: string # This is relative to the project's root
|
||||
fullPath*: AbsoluteFile # This is a canonical full filesystem path
|
||||
projPath*: RelativeFile # This is relative to the project's root
|
||||
shortName*: string # short name of the module
|
||||
quotedName*: Rope # cached quoted short name for codegen
|
||||
# purposes
|
||||
|
|
@ -191,7 +191,7 @@ type
|
|||
# used for better error messages and
|
||||
# embedding the original source in the
|
||||
# generated code
|
||||
dirtyfile*: string # the file that is actually read into memory
|
||||
dirtyfile*: AbsoluteFile # the file that is actually read into memory
|
||||
# and parsed; usually "" but is used
|
||||
# for 'nimsuggest'
|
||||
hash*: string # the checksum of the file
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import
|
|||
strutils, os, intsets, strtabs
|
||||
|
||||
import options, ast, astalgo, msgs, semdata, ropes, idents,
|
||||
lineinfos
|
||||
lineinfos, pathutils
|
||||
|
||||
const
|
||||
Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
|
||||
|
|
@ -42,7 +42,7 @@ proc overwriteFiles*(conf: ConfigRef) =
|
|||
let newFile = if gOverWrite: conf.m.fileInfos[i].fullpath
|
||||
else: conf.m.fileInfos[i].fullpath.changeFileExt(".pretty.nim")
|
||||
try:
|
||||
var f = open(newFile, fmWrite)
|
||||
var f = open(newFile.string, fmWrite)
|
||||
for line in conf.m.fileInfos[i].lines:
|
||||
if doStrip:
|
||||
f.write line.strip(leading = false, trailing = true)
|
||||
|
|
@ -51,7 +51,7 @@ proc overwriteFiles*(conf: ConfigRef) =
|
|||
f.write(conf.m.fileInfos[i], "\L")
|
||||
f.close
|
||||
except IOError:
|
||||
rawMessage(conf, errGenerated, "cannot open file: " & newFile)
|
||||
rawMessage(conf, errGenerated, "cannot open file: " & newFile.string)
|
||||
|
||||
proc `=~`(s: string, a: openArray[string]): bool =
|
||||
for x in a:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
## Low-level streams for high performance.
|
||||
|
||||
import
|
||||
strutils
|
||||
strutils, pathutils
|
||||
|
||||
# support '-d:useGnuReadline' for backwards compatibility:
|
||||
when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)):
|
||||
|
|
@ -41,10 +41,10 @@ proc llStreamOpen*(f: File): PLLStream =
|
|||
result.f = f
|
||||
result.kind = llsFile
|
||||
|
||||
proc llStreamOpen*(filename: string, mode: FileMode): PLLStream =
|
||||
proc llStreamOpen*(filename: AbsoluteFile, mode: FileMode): PLLStream =
|
||||
new(result)
|
||||
result.kind = llsFile
|
||||
if not open(result.f, filename, mode): result = nil
|
||||
if not open(result.f, filename.string, mode): result = nil
|
||||
|
||||
proc llStreamOpen*(): PLLStream =
|
||||
new(result)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import
|
|||
cgen, jsgen, json, nversion,
|
||||
platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
|
||||
docgen2, parser, modules, ccgutils, sigmatch, ropes,
|
||||
modulegraphs, tables, rod, lineinfos
|
||||
modulegraphs, tables, rod, lineinfos, pathutils
|
||||
|
||||
from magicsys import resetSysTypes
|
||||
|
||||
|
|
@ -30,8 +30,8 @@ proc semanticPasses(g: ModuleGraph) =
|
|||
registerPass g, verbosePass
|
||||
registerPass g, semPass
|
||||
|
||||
proc writeDepsFile(g: ModuleGraph; project: string) =
|
||||
let f = open(changeFileExt(project, "deps"), fmWrite)
|
||||
proc writeDepsFile(g: ModuleGraph; project: AbsoluteFile) =
|
||||
let f = open(changeFileExt(project, "deps").string, fmWrite)
|
||||
for m in g.modules:
|
||||
if m != nil:
|
||||
f.writeLine(toFullPath(g.config, m.position.FileIndex))
|
||||
|
|
@ -47,8 +47,9 @@ proc commandGenDepend(graph: ModuleGraph) =
|
|||
let project = graph.config.projectFull
|
||||
writeDepsFile(graph, project)
|
||||
generateDot(graph, project)
|
||||
execExternalProgram(graph.config, "dot -Tpng -o" & changeFileExt(project, "png") &
|
||||
' ' & changeFileExt(project, "dot"))
|
||||
execExternalProgram(graph.config, "dot -Tpng -o" &
|
||||
changeFileExt(project, "png").string &
|
||||
' ' & changeFileExt(project, "dot").string)
|
||||
|
||||
proc commandCheck(graph: ModuleGraph) =
|
||||
graph.config.errorMax = high(int) # do not stop after first error
|
||||
|
|
@ -126,7 +127,7 @@ proc commandEval(graph: ModuleGraph; exp: string) =
|
|||
makeStdinModule(graph))
|
||||
|
||||
proc commandScan(cache: IdentCache, config: ConfigRef) =
|
||||
var f = addFileExt(mainCommandArg(config), NimExt)
|
||||
var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt)
|
||||
var stream = llStreamOpen(f, fmRead)
|
||||
if stream != nil:
|
||||
var
|
||||
|
|
@ -140,7 +141,7 @@ proc commandScan(cache: IdentCache, config: ConfigRef) =
|
|||
if tok.tokType == tkEof: break
|
||||
closeLexer(L)
|
||||
else:
|
||||
rawMessage(config, errGenerated, "cannot open file: " & f)
|
||||
rawMessage(config, errGenerated, "cannot open file: " & f.string)
|
||||
|
||||
const
|
||||
PrintRopeCacheStats = false
|
||||
|
|
@ -231,11 +232,11 @@ proc mainCommand*(graph: ModuleGraph) =
|
|||
for s in definedSymbolNames(conf.symbols): definedSymbols.elems.add(%s)
|
||||
|
||||
var libpaths = newJArray()
|
||||
for dir in conf.searchPaths: libpaths.elems.add(%dir)
|
||||
for dir in conf.searchPaths: libpaths.elems.add(%dir.string)
|
||||
|
||||
var dumpdata = % [
|
||||
(key: "version", val: %VersionAsString),
|
||||
(key: "project_path", val: %conf.projectFull),
|
||||
(key: "project_path", val: %conf.projectFull.string),
|
||||
(key: "defined_symbols", val: definedSymbols),
|
||||
(key: "lib_paths", val: libpaths)
|
||||
]
|
||||
|
|
@ -247,7 +248,7 @@ proc mainCommand*(graph: ModuleGraph) =
|
|||
for s in definedSymbolNames(conf.symbols): msgWriteln(conf, s, {msgStdout, msgSkipHook})
|
||||
msgWriteln(conf, "-- end of list --", {msgStdout, msgSkipHook})
|
||||
|
||||
for it in conf.searchPaths: msgWriteln(conf, it)
|
||||
for it in conf.searchPaths: msgWriteln(conf, it.string)
|
||||
of "check":
|
||||
conf.cmd = cmdCheck
|
||||
commandCheck(graph)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue