Improvements to API of nimscriptsupport module.

* setCommand "nop" no longer needed.
* Recursive setCommand supported.
* Explicit execTask procedure which executes the task explicitly instead of setting global compiler variables.
This commit is contained in:
Dominik Picheta 2015-12-23 13:05:59 +00:00
commit 36273f1166
2 changed files with 73 additions and 19 deletions

View file

@ -10,7 +10,7 @@ import nimblepkg/packageinfo, nimblepkg/version, nimblepkg/tools,
nimblepkg/download, nimblepkg/config, nimblepkg/nimbletypes,
nimblepkg/publish
import compiler/options as compiler_options
import nimblepkg/nimscriptsupport
when not defined(windows):
from posix import getpid
@ -223,7 +223,7 @@ proc parseCmdLine(): Options =
case kind
of cmdArgument:
if result.action.typ == actionNil:
compiler_options.command = key
setNimScriptCommand(key)
result.action.typ = parseActionType(key)
initAction(result, key)
else:
@ -1017,14 +1017,9 @@ proc doAction(options: Options) =
if not existsDir(options.getPkgsDir):
createDir(options.getPkgsDir)
# The nimscript file may use `setCommand` to set the command so we need to
# re-read it from the compiler.
# TODO: It doesn't appear that this actually happens, can we just remove this?
var command = compiler_options.command.parseActionType()
var doLoop = true
while doLoop:
doLoop = false
let cmd = compiler_options.command.normalize
var command = getNimScriptCommand().parseActionType()
# The loop is necessary to support tasks using `setCommand`.
while true:
case command
of actionUpdate:
update(options)
@ -1050,11 +1045,22 @@ proc doAction(options: Options) =
publish(pkgInfo)
of actionDump:
dump(options)
of actionNil: discard "assuming nimscript 'nop' command here"
of actionNil:
assert false
of actionCustom:
# calls Nimscript as a side effect :-/
discard getPkgInfo(getCurrentDir())
doLoop = cmd != compiler_options.command.normalize
# Custom command. Attempt to call a NimScript task.
let (isNimScript, nimbleFile) = findNimbleFile(getCurrentDir(), true)
if not isNimScript:
writeHelp()
let oldCmd = getNimScriptCommand()
if not execTask(nimbleFile, oldCmd):
echo("FAILURE: Could not find task ", oldCmd, " in ", nimbleFile)
writeHelp()
if getNimScriptCommand().normalize == "nop":
echo("WARNING: Using `setCommand 'nop'` is not necessary.")
break
command = getNimScriptCommand().parseActionType()
if not hasTaskRequestedCommand(): break
when isMainModule:
when defined(release):

View file

@ -11,10 +11,15 @@ import
compiler/msgs, compiler/magicsys, compiler/lists
from compiler/scriptconfig import setupVM
from compiler/idents import getIdent
from compiler/astalgo import strTableGet, `$`
import nimbletypes, version
import os, strutils
const
internalCmd = "NimbleInternal"
proc raiseVariableError(ident, typ: string) {.noinline.} =
raise newException(NimbleError,
"NimScript's variable '" & ident & "' needs a value of type '" & typ & "'.")
@ -53,7 +58,10 @@ proc extractRequires(result: var seq[PkgTuple]) =
else:
raiseVariableError("requiresData", "seq[(string, VersionReq)]")
proc readPackageInfoFromNims*(scriptName: string; result: var PackageInfo) =
proc execScript(scriptName: string) =
## Executes the specified script.
##
## No clean up is performed and must be done manually!
setDefaultLibpath()
passes.gIncludeFile = includeModule
passes.gImportModule = importModule
@ -74,6 +82,21 @@ proc readPackageInfoFromNims*(scriptName: string; result: var PackageInfo) =
compileSystemModule()
processModule(m, llStreamOpen(scriptName, fmRead), nil)
proc cleanup() =
# ensure everything can be called again:
resetAllModulesHard()
clearPasses()
vm.globalCtx = nil
initDefines()
proc readPackageInfoFromNims*(scriptName: string; result: var PackageInfo) =
## Executes the `scriptName` nimscript file. Reads the package information
## that it populates.
# Execute the nimscript file.
execScript(scriptName)
# Extract all the necessary fields populated by the nimscript file.
template trivialField(field) =
result.field = getGlobal(astToStr field)
@ -111,7 +134,32 @@ proc readPackageInfoFromNims*(scriptName: string; result: var PackageInfo) =
else:
result.backend = backend.toLower()
# ensure everything can be called again:
resetAllModulesHard()
vm.globalCtx = nil
initDefines()
cleanup()
proc execTask*(scriptName, taskName: string): bool =
## Executes the specified task in the specified script.
##
## `scriptName` should be a filename pointing to the nimscript file.
result = true
options.command = internalCmd
echo("Executing task ", taskName, " in ", scriptName)
execScript(scriptName)
# Explicitly execute the task procedure, instead of relying on hack.
assert vm.globalCtx.module.kind == skModule
let prc = vm.globalCtx.module.tab.strTableGet(getIdent(taskName & "Task"))
if prc.isNil:
# Procedure not defined in the NimScript module.
return false
discard vm.globalCtx.execProc(prc, [])
cleanup()
proc getNimScriptCommand*(): string =
options.command
proc setNimScriptCommand*(command: string) =
options.command = command
proc hasTaskRequestedCommand*(): bool =
## Determines whether the last executed task used ``setCommand``
return getNimScriptCommand() != internalCmd