cmdline: improve command processing (#16056)

This commit is contained in:
Timothee Cour 2020-11-26 15:55:56 -08:00 • committed by GitHub
commit 52829fc8d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 144 additions and 137 deletions

View file

@ -765,7 +765,7 @@ type
locOther # location is something other locOther # location is something other
TLocFlag* = enum TLocFlag* = enum
lfIndirect, # backend introduced a pointer lfIndirect, # backend introduced a pointer
lfFullExternalName, # only used when 'conf.cmd == cmdPretty': Indicates lfFullExternalName, # only used when 'conf.cmd == cmdNimfix': Indicates
# that the symbol has been imported via 'importc: "fullname"' and # that the symbol has been imported via 'importc: "fullname"' and
# no format string. # no format string.
lfNoDeepCopy, # no need for a deep copy lfNoDeepCopy, # no need for a deep copy

View file

@ -1986,7 +1986,7 @@ proc writeModule(m: BModule, pending: bool) =
var code = genModule(m, cf) var code = genModule(m, cf)
if code != nil or m.config.symbolFiles != disabledSf: if code != nil or m.config.symbolFiles != disabledSf:
when hasTinyCBackend: when hasTinyCBackend:
if m.config.cmd == cmdRun: if m.config.cmd == cmdTcc:
tccgen.compileCCode($code, m.config) tccgen.compileCCode($code, m.config)
onExit() onExit()
return return

View file

@ -13,8 +13,6 @@ import
options, idents, nimconf, extccomp, commands, msgs, options, idents, nimconf, extccomp, commands, msgs,
lineinfos, modulegraphs, condsyms, os, pathutils, parseopt lineinfos, modulegraphs, condsyms, os, pathutils, parseopt
from strutils import normalize
proc prependCurDir*(f: AbsoluteFile): AbsoluteFile = proc prependCurDir*(f: AbsoluteFile): AbsoluteFile =
when defined(unix): when defined(unix):
if os.isAbsolute(f.string): result = f if os.isAbsolute(f.string): result = f
@ -60,8 +58,8 @@ proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
proc loadConfigsAndProcessCmdLine*(self: NimProg, cache: IdentCache; conf: ConfigRef; proc loadConfigsAndProcessCmdLine*(self: NimProg, cache: IdentCache; conf: ConfigRef;
graph: ModuleGraph): bool = graph: ModuleGraph): bool =
if self.suggestMode: if self.suggestMode:
conf.command = "nimsuggest" conf.setCmd cmdIdeTools
if conf.command == "e": if conf.cmd == cmdNimscript:
incl(conf.globalOptions, optWasNimscript) incl(conf.globalOptions, optWasNimscript)
loadConfigs(DefaultConfig, cache, conf, graph.idgen) # load all config files loadConfigs(DefaultConfig, cache, conf, graph.idgen) # load all config files
@ -69,17 +67,13 @@ proc loadConfigsAndProcessCmdLine*(self: NimProg, cache: IdentCache; conf: Confi
let scriptFile = conf.projectFull.changeFileExt("nims") let scriptFile = conf.projectFull.changeFileExt("nims")
# 'nim foo.nims' means to just run the NimScript file and do nothing more: # 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile == conf.projectFull: if fileExists(scriptFile) and scriptFile == conf.projectFull:
if conf.command == "": if conf.cmd == cmdNone: conf.setCmd cmdNimscript
conf.command = "e" if conf.cmd == cmdNimscript: return false
return false
elif conf.command.normalize == "e":
return false
# now process command line arguments again, because some options in the # now process command line arguments again, because some options in the
# command line can overwrite the config file's settings # command line can overwrite the config file's settings
extccomp.initVars(conf) extccomp.initVars(conf)
self.processCmdLine(passCmd2, "", conf) self.processCmdLine(passCmd2, "", conf)
if conf.command == "": if conf.cmd == cmdNone:
rawMessage(conf, errGenerated, "command missing") rawMessage(conf, errGenerated, "command missing")
graph.suggestMode = self.suggestMode graph.suggestMode = self.suggestMode

View file

@ -398,6 +398,48 @@ proc handleCmdInput*(conf: ConfigRef) =
conf.projectName = "cmdfile" conf.projectName = "cmdfile"
handleStdinOrCmdInput() handleStdinOrCmdInput()
proc parseCommand*(command: string): Command =
case command.normalize
of "c", "cc", "compile", "compiletoc": cmdCompileToC
of "cpp", "compiletocpp": cmdCompileToCpp
of "objc", "compiletooc": cmdCompileToOC
of "js", "compiletojs": cmdCompileToJS
of "r": cmdCrun
of "run": cmdTcc
of "check": cmdCheck
of "e": cmdNimscript
of "doc0": cmdDoc0
of "doc2", "doc": cmdDoc2
of "rst2html": cmdRst2html
of "rst2tex": cmdRst2tex
of "jsondoc0": cmdJsondoc0
of "jsondoc2", "jsondoc": cmdJsondoc
of "ctags": cmdCtags
of "buildindex": cmdBuildindex
of "gendepend": cmdGendepend
of "dump": cmdDump
of "parse": cmdParse
of "scan": cmdScan
of "secret": cmdInteractive
of "nop", "help": cmdNop
of "jsonscript": cmdJsonscript
else: cmdUnknown
proc setCmd*(conf: ConfigRef, cmd: Command) =
## sets cmd, backend so subsequent flags can query it (e.g. so --gc:arc can be ignored for backendJs)
# Note that `--backend` can override the backend, so the logic here must remain reversible.
conf.cmd = cmd
case cmd
of cmdCompileToC, cmdCrun, cmdTcc: conf.backend = backendC
of cmdCompileToCpp: conf.backend = backendCpp
of cmdCompileToOC: conf.backend = backendObjc
of cmdCompileToJS: conf.backend = backendJs
else: discard
proc setCommandEarly*(conf: ConfigRef, command: string) =
conf.command = command
setCmd(conf, command.parseCommand)
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf: ConfigRef) = conf: ConfigRef) =
var var
@ -407,8 +449,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
expectArg(conf, switch, arg, pass, info) expectArg(conf, switch, arg, pass, info)
conf.projectIsCmd = true conf.projectIsCmd = true
conf.cmdInput = arg # can be empty (a nim file with empty content is valid too) conf.cmdInput = arg # can be empty (a nim file with empty content is valid too)
if conf.command == "": if conf.cmd == cmdNone:
conf.command = "e" # better than "r" as a default conf.setCmd cmdNimscript # better than `cmdCrun` as a default
conf.implicitCmd = true conf.implicitCmd = true
of "path", "p": of "path", "p":
expectArg(conf, switch, arg, pass, info) expectArg(conf, switch, arg, pass, info)
@ -499,11 +541,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "project": of "project":
processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info) processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
of "gc": of "gc":
if conf.backend == backendJs or conf.command == "js": if conf.backend == backendJs: return # for: bug #16033
# for: bug #16033
# This might still be imperfect, in rarse corner cases
# (where command is reset in nimscript, maybe).
return
expectArg(conf, switch, arg, pass, info) expectArg(conf, switch, arg, pass, info)
if pass in {passCmd2, passPP}: if pass in {passCmd2, passPP}:
case arg.normalize case arg.normalize
@ -955,13 +993,12 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
if argsCount == 0: if argsCount == 0:
# nim filename.nims is the same as "nim e filename.nims": # nim filename.nims is the same as "nim e filename.nims":
if p.key.endsWith(".nims"): if p.key.endsWith(".nims"):
config.command = "e" config.setCmd cmdNimscript
incl(config.globalOptions, optWasNimscript) incl(config.globalOptions, optWasNimscript)
config.projectName = unixToNativePath(p.key) config.projectName = unixToNativePath(p.key)
config.arguments = cmdLineRest(p) config.arguments = cmdLineRest(p)
result = true result = true
elif pass != passCmd2: elif pass != passCmd2: setCommandEarly(config, p.key)
config.command = p.key
else: else:
if pass == passCmd1: config.commandArgs.add p.key if pass == passCmd1: config.commandArgs.add p.key
if argsCount == 1: if argsCount == 1:

