mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
241 lines
7.5 KiB
Nim
241 lines
7.5 KiB
Nim
#
|
|
#
|
|
# 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, idents, condsyms,
|
|
options, llstream, vm, vmdef, commands,
|
|
os, times, osproc, wordrecg, strtabs, modulegraphs,
|
|
pathutils, pipelines
|
|
|
|
when defined(nimPreviewSlimSystem):
|
|
import std/syncio
|
|
|
|
# we support 'cmpIgnoreStyle' natively for efficiency:
|
|
from strutils import cmpIgnoreStyle, contains
|
|
|
|
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; cache: IdentCache; scriptName: string;
|
|
graph: ModuleGraph; idgen: IdGenerator): PEvalContext =
|
|
# For Nimble we need to export 'setupVM'.
|
|
result = newCtx(module, cache, graph, idgen)
|
|
result.mode = emRepl
|
|
registerAdditionalOps(result)
|
|
let conf = graph.config
|
|
|
|
# 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 cbexc(name, exc, body) {.dirty.} =
|
|
result.registerCallback "stdlib.system." & astToStr(name),
|
|
proc (a: VmArgs) =
|
|
errorMsg = ""
|
|
try:
|
|
body
|
|
except exc:
|
|
errorMsg = getCurrentExceptionMsg()
|
|
|
|
template cbos(name, body) {.dirty.} =
|
|
cbexc(name, OSError, body)
|
|
|
|
# Idea: Treat link to file as a file, but ignore link to directory to prevent
|
|
# endless recursions out of the box.
|
|
cbos listFilesImpl:
|
|
listDirs(a, {pcFile, pcLinkToFile})
|
|
cbos listDirsImpl:
|
|
listDirs(a, {pcDir})
|
|
cbos removeDir:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
os.removeDir(getString(a, 0), getBool(a, 1))
|
|
cbos removeFile:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
os.removeFile getString(a, 0)
|
|
cbos createDir:
|
|
os.createDir getString(a, 0)
|
|
|
|
result.registerCallback "stdlib.system.getError",
|
|
proc (a: VmArgs) = setResult(a, errorMsg)
|
|
|
|
cbos setCurrentDir:
|
|
os.setCurrentDir getString(a, 0)
|
|
cbos getCurrentDir:
|
|
setResult(a, os.getCurrentDir())
|
|
cbos moveFile:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
os.moveFile(getString(a, 0), getString(a, 1))
|
|
cbos moveDir:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
os.moveDir(getString(a, 0), getString(a, 1))
|
|
cbos copyFile:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
os.copyFile(getString(a, 0), getString(a, 1))
|
|
cbos copyDir:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
os.copyDir(getString(a, 0), getString(a, 1))
|
|
cbos getLastModificationTime:
|
|
setResult(a, getLastModificationTime(getString(a, 0)).toUnix)
|
|
cbos findExe:
|
|
setResult(a, os.findExe(getString(a, 0)))
|
|
|
|
cbos rawExec:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
discard
|
|
else:
|
|
setResult(a, osproc.execCmd getString(a, 0))
|
|
|
|
cbconf getEnv:
|
|
setResult(a, os.getEnv(a.getString 0, a.getString 1))
|
|
cbconf existsEnv:
|
|
setResult(a, os.existsEnv(a.getString 0))
|
|
cbconf putEnv:
|
|
os.putEnv(a.getString 0, a.getString 1)
|
|
cbconf delEnv:
|
|
os.delEnv(a.getString 0)
|
|
cbconf dirExists:
|
|
setResult(a, os.dirExists(a.getString 0))
|
|
cbconf fileExists:
|
|
setResult(a, os.fileExists(a.getString 0))
|
|
|
|
cbconf projectName:
|
|
setResult(a, conf.projectName)
|
|
cbconf projectDir:
|
|
setResult(a, conf.projectPath.string)
|
|
cbconf projectPath:
|
|
setResult(a, conf.projectFull.string)
|
|
cbconf thisDir:
|
|
setResult(a, vthisDir)
|
|
cbconf put:
|
|
options.setConfigVar(conf, getString(a, 0), getString(a, 1))
|
|
cbconf get:
|
|
setResult(a, options.getConfigVar(conf, a.getString 0))
|
|
cbconf exists:
|
|
setResult(a, options.existsConfigVar(conf, a.getString 0))
|
|
cbconf nimcacheDir:
|
|
setResult(a, options.getNimcacheDir(conf).string)
|
|
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 cmpIgnoreCase:
|
|
setResult(a, strutils.cmpIgnoreCase(a.getString 0, a.getString 1))
|
|
cbconf setCommand:
|
|
conf.setCommandEarly(a.getString 0)
|
|
let arg = a.getString 1
|
|
incl(conf.globalOptions, optWasNimscript)
|
|
if arg.len > 0: setFromProjectName(conf, arg)
|
|
cbconf getCommand:
|
|
setResult(a, conf.command)
|
|
cbconf switch:
|
|
processSwitch(a.getString 0, a.getString 1, passPP, module.info, conf)
|
|
cbconf hintImpl:
|
|
processSpecificNote(a.getString 0, wHint, passPP, module.info,
|
|
a.getString 1, conf)
|
|
cbconf warningImpl:
|
|
processSpecificNote(a.getString 0, wWarning, passPP, module.info,
|
|
a.getString 1, conf)
|
|
cbconf patchFile:
|
|
let key = a.getString(0) & "_" & a.getString(1)
|
|
var val = a.getString(2).addFileExt(NimExt)
|
|
if {'$', '~'} in val:
|
|
val = pathSubs(conf, val, vthisDir)
|
|
elif not isAbsolute(val):
|
|
val = vthisDir / val
|
|
conf.moduleOverrides[key] = val
|
|
cbconf selfExe:
|
|
setResult(a, os.getAppFilename())
|
|
cbconf cppDefine:
|
|
options.cppDefine(conf, a.getString(0))
|
|
cbexc stdinReadLine, EOFError:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
setResult(a, "")
|
|
else:
|
|
setResult(a, stdin.readLine())
|
|
cbexc stdinReadAll, EOFError:
|
|
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
|
setResult(a, "")
|
|
else:
|
|
setResult(a, stdin.readAll())
|
|
|
|
proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
|
idgen: IdGenerator;
|
|
freshDefines=true; conf: ConfigRef, stream: PLLStream) =
|
|
let oldSymbolFiles = conf.symbolFiles
|
|
conf.symbolFiles = disabledSf
|
|
|
|
let graph = newModuleGraph(cache, conf)
|
|
connectPipelineCallbacks(graph)
|
|
if freshDefines: initDefines(conf.symbols)
|
|
|
|
defineSymbol(conf.symbols, "nimscript")
|
|
defineSymbol(conf.symbols, "nimconfig")
|
|
|
|
conf.searchPaths.add(conf.libpath)
|
|
|
|
let oldGlobalOptions = conf.globalOptions
|
|
let oldSelectedGC = conf.selectedGC
|
|
undefSymbol(conf.symbols, "nimv2")
|
|
conf.globalOptions.excl {optTinyRtti, optOwnedRefs, optSeqDestructors}
|
|
conf.selectedGC = gcUnselected
|
|
|
|
var m = graph.makeModule(scriptName)
|
|
incl(m.flags, sfMainModule)
|
|
var vm = setupVM(m, cache, scriptName.string, graph, idgen)
|
|
graph.vm = vm
|
|
|
|
graph.setPipeLinePass(EvalPass)
|
|
graph.compilePipelineSystemModule()
|
|
discard graph.processPipelineModule(m, vm.idgen, stream)
|
|
|
|
# watch out, "newruntime" can be set within NimScript itself and then we need
|
|
# to remember this:
|
|
if conf.selectedGC == gcUnselected:
|
|
conf.selectedGC = oldSelectedGC
|
|
if optOwnedRefs in oldGlobalOptions:
|
|
conf.globalOptions.incl {optTinyRtti, optOwnedRefs, optSeqDestructors}
|
|
defineSymbol(conf.symbols, "nimv2")
|
|
if conf.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
|
|
conf.globalOptions.incl {optTinyRtti, optSeqDestructors}
|
|
defineSymbol(conf.symbols, "nimv2")
|
|
|
|
# ensure we load 'system.nim' again for the real non-config stuff!
|
|
resetSystemArtifacts(graph)
|
|
# do not remove the defined symbols
|
|
#initDefines()
|
|
undefSymbol(conf.symbols, "nimscript")
|
|
undefSymbol(conf.symbols, "nimconfig")
|
|
conf.symbolFiles = oldSymbolFiles
|