diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/commands.nim | 2 | ||||
-rw-r--r-- | compiler/main.nim | 3 | ||||
-rw-r--r-- | compiler/modules.nim | 20 | ||||
-rw-r--r-- | compiler/nim.nim | 9 | ||||
-rw-r--r-- | compiler/options.nim | 6 | ||||
-rw-r--r-- | compiler/scriptconfig.nim | 119 | ||||
-rw-r--r-- | compiler/vm.nim | 4 | ||||
-rw-r--r-- | compiler/vmhooks.nim | 12 |
8 files changed, 159 insertions, 16 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index 7a908b270..fc28577aa 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -641,7 +641,7 @@ proc processSwitch*(pass: TCmdLinePass; p: OptParser) = proc processArgument*(pass: TCmdLinePass; p: OptParser; argsCount: var int): bool = if argsCount == 0: - options.command = p.key + if pass != passCmd2: options.command = p.key else: if pass == passCmd1: options.commandArgs.add p.key if argsCount == 1: diff --git a/compiler/main.nim b/compiler/main.nim index 47fae7fa7..014605cc9 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -116,7 +116,7 @@ proc interactivePasses = #incl(gGlobalOptions, optSafeCode) #setTarget(osNimrodVM, cpuNimrodVM) initDefines() - defineSymbol("nimrodvm") + defineSymbol("nimscript") when hasFFI: defineSymbol("nimffi") registerPass(verbosePass) registerPass(semPass) @@ -356,6 +356,7 @@ proc mainCommand* = gGlobalOptions.incl(optCaasEnabled) msgs.gErrorMax = high(int) # do not stop after first error serve(mainCommand) + of "nop": discard else: rawMessage(errInvalidCommandX, command) diff --git a/compiler/modules.nim b/compiler/modules.nim index 2d0267c93..ad68e6315 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -85,6 +85,15 @@ proc resetAllModules* = resetPackageCache() # for m in cgenModules(): echo "CGEN MODULE FOUND" +proc resetAllModulesHard* = + resetPackageCache() + gCompiledModules.setLen 0 + gMemCacheData.setLen 0 + magicsys.resetSysTypes() + # XXX + #gOwners = @[] + #rangeDestructorProc = nil + proc checkDepMem(fileIdx: int32): TNeedRecompile = template markDirty = resetModule(fileIdx) @@ -205,9 +214,8 @@ proc compileProject*(projectFileIdx = -1'i32) = compileSystemModule() discard compileModule(projectFile, {sfMainModule}) -var stdinModule: PSym -proc makeStdinModule*(): PSym = - if stdinModule == nil: - stdinModule = newModule(fileInfoIdx"stdin") - stdinModule.id = getID() - result = stdinModule +proc makeModule*(filename: string): PSym = + result = newModule(fileInfoIdx filename) + result.id = getID() + +proc makeStdinModule*(): PSym = makeModule"stdin" diff --git a/compiler/nim.nim b/compiler/nim.nim index ce9028d53..51f4cae92 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -1,7 +1,7 @@ # # # The Nim Compiler -# (c) Copyright 2013 Andreas Rumpf +# (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -16,7 +16,7 @@ when defined(gcc) and defined(windows): import commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, extccomp, strutils, os, osproc, platform, main, parseopt, service, - nodejs + nodejs, scriptconfig when hasTinyCBackend: import tccgen @@ -54,6 +54,11 @@ proc handleCmdLine() = else: gProjectPath = getCurrentDir() loadConfigs(DefaultConfig) # load all config files + let scriptFile = gProjectFull.changeFileExt("nims") + if fileExists(scriptFile): + runNimScript(scriptFile) + # 'nim foo.nims' means to just run the NimScript file and do nothing more: + if scriptFile == gProjectFull: return # now process command line arguments again, because some options in the # command line can overwite the config file's settings extccomp.initVars() diff --git a/compiler/options.nim b/compiler/options.nim index af1e21e60..adf2017d6 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -210,7 +210,7 @@ proc removeTrailingDirSep*(path: string): string = else: result = path -proc getGeneratedPath: string = +proc getNimcacheDir*: string = result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir / genSubDir @@ -266,7 +266,7 @@ proc toGeneratedFile*(path, ext: string): string = ## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod" var (head, tail) = splitPath(path) #if len(head) > 0: head = shortenDir(head & dirSep) - result = joinPath([getGeneratedPath(), changeFileExt(tail, ext)]) + result = joinPath([getNimcacheDir(), changeFileExt(tail, ext)]) #echo "toGeneratedFile(", path, ", ", ext, ") = ", result when noTimeMachine: @@ -294,7 +294,7 @@ when noTimeMachine: proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string = var (head, tail) = splitPath(f) #if len(head) > 0: head = removeTrailingDirSep(shortenDir(head & dirSep)) - var subdir = getGeneratedPath() # / head + var subdir = getNimcacheDir() # / head if createSubDir: try: createDir(subdir) 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() diff --git a/compiler/vm.nim b/compiler/vm.nim index b1d71d73b..57ed8397c 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1407,7 +1407,7 @@ include vmops # storing&loading the 'globals' environment to get what a component system # requires. var - globalCtx: PCtx + globalCtx*: PCtx proc setupGlobalCtx(module: PSym) = if globalCtx.isNil: @@ -1516,7 +1516,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode = # return value: tos.slots[0].kind = rkNode tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0]) - + # setup parameters: for i in 1.. <sym.typ.len: tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i]) diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim index 6ec5f6044..5dd27feda 100644 --- a/compiler/vmhooks.nim +++ b/compiler/vmhooks.nim @@ -17,7 +17,7 @@ template setX(k, field) {.immediate, dirty.} = proc setResult*(a: VmArgs; v: BiggestInt) = setX(rkInt, intVal) proc setResult*(a: VmArgs; v: BiggestFloat) = setX(rkFloat, floatVal) -proc setResult*(a: VmArgs; v: bool) = +proc setResult*(a: VmArgs; v: bool) = let v = v.ord setX(rkInt, intVal) @@ -30,6 +30,16 @@ proc setResult*(a: VmArgs; v: string) = s[a.ra].node = newNode(nkStrLit) s[a.ra].node.strVal = v +proc setResult*(a: VmArgs; v: seq[string]) = + var s: seq[TFullReg] + move(s, cast[seq[TFullReg]](a.slots)) + if s[a.ra].kind != rkNode: + myreset(s[a.ra]) + s[a.ra].kind = rkNode + var n = newNode(nkBracket) + for x in v: n.add newStrNode(nkStrLit, x) + s[a.ra].node = n + template getX(k, field) {.immediate, dirty.} = doAssert i < a.rc-1 let s = cast[seq[TFullReg]](a.slots) |