diff options
Diffstat (limited to 'compiler/scriptconfig.nim')
-rw-r--r-- | compiler/scriptconfig.nim | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim new file mode 100644 index 000000000..1e4fc25af --- /dev/null +++ b/compiler/scriptconfig.nim @@ -0,0 +1,119 @@ +# +# +# The Nim Compiler +# (c) Copyright 2015 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Implements the new configuration system for Nim. Uses Nim as a scripting +## language. + +import + ast, modules, passes, passaux, condsyms, + options, nimconf, lists, sem, semdata, llstream, vm, vmdef, commands, msgs, + os, times + +# we support 'cmpIgnoreStyle' natively for efficiency: +from strutils import cmpIgnoreStyle + +proc listDirs(a: VmArgs, filter: set[PathComponent]) = + let dir = getString(a, 0) + var result: seq[string] = @[] + for kind, path in walkDir(dir): + if kind in filter: result.add path + setResult(a, result) + +proc setupVM(module: PSym; scriptName: string): PEvalContext = + result = newCtx(module) + result.mode = emRepl + registerAdditionalOps(result) + + # captured vars: + var errorMsg: string + var vthisDir = scriptName.splitFile.dir + + template cbconf(name, body) {.dirty.} = + result.registerCallback "stdlib.system." & astToStr(name), + proc (a: VmArgs) = + body + + template cbos(name, body) {.dirty.} = + result.registerCallback "stdlib.system." & astToStr(name), + proc (a: VmArgs) = + try: + body + except OSError: + errorMsg = getCurrentExceptionMsg() + + # Idea: Treat link to file as a file, but ignore link to directory to prevent + # endless recursions out of the box. + cbos listFiles: + listDirs(a, {pcFile, pcLinkToFile}) + cbos listDirs: + listDirs(a, {pcDir}) + cbos removeDir: + os.removeDir getString(a, 0) + cbos removeFile: + os.removeFile getString(a, 0) + cbos createDir: + os.createDir getString(a, 0) + cbos getOsError: + setResult(a, errorMsg) + cbos setCurrentDir: + os.setCurrentDir getString(a, 0) + cbos getCurrentDir: + setResult(a, os.getCurrentDir()) + cbos moveFile: + os.moveFile(getString(a, 0), getString(a, 1)) + cbos getLastModificationTime: + setResult(a, toSeconds(getLastModificationTime(getString(a, 0)))) + + cbconf thisDir: + setResult(a, vthisDir) + cbconf put: + options.setConfigVar(getString(a, 0), getString(a, 1)) + cbconf get: + setResult(a, options.getConfigVar(a.getString 0)) + cbconf exists: + setResult(a, options.existsConfigVar(a.getString 0)) + cbconf nimcacheDir: + setResult(a, options.getNimcacheDir()) + cbconf paramStr: + setResult(a, os.paramStr(int a.getInt 0)) + cbconf paramCount: + setResult(a, os.paramCount()) + cbconf cmpIgnoreStyle: + setResult(a, strutils.cmpIgnoreStyle(a.getString 0, a.getString 1)) + cbconf setCommand: + options.command = a.getString 0 + cbconf getCommand: + setResult(a, options.command) + cbconf switch: + processSwitch(a.getString 0, a.getString 1, passPP, unknownLineInfo()) + + +proc runNimScript*(scriptName: string) = + passes.gIncludeFile = includeModule + passes.gImportModule = importModule + initDefines() + + defineSymbol("nimscript") + defineSymbol("nimconfig") + registerPass(semPass) + registerPass(evalPass) + + appendStr(searchPaths, options.libpath) + + var m = makeModule(scriptName) + incl(m.flags, sfMainModule) + vm.globalCtx = setupVM(m, scriptName) + + compileSystemModule() + processModule(m, llStreamOpen(scriptName, fmRead), nil) + + # ensure we load 'system.nim' again for the real non-config stuff! + resetAllModulesHard() + vm.globalCtx = nil + initDefines() |