Skip to content

Commit

Permalink
refactor handleCmdLine for nim and nimsuggest
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Aug 28, 2018
1 parent 3753d0b commit 3b8caa8
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 122 deletions.
83 changes: 83 additions & 0 deletions compiler/cmdlinehelper.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
## 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

type ProgBase* = ref object of RootObj
name*: string
suggestMode*: bool

method processCmdLine(self: ProgBase, pass: TCmdLinePass, cmd: string; config: ConfigRef) {.base.} =
doAssert false

method mainCommand(self: ProgBase, graph: ModuleGraph) {.base.} =
doAssert false

proc initDefinesProg*(self: ProgBase, conf: ConfigRef) =
condsyms.initDefines(conf.symbols)
defineSymbol conf.symbols, self.name

proc processCmdLineAndProjectPath*(self: ProgBase, conf: ConfigRef) =
self.processCmdLine(passCmd1, "", conf)
if conf.projectName == "-":
conf.projectName = "stdinfile"
conf.projectFull = "stdinfile"
conf.projectPath = canonicalizePath(conf, getCurrentDir())
conf.projectIsStdin = true
elif conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, conf.projectName)
except OSError:
conf.projectFull = conf.projectName
let p = splitFile(conf.projectFull)
let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
conf.projectPath = canonicalizePath(conf, dir)
conf.projectName = p.name
else:
conf.projectPath = canonicalizePath(conf, getCurrentDir())

proc loadConfigsAndRunMainCommand*(self: ProgBase, cache: IdentCache; conf: ConfigRef): bool =
loadConfigs(DefaultConfig, cache, conf) # load all config files
if self.suggestMode:
conf.command = "nimsuggest"

proc runNimScriptIfExists(scriptFile: string)=
if fileExists(scriptFile):
runNimScript(cache, scriptFile, freshDefines=false, conf)

# TODO:
# merge this complex logic with `loadConfigs`
# check whether these should be controlled via
# optSkipConfigFile, optSkipUserConfigFile
const configNims = "config.nims"
runNimScriptIfExists(getSystemConfigPath(conf, configNims))
runNimScriptIfExists(getUserConfigPath(configNims))
runNimScriptIfExists(conf.projectPath / configNims)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
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:
return false
else:
if scriptFile.cmpPaths(conf.projectFull) != 0:
runNimScriptIfExists(scriptFile)
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard

# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars(conf)
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")

let graph = newModuleGraph(cache, conf)
graph.suggestMode = self.suggestMode
self.mainCommand(graph)
return true
110 changes: 37 additions & 73 deletions compiler/nim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ when defined(i386) and defined(windows) and defined(vcc):
import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt,
nodejs, scriptconfig, idents, modulegraphs, lineinfos
nodejs, scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper

when hasTinyCBackend:
import tccgen
Expand All @@ -37,7 +37,9 @@ proc prependCurDir(f: string): string =
else:
result = f

proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
type ProgNim=ref object of ProgBase

method processCmdLine(self: ProgNim, pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
while true:
Expand All @@ -56,81 +58,43 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
if optRun notin config.globalOptions and config.arguments.len > 0 and config.command.normalize != "run":
rawMessage(config, errGenerated, errArgsNeedRunOption)

method mainCommand(self: ProgNim, graph: ModuleGraph)=
mainCommand(graph)

proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
condsyms.initDefines(conf.symbols)
let self = ProgNim(name: "nim_compiler")
self.initDefinesProg(conf)
if paramCount() == 0:
writeCommandLineUsage(conf, conf.helpWritten)
else:
# Process command line arguments:
processCmdLine(passCmd1, "", conf)
if conf.projectName == "-":
conf.projectName = "stdinfile"
conf.projectFull = "stdinfile"
conf.projectPath = canonicalizePath(conf, getCurrentDir())
conf.projectIsStdin = true
elif conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, conf.projectName)
except OSError:
conf.projectFull = conf.projectName
let p = splitFile(conf.projectFull)
let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
conf.projectPath = canonicalizePath(conf, dir)
conf.projectName = p.name
else:
conf.projectPath = canonicalizePath(conf, getCurrentDir())
loadConfigs(DefaultConfig, cache, conf) # load all config files

proc runNimScriptIfExists(scriptFile: string)=
if fileExists(scriptFile):
runNimScript(cache, scriptFile, freshDefines=false, conf)
return

# TODO:
# merge this complex logic with `loadConfigs`
# check whether these should be controlled via
# optSkipConfigFile, optSkipUserConfigFile
const configNims = "config.nims"
runNimScriptIfExists(getSystemConfigPath(conf, configNims))
runNimScriptIfExists(getUserConfigPath(configNims))
runNimScriptIfExists(conf.projectPath / configNims)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
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: return

# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars(conf)
processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")
mainCommand(newModuleGraph(cache, conf))
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter == 0:
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.run(conf.arguments)
if optRun in conf.globalOptions:
if conf.cmd == cmdCompileToJS:
var ex: string
if conf.outFile.len > 0:
ex = conf.outFile.prependCurDir.quoteShell
else:
ex = quoteShell(
completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
else:
var binPath: string
if conf.outFile.len > 0:
# If the user specified an outFile path, use that directly.
binPath = conf.outFile.prependCurDir
else:
# Figure out ourselves a valid binary name.
binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
var ex = quoteShell(binPath)
execExternalProgram(conf, ex & ' ' & conf.arguments)
self.processCmdLineAndProjectPath(conf)
if not self.loadConfigsAndRunMainCommand(cache, conf): return
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter != 0: return
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.run(conf.arguments)
if optRun in conf.globalOptions:
if conf.cmd == cmdCompileToJS:
var ex: string
if conf.outFile.len > 0:
ex = conf.outFile.prependCurDir.quoteShell
else:
ex = quoteShell(
completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
else:
var binPath: string
if conf.outFile.len > 0:
# If the user specified an outFile path, use that directly.
binPath = conf.outFile.prependCurDir
else:
# Figure out ourselves a valid binary name.
binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
var ex = quoteShell(binPath)
execExternalProgram(conf, ex & ' ' & conf.arguments)

when declared(GC_setMaxPause):
GC_setMaxPause 2_000
Expand Down
73 changes: 24 additions & 49 deletions nimsuggest/nimsuggest.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import compiler / [options, commands, modules, sem,
passes, passaux, msgs, nimconf,
extccomp, condsyms,
sigmatch, ast, scriptconfig,
idents, modulegraphs, vm, prefixmatches, lineinfos]
idents, modulegraphs, vm, prefixmatches, lineinfos, cmdlinehelper]

when defined(windows):
import winlean
Expand Down Expand Up @@ -487,7 +487,9 @@ proc mainThread(graph: ModuleGraph) =
var
inputThread: Thread[ThreadParams]

proc mainCommand(graph: ModuleGraph) =
type ProgNimsuggest=ref object of ProgBase

method mainCommand(self: ProgNimsuggest, graph: ModuleGraph) =
let conf = graph.config
clearPasses(graph)
registerPass graph, verbosePass
Expand Down Expand Up @@ -582,55 +584,28 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
# if processArgument(pass, p, argsCount): break

proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
condsyms.initDefines(conf.symbols)
defineSymbol conf.symbols, "nimsuggest"
let self = ProgNimsuggest(suggestMode:true, name:"nimsuggest")
self.initDefinesProg(conf)

if paramCount() == 0:
stdout.writeline(Usage)
else:
processCmdLine(passCmd1, "", conf)
if gMode != mstdin:
conf.writelnHook = proc (msg: string) = discard
if conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, conf.projectName)
except OSError:
conf.projectFull = conf.projectName
var p = splitFile(conf.projectFull)
conf.projectPath = canonicalizePath(conf, p.dir)
conf.projectName = p.name
else:
conf.projectPath = canonicalizePath(conf, getCurrentDir())

# Find Nim's prefix dir.
let binaryPath = findExe("nim")
if binaryPath == "":
raise newException(IOError,
"Cannot find Nim standard library: Nim compiler not in PATH")
conf.prefixDir = binaryPath.splitPath().head.parentDir()
if not dirExists(conf.prefixDir / "lib"): conf.prefixDir = ""

#msgs.writelnHook = proc (line: string) = log(line)
myLog("START " & conf.projectFull)

loadConfigs(DefaultConfig, cache, conf) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
conf.command = "nimsuggest"
let scriptFile = conf.projectFull.changeFileExt("nims")
if fileExists(scriptFile):
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file:
if scriptFile != conf.projectFull:
runNimScript(cache, scriptFile, freshDefines=false, conf)
elif fileExists(conf.projectPath / "config.nims"):
# directory wide NimScript file
runNimScript(cache, conf.projectPath / "config.nims", freshDefines=false, conf)

extccomp.initVars(conf)
processCmdLine(passCmd2, "", conf)

let graph = newModuleGraph(cache, conf)
graph.suggestMode = true
mainCommand(graph)
return

self.processCmdLineAndProjectPath(conf)

if gMode != mstdin:
conf.writelnHook = proc (msg: string) = discard
# Find Nim's prefix dir.
let binaryPath = findExe("nim")
if binaryPath == "":
raise newException(IOError,
"Cannot find Nim standard library: Nim compiler not in PATH")
conf.prefixDir = binaryPath.splitPath().head.parentDir()
if not dirExists(conf.prefixDir / "lib"): conf.prefixDir = ""

#msgs.writelnHook = proc (line: string) = log(line)
myLog("START " & conf.projectFull)

discard self.loadConfigsAndRunMainCommand(cache, conf)

handleCmdline(newIdentCache(), newConfigRef())

0 comments on commit 3b8caa8

Please sign in to comment.