From e2869714b8bdc7af8f7be581f481fe2914c25a2a Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 13 May 2018 20:07:27 +0200 Subject: [PATCH] prepare Nimble for the upcoming compiler API changes (#488) * prepare Nimble for the upcoming compiler API changes * attempt to make tests green --- src/nimblepkg/nimscriptsupport.nim | 222 +++++++++++++++++++++-------- 1 file changed, 162 insertions(+), 60 deletions(-) diff --git a/src/nimblepkg/nimscriptsupport.nim b/src/nimblepkg/nimscriptsupport.nim index 0222980..6f55881 100644 --- a/src/nimblepkg/nimscriptsupport.nim +++ b/src/nimblepkg/nimscriptsupport.nim @@ -9,7 +9,7 @@ import compiler/condsyms, compiler/sem, compiler/semdata, compiler/llstream, compiler/vm, compiler/vmdef, compiler/commands, compiler/msgs, compiler/magicsys, compiler/idents, - compiler/nimconf + compiler/nimconf, compiler/nversion from compiler/scriptconfig import setupVM from compiler/astalgo import strTableGet @@ -75,13 +75,14 @@ proc extractRequires(ident: PSym, result: var seq[PkgTuple]) = when declared(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 ## is too Nim-specific to be used by Nimble. ## Specifically, the implementation of ``switch`` is problematic. Sooo ## I simply copied it here and edited it :) - - when declared(newIdentCache): + when declared(NimCompilerApiVersion): + result = newCtx(module, identCache, graph) + elif declared(newIdentCache): result = newCtx(module, identCache) else: result = newCtx(module) @@ -89,6 +90,7 @@ proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext = registerAdditionalOps(result) # captured vars: + let conf = graph.config var errorMsg: string var vthisDir = scriptName.splitFile.dir @@ -152,13 +154,25 @@ proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext = cbconf thisDir: setResult(a, vthisDir) 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: - 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: - 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: - setResult(a, compiler_options.getNimcacheDir()) + when declared(NimCompilerApiVersion): + setResult(a, compiler_options.getNimcacheDir(conf)) + else: + setResult(a, compiler_options.getNimcacheDir()) cbconf paramStr: setResult(a, os.paramStr(int a.getInt 0)) cbconf paramCount: @@ -168,16 +182,29 @@ proc setupVM(module: PSym; scriptName: string, flags: Flags): PEvalContext = cbconf cmpIgnoreCase: setResult(a, strutils.cmpIgnoreCase(a.getString 0, a.getString 1)) cbconf setCommand: - 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 + when declared(NimCompilerApiVersion): + conf.command = a.getString 0 + let arg = a.getString 1 + if arg.len > 0: + conf.projectName = arg + try: + conf.projectFull = canonicalizePath(conf, conf.projectPath / conf.projectName) + 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: - setResult(a, compiler_options.command) + when declared(NimCompilerApiVersion): + setResult(a, conf.command) + else: + setResult(a, compiler_options.command) cbconf switch: if not flags.isNil: let @@ -248,7 +275,13 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym = ## Executes the specified script. Returns the script's module symbol. ## ## 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: if "nimblepkg/nimscriptapi" notin compiler_options.implicitIncludes: 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") # Ensure the compiler can find its standard library #220. - compiler_options.gPrefixDir = getNimPrefixDir(options) - display("Setting", "Nim stdlib prefix to " & compiler_options.gPrefixDir, - priority=LowPriority) + when declared(NimCompilerApiVersion): + conf.prefixDir = getNimPrefixDir(options) + display("Setting", "Nim stdlib prefix to " & conf.prefixDir, + priority=LowPriority) - # Verify that lib path points to existing stdlib. - compiler_options.setDefaultLibpath() - display("Setting", "Nim stdlib path to " & compiler_options.libpath, + template myLibPath(): untyped = conf.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) - if not isValidLibPath(compiler_options.libpath): + if not isValidLibPath(myLibPath()): 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, " & "sometimes this fails. You can set the environment variable " & "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 # was compiled with. - let libVersion = getLibVersion(compiler_options.libpath) + let libVersion = getLibVersion(myLibPath()) if NimVersion.newVersion() > libVersion: 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: $#.") % - [compiler_options.libpath, $libVersion, NimVersion] + [myLibPath(), $libVersion, NimVersion] 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 " & "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" createDir(tmpNimscriptApiPath.splitFile.dir) writeFile(tmpNimscriptApiPath, nimscriptApi) - searchPaths.add(t) + when declared(NimCompilerApiVersion): + conf.searchPaths.add(t) + else: + searchPaths.add(t) - initDefines() - loadConfigs(DefaultConfig) - passes.gIncludeFile = includeModule - passes.gImportModule = importModule + when declared(NimCompilerApiVersion): + initDefines(conf.symbols) + loadConfigs(DefaultConfig, conf) + passes.gIncludeFile = includeModule + passes.gImportModule = importModule - defineSymbol("nimscript") - defineSymbol("nimconfig") - defineSymbol("nimble") - registerPass(semPass) - registerPass(evalPass) + defineSymbol(conf.symbols, "nimscript") + defineSymbol(conf.symbols, "nimconfig") + defineSymbol(conf.symbols, "nimble") + registerPass(semPass) + 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): result = makeModule(scriptName) else: - graph = newModuleGraph() result = graph.makeModule(scriptName) incl(result.flags, sfMainModule) - vm.globalCtx = setupVM(result, scriptName, flags) + vm.globalCtx = setupVM(graph, result, scriptName, flags) # Setup builtins defined in nimscriptapi.nim template cbApi(name, body) {.dirty.} = @@ -342,17 +404,30 @@ proc execScript(scriptName: string, flags: Flags, options: Options): PSym = proc cleanup() = # ensure everything can be called again: - compiler_options.gProjectName = "" - compiler_options.command = "" - when declared(resetAllModulesHard): + when declared(NimCompilerApiVersion): + let conf = graph.config + conf.projectName = "" + conf.command = "" + else: + compiler_options.gProjectName = "" + compiler_options.command = "" + when declared(NimCompilerApiVersion): + resetSystemArtifacts(graph) + elif declared(resetAllModulesHard): resetAllModulesHard() else: resetSystemArtifacts() clearPasses() - msgs.gErrorMax = 1 - msgs.writeLnHook = nil - vm.globalCtx = nil - initDefines() + when declared(NimCompilerApiVersion): + conf.errorMax = 1 + msgs.writeLnHook = nil + vm.globalCtx = nil + initDefines(conf.symbols) + else: + msgs.gErrorMax = 1 + msgs.writeLnHook = nil + vm.globalCtx = nil + initDefines() proc readPackageInfoFromNims*(scriptName: string, options: Options, result: var PackageInfo) = @@ -360,12 +435,21 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options, ## that it populates. # 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 = "" msgs.writeLnHook = proc (output: string) = # The error counter is incremented after the writeLnHook is invoked. - if msgs.gErrorCounter > 0: + if errCounter() > 0: raise newException(NimbleError, previousMsg) elif previousMsg.len > 0: display("Info", previousMsg, priority = MediumPriority) @@ -373,7 +457,10 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options, raise newException(NimbleError, output) previousMsg = output - compiler_options.command = internalCmd + when declared(NimCompilerApiVersion): + conf.command = internalCmd + else: + compiler_options.command = internalCmd # Execute the nimscript file. let thisModule = execScript(scriptName, nil, options) @@ -390,7 +477,7 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options, doAssert apiModule != nil # Check whether an error has occurred. - if msgs.gErrorCounter > 0: + if errCounter() > 0: raise newException(NimbleError, previousMsg) # Extract all the necessary fields populated by the nimscript file. @@ -448,6 +535,13 @@ proc readPackageInfoFromNims*(scriptName: string, options: Options, 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, options: Options): ExecutionResult[void] = ## 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. result.success = true 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], priority = HighPriority) @@ -468,9 +564,9 @@ proc execTask*(scriptName, taskName: string, discard vm.globalCtx.execProc(prc, []) # Read the command, arguments and flags set by the executed task. - result.command = compiler_options.command + result.command = nimCommand() result.arguments = @[] - for arg in compiler_options.gProjectName.split(): + for arg in nimProjectName().split(): result.arguments.add(arg) cleanup() @@ -481,9 +577,11 @@ proc execHook*(scriptName, actionName: string, before: bool, ## the "before" or the "after" hook. ## ## `scriptName` should be a filename pointing to the nimscript file. + when declared(NimCompilerApiVersion): + let conf = graph.config result.success = true result.flags = newTable[string, seq[string]]() - compiler_options.command = internalCmd + nimCommand() = internalCmd let hookName = if before: actionName.toLowerAscii & "Before" else: actionName.toLowerAscii & "After" @@ -505,18 +603,22 @@ proc execHook*(scriptName, actionName: string, before: bool, else: assert false # Read the command, arguments and flags set by the executed task. - result.command = compiler_options.command + result.command = nimCommand() result.arguments = @[] - for arg in compiler_options.gProjectName.split(): + for arg in nimProjectName().split(): result.arguments.add(arg) cleanup() proc getNimScriptCommand(): string = - compiler_options.command + when declared(NimCompilerApiVersion): + let conf = graph.config + nimCommand() proc setNimScriptCommand(command: string) = - compiler_options.command = command + when declared(NimCompilerApiVersion): + let conf = graph.config + nimCommand() = command proc hasTaskRequestedCommand*(execResult: ExecutionResult): bool = ## Determines whether the last executed task used ``setCommand``