prepare Nimble for the upcoming compiler API changes (#488)

* prepare Nimble for the upcoming compiler API changes

* attempt to make tests green
This commit is contained in:
Andreas Rumpf 2018-05-13 20:07:27 +02:00 committed by Dominik Picheta
commit e2869714b8

View file

@ -9,7 +9,7 @@ import
compiler/condsyms, compiler/sem, compiler/semdata, compiler/condsyms, compiler/sem, compiler/semdata,
compiler/llstream, compiler/vm, compiler/vmdef, compiler/commands, compiler/llstream, compiler/vm, compiler/vmdef, compiler/commands,
compiler/msgs, compiler/magicsys, compiler/idents, compiler/msgs, compiler/magicsys, compiler/idents,
compiler/nimconf compiler/nimconf, compiler/nversion
from compiler/scriptconfig import setupVM from compiler/scriptconfig import setupVM
from compiler/astalgo import strTableGet from compiler/astalgo import strTableGet
@ -75,13 +75,14 @@ proc extractRequires(ident: PSym, result: var seq[PkgTuple]) =
when declared(newIdentCache): when declared(newIdentCache):
var identCache = newIdentCache() var identCache = newIdentCache()
proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext = proc setupVM(graph: ModuleGraph; module: PSym; scriptName: string, flags: Flags): PEvalContext =
## This procedure is exported in the compiler sources, but its implementation ## This procedure is exported in the compiler sources, but its implementation
## is too Nim-specific to be used by Nimble. ## is too Nim-specific to be used by Nimble.
## Specifically, the implementation of ``switch`` is problematic. Sooo ## Specifically, the implementation of ``switch`` is problematic. Sooo
## I simply copied it here and edited it :) ## I simply copied it here and edited it :)
when declared(NimCompilerApiVersion):
when declared(newIdentCache): result = newCtx(module, identCache, graph)
elif declared(newIdentCache):
result = newCtx(module, identCache) result = newCtx(module, identCache)
else: else:
result = newCtx(module) result = newCtx(module)
@ -89,6 +90,7 @@ proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext =
registerAdditionalOps(result) registerAdditionalOps(result)
# captured vars: # captured vars:
let conf = graph.config
var errorMsg: string var errorMsg: string
var vthisDir = scriptName.splitFile.dir var vthisDir = scriptName.splitFile.dir
@ -152,13 +154,25 @@ proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext =
cbconf thisDir: cbconf thisDir:
setResult(a, vthisDir) setResult(a, vthisDir)
cbconf put: cbconf put:
compiler_options.setConfigVar(getString(a, 0), getString(a, 1)) when declared(NimCompilerApiVersion):
compiler_options.setConfigVar(conf, getString(a, 0), getString(a, 1))
else:
compiler_options.setConfigVar(getString(a, 0), getString(a, 1))
cbconf get: cbconf get:
setResult(a, compiler_options.getConfigVar(a.getString 0)) when declared(NimCompilerApiVersion):
setResult(a, compiler_options.getConfigVar(conf, a.getString 0))
else:
setResult(a, compiler_options.getConfigVar(a.getString 0))
cbconf exists: cbconf exists:
setResult(a, compiler_options.existsConfigVar(a.getString 0)) when declared(NimCompilerApiVersion):
setResult(a, compiler_options.existsConfigVar(conf, a.getString 0))
else:
setResult(a, compiler_options.existsConfigVar(a.getString 0))
cbconf nimcacheDir: cbconf nimcacheDir:
setResult(a, compiler_options.getNimcacheDir()) when declared(NimCompilerApiVersion):
setResult(a, compiler_options.getNimcacheDir(conf))
else:
setResult(a, compiler_options.getNimcacheDir())
cbconf paramStr: cbconf paramStr:
setResult(a, os.paramStr(int a.getInt 0)) setResult(a, os.paramStr(int a.getInt 0))
cbconf paramCount: cbconf paramCount:
@ -168,16 +182,29 @@ proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext =
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:
compiler_options.command = a.getString 0 when declared(NimCompilerApiVersion):
let arg = a.getString 1 conf.command = a.getString 0
if arg.len > 0: let arg = a.getString 1
gProjectName = arg if arg.len > 0:
try: conf.projectName = arg
gProjectFull = canonicalizePath(gProjectPath / gProjectName) try:
except OSError: conf.projectFull = canonicalizePath(conf, conf.projectPath / conf.projectName)
gProjectFull = gProjectName except OSError:
conf.projectFull = conf.projectName
else:
compiler_options.command = a.getString 0
let arg = a.getString 1
if arg.len > 0:
gProjectName = arg
try:
gProjectFull = canonicalizePath(gProjectPath / gProjectName)
except OSError:
gProjectFull = gProjectName
cbconf getCommand: cbconf getCommand:
setResult(a, compiler_options.command) when declared(NimCompilerApiVersion):
setResult(a, conf.command)
else:
setResult(a, compiler_options.command)
cbconf switch: cbconf switch:
if not flags.isNil: if not flags.isNil:
let let
@ -248,7 +275,13 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
## Executes the specified script. Returns the script's module symbol. ## Executes the specified script. Returns the script's module symbol.
## ##
## No clean up is performed and must be done manually! ## No clean up is performed and must be done manually!
when declared(resetAllModulesHard): graph = newModuleGraph()
let conf = graph.config
when declared(NimCompilerApiVersion):
if "nimblepkg/nimscriptapi" notin conf.implicitImports:
conf.implicitImports.add("nimblepkg/nimscriptapi")
elif declared(resetAllModulesHard):
# for compatibility with older Nim versions: # for compatibility with older Nim versions:
if "nimblepkg/nimscriptapi" notin compiler_options.implicitIncludes: if "nimblepkg/nimscriptapi" notin compiler_options.implicitIncludes:
compiler_options.implicitIncludes.add("nimblepkg/nimscriptapi") compiler_options.implicitIncludes.add("nimblepkg/nimscriptapi")
@ -257,17 +290,30 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
compiler_options.implicitImports.add("nimblepkg/nimscriptapi") compiler_options.implicitImports.add("nimblepkg/nimscriptapi")
# Ensure the compiler can find its standard library #220. # Ensure the compiler can find its standard library #220.
compiler_options.gPrefixDir = getNimPrefixDir(options) when declared(NimCompilerApiVersion):
display("Setting", "Nim stdlib prefix to " & compiler_options.gPrefixDir, conf.prefixDir = getNimPrefixDir(options)
priority=LowPriority) display("Setting", "Nim stdlib prefix to " & conf.prefixDir,
priority=LowPriority)
# Verify that lib path points to existing stdlib. template myLibPath(): untyped = conf.libpath
compiler_options.setDefaultLibpath()
display("Setting", "Nim stdlib path to " & compiler_options.libpath, # Verify that lib path points to existing stdlib.
setDefaultLibpath(conf)
else:
compiler_options.gPrefixDir = getNimPrefixDir(options)
display("Setting", "Nim stdlib prefix to " & compiler_options.gPrefixDir,
priority=LowPriority)
template myLibPath(): untyped = compiler_options.libpath
# Verify that lib path points to existing stdlib.
compiler_options.setDefaultLibpath()
display("Setting", "Nim stdlib path to " & myLibPath(),
priority=LowPriority) priority=LowPriority)
if not isValidLibPath(compiler_options.libpath): if not isValidLibPath(myLibPath()):
let msg = "Nimble cannot find Nim's standard library.\nLast try in:\n - $1" % let msg = "Nimble cannot find Nim's standard library.\nLast try in:\n - $1" %
compiler_options.libpath myLibPath()
let hint = "Nimble does its best to find Nim's standard library, " & let hint = "Nimble does its best to find Nim's standard library, " &
"sometimes this fails. You can set the environment variable " & "sometimes this fails. You can set the environment variable " &
"NIM_LIB_PREFIX to where Nim's `lib` directory is located as " & "NIM_LIB_PREFIX to where Nim's `lib` directory is located as " &
@ -278,11 +324,11 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
# Verify that the stdlib that was found isn't older than the stdlib that Nimble # Verify that the stdlib that was found isn't older than the stdlib that Nimble
# was compiled with. # was compiled with.
let libVersion = getLibVersion(compiler_options.libpath) let libVersion = getLibVersion(myLibPath())
if NimVersion.newVersion() > libVersion: if NimVersion.newVersion() > libVersion:
let msg = ("Nimble cannot use an older stdlib than the one it was compiled " & let msg = ("Nimble cannot use an older stdlib than the one it was compiled " &
"with.\n Stdlib in '$#' has version: $#.\n Nimble needs at least: $#.") % "with.\n Stdlib in '$#' has version: $#.\n Nimble needs at least: $#.") %
[compiler_options.libpath, $libVersion, NimVersion] [myLibPath(), $libVersion, NimVersion]
let hint = "You may be running a newer version of Nimble than you intended " & let hint = "You may be running a newer version of Nimble than you intended " &
"to. Run an older version of Nimble that is compatible with " & "to. Run an older version of Nimble that is compatible with " &
"the stdlib that Nimble is attempting to use or set the environment variable " & "the stdlib that Nimble is attempting to use or set the environment variable " &
@ -300,29 +346,45 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
let tmpNimscriptApiPath = t / "nimblepkg" / "nimscriptapi.nim" let tmpNimscriptApiPath = t / "nimblepkg" / "nimscriptapi.nim"
createDir(tmpNimscriptApiPath.splitFile.dir) createDir(tmpNimscriptApiPath.splitFile.dir)
writeFile(tmpNimscriptApiPath, nimscriptApi) writeFile(tmpNimscriptApiPath, nimscriptApi)
searchPaths.add(t) when declared(NimCompilerApiVersion):
conf.searchPaths.add(t)
else:
searchPaths.add(t)
initDefines() when declared(NimCompilerApiVersion):
loadConfigs(DefaultConfig) initDefines(conf.symbols)
passes.gIncludeFile = includeModule loadConfigs(DefaultConfig, conf)
passes.gImportModule = importModule passes.gIncludeFile = includeModule
passes.gImportModule = importModule
defineSymbol("nimscript") defineSymbol(conf.symbols, "nimscript")
defineSymbol("nimconfig") defineSymbol(conf.symbols, "nimconfig")
defineSymbol("nimble") defineSymbol(conf.symbols, "nimble")
registerPass(semPass) registerPass(semPass)
registerPass(evalPass) registerPass(evalPass)
searchPaths.add(compiler_options.libpath) conf.searchPaths.add(conf.libpath)
else:
initDefines()
loadConfigs(DefaultConfig)
passes.gIncludeFile = includeModule
passes.gImportModule = importModule
defineSymbol("nimscript")
defineSymbol("nimconfig")
defineSymbol("nimble")
registerPass(semPass)
registerPass(evalPass)
searchPaths.add(compiler_options.libpath)
when declared(resetAllModulesHard): when declared(resetAllModulesHard):
result = makeModule(scriptName) result = makeModule(scriptName)
else: else:
graph = newModuleGraph()
result = graph.makeModule(scriptName) result = graph.makeModule(scriptName)
incl(result.flags, sfMainModule) incl(result.flags, sfMainModule)
vm.globalCtx = setupVM(result, scriptName, flags) vm.globalCtx = setupVM(graph, result, scriptName, flags)
# Setup builtins defined in nimscriptapi.nim # Setup builtins defined in nimscriptapi.nim
template cbApi(name, body) {.dirty.} = template cbApi(name, body) {.dirty.} =
@ -342,17 +404,30 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym =
proc cleanup() = proc cleanup() =
# ensure everything can be called again: # ensure everything can be called again:
compiler_options.gProjectName = "" when declared(NimCompilerApiVersion):
compiler_options.command = "" let conf = graph.config
when declared(resetAllModulesHard): conf.projectName = ""
conf.command = ""
else:
compiler_options.gProjectName = ""
compiler_options.command = ""
when declared(NimCompilerApiVersion):
resetSystemArtifacts(graph)
elif declared(resetAllModulesHard):
resetAllModulesHard() resetAllModulesHard()
else: else:
resetSystemArtifacts() resetSystemArtifacts()
clearPasses() clearPasses()
msgs.gErrorMax = 1 when declared(NimCompilerApiVersion):
msgs.writeLnHook = nil conf.errorMax = 1
vm.globalCtx = nil msgs.writeLnHook = nil
initDefines() vm.globalCtx = nil
initDefines(conf.symbols)
else:
msgs.gErrorMax = 1
msgs.writeLnHook = nil
vm.globalCtx = nil
initDefines()
proc readPackageInfoFromNims*(scriptName: string, options: Options, proc readPackageInfoFromNims*(scriptName: string, options: Options,
result: var PackageInfo) = result: var PackageInfo) =
@ -360,12 +435,21 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
## that it populates. ## that it populates.
# Setup custom error handling. # Setup custom error handling.
msgs.gErrorMax = high(int) when declared(NimCompilerApiVersion):
let conf = graph.config
conf.errorMax = high(int)
else:
msgs.gErrorMax = high(int)
template errCounter(): int =
when declared(NimCompilerApiVersion): conf.errorCounter
else: msgs.gErrorCounter
var previousMsg = "" var previousMsg = ""
msgs.writeLnHook = msgs.writeLnHook =
proc (output: string) = proc (output: string) =
# The error counter is incremented after the writeLnHook is invoked. # The error counter is incremented after the writeLnHook is invoked.
if msgs.gErrorCounter > 0: if errCounter() > 0:
raise newException(NimbleError, previousMsg) raise newException(NimbleError, previousMsg)
elif previousMsg.len > 0: elif previousMsg.len > 0:
display("Info", previousMsg, priority = MediumPriority) display("Info", previousMsg, priority = MediumPriority)
@ -373,7 +457,10 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
raise newException(NimbleError, output) raise newException(NimbleError, output)
previousMsg = output previousMsg = output
compiler_options.command = internalCmd when declared(NimCompilerApiVersion):
conf.command = internalCmd
else:
compiler_options.command = internalCmd
# Execute the nimscript file. # Execute the nimscript file.
let thisModule = execScript(scriptName, nil, options) let thisModule = execScript(scriptName, nil, options)
@ -390,7 +477,7 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
doAssert apiModule != nil doAssert apiModule != nil
# Check whether an error has occurred. # Check whether an error has occurred.
if msgs.gErrorCounter > 0: if errCounter() > 0:
raise newException(NimbleError, previousMsg) raise newException(NimbleError, previousMsg)
# Extract all the necessary fields populated by the nimscript file. # Extract all the necessary fields populated by the nimscript file.
@ -448,6 +535,13 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options,
cleanup() cleanup()
when declared(NimCompilerApiVersion):
template nimCommand(): untyped = conf.command
template nimProjectName(): untyped = conf.projectName
else:
template nimCommand(): untyped = compiler_options.command
template nimProjectName(): untyped = compiler_options.gProjectName
proc execTask*(scriptName, taskName: string, proc execTask*(scriptName, taskName: string,
options: Options): ExecutionResult[void] = options: Options): ExecutionResult[void] =
## Executes the specified task in the specified script. ## Executes the specified task in the specified script.
@ -455,7 +549,9 @@ proc execTask*(scriptName, taskName: string,
## `scriptName` should be a filename pointing to the nimscript file. ## `scriptName` should be a filename pointing to the nimscript file.
result.success = true result.success = true
result.flags = newTable[string, seq[string]]() result.flags = newTable[string, seq[string]]()
compiler_options.command = internalCmd when declared(NimCompilerApiVersion):
let conf = graph.config
nimCommand() = internalCmd
display("Executing", "task $# in $#" % [taskName, scriptName], display("Executing", "task $# in $#" % [taskName, scriptName],
priority = HighPriority) priority = HighPriority)
@ -468,9 +564,9 @@ proc execTask*(scriptName, taskName: string,
discard vm.globalCtx.execProc(prc, []) discard vm.globalCtx.execProc(prc, [])
# Read the command, arguments and flags set by the executed task. # Read the command, arguments and flags set by the executed task.
result.command = compiler_options.command result.command = nimCommand()
result.arguments = @[] result.arguments = @[]
for arg in compiler_options.gProjectName.split(): for arg in nimProjectName().split():
result.arguments.add(arg) result.arguments.add(arg)
cleanup() cleanup()
@ -481,9 +577,11 @@ proc execHook*(scriptName, actionName: string, before: bool,
## the "before" or the "after" hook. ## the "before" or the "after" hook.
## ##
## `scriptName` should be a filename pointing to the nimscript file. ## `scriptName` should be a filename pointing to the nimscript file.
when declared(NimCompilerApiVersion):
let conf = graph.config
result.success = true result.success = true
result.flags = newTable[string, seq[string]]() result.flags = newTable[string, seq[string]]()
compiler_options.command = internalCmd nimCommand() = internalCmd
let hookName = let hookName =
if before: actionName.toLowerAscii & "Before" if before: actionName.toLowerAscii & "Before"
else: actionName.toLowerAscii & "After" else: actionName.toLowerAscii & "After"
@ -505,18 +603,22 @@ proc execHook*(scriptName, actionName: string, before: bool,
else: assert false else: assert false
# Read the command, arguments and flags set by the executed task. # Read the command, arguments and flags set by the executed task.
result.command = compiler_options.command result.command = nimCommand()
result.arguments = @[] result.arguments = @[]
for arg in compiler_options.gProjectName.split(): for arg in nimProjectName().split():
result.arguments.add(arg) result.arguments.add(arg)
cleanup() cleanup()
proc getNimScriptCommand(): string = proc getNimScriptCommand(): string =
compiler_options.command when declared(NimCompilerApiVersion):
let conf = graph.config
nimCommand()
proc setNimScriptCommand(command: string) = proc setNimScriptCommand(command: string) =
compiler_options.command = command when declared(NimCompilerApiVersion):
let conf = graph.config
nimCommand() = command
proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool = proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool =
## Determines whether the last executed task used ``setCommand`` ## Determines whether the last executed task used ``setCommand``