View file

@ -85,7 +85,7 @@ proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
result = s result = s
else: else:
result = s.owner result = s.owner
if conf.cmd == cmdPretty: if conf.cmd == cmdNimfix:
prettybase.replaceDeprecated(conf, n.info, s, result) prettybase.replaceDeprecated(conf, n.info, s, result)
else: else:
message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " & message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " &

View file

@ -87,7 +87,7 @@ proc commandCompileToC(graph: ModuleGraph) =
if graph.config.errorCounter > 0: if graph.config.errorCounter > 0:
return # issue #9933 return # issue #9933
cgenWriteModules(graph.backend, conf) cgenWriteModules(graph.backend, conf)
if conf.cmd != cmdRun: if conf.cmd != cmdTcc:
extccomp.callCCompiler(conf) extccomp.callCCompiler(conf)
# for now we do not support writing out a .json file with the build instructions when HCR is on # for now we do not support writing out a .json file with the build instructions when HCR is on
if not conf.hcrOn: if not conf.hcrOn:
@ -195,12 +195,8 @@ proc mainCommand*(graph: ModuleGraph) =
if conf.selectedGC in {gcArc, gcOrc} and conf.backend != backendCpp: if conf.selectedGC in {gcArc, gcOrc} and conf.backend != backendCpp:
conf.exc = excGoto conf.exc = excGoto
var commandAlreadyProcessed = false proc compileToBackend() =
customizeForBackend(conf.backend)
proc compileToBackend(backend: TBackend, cmd = cmdCompileToBackend) =
commandAlreadyProcessed = true
conf.cmd = cmd
customizeForBackend(backend)
case conf.backend case conf.backend
of backendC: commandCompileToC(graph) of backendC: commandCompileToC(graph)
of backendCpp: commandCompileToC(graph) of backendCpp: commandCompileToC(graph)
@ -213,18 +209,13 @@ proc mainCommand*(graph: ModuleGraph) =
quit "compiler wasn't built with documentation generator" quit "compiler wasn't built with documentation generator"
else: else:
wantMainModule(conf) wantMainModule(conf)
conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf, graph.idgen) loadConfigs(DocConfig, cache, conf, graph.idgen)
defineSymbol(conf.symbols, "nimdoc") defineSymbol(conf.symbols, "nimdoc")
body body
block: ## command prepass block: ## command prepass
var docLikeCmd2 = false # includes what calls `docLikeCmd` + some more if conf.cmd == cmdCrun: conf.globalOptions.incl {optRun, optUseNimcache}
case conf.command.normalize if conf.cmd notin cmdBackends + {cmdTcc}: customizeForBackend(backendC)
of "r": conf.globalOptions.incl {optRun, optUseNimcache}
of "doc0", "doc2", "doc", "rst2html", "rst2tex", "jsondoc0", "jsondoc2",
"jsondoc", "ctags", "buildindex": docLikeCmd2 = true
else: discard
if conf.outDir.isEmpty: if conf.outDir.isEmpty:
# doc like commands can generate a lot of files (especially with --project) # doc like commands can generate a lot of files (especially with --project)
# so by default should not end up in $PWD nor in $projectPath. # so by default should not end up in $PWD nor in $projectPath.
@ -232,30 +223,22 @@ proc mainCommand*(graph: ModuleGraph) =
var ret = if optUseNimcache in conf.globalOptions: getNimcacheDir(conf) var ret = if optUseNimcache in conf.globalOptions: getNimcacheDir(conf)
else: conf.projectPath else: conf.projectPath
doAssert ret.string.isAbsolute # `AbsoluteDir` is not a real guarantee doAssert ret.string.isAbsolute # `AbsoluteDir` is not a real guarantee
if docLikeCmd2: ret = ret / htmldocsDir if conf.cmd in cmdDocLike + {cmdRst2html, cmdRst2tex}: ret = ret / htmldocsDir
ret ret
## process all backend commands ## process all commands
case conf.command.normalize case conf.cmd
of "c", "cc", "compile", "compiletoc": compileToBackend(backendC) # compile means compileToC currently of cmdBackends: compileToBackend()
of "cpp", "compiletocpp": compileToBackend(backendCpp) of cmdTcc:
of "objc", "compiletooc": compileToBackend(backendObjc)
of "js", "compiletojs": compileToBackend(backendJs)
of "r": compileToBackend(backendC) # different from `"run"`!
of "run":
when hasTinyCBackend: when hasTinyCBackend:
extccomp.setCC(conf, "tcc", unknownLineInfo) extccomp.setCC(conf, "tcc", unknownLineInfo)
if conf.backend notin {backendC, backendInvalid}: if conf.backend != backendC:
rawMessage(conf, errGenerated, "'run' requires c backend, got: '$1'" % $conf.backend) rawMessage(conf, errGenerated, "'run' requires c backend, got: '$1'" % $conf.backend)
compileToBackend(backendC, cmd = cmdRun) compileToBackend()
else: else:
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc") rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
else: customizeForBackend(backendC) # fallback for other commands of cmdDoc0: docLikeCmd commandDoc(cache, conf)
of cmdDoc2:
## process all other commands
case conf.command.normalize # synchronize with `cmdUsingHtmlDocs`
of "doc0": docLikeCmd commandDoc(cache, conf)
of "doc2", "doc":
docLikeCmd(): docLikeCmd():
conf.setNoteDefaults(warnLockLevel, false) # issue #13218 conf.setNoteDefaults(warnLockLevel, false) # issue #13218
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218 conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218
@ -266,30 +249,25 @@ proc mainCommand*(graph: ModuleGraph) =
commandDoc2(graph, false) commandDoc2(graph, false)
if optGenIndex in conf.globalOptions and optWholeProject in conf.globalOptions: if optGenIndex in conf.globalOptions and optWholeProject in conf.globalOptions:
commandBuildIndex(conf, $conf.outDir) commandBuildIndex(conf, $conf.outDir)
of "rst2html": of cmdRst2html:
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # similar to issue #13218 conf.setNoteDefaults(warnRedefinitionOfLabel, false) # similar to issue #13218
when defined(leanCompiler): when defined(leanCompiler):
quit "compiler wasn't built with documentation generator" quit "compiler wasn't built with documentation generator"
else: else:
conf.cmd = cmdRst2html
loadConfigs(DocConfig, cache, conf, graph.idgen) loadConfigs(DocConfig, cache, conf, graph.idgen)
commandRst2Html(cache, conf) commandRst2Html(cache, conf)
of "rst2tex": of cmdRst2tex:
when defined(leanCompiler): when defined(leanCompiler):
quit "compiler wasn't built with documentation generator" quit "compiler wasn't built with documentation generator"
else: else:
conf.cmd = cmdRst2tex
loadConfigs(DocTexConfig, cache, conf, graph.idgen) loadConfigs(DocTexConfig, cache, conf, graph.idgen)
commandRst2TeX(cache, conf) commandRst2TeX(cache, conf)
of "jsondoc0": docLikeCmd commandJson(cache, conf) of cmdJsondoc0: docLikeCmd commandJson(cache, conf)
of "jsondoc2", "jsondoc": docLikeCmd commandDoc2(graph, true) of cmdJsondoc: docLikeCmd commandDoc2(graph, true)
of "ctags": docLikeCmd commandTags(cache, conf) of cmdCtags: docLikeCmd commandTags(cache, conf)
of "buildindex": docLikeCmd commandBuildIndex(conf, $conf.projectFull, conf.outFile) of cmdBuildindex: docLikeCmd commandBuildIndex(conf, $conf.projectFull, conf.outFile)
of "gendepend": of cmdGendepend: commandGenDepend(graph)
conf.cmd = cmdGenDepend of cmdDump:
commandGenDepend(graph)
of "dump":
conf.cmd = cmdDump
if getConfigVar(conf, "dump.format") == "json": if getConfigVar(conf, "dump.format") == "json":
wantMainModule(conf) wantMainModule(conf)
@ -332,41 +310,30 @@ proc mainCommand*(graph: ModuleGraph) =
msgWriteln(conf, "-- end of list --", {msgStdout, msgSkipHook}) msgWriteln(conf, "-- end of list --", {msgStdout, msgSkipHook})
for it in conf.searchPaths: msgWriteln(conf, it.string) for it in conf.searchPaths: msgWriteln(conf, it.string)
of "check": of cmdCheck: commandCheck(graph)
conf.cmd = cmdCheck of cmdParse:
commandCheck(graph)
of "parse":
conf.cmd = cmdParse
wantMainModule(conf) wantMainModule(conf)
discard parseFile(conf.projectMainIdx, cache, conf) discard parseFile(conf.projectMainIdx, cache, conf)
of "scan": of cmdScan:
conf.cmd = cmdScan
wantMainModule(conf) wantMainModule(conf)
commandScan(cache, conf) commandScan(cache, conf)
msgWriteln(conf, "Beware: Indentation tokens depend on the parser's state!") msgWriteln(conf, "Beware: Indentation tokens depend on the parser's state!")
of "secret": of cmdInteractive: commandInteractive(graph)
conf.cmd = cmdInteractive of cmdNimscript:
commandInteractive(graph)
of "e":
if conf.projectIsCmd or conf.projectIsStdin: discard if conf.projectIsCmd or conf.projectIsStdin: discard
elif not fileExists(conf.projectFull): elif not fileExists(conf.projectFull):
rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string) rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string)
elif not conf.projectFull.string.endsWith(".nims"): elif not conf.projectFull.string.endsWith(".nims"):
rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string) rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string)
# main NimScript logic handled in `loadConfigs`. # main NimScript logic handled in `loadConfigs`.
of "nop", "help": of cmdNop: discard
# prevent the "success" message: of cmdJsonscript:
conf.cmd = cmdDump
of "jsonscript":
conf.cmd = cmdJsonScript
setOutFile(graph.config) setOutFile(graph.config)
commandJsonScript(graph) commandJsonScript(graph)
elif commandAlreadyProcessed: discard # already handled of cmdUnknown, cmdNone, cmdIdeTools, cmdNimfix:
else:
rawMessage(conf, errGenerated, "invalid command: " & conf.command) rawMessage(conf, errGenerated, "invalid command: " & conf.command)
if conf.errorCounter == 0 and if conf.errorCounter == 0 and conf.cmd notin {cmdTcc, cmdDump, cmdNop}:
conf.cmd notin {cmdInterpret, cmdRun, cmdDump}:
let mem = let mem =
when declared(system.getMaxMem): formatSize(getMaxMem()) & " peakmem" when declared(system.getMaxMem): formatSize(getMaxMem()) & " peakmem"
else: formatSize(getTotalMem()) & " totmem" else: formatSize(getTotalMem()) & " totmem"
@ -378,9 +345,9 @@ proc mainCommand*(graph: ModuleGraph) =
let project = if optListFullPaths in conf.globalOptions: $conf.projectFull else: $conf.projectName let project = if optListFullPaths in conf.globalOptions: $conf.projectFull else: $conf.projectName
var output: string var output: string
if optCompileOnly in conf.globalOptions and conf.cmd != cmdJsonScript: if optCompileOnly in conf.globalOptions and conf.cmd != cmdJsonscript:
output = $conf.jsonBuildFile output = $conf.jsonBuildFile
elif conf.outFile.isEmpty and conf.cmd notin {cmdJsonScript, cmdCompileToBackend, cmdDoc}: elif conf.outFile.isEmpty and conf.cmd notin {cmdJsonscript} + cmdDocLike + cmdBackends:
# for some cmd we expect a valid absOutFile # for some cmd we expect a valid absOutFile
output = "unknownOutput" output = "unknownOutput"
else: else:

View file

@ -64,7 +64,7 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
if processArgument(pass, p, argsCount, config): break if processArgument(pass, p, argsCount, config): break
if pass == passCmd2: if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and if {optRun, optWasNimscript} * config.globalOptions == {} and
config.arguments.len > 0 and config.command.normalize notin ["run", "e", "r"]: config.arguments.len > 0 and config.cmd notin {cmdTcc, cmdNimscript, cmdCrun}:
rawMessage(config, errGenerated, errArgsNeedRunOption) rawMessage(config, errGenerated, errArgsNeedRunOption)
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
@ -86,19 +86,19 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
#echo(GC_getStatistics()) #echo(GC_getStatistics())
if conf.errorCounter != 0: return if conf.errorCounter != 0: return
when hasTinyCBackend: when hasTinyCBackend:
if conf.cmd == cmdRun: if conf.cmd == cmdTcc:
tccgen.run(conf, conf.arguments) tccgen.run(conf, conf.arguments)
if optRun in conf.globalOptions: if optRun in conf.globalOptions:
let output = conf.absOutFile let output = conf.absOutFile
case conf.cmd case conf.cmd
of cmdCompileToBackend: of cmdBackends, cmdTcc:
var cmdPrefix = "" var cmdPrefix = ""
case conf.backend case conf.backend
of backendC, backendCpp, backendObjc: discard of backendC, backendCpp, backendObjc: discard
of backendJs: cmdPrefix = findNodeJs() & " " of backendJs: cmdPrefix = findNodeJs() & " "
else: doAssert false, $conf.backend else: doAssert false, $conf.backend
execExternalProgram(conf, cmdPrefix & output.quoteShell & ' ' & conf.arguments) execExternalProgram(conf, cmdPrefix & output.quoteShell & ' ' & conf.arguments)
of cmdDoc, cmdRst2html: of cmdDocLike, cmdRst2html, cmdRst2tex: # bugfix(cmdRst2tex was missing)
if conf.arguments.len > 0: if conf.arguments.len > 0:
# reserved for future use # reserved for future use
rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd]) rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd])

View file

@ -301,7 +301,7 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen:
if scriptIsProj: if scriptIsProj:
showHintConf() showHintConf()
configFiles.setLen 0 configFiles.setLen 0
if conf.command != "nimsuggest": if conf.cmd != cmdIdeTools:
runNimScriptIfExists(scriptFile, isMain = true) runNimScriptIfExists(scriptFile, isMain = true)
else: else:
if not scriptIsProj: if not scriptIsProj:

View file

@ -10,7 +10,7 @@
## exposes the Nim VM to clients. ## exposes the Nim VM to clients.
import import
ast, astalgo, modules, passes, condsyms, ast, astalgo, modules, passes, condsyms,
options, sem, semdata, llstream, lineinfos, vm, options, sem, llstream, lineinfos, vm,
vmdef, modulegraphs, idents, os, pathutils, vmdef, modulegraphs, idents, os, pathutils,
passaux, scriptconfig passaux, scriptconfig
@ -153,7 +153,7 @@ proc runRepl*(r: TLLRepl;
conf.searchPaths.add(AbsoluteDir p) conf.searchPaths.add(AbsoluteDir p)
if conf.libpath.isEmpty: conf.libpath = AbsoluteDir p if conf.libpath.isEmpty: conf.libpath = AbsoluteDir p
conf.cmd = cmdInteractive conf.cmd = cmdInteractive # see also `setCmd`
conf.setErrorMaxHighMaybe conf.setErrorMaxHighMaybe
initDefines(conf.symbols) initDefines(conf.symbols)
defineSymbol(conf.symbols, "nimscript") defineSymbol(conf.symbols, "nimscript")

View file

@ -38,7 +38,7 @@ In addition, all command line options of Nim are supported.
proc mainCommand = proc mainCommand =
registerPass verbosePass registerPass verbosePass
registerPass semPass registerPass semPass
conf.cmd = cmdPretty conf.setCmd cmdNimfix
searchPaths.add options.libpath searchPaths.add options.libpath
if gProjectFull.len != 0: if gProjectFull.len != 0:
# current path is always looked first for modules # current path is always looked first for modules

View file

@ -47,7 +47,7 @@ type # please make sure we have under 32 options
TOptions* = set[TOption] TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible** TGlobalOption* = enum # **keep binary compatible**
gloptNone, optForceFullMake, gloptNone, optForceFullMake,
optWasNimscript, optWasNimscript, # redundant with `cmdNimscript`, could be removed
optListCmd, optCompileOnly, optNoLinking, optListCmd, optCompileOnly, optNoLinking,
optCDebug, # turn on debugging information optCDebug, # turn on debugging information
optGenDynLib, # generate a dynamic library optGenDynLib, # generate a dynamic library
@ -110,34 +110,44 @@ type
TBackend* = enum TBackend* = enum
backendInvalid = "" # for parseEnum backendInvalid = "" # for parseEnum
backendC = "c" backendC = "c"
backendCpp = "cpp" # was cmdCompileToCpp backendCpp = "cpp"
backendJs = "js" # was cmdCompileToJS backendJs = "js"
backendObjc = "objc" # was cmdCompileToOC backendObjc = "objc"
# backendNimscript = "nimscript" # this could actually work # backendNimscript = "nimscript" # this could actually work
# backendLlvm = "llvm" # probably not well supported; was cmdCompileToLLVM # backendLlvm = "llvm" # probably not well supported; was cmdCompileToLLVM
Command* = enum ## Nim's commands
cmdNone # not yet processed command
cmdUnknown # command unmapped
cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS
cmdCrun # compile and run in nimache
cmdTcc # run the project via TCC backend
cmdCheck # semantic checking for whole project
cmdParse # parse a single file (for debugging)
cmdScan # scan a single file (for debugging)
cmdIdeTools # ide tools (e.g. nimsuggest)
cmdNimscript # evaluate nimscript
cmdDoc0
cmdDoc2
cmdRst2html # convert a reStructuredText file to HTML
cmdRst2tex # convert a reStructuredText file to TeX
cmdJsondoc0
cmdJsondoc
cmdCtags
cmdBuildindex
cmdGendepend
cmdDump
cmdInteractive # start interactive session
cmdNop
cmdJsonscript # compile a .json build file
cmdNimfix
# old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs)
const
cmdBackends* = {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, cmdCrun}
cmdDocLike* = {cmdDoc0, cmdDoc2, cmdJsondoc0, cmdJsondoc, cmdCtags, cmdBuildindex}
type type
TCommands* = enum # Nim's commands
# **keep binary compatible**
cmdNone,
cmdCompileToC, # deadcode
cmdCompileToCpp, # deadcode
cmdCompileToOC, # deadcode
cmdCompileToJS, # deadcode
cmdCompileToLLVM, # deadcode
cmdInterpret, cmdPretty, cmdDoc,
cmdGenDepend, cmdDump,
cmdCheck, # semantic checking for whole project
cmdParse, # parse a single file (for debugging)
cmdScan, # scan a single file (for debugging)
cmdIdeTools, # ide tools
cmdDef, # def feature (find definition for IDEs)
cmdRst2html, # convert a reStructuredText file to HTML
cmdRst2tex, # convert a reStructuredText file to TeX
cmdInteractive, # start interactive session
cmdRun, # run the project via TCC backend
cmdJsonScript # compile a .json build file
cmdCompileToBackend, # compile to backend in TBackend
TStringSeq* = seq[string] TStringSeq* = seq[string]
TGCMode* = enum # the selected GC TGCMode* = enum # the selected GC
gcUnselected, gcNone, gcBoehm, gcRegions, gcArc, gcOrc, gcUnselected, gcNone, gcBoehm, gcRegions, gcArc, gcOrc,
@ -245,7 +255,7 @@ type
evalTemplateCounter*: int evalTemplateCounter*: int
evalMacroCounter*: int evalMacroCounter*: int
exitcode*: int8 exitcode*: int8
cmd*: TCommands # the command cmd*: Command # raw command parsed as enum
cmdInput*: string # input command cmdInput*: string # input command
projectIsCmd*: bool # whether we're compiling from a command input projectIsCmd*: bool # whether we're compiling from a command input
implicitCmd*: bool # whether some flag triggered an implicit `command` implicitCmd*: bool # whether some flag triggered an implicit `command`
@ -531,7 +541,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
osDragonfly, osMacosx} osDragonfly, osMacosx}
else: discard else: discard
proc importantComments*(conf: ConfigRef): bool {.inline.} = conf.cmd in {cmdDoc, cmdIdeTools} proc importantComments*(conf: ConfigRef): bool {.inline.} = conf.cmd notin cmdDocLike + {cmdIdeTools}
proc usesWriteBarrier*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc proc usesWriteBarrier*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc
template compilationCachePresent*(conf: ConfigRef): untyped = template compilationCachePresent*(conf: ConfigRef): untyped =

View file

@ -155,7 +155,7 @@ proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) =
localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)") localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)")
when hasFFI: when hasFFI:
s.cname = $s.loc.r s.cname = $s.loc.r
if c.config.cmd == cmdPretty and '$' notin extname: if c.config.cmd == cmdNimfix and '$' notin extname:
# note that '{.importc.}' is transformed into '{.importc: "$1".}' # note that '{.importc.}' is transformed into '{.importc: "$1".}'
s.loc.flags.incl(lfFullExternalName) s.loc.flags.incl(lfFullExternalName)

View file

@ -150,7 +150,8 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
cbconf cmpIgnoreCase: cbconf cmpIgnoreCase:
setResult(a, strutils.cmpIgnoreCase(a.getString 0, a.getString 1)) setResult(a, strutils.cmpIgnoreCase(a.getString 0, a.getString 1))
cbconf setCommand: cbconf setCommand:
conf.command = a.getString 0 conf.setCommandEarly(a.getString 0)
# xxx move remaining logic to commands.nim or other
let arg = a.getString 1 let arg = a.getString 1
incl(conf.globalOptions, optWasNimscript) incl(conf.globalOptions, optWasNimscript)
if arg.len > 0: if arg.len > 0:

View file

@ -2280,7 +2280,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = magicsAfterOverloadResolution(c, result, flags) result = magicsAfterOverloadResolution(c, result, flags)
of mRunnableExamples: of mRunnableExamples:
markUsed(c, n.info, s) markUsed(c, n.info, s)
if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList: if c.config.cmd in cmdDocLike and n.len >= 2 and n.lastSon.kind == nkStmtList:
when false: when false:
# some of this dead code was moved to `prepareExamples` # some of this dead code was moved to `prepareExamples`
if sfMainModule in c.module.flags: if sfMainModule in c.module.flags:
@ -2724,7 +2724,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
let mode = if nfDotField in n.flags: {} else: {checkUndeclared} let mode = if nfDotField in n.flags: {} else: {checkUndeclared}
var s = qualifiedLookUp(c, n[0], mode) var s = qualifiedLookUp(c, n[0], mode)
if s != nil: if s != nil:
#if c.config.cmd == cmdPretty and n[0].kind == nkDotExpr: #if c.config.cmd == cmdNimfix and n[0].kind == nkDotExpr:
# pretty.checkUse(n[0][1].info, s) # pretty.checkUse(n[0][1].info, s)
case s.kind case s.kind
of skMacro, skTemplate: of skMacro, skTemplate:

View file

@ -134,7 +134,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
e.position = int(counter) e.position = int(counter)
let symNode = newSymNode(e) let symNode = newSymNode(e)
if optNimV1Emulation notin c.config.globalOptions and identToReplace != nil and if optNimV1Emulation notin c.config.globalOptions and identToReplace != nil and
c.config.cmd != cmdDoc: # A hack to produce documentation for enum fields. c.config.cmd notin cmdDocLike: # A hack to produce documentation for enum fields.
identToReplace[] = symNode identToReplace[] = symNode
if e.position == 0: hasNull = true if e.position == 0: hasNull = true
if result.sym != nil and sfExported in result.sym.flags: if result.sym != nil and sfExported in result.sym.flags:

View file

@ -1223,9 +1223,7 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var argsCount = 1 var argsCount = 1
config.commandLine.setLen 0 config.commandLine.setLen 0
config.command = "check" config.setCmd cmdCheck
config.cmd = cmdCheck
while true: while true:
parseopt.next(p) parseopt.next(p)
case p.kind case p.kind
@ -1253,7 +1251,7 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
if processArgument(pass, p, argsCount, config): break if processArgument(pass, p, argsCount, config): break
if pass == passCmd2: if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and if {optRun, optWasNimscript} * config.globalOptions == {} and
config.arguments.len > 0 and config.command.normalize notin ["run", "e"]: config.arguments.len > 0 and config.cmd notin {cmdTcc, cmdNimscript}:
rawMessage(config, errGenerated, errArgsNeedRunOption) rawMessage(config, errGenerated, errArgsNeedRunOption)
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =

View file

@ -517,7 +517,7 @@ proc mainCommand(graph: ModuleGraph) =
clearPasses(graph) clearPasses(graph)
registerPass graph, verbosePass registerPass graph, verbosePass
registerPass graph, semPass registerPass graph, semPass
conf.cmd = cmdIdeTools conf.setCmd cmdIdeTools
wantMainModule(conf) wantMainModule(conf)
if not fileExists(conf.projectFull): if not fileExists(conf.projectFull):
@ -666,7 +666,7 @@ else:
clearPasses(graph) clearPasses(graph)
registerPass graph, verbosePass registerPass graph, verbosePass
registerPass graph, semPass registerPass graph, semPass
conf.cmd = cmdIdeTools conf.setCmd cmdIdeTools
wantMainModule(conf) wantMainModule(conf)
if not fileExists(conf.projectFull): if not fileExists(conf.projectFull):

View file

@ -158,7 +158,7 @@ proc mainCommand(graph: ModuleGraph) =
clearPasses(graph) clearPasses(graph)
registerPass graph, verbosePass registerPass graph, verbosePass
registerPass graph, semPass registerPass graph, semPass
conf.cmd = cmdIdeTools conf.setCmd cmdIdeTools
wantMainModule(conf) wantMainModule(conf)
setupDb(graph, dbfile) setupDb(graph, dbfile)