summary refs log tree commit diff stats
path: root/compiler/scriptconfig.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/scriptconfig.nim')
-rw-r--r--compiler/scriptconfig.nim119
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()