implements experimental new config system based on NimScript
This commit is contained in:
parent
d81578cb9b
commit
69b32637b1
13 changed files with 398 additions and 69 deletions
|
|
@ -641,7 +641,7 @@ proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
|
||||||
proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
||||||
argsCount: var int): bool =
|
argsCount: var int): bool =
|
||||||
if argsCount == 0:
|
if argsCount == 0:
|
||||||
options.command = p.key
|
if pass != passCmd2: options.command = p.key
|
||||||
else:
|
else:
|
||||||
if pass == passCmd1: options.commandArgs.add p.key
|
if pass == passCmd1: options.commandArgs.add p.key
|
||||||
if argsCount == 1:
|
if argsCount == 1:
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ proc interactivePasses =
|
||||||
#incl(gGlobalOptions, optSafeCode)
|
#incl(gGlobalOptions, optSafeCode)
|
||||||
#setTarget(osNimrodVM, cpuNimrodVM)
|
#setTarget(osNimrodVM, cpuNimrodVM)
|
||||||
initDefines()
|
initDefines()
|
||||||
defineSymbol("nimrodvm")
|
defineSymbol("nimscript")
|
||||||
when hasFFI: defineSymbol("nimffi")
|
when hasFFI: defineSymbol("nimffi")
|
||||||
registerPass(verbosePass)
|
registerPass(verbosePass)
|
||||||
registerPass(semPass)
|
registerPass(semPass)
|
||||||
|
|
@ -356,6 +356,7 @@ proc mainCommand* =
|
||||||
gGlobalOptions.incl(optCaasEnabled)
|
gGlobalOptions.incl(optCaasEnabled)
|
||||||
msgs.gErrorMax = high(int) # do not stop after first error
|
msgs.gErrorMax = high(int) # do not stop after first error
|
||||||
serve(mainCommand)
|
serve(mainCommand)
|
||||||
|
of "nop": discard
|
||||||
else:
|
else:
|
||||||
rawMessage(errInvalidCommandX, command)
|
rawMessage(errInvalidCommandX, command)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,15 @@ proc resetAllModules* =
|
||||||
resetPackageCache()
|
resetPackageCache()
|
||||||
# for m in cgenModules(): echo "CGEN MODULE FOUND"
|
# 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 =
|
proc checkDepMem(fileIdx: int32): TNeedRecompile =
|
||||||
template markDirty =
|
template markDirty =
|
||||||
resetModule(fileIdx)
|
resetModule(fileIdx)
|
||||||
|
|
@ -205,9 +214,8 @@ proc compileProject*(projectFileIdx = -1'i32) =
|
||||||
compileSystemModule()
|
compileSystemModule()
|
||||||
discard compileModule(projectFile, {sfMainModule})
|
discard compileModule(projectFile, {sfMainModule})
|
||||||
|
|
||||||
var stdinModule: PSym
|
proc makeModule*(filename: string): PSym =
|
||||||
proc makeStdinModule*(): PSym =
|
result = newModule(fileInfoIdx filename)
|
||||||
if stdinModule == nil:
|
result.id = getID()
|
||||||
stdinModule = newModule(fileInfoIdx"stdin")
|
|
||||||
stdinModule.id = getID()
|
proc makeStdinModule*(): PSym = makeModule"stdin"
|
||||||
result = stdinModule
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nim Compiler
|
# The Nim Compiler
|
||||||
# (c) Copyright 2013 Andreas Rumpf
|
# (c) Copyright 2015 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -16,7 +16,7 @@ when defined(gcc) and defined(windows):
|
||||||
import
|
import
|
||||||
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
|
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
|
||||||
extccomp, strutils, os, osproc, platform, main, parseopt, service,
|
extccomp, strutils, os, osproc, platform, main, parseopt, service,
|
||||||
nodejs
|
nodejs, scriptconfig
|
||||||
|
|
||||||
when hasTinyCBackend:
|
when hasTinyCBackend:
|
||||||
import tccgen
|
import tccgen
|
||||||
|
|
@ -54,6 +54,11 @@ proc handleCmdLine() =
|
||||||
else:
|
else:
|
||||||
gProjectPath = getCurrentDir()
|
gProjectPath = getCurrentDir()
|
||||||
loadConfigs(DefaultConfig) # load all config files
|
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
|
# now process command line arguments again, because some options in the
|
||||||
# command line can overwite the config file's settings
|
# command line can overwite the config file's settings
|
||||||
extccomp.initVars()
|
extccomp.initVars()
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ proc removeTrailingDirSep*(path: string): string =
|
||||||
else:
|
else:
|
||||||
result = path
|
result = path
|
||||||
|
|
||||||
proc getGeneratedPath: string =
|
proc getNimcacheDir*: string =
|
||||||
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
result = if nimcacheDir.len > 0: nimcacheDir else: gProjectPath.shortenDir /
|
||||||
genSubDir
|
genSubDir
|
||||||
|
|
||||||
|
|
@ -266,7 +266,7 @@ proc toGeneratedFile*(path, ext: string): string =
|
||||||
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
||||||
var (head, tail) = splitPath(path)
|
var (head, tail) = splitPath(path)
|
||||||
#if len(head) > 0: head = shortenDir(head & dirSep)
|
#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
|
#echo "toGeneratedFile(", path, ", ", ext, ") = ", result
|
||||||
|
|
||||||
when noTimeMachine:
|
when noTimeMachine:
|
||||||
|
|
@ -294,7 +294,7 @@ when noTimeMachine:
|
||||||
proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
|
proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
|
||||||
var (head, tail) = splitPath(f)
|
var (head, tail) = splitPath(f)
|
||||||
#if len(head) > 0: head = removeTrailingDirSep(shortenDir(head & dirSep))
|
#if len(head) > 0: head = removeTrailingDirSep(shortenDir(head & dirSep))
|
||||||
var subdir = getGeneratedPath() # / head
|
var subdir = getNimcacheDir() # / head
|
||||||
if createSubDir:
|
if createSubDir:
|
||||||
try:
|
try:
|
||||||
createDir(subdir)
|
createDir(subdir)
|
||||||
|
|
|
||||||
119
compiler/scriptconfig.nim
Normal file
119
compiler/scriptconfig.nim
Normal file
|
|
@ -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()
|
||||||
|
|
@ -1407,7 +1407,7 @@ include vmops
|
||||||
# storing&loading the 'globals' environment to get what a component system
|
# storing&loading the 'globals' environment to get what a component system
|
||||||
# requires.
|
# requires.
|
||||||
var
|
var
|
||||||
globalCtx: PCtx
|
globalCtx*: PCtx
|
||||||
|
|
||||||
proc setupGlobalCtx(module: PSym) =
|
proc setupGlobalCtx(module: PSym) =
|
||||||
if globalCtx.isNil:
|
if globalCtx.isNil:
|
||||||
|
|
@ -1516,7 +1516,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||||
# return value:
|
# return value:
|
||||||
tos.slots[0].kind = rkNode
|
tos.slots[0].kind = rkNode
|
||||||
tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
|
tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
|
||||||
|
|
||||||
# setup parameters:
|
# setup parameters:
|
||||||
for i in 1.. <sym.typ.len:
|
for i in 1.. <sym.typ.len:
|
||||||
tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i])
|
tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i])
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ template setX(k, field) {.immediate, dirty.} =
|
||||||
|
|
||||||
proc setResult*(a: VmArgs; v: BiggestInt) = setX(rkInt, intVal)
|
proc setResult*(a: VmArgs; v: BiggestInt) = setX(rkInt, intVal)
|
||||||
proc setResult*(a: VmArgs; v: BiggestFloat) = setX(rkFloat, floatVal)
|
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
|
let v = v.ord
|
||||||
setX(rkInt, intVal)
|
setX(rkInt, intVal)
|
||||||
|
|
||||||
|
|
@ -30,6 +30,16 @@ proc setResult*(a: VmArgs; v: string) =
|
||||||
s[a.ra].node = newNode(nkStrLit)
|
s[a.ra].node = newNode(nkStrLit)
|
||||||
s[a.ra].node.strVal = v
|
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.} =
|
template getX(k, field) {.immediate, dirty.} =
|
||||||
doAssert i < a.rc-1
|
doAssert i < a.rc-1
|
||||||
let s = cast[seq[TFullReg]](a.slots)
|
let s = cast[seq[TFullReg]](a.slots)
|
||||||
|
|
|
||||||
108
lib/system.nim
108
lib/system.nim
|
|
@ -190,9 +190,9 @@ proc new*(T: typedesc): auto =
|
||||||
## When ``T`` is a ref type then the resulting type will be ``T``,
|
## When ``T`` is a ref type then the resulting type will be ``T``,
|
||||||
## otherwise it will be ``ref T``.
|
## otherwise it will be ``ref T``.
|
||||||
when (T is ref):
|
when (T is ref):
|
||||||
var r: T
|
var r: T
|
||||||
else:
|
else:
|
||||||
var r: ref T
|
var r: ref T
|
||||||
new(r)
|
new(r)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
@ -347,7 +347,7 @@ const
|
||||||
|
|
||||||
include "system/inclrtl"
|
include "system/inclrtl"
|
||||||
|
|
||||||
const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
|
const NoFakeVars* = defined(nimscript) ## true if the backend doesn't support \
|
||||||
## "fake variables" like 'var EBADF {.importc.}: cint'.
|
## "fake variables" like 'var EBADF {.importc.}: cint'.
|
||||||
|
|
||||||
const ArrayDummySize = when defined(cpu16): 10_000 else: 100_000_000
|
const ArrayDummySize = when defined(cpu16): 10_000 else: 100_000_000
|
||||||
|
|
@ -365,7 +365,7 @@ when not defined(JS):
|
||||||
data: UncheckedCharArray
|
data: UncheckedCharArray
|
||||||
NimString = ptr NimStringDesc
|
NimString = ptr NimStringDesc
|
||||||
|
|
||||||
when not defined(JS) and not defined(NimrodVM):
|
when not defined(JS) and not defined(nimscript):
|
||||||
template space(s: PGenericSeq): int {.dirty.} =
|
template space(s: PGenericSeq): int {.dirty.} =
|
||||||
s.reserved and not seqShallowFlag
|
s.reserved and not seqShallowFlag
|
||||||
|
|
||||||
|
|
@ -1260,11 +1260,11 @@ template sysAssert(cond: bool, msg: string) =
|
||||||
echo "[SYSASSERT] ", msg
|
echo "[SYSASSERT] ", msg
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
const hasAlloc = hostOS != "standalone" or not defined(nogc)
|
const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript)
|
||||||
|
|
||||||
when not defined(JS) and not defined(nimrodVm) and hostOS != "standalone":
|
when not defined(JS) and not defined(nimscript) and hostOS != "standalone":
|
||||||
include "system/cgprocs"
|
include "system/cgprocs"
|
||||||
when not defined(JS) and not defined(nimrodVm) and hasAlloc:
|
when not defined(JS) and not defined(nimscript) and hasAlloc:
|
||||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
|
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
|
||||||
proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
|
proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
|
||||||
|
|
||||||
|
|
@ -1445,7 +1445,7 @@ proc substr*(s: string, first, last: int): string {.
|
||||||
## is used instead: This means ``substr`` can also be used to `cut`:idx:
|
## is used instead: This means ``substr`` can also be used to `cut`:idx:
|
||||||
## or `limit`:idx: a string's length.
|
## or `limit`:idx: a string's length.
|
||||||
|
|
||||||
when not defined(nimrodVM):
|
when not defined(nimscript):
|
||||||
proc zeroMem*(p: pointer, size: Natural) {.importc, noDecl, benign.}
|
proc zeroMem*(p: pointer, size: Natural) {.importc, noDecl, benign.}
|
||||||
## overwrites the contents of the memory at ``p`` with the value 0.
|
## overwrites the contents of the memory at ``p`` with the value 0.
|
||||||
## Exactly ``size`` bytes will be overwritten. Like any procedure
|
## Exactly ``size`` bytes will be overwritten. Like any procedure
|
||||||
|
|
@ -1607,7 +1607,7 @@ proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
|
||||||
## The stringify operator for an integer argument. Returns `x`
|
## The stringify operator for an integer argument. Returns `x`
|
||||||
## converted to a decimal string.
|
## converted to a decimal string.
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
when not defined(JS) and hasAlloc:
|
when not defined(JS) and hasAlloc:
|
||||||
proc `$` *(x: uint64): string {.noSideEffect.}
|
proc `$` *(x: uint64): string {.noSideEffect.}
|
||||||
## The stringify operator for an unsigned integer argument. Returns `x`
|
## The stringify operator for an unsigned integer argument. Returns `x`
|
||||||
|
|
@ -1675,7 +1675,7 @@ const
|
||||||
|
|
||||||
# GC interface:
|
# GC interface:
|
||||||
|
|
||||||
when not defined(nimrodVM) and hasAlloc:
|
when not defined(nimscript) and hasAlloc:
|
||||||
proc getOccupiedMem*(): int {.rtl.}
|
proc getOccupiedMem*(): int {.rtl.}
|
||||||
## returns the number of bytes that are owned by the process and hold data.
|
## returns the number of bytes that are owned by the process and hold data.
|
||||||
|
|
||||||
|
|
@ -2016,7 +2016,7 @@ proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
|
||||||
for i in 0..y.len-1:
|
for i in 0..y.len-1:
|
||||||
result[i+1] = y[i]
|
result[i+1] = y[i]
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
when not defined(JS):
|
when not defined(JS):
|
||||||
proc seqToPtr[T](x: seq[T]): pointer {.inline, nosideeffect.} =
|
proc seqToPtr[T](x: seq[T]): pointer {.inline, nosideeffect.} =
|
||||||
result = cast[pointer](x)
|
result = cast[pointer](x)
|
||||||
|
|
@ -2235,7 +2235,7 @@ when false:
|
||||||
|
|
||||||
# ----------------- GC interface ---------------------------------------------
|
# ----------------- GC interface ---------------------------------------------
|
||||||
|
|
||||||
when not defined(nimrodVM) and hasAlloc:
|
when not defined(nimscript) and hasAlloc:
|
||||||
proc GC_disable*() {.rtl, inl, benign.}
|
proc GC_disable*() {.rtl, inl, benign.}
|
||||||
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
|
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
|
||||||
## reactivate the GC. Note that in most circumstances one should only disable
|
## reactivate the GC. Note that in most circumstances one should only disable
|
||||||
|
|
@ -2457,10 +2457,10 @@ else:
|
||||||
if x < 0: -x else: x
|
if x < 0: -x else: x
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
when not defined(JS): #and not defined(NimrodVM):
|
when not defined(JS): #and not defined(nimscript):
|
||||||
{.push stack_trace: off, profiler:off.}
|
{.push stack_trace: off, profiler:off.}
|
||||||
|
|
||||||
when not defined(NimrodVM) and not defined(nogc):
|
when not defined(nimscript) and not defined(nogc):
|
||||||
proc initGC()
|
proc initGC()
|
||||||
when not defined(boehmgc) and not defined(useMalloc) and not defined(gogc):
|
when not defined(boehmgc) and not defined(useMalloc) and not defined(gogc):
|
||||||
proc initAllocator() {.inline.}
|
proc initAllocator() {.inline.}
|
||||||
|
|
@ -2488,13 +2488,19 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
strDesc.kind = tyString
|
strDesc.kind = tyString
|
||||||
strDesc.flags = {ntfAcyclic}
|
strDesc.flags = {ntfAcyclic}
|
||||||
|
|
||||||
include "system/ansi_c"
|
when not defined(nimscript):
|
||||||
|
include "system/ansi_c"
|
||||||
|
|
||||||
proc cmp(x, y: string): int =
|
proc cmp(x, y: string): int =
|
||||||
result = int(c_strcmp(x, y))
|
result = int(c_strcmp(x, y))
|
||||||
|
else:
|
||||||
|
proc cmp(x, y: string): int =
|
||||||
|
if x < y: result = -1
|
||||||
|
elif x > y: result = 1
|
||||||
|
else: result = 0
|
||||||
|
|
||||||
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
|
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
# work-around C's sucking abstraction:
|
# work-around C's sucking abstraction:
|
||||||
# BUGFIX: stdin and stdout should be binary files!
|
# BUGFIX: stdin and stdout should be binary files!
|
||||||
|
|
@ -2536,14 +2542,15 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
|
|
||||||
{.deprecated: [TFile: File, TFileHandle: FileHandle, TFileMode: FileMode].}
|
{.deprecated: [TFile: File, TFileHandle: FileHandle, TFileMode: FileMode].}
|
||||||
|
|
||||||
# text file handling:
|
when not defined(nimscript):
|
||||||
var
|
# text file handling:
|
||||||
stdin* {.importc: "stdin", header: "<stdio.h>".}: File
|
var
|
||||||
## The standard input stream.
|
stdin* {.importc: "stdin", header: "<stdio.h>".}: File
|
||||||
stdout* {.importc: "stdout", header: "<stdio.h>".}: File
|
## The standard input stream.
|
||||||
## The standard output stream.
|
stdout* {.importc: "stdout", header: "<stdio.h>".}: File
|
||||||
stderr* {.importc: "stderr", header: "<stdio.h>".}: File
|
## The standard output stream.
|
||||||
## The standard error stream.
|
stderr* {.importc: "stderr", header: "<stdio.h>".}: File
|
||||||
|
## The standard error stream.
|
||||||
|
|
||||||
when defined(useStdoutAsStdmsg):
|
when defined(useStdoutAsStdmsg):
|
||||||
template stdmsg*: File = stdout
|
template stdmsg*: File = stdout
|
||||||
|
|
@ -2738,7 +2745,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
inc(i)
|
inc(i)
|
||||||
dealloc(a)
|
dealloc(a)
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
proc atomicInc*(memLoc: var int, x: int = 1): int {.inline,
|
proc atomicInc*(memLoc: var int, x: int = 1): int {.inline,
|
||||||
discardable, benign.}
|
discardable, benign.}
|
||||||
## atomic increment of `memLoc`. Returns the value after the operation.
|
## atomic increment of `memLoc`. Returns the value after the operation.
|
||||||
|
|
@ -2749,27 +2756,27 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
|
|
||||||
include "system/atomics"
|
include "system/atomics"
|
||||||
|
|
||||||
type
|
type
|
||||||
PSafePoint = ptr TSafePoint
|
PSafePoint = ptr TSafePoint
|
||||||
TSafePoint {.compilerproc, final.} = object
|
TSafePoint {.compilerproc, final.} = object
|
||||||
prev: PSafePoint # points to next safe point ON THE STACK
|
prev: PSafePoint # points to next safe point ON THE STACK
|
||||||
status: int
|
status: int
|
||||||
context: C_JmpBuf
|
context: C_JmpBuf
|
||||||
hasRaiseAction: bool
|
hasRaiseAction: bool
|
||||||
raiseAction: proc (e: ref Exception): bool {.closure.}
|
raiseAction: proc (e: ref Exception): bool {.closure.}
|
||||||
SafePoint = TSafePoint
|
SafePoint = TSafePoint
|
||||||
# {.deprecated: [TSafePoint: SafePoint].}
|
# {.deprecated: [TSafePoint: SafePoint].}
|
||||||
|
|
||||||
when declared(initAllocator):
|
when declared(initAllocator):
|
||||||
initAllocator()
|
initAllocator()
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
include "system/syslocks"
|
include "system/syslocks"
|
||||||
when hostOS != "standalone": include "system/threads"
|
when hostOS != "standalone": include "system/threads"
|
||||||
elif not defined(nogc) and not defined(NimrodVM):
|
elif not defined(nogc) and not defined(nimscript):
|
||||||
when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom()
|
when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom()
|
||||||
when declared(initGC): initGC()
|
when declared(initGC): initGC()
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
proc setControlCHook*(hook: proc () {.noconv.} not nil)
|
proc setControlCHook*(hook: proc () {.noconv.} not nil)
|
||||||
## allows you to override the behaviour of your application when CTRL+C
|
## allows you to override the behaviour of your application when CTRL+C
|
||||||
## is pressed. Only one such hook is supported.
|
## is pressed. Only one such hook is supported.
|
||||||
|
|
@ -2798,9 +2805,9 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
{.pop.} # stack trace
|
{.pop.} # stack trace
|
||||||
{.pop.} # stack trace
|
{.pop.} # stack trace
|
||||||
|
|
||||||
when hostOS != "standalone" and not defined(NimrodVM):
|
when hostOS != "standalone" and not defined(nimscript):
|
||||||
include "system/dyncalls"
|
include "system/dyncalls"
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
include "system/sets"
|
include "system/sets"
|
||||||
|
|
||||||
when defined(gogc):
|
when defined(gogc):
|
||||||
|
|
@ -2875,11 +2882,11 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
var res = TaintedString(newStringOfCap(80))
|
var res = TaintedString(newStringOfCap(80))
|
||||||
while f.readLine(res): yield res
|
while f.readLine(res): yield res
|
||||||
|
|
||||||
when not defined(NimrodVM) and hasAlloc:
|
when not defined(nimscript) and hasAlloc:
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
include "system/repr"
|
include "system/repr"
|
||||||
|
|
||||||
when hostOS != "standalone" and not defined(NimrodVM):
|
when hostOS != "standalone" and not defined(nimscript):
|
||||||
proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} =
|
proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} =
|
||||||
## retrieves the current exception; if there is none, nil is returned.
|
## retrieves the current exception; if there is none, nil is returned.
|
||||||
result = currException
|
result = currException
|
||||||
|
|
@ -2907,14 +2914,14 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
currException = exc
|
currException = exc
|
||||||
|
|
||||||
{.push stack_trace: off, profiler:off.}
|
{.push stack_trace: off, profiler:off.}
|
||||||
when defined(endb) and not defined(NimrodVM):
|
when defined(endb) and not defined(nimscript):
|
||||||
include "system/debugger"
|
include "system/debugger"
|
||||||
|
|
||||||
when defined(profiler) or defined(memProfiler):
|
when defined(profiler) or defined(memProfiler):
|
||||||
include "system/profiler"
|
include "system/profiler"
|
||||||
{.pop.} # stacktrace
|
{.pop.} # stacktrace
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(nimscript):
|
||||||
proc likely*(val: bool): bool {.importc: "likely", nodecl, nosideeffect.}
|
proc likely*(val: bool): bool {.importc: "likely", nodecl, nosideeffect.}
|
||||||
## Hints the optimizer that `val` is likely going to be true.
|
## Hints the optimizer that `val` is likely going to be true.
|
||||||
##
|
##
|
||||||
|
|
@ -2992,7 +2999,7 @@ elif defined(JS):
|
||||||
when defined(JS):
|
when defined(JS):
|
||||||
include "system/jssys"
|
include "system/jssys"
|
||||||
include "system/reprjs"
|
include "system/reprjs"
|
||||||
elif defined(NimrodVM):
|
elif defined(nimscript):
|
||||||
proc cmp(x, y: string): int =
|
proc cmp(x, y: string): int =
|
||||||
if x == y: return 0
|
if x == y: return 0
|
||||||
if x < y: return -1
|
if x < y: return -1
|
||||||
|
|
@ -3305,7 +3312,7 @@ proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
|
||||||
## marks a sequence `s` as `shallow`:idx:. Subsequent assignments will not
|
## marks a sequence `s` as `shallow`:idx:. Subsequent assignments will not
|
||||||
## perform deep copies of `s`. This is only useful for optimization
|
## perform deep copies of `s`. This is only useful for optimization
|
||||||
## purposes.
|
## purposes.
|
||||||
when not defined(JS) and not defined(NimrodVM):
|
when not defined(JS) and not defined(nimscript):
|
||||||
var s = cast[PGenericSeq](s)
|
var s = cast[PGenericSeq](s)
|
||||||
s.reserved = s.reserved or seqShallowFlag
|
s.reserved = s.reserved or seqShallowFlag
|
||||||
|
|
||||||
|
|
@ -3313,7 +3320,7 @@ proc shallow*(s: var string) {.noSideEffect, inline.} =
|
||||||
## marks a string `s` as `shallow`:idx:. Subsequent assignments will not
|
## marks a string `s` as `shallow`:idx:. Subsequent assignments will not
|
||||||
## perform deep copies of `s`. This is only useful for optimization
|
## perform deep copies of `s`. This is only useful for optimization
|
||||||
## purposes.
|
## purposes.
|
||||||
when not defined(JS) and not defined(NimrodVM):
|
when not defined(JS) and not defined(nimscript):
|
||||||
var s = cast[PGenericSeq](s)
|
var s = cast[PGenericSeq](s)
|
||||||
s.reserved = s.reserved or seqShallowFlag
|
s.reserved = s.reserved or seqShallowFlag
|
||||||
|
|
||||||
|
|
@ -3402,7 +3409,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} =
|
||||||
## # -> B is 1
|
## # -> B is 1
|
||||||
discard
|
discard
|
||||||
|
|
||||||
when hasAlloc and not defined(NimrodVM) and not defined(JS):
|
when hasAlloc and not defined(nimscript) and not defined(JS):
|
||||||
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
||||||
## performs a deep copy of `x`. This is also used by the code generator
|
## performs a deep copy of `x`. This is also used by the code generator
|
||||||
## for the implementation of ``spawn``.
|
## for the implementation of ``spawn``.
|
||||||
|
|
@ -3444,3 +3451,6 @@ proc xlen*[T](x: seq[T]): int {.magic: "XLenSeq", noSideEffect.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}
|
{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}
|
||||||
|
|
||||||
|
when defined(nimconfig):
|
||||||
|
include "system/nimscript"
|
||||||
|
|
|
||||||
152
lib/system/nimscript.nim
Normal file
152
lib/system/nimscript.nim
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nim's Runtime Library
|
||||||
|
# (c) Copyright 2015 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
# Nim's configuration system now uses Nim for scripting. This module provides
|
||||||
|
# a few things that are required for this to work.
|
||||||
|
|
||||||
|
template builtin = discard
|
||||||
|
|
||||||
|
proc listDirs*(dir: string): seq[string] = builtin
|
||||||
|
proc listFiles*(dir: string): seq[string] = builtin
|
||||||
|
|
||||||
|
proc removeDir(dir: string) = builtin
|
||||||
|
proc removeFile(dir: string) = builtin
|
||||||
|
proc moveFile(src, dest: string) = builtin
|
||||||
|
proc createDir(dir: string) = builtin
|
||||||
|
proc getOsError: string = builtin
|
||||||
|
proc setCurrentDir(dir: string) = builtin
|
||||||
|
proc getCurrentDir(): string = builtin
|
||||||
|
proc paramStr*(i: int): string = builtin
|
||||||
|
proc paramCount*(): int = builtin
|
||||||
|
|
||||||
|
proc switch*(key: string, val="") = builtin
|
||||||
|
proc getCommand*(): string = builtin
|
||||||
|
proc setCommand*(cmd: string) = builtin
|
||||||
|
proc cmpIgnoreStyle(a, b: string): int = builtin
|
||||||
|
|
||||||
|
proc strip(s: string): string =
|
||||||
|
var i = 0
|
||||||
|
while s[i] in {' ', '\c', '\L'}: inc i
|
||||||
|
result = s.substr(i)
|
||||||
|
|
||||||
|
template `--`*(key, val: untyped) = switch(astToStr(key), strip astToStr(val))
|
||||||
|
template `--`*(key: untyped) = switch(astToStr(key), "")
|
||||||
|
|
||||||
|
type
|
||||||
|
ScriptMode* {.pure.} = enum
|
||||||
|
Silent,
|
||||||
|
Verbose,
|
||||||
|
Whatif
|
||||||
|
|
||||||
|
var
|
||||||
|
mode*: ScriptMode ## Set this to influence how mkDir, rmDir, rmFile etc.
|
||||||
|
## behave
|
||||||
|
|
||||||
|
template checkOsError =
|
||||||
|
let err = getOsError()
|
||||||
|
if err.len > 0: raise newException(OSError, err)
|
||||||
|
|
||||||
|
template log(msg: string, body: untyped) =
|
||||||
|
if mode == ScriptMode.Verbose or mode == ScriptMode.Whatif:
|
||||||
|
echo "[NimScript] ", msg
|
||||||
|
if mode != ScriptMode.WhatIf:
|
||||||
|
body
|
||||||
|
|
||||||
|
proc rmDir*(dir: string) {.raises: [OSError].} =
|
||||||
|
log "rmDir: " & dir:
|
||||||
|
removeDir dir
|
||||||
|
checkOsError()
|
||||||
|
|
||||||
|
proc rmFile*(dir: string) {.raises: [OSError].} =
|
||||||
|
log "rmFile: " & dir:
|
||||||
|
removeFile dir
|
||||||
|
checkOsError()
|
||||||
|
|
||||||
|
proc mkDir*(dir: string) {.raises: [OSError].} =
|
||||||
|
log "mkDir: " & dir:
|
||||||
|
createDir dir
|
||||||
|
checkOsError()
|
||||||
|
|
||||||
|
proc mvFile*(`from`, to: string) {.raises: [OSError].} =
|
||||||
|
log "mvFile: " & `from` & ", " & to:
|
||||||
|
moveFile `from`, to
|
||||||
|
checkOsError()
|
||||||
|
|
||||||
|
proc exec*(command: string, input = "", cache = "") =
|
||||||
|
## Executes an external process.
|
||||||
|
log "exec: " & command:
|
||||||
|
echo staticExec(command, input, cache)
|
||||||
|
|
||||||
|
proc put*(key, value: string) =
|
||||||
|
## Sets a configuration 'key' like 'gcc.options.always' to its value.
|
||||||
|
builtin
|
||||||
|
|
||||||
|
proc get*(key: string): string =
|
||||||
|
## Retrieves a configuration 'key' like 'gcc.options.always'.
|
||||||
|
builtin
|
||||||
|
|
||||||
|
proc exists*(key: string): bool =
|
||||||
|
## Checks for the existance of a configuration 'key'
|
||||||
|
## like 'gcc.options.always'.
|
||||||
|
builtin
|
||||||
|
|
||||||
|
proc nimcacheDir*(): string =
|
||||||
|
## Retrieves the location of 'nimcache'.
|
||||||
|
builtin
|
||||||
|
|
||||||
|
proc thisDir*(): string =
|
||||||
|
## Retrieves the location of the current ``nims`` script file.
|
||||||
|
builtin
|
||||||
|
|
||||||
|
proc cd*(dir: string) {.raises: [OSError].} =
|
||||||
|
## Changes the current directory.
|
||||||
|
##
|
||||||
|
## The change is permanent for the rest of the execution, since this is just
|
||||||
|
## a shortcut for `os.setCurrentDir()
|
||||||
|
## <http://nim-lang.org/os.html#setCurrentDir,string>`_ . Use the `withDir()
|
||||||
|
## <#withDir>`_ template if you want to perform a temporary change only.
|
||||||
|
setCurrentDir(dir)
|
||||||
|
checkOsError()
|
||||||
|
|
||||||
|
template withDir*(dir: string; body: untyped): untyped =
|
||||||
|
## Changes the current directory temporarily.
|
||||||
|
##
|
||||||
|
## If you need a permanent change, use the `cd() <#cd>`_ proc. Usage example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nimrod
|
||||||
|
## withDir "foo":
|
||||||
|
## # inside foo
|
||||||
|
## #back to last dir
|
||||||
|
var curDir = getCurrentDir()
|
||||||
|
try:
|
||||||
|
cd(dir)
|
||||||
|
body
|
||||||
|
finally:
|
||||||
|
cd(curDir)
|
||||||
|
|
||||||
|
template `==?`(a, b: string): bool = cmpIgnoreStyle(a, b) == 0
|
||||||
|
|
||||||
|
proc writeTask(name, desc: string) =
|
||||||
|
if desc.len > 0:
|
||||||
|
var spaces = " "
|
||||||
|
for i in 0 ..< 20 - name.len: spaces.add ' '
|
||||||
|
echo name, spaces, desc
|
||||||
|
|
||||||
|
template task*(name: untyped; description: string; body: untyped): untyped =
|
||||||
|
## Defines a task. Hidden tasks are supported via an empty description.
|
||||||
|
proc `name Task`() = body
|
||||||
|
|
||||||
|
let cmd = getCommand()
|
||||||
|
if cmd.len == 0 or cmd ==? "help" or cmd == "nop":
|
||||||
|
setCommand "nop"
|
||||||
|
writeTask(astToStr(name), description)
|
||||||
|
elif cmd ==? astToStr(name):
|
||||||
|
setCommand "nop"
|
||||||
|
`name Task`()
|
||||||
|
|
@ -182,7 +182,10 @@ proc readAllFile(file: File): string =
|
||||||
proc readAll(file: File): TaintedString =
|
proc readAll(file: File): TaintedString =
|
||||||
# Separate handling needed because we need to buffer when we
|
# Separate handling needed because we need to buffer when we
|
||||||
# don't know the overall length of the File.
|
# don't know the overall length of the File.
|
||||||
let len = if file != stdin: rawFileSize(file) else: -1
|
when declared(stdin):
|
||||||
|
let len = if file != stdin: rawFileSize(file) else: -1
|
||||||
|
else:
|
||||||
|
let len = rawFileSize(file)
|
||||||
if len > 0:
|
if len > 0:
|
||||||
result = readAllFile(file, len).TaintedString
|
result = readAllFile(file, len).TaintedString
|
||||||
else:
|
else:
|
||||||
|
|
@ -216,9 +219,9 @@ proc writeLine[Ty](f: File, x: varargs[Ty, `$`]) =
|
||||||
for i in items(x): write(f, i)
|
for i in items(x): write(f, i)
|
||||||
write(f, "\n")
|
write(f, "\n")
|
||||||
|
|
||||||
|
when declared(stdout):
|
||||||
proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x)
|
proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x)
|
||||||
proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
|
proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
|
||||||
|
|
||||||
# interface to the C procs:
|
# interface to the C procs:
|
||||||
|
|
||||||
|
|
|
||||||
7
tests/newconfig/tfoo.nim
Normal file
7
tests/newconfig/tfoo.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
discard """
|
||||||
|
cmd: "nim default $file"
|
||||||
|
output: '''hello world!'''
|
||||||
|
msg: '''[NimScript] exec: gcc -v'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
echo "hello world!"
|
||||||
14
tests/newconfig/tfoo.nims
Normal file
14
tests/newconfig/tfoo.nims
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
mode = ScriptMode.Whatif
|
||||||
|
|
||||||
|
exec "gcc -v"
|
||||||
|
|
||||||
|
--forceBuild
|
||||||
|
|
||||||
|
task listDirs, "lists every subdirectory":
|
||||||
|
for x in listDirs("."):
|
||||||
|
echo "DIR ", x
|
||||||
|
|
||||||
|
task default, "default target":
|
||||||
|
setCommand "c"
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue