Merge pull request #2 from nim-lang/devel

Pull 25-04-18
This commit is contained in:
Michael Voronin 2018-04-25 12:26:59 +03:00 • committed by GitHub
commit 3949c9f977
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
90 changed files with 404 additions and 378 deletions

View file

@ -102,4 +102,10 @@
- Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual - Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
machine. machine.
- The ``deadCodeElim`` option is now always turned on and the switch has no
effect anymore, but is recognized for backwards compatibility.
- ``experimental`` is now a pragma / command line switch that can enable specific
language extensions, it is not an all-or-nothing switch anymore.
### Bugfixes ### Bugfixes

View file

@ -262,7 +262,8 @@ type
# variable is a thread variable # variable is a thread variable
sfCompileTime, # proc can be evaluated at compile time sfCompileTime, # proc can be evaluated at compile time
sfConstructor, # proc is a C++ constructor sfConstructor, # proc is a C++ constructor
sfDeadCodeElim, # dead code elimination for the module is turned on sfDispatcher, # copied method symbol is the dispatcher
# deprecated and unused, except for the con
sfBorrow, # proc is borrowed sfBorrow, # proc is borrowed
sfInfixCall, # symbol needs infix call syntax in target language; sfInfixCall, # symbol needs infix call syntax in target language;
# for interfacing with C++, JS # for interfacing with C++, JS
@ -275,10 +276,9 @@ type
TSymFlags* = set[TSymFlag] TSymFlags* = set[TSymFlag]
const const
sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher
sfNoInit* = sfMainModule # don't generate code to init the variable sfNoInit* = sfMainModule # don't generate code to init the variable
sfImmediate* = sfDeadCodeElim sfImmediate* = sfDispatcher
# macro or template is immediately expanded # macro or template is immediately expanded
# without considering any possible overloads # without considering any possible overloads
sfAllUntyped* = sfVolatile # macro or template is immediately expanded \ sfAllUntyped* = sfVolatile # macro or template is immediately expanded \
@ -1622,7 +1622,7 @@ iterator items*(n: PNode): PNode =
for i in 0..<n.safeLen: yield n.sons[i] for i in 0..<n.safeLen: yield n.sons[i]
iterator pairs*(n: PNode): tuple[i: int, n: PNode] = iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
for i in 0..<n.len: yield (i, n.sons[i]) for i in 0..<n.safeLen: yield (i, n.sons[i])
proc isAtom*(n: PNode): bool {.inline.} = proc isAtom*(n: PNode): bool {.inline.} =
result = n.kind >= nkNone and n.kind <= nkNilLit result = n.kind >= nkNone and n.kind <= nkNilLit

View file

@ -2264,7 +2264,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkEmpty: discard of nkEmpty: discard
of nkWhileStmt: genWhileStmt(p, n) of nkWhileStmt: genWhileStmt(p, n)
of nkVarSection, nkLetSection: genVarStmt(p, n) of nkVarSection, nkLetSection: genVarStmt(p, n)
of nkConstSection: genConstStmt(p, n) of nkConstSection: discard # consts generated lazily on use
of nkForStmt: internalError(n.info, "for statement not eliminated") of nkForStmt: internalError(n.info, "for statement not eliminated")
of nkCaseStmt: genCase(p, n, d) of nkCaseStmt: genCase(p, n, d)
of nkReturnStmt: genReturnStmt(p, n) of nkReturnStmt: genReturnStmt(p, n)
@ -2315,8 +2315,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
# are not transformed correctly. We work around this issue (#411) here # are not transformed correctly. We work around this issue (#411) here
# by ensuring it's no inner proc (owner is a module): # by ensuring it's no inner proc (owner is a module):
if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags: if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
if (not emitLazily(prc)) or if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
(sfExportc in prc.flags and lfExportLib in prc.loc.flags) or (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
(prc.kind == skMethod): (prc.kind == skMethod):
# we have not only the header: # we have not only the header:

View file

@ -280,20 +280,6 @@ proc genVarStmt(p: BProc, n: PNode) =
else: else:
genVarTuple(p, it) genVarTuple(p, it)
proc genConstStmt(p: BProc, n: PNode) =
for it in n.sons:
if it.kind == nkCommentStmt: continue
if it.kind != nkConstDef: internalError(n.info, "genConstStmt")
let sym = it.sons[0].sym
if sym.typ.containsCompileTimeOnly or
sym.typ.kind notin ConstantDataTypes or
sym.ast.len == 0 or
emitLazily(sym):
continue
requestConstImpl(p, sym)
proc genIf(p: BProc, n: PNode, d: var TLoc) = proc genIf(p: BProc, n: PNode, d: var TLoc) =
# #
# { if (!expr1) goto L1; # { if (!expr1) goto L1;
@ -587,7 +573,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
genLineDir(p, t) genLineDir(p, t)
if isImportedException(typ): if isImportedException(typ):
lineF(p, cpsStmts, "throw $1;$n", [e]) lineF(p, cpsStmts, "throw $1;$n", [e])
else: else:
lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n", lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n",
[e, makeCString(typ.sym.name.s)]) [e, makeCString(typ.sym.name.s)])
else: else:
@ -836,7 +822,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
else: else:
for j in 0..t[i].len-2: for j in 0..t[i].len-2:
if t[i][j].isInfixAs(): if t[i][j].isInfixAs():
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:` let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnUnknown) fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnUnknown)
startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc)) startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc))
else: else:

View file

@ -211,8 +211,4 @@ proc mangle*(name: string): string =
if requiresUnderscore: if requiresUnderscore:
result.add "_" result.add "_"
proc emitLazily*(s: PSym): bool {.inline.} =
result = optDeadCodeElim in gGlobalOptions or
sfDeadCodeElim in getModule(s).flags
initTypeTables() initTypeTables()

View file

@ -1309,10 +1309,6 @@ proc newModule(g: BModuleList; module: PSym): BModule =
growCache g.modules, module.position growCache g.modules, module.position
g.modules[module.position] = result g.modules[module.position] = result
if (optDeadCodeElim in gGlobalOptions):
if (sfDeadCodeElim in module.flags):
internalError("added pending module twice: " & toFilename(FileIndex module.position))
template injectG(config) {.dirty.} = template injectG(config) {.dirty.} =
if graph.backend == nil: if graph.backend == nil:
graph.backend = newModuleList(config) graph.backend = newModuleList(config)

View file

@ -46,9 +46,9 @@ type
passCmd2, # second pass over the command line passCmd2, # second pass over the command line
passPP # preprocessor called processCommand() passPP # preprocessor called processCommand()
proc processCommand*(switch: string, pass: TCmdLinePass) proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef)
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
config: ConfigRef = nil) config: ConfigRef)
# implementation # implementation
@ -58,7 +58,13 @@ const
const const
Usage = slurp"../doc/basicopt.txt".replace("//", "") Usage = slurp"../doc/basicopt.txt".replace("//", "")
AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") FeatureDesc = block:
var x = ""
for f in low(Feature)..high(Feature):
if x.len > 0: x.add "|"
x.add $f
x
AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") % FeatureDesc
proc getCommandLineDesc(): string = proc getCommandLineDesc(): string =
result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name,
@ -268,7 +274,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
of "movechecks": result = contains(gOptions, optMoveCheck) of "movechecks": result = contains(gOptions, optMoveCheck)
of "linedir": result = contains(gOptions, optLineDir) of "linedir": result = contains(gOptions, optLineDir)
of "assertions", "a": result = contains(gOptions, optAssert) of "assertions", "a": result = contains(gOptions, optAssert)
of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim)
of "run", "r": result = contains(gGlobalOptions, optRun) of "run", "r": result = contains(gGlobalOptions, optRun)
of "symbolfiles": result = gSymbolFiles != disabledSf of "symbolfiles": result = gSymbolFiles != disabledSf
of "genscript": result = contains(gGlobalOptions, optGenScript) of "genscript": result = contains(gGlobalOptions, optGenScript)
@ -277,7 +282,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation) of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
of "implicitstatic": result = contains(gOptions, optImplicitStatic) of "implicitstatic": result = contains(gOptions, optImplicitStatic)
of "patterns": result = contains(gOptions, optPatterns) of "patterns": result = contains(gOptions, optPatterns)
of "experimental": result = gExperimentalMode
of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace) of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace)
else: invalidCmdLineOption(passCmd1, switch, info) else: invalidCmdLineOption(passCmd1, switch, info)
@ -340,7 +344,7 @@ proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
options.inclDynlibOverride(arg) options.inclDynlibOverride(arg)
proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
config: ConfigRef = nil) = config: ConfigRef) =
var var
theOS: TSystemOS theOS: TSystemOS
cpu: TSystemCPU cpu: TSystemCPU
@ -509,7 +513,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info) of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info)
of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info) of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info) of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info) of "deadcodeelim": discard # deprecated, dead code elim always on
of "threads": of "threads":
processOnOffSwitchG({optThreads}, arg, pass, info) processOnOffSwitchG({optThreads}, arg, pass, info)
#if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe) #if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe)
@ -648,6 +652,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "genscript", "gendeps": of "genscript", "gendeps":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optGenScript) incl(gGlobalOptions, optGenScript)
incl(gGlobalOptions, optCompileOnly)
of "colors": processOnOffSwitchG({optUseColors}, arg, pass, info) of "colors": processOnOffSwitchG({optUseColors}, arg, pass, info)
of "lib": of "lib":
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
@ -695,8 +700,13 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
# only supported for compatibility. Does nothing. # only supported for compatibility. Does nothing.
expectArg(switch, arg, pass, info) expectArg(switch, arg, pass, info)
of "experimental": of "experimental":
expectNoArg(switch, arg, pass, info) if arg.len == 0:
gExperimentalMode = true config.features.incl oldExperimentalFeatures
else:
try:
config.features.incl parseEnum[Feature](arg)
except ValueError:
localError(info, "unknown experimental feature")
of "nocppexceptions": of "nocppexceptions":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
incl(gGlobalOptions, optNoCppExceptions) incl(gGlobalOptions, optNoCppExceptions)
@ -707,7 +717,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
config.cppDefine(arg) config.cppDefine(arg)
of "newruntime": of "newruntime":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
newDestructors = true doAssert(config != nil)
incl(config.features, destructor)
defineSymbol("nimNewRuntime") defineSymbol("nimNewRuntime")
of "cppcompiletonamespace": of "cppcompiletonamespace":
expectNoArg(switch, arg, pass, info) expectNoArg(switch, arg, pass, info)
@ -717,36 +728,31 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
else: invalidCmdLineOption(pass, switch, info) else: invalidCmdLineOption(pass, switch, info)
proc processCommand(switch: string, pass: TCmdLinePass) = proc processCommand(switch: string, pass: TCmdLinePass; config: ConfigRef) =
var cmd, arg: string var cmd, arg: string
splitSwitch(switch, cmd, arg, pass, gCmdLineInfo) splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
processSwitch(cmd, arg, pass, gCmdLineInfo) processSwitch(cmd, arg, pass, gCmdLineInfo, config)
var proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
arguments* = ""
# the arguments to be passed to the program that
# should be run
proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
# hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
# we fix this here # we fix this here
var bracketLe = strutils.find(p.key, '[') var bracketLe = strutils.find(p.key, '[')
if bracketLe >= 0: if bracketLe >= 0:
var key = substr(p.key, 0, bracketLe - 1) var key = substr(p.key, 0, bracketLe - 1)
var val = substr(p.key, bracketLe + 1) & ':' & p.val var val = substr(p.key, bracketLe + 1) & ':' & p.val
processSwitch(key, val, pass, gCmdLineInfo) processSwitch(key, val, pass, gCmdLineInfo, config)
else: else:
processSwitch(p.key, p.val, pass, gCmdLineInfo) processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
proc processArgument*(pass: TCmdLinePass; p: OptParser; proc processArgument*(pass: TCmdLinePass; p: OptParser;
argsCount: var int): bool = argsCount: var int; config: ConfigRef): bool =
if argsCount == 0: if argsCount == 0:
# nim filename.nims is the same as "nim e filename.nims": # nim filename.nims is the same as "nim e filename.nims":
if p.key.endswith(".nims"): if p.key.endswith(".nims"):
options.command = "e" options.command = "e"
options.gProjectName = unixToNativePath(p.key) options.gProjectName = unixToNativePath(p.key)
arguments = cmdLineRest(p) config.arguments = cmdLineRest(p)
result = true result = true
elif pass != passCmd2: elif pass != passCmd2:
options.command = p.key options.command = p.key
@ -755,6 +761,6 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
if argsCount == 1: if argsCount == 1:
# support UNIX style filenames everywhere for portable build scripts: # support UNIX style filenames everywhere for portable build scripts:
options.gProjectName = unixToNativePath(p.key) options.gProjectName = unixToNativePath(p.key)
arguments = cmdLineRest(p) config.arguments = cmdLineRest(p)
result = true result = true
inc argsCount inc argsCount

View file

@ -470,8 +470,9 @@ proc execExternalProgram*(cmd: string, msg = hintExecuting) =
proc generateScript(projectFile: string, script: Rope) = proc generateScript(projectFile: string, script: Rope) =
let (dir, name, ext) = splitFile(projectFile) let (dir, name, ext) = splitFile(projectFile)
writeRope(script, dir / addFileExt("compile_" & name, writeRope(script, getNimcacheDir() / addFileExt("compile_" & name,
platform.OS[targetOS].scriptExt)) platform.OS[targetOS].scriptExt))
copyFile(libpath / "nimbase.h", getNimcacheDir() / "nimbase.h")
proc getOptSpeed(c: TSystemCC): string = proc getOptSpeed(c: TSystemCC): string =
result = getConfigVar(c, ".options.speed") result = getConfigVar(c, ".options.speed")

View file

@ -42,7 +42,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
writeCommandLineUsage() writeCommandLineUsage()
else: else:
# Process command line arguments: # Process command line arguments:
processCmdLine(passCmd1, "") processCmdLine(passCmd1, "", config)
if gProjectName == "-": if gProjectName == "-":
gProjectName = "stdinfile" gProjectName = "stdinfile"
gProjectFull = "stdinfile" gProjectFull = "stdinfile"
@ -71,7 +71,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
# 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()
processCmdLine(passCmd2, "") processCmdLine(passCmd2, "", config)
if options.command == "": if options.command == "":
rawMessage(errNoCommand, command) rawMessage(errNoCommand, command)
mainCommand(newModuleGraph(config), cache) mainCommand(newModuleGraph(config), cache)
@ -80,7 +80,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
if msgs.gErrorCounter == 0: if msgs.gErrorCounter == 0:
when hasTinyCBackend: when hasTinyCBackend:
if gCmd == cmdRun: if gCmd == cmdRun:
tccgen.run(commands.arguments) tccgen.run(config.arguments)
if optRun in gGlobalOptions: if optRun in gGlobalOptions:
if gCmd == cmdCompileToJS: if gCmd == cmdCompileToJS:
var ex: string var ex: string
@ -89,7 +89,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
else: else:
ex = quoteShell( ex = quoteShell(
completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir)) completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
execExternalProgram(findNodeJs() & " " & ex & ' ' & commands.arguments) execExternalProgram(findNodeJs() & " " & ex & ' ' & config.arguments)
else: else:
var binPath: string var binPath: string
if options.outFile.len > 0: if options.outFile.len > 0:
@ -99,7 +99,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
# Figure out ourselves a valid binary name. # Figure out ourselves a valid binary name.
binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir
var ex = quoteShell(binPath) var ex = quoteShell(binPath)
execExternalProgram(ex & ' ' & commands.arguments) execExternalProgram(ex & ' ' & config.arguments)
when declared(GC_setMaxPause): when declared(GC_setMaxPause):
GC_setMaxPause 2_000 GC_setMaxPause 2_000

View file

@ -247,10 +247,6 @@ proc loadConfigs*(cfg: string; cache: IdentCache; config: ConfigRef = nil) =
var projectConfig = changeFileExt(gProjectFull, "nimcfg") var projectConfig = changeFileExt(gProjectFull, "nimcfg")
if not fileExists(projectConfig): if not fileExists(projectConfig):
projectConfig = changeFileExt(gProjectFull, "nim.cfg") projectConfig = changeFileExt(gProjectFull, "nim.cfg")
if not fileExists(projectConfig):
projectConfig = changeFileExt(gProjectFull, "nimrod.cfg")
if fileExists(projectConfig):
rawMessage(warnDeprecated, projectConfig)
readConfigFile(projectConfig, cache, config) readConfigFile(projectConfig, cache, config)
proc loadConfigs*(cfg: string; config: ConfigRef = nil) = proc loadConfigs*(cfg: string; config: ConfigRef = nil) =

View file

@ -41,7 +41,8 @@ type # please make sure we have under 32 options
TOptions* = set[TOption] TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible** TGlobalOption* = enum # **keep binary compatible**
gloptNone, optForceFullMake, optDeadCodeElim, gloptNone, optForceFullMake,
optDeadCodeElimUnused, # deprecated, always on
optListCmd, optCompileOnly, optNoLinking, optListCmd, optCompileOnly, optNoLinking,
optCDebug, # turn on debugging information optCDebug, # turn on debugging information
optGenDynLib, # generate a dynamic library optGenDynLib, # generate a dynamic library
@ -102,13 +103,25 @@ type
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod, ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
ideHighlight, ideOutline, ideKnown, ideMsg ideHighlight, ideOutline, ideKnown, ideMsg
Feature* = enum ## experimental features
implicitDeref,
dotOperators,
callOperator,
parallel,
destructor
ConfigRef* = ref object ## eventually all global configuration should be moved here ConfigRef* = ref object ## eventually all global configuration should be moved here
cppDefines*: HashSet[string] cppDefines*: HashSet[string]
headerFile*: string headerFile*: string
features*: set[Feature]
arguments*: string ## the arguments to be passed to the program that
## should be run
const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
proc newConfigRef*(): ConfigRef = proc newConfigRef*(): ConfigRef =
result = ConfigRef(cppDefines: initSet[string](), result = ConfigRef(cppDefines: initSet[string](),
headerFile: "") headerFile: "", features: {})
proc cppDefine*(c: ConfigRef; define: string) = proc cppDefine*(c: ConfigRef; define: string) =
c.cppDefines.incl define c.cppDefines.incl define
@ -145,8 +158,6 @@ var
gListFullPaths*: bool gListFullPaths*: bool
gPreciseStack*: bool = false gPreciseStack*: bool = false
gNoNimblePath* = false gNoNimblePath* = false
gExperimentalMode*: bool
newDestructors*: bool
gDynlibOverrideAll*: bool gDynlibOverrideAll*: bool
useNimNamespace*: bool useNimNamespace*: bool

View file

@ -166,7 +166,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
p: TParsers p: TParsers
a: TPassContextArray a: TPassContextArray
s: PLLStream s: PLLStream
fileIdx = FileIndex module.fileIdx fileIdx = module.fileIdx
if module.id < 0: if module.id < 0:
# new module caching mechanism: # new module caching mechanism:
for i in 0..<gPassesLen: for i in 0..<gPassesLen:

View file

@ -44,7 +44,9 @@ const
wWarnings, wHints, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop, wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, wBreakpoint, wWatchPoint, wPassl, wPassc,
wDeadCodeElimUnused, # deprecated, always on
wDeprecated,
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto, wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental, wThis} wInjectStmt, wDeprecated, wExperimental, wThis}
@ -215,10 +217,6 @@ proc onOff(c: PContext, n: PNode, op: TOptions) =
if isTurnedOn(c, n): gOptions = gOptions + op if isTurnedOn(c, n): gOptions = gOptions + op
else: gOptions = gOptions - op else: gOptions = gOptions - op
proc pragmaDeadCodeElim(c: PContext, n: PNode) =
if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
else: excl(c.module.flags, sfDeadCodeElim)
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) = proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
if isTurnedOn(c, n): incl(c.module.flags, flag) if isTurnedOn(c, n): incl(c.module.flags, flag)
else: excl(c.module.flags, flag) else: excl(c.module.flags, flag)
@ -682,6 +680,22 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
elif n.kind == nkExprColonExpr: elif n.kind == nkExprColonExpr:
result.kind = n.kind # pragma(arg) -> pragma: arg result.kind = n.kind # pragma(arg) -> pragma: arg
proc processExperimental(c: PContext; n: PNode; s: PSym) =
if not isTopLevel(c):
localError(n.info, "'experimental' pragma only valid as toplevel statement")
if n.kind notin nkPragmaCallKinds or n.len != 2:
c.features.incl oldExperimentalFeatures
else:
n[1] = c.semConstExpr(c, n[1])
case n[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
c.features.incl parseEnum[Feature](n[1].strVal)
except ValueError:
localError(n[1].info, "unknown experimental feature")
else:
localError(n.info, errStringLiteralExpected)
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
validPragmas: TSpecialWords): bool = validPragmas: TSpecialWords): bool =
var it = n.sons[i] var it = n.sons[i]
@ -764,7 +778,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wThreadVar: of wThreadVar:
noVal(it) noVal(it)
incl(sym.flags, sfThread) incl(sym.flags, sfThread)
of wDeadCodeElim: pragmaDeadCodeElim(c, it) of wDeadCodeElimUnused: discard # deprecated, dead code elim always on
of wNoForward: pragmaNoForward(c, it) of wNoForward: pragmaNoForward(c, it)
of wReorder: pragmaNoForward(c, it, sfReorder) of wReorder: pragmaNoForward(c, it, sfReorder)
of wMagic: processMagic(c, it, sym) of wMagic: processMagic(c, it, sym)
@ -960,10 +974,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if sym.kind != skType or sym.typ == nil: invalidPragma(it) if sym.kind != skType or sym.typ == nil: invalidPragma(it)
else: else:
incl(sym.typ.flags, tfPartial) incl(sym.typ.flags, tfPartial)
# .partial types can only work with dead code elimination
# to prevent the codegen from doing anything before we compiled
# the whole program:
incl gGlobalOptions, optDeadCodeElim
of wInject, wGensym: of wInject, wGensym:
# We check for errors, but do nothing with these pragmas otherwise # We check for errors, but do nothing with these pragmas otherwise
# as they are handled directly in 'evalTemplate'. # as they are handled directly in 'evalTemplate'.
@ -999,11 +1009,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else: else:
it.sons[1] = c.semExpr(c, it.sons[1]) it.sons[1] = c.semExpr(c, it.sons[1])
of wExperimental: of wExperimental:
noVal(it) processExperimental(c, it, sym)
if isTopLevel(c):
c.module.flags.incl sfExperimental
else:
localError(it.info, "'experimental' pragma only valid as toplevel statement")
of wThis: of wThis:
if it.kind in nkPragmaCallKinds and it.len == 2: if it.kind in nkPragmaCallKinds and it.len == 2:
c.selfName = considerQuotedIdent(it[1]) c.selfName = considerQuotedIdent(it[1])

View file

@ -172,32 +172,6 @@ proc put(g: var TSrcGen, kind: TTokType, s: string) =
else: else:
g.pendingWhitespace = s.len g.pendingWhitespace = s.len
proc addNimChar(dst: var string; c: char): void =
case c
of '\0': dst.add "\\x00" # not "\\0" to avoid ambiguous cases like "\\012".
of '\a': dst.add "\\a" # \x07
of '\b': dst.add "\\b" # \x08
of '\t': dst.add "\\t" # \x09
of '\L': dst.add "\\L" # \x0A
of '\v': dst.add "\\v" # \x0B
of '\f': dst.add "\\f" # \x0C
of '\c': dst.add "\\c" # \x0D
of '\e': dst.add "\\e" # \x1B
of '\x01'..'\x06', '\x0E'..'\x1A', '\x1C'..'\x1F', '\x80'..'\xFF':
dst.add "\\x"
dst.add strutils.toHex(ord(c), 2)
of '\'', '\"', '\\':
dst.add '\\'
dst.add c
else:
dst.add c
proc makeNimString(s: string): string =
result = "\""
for c in s:
result.addNimChar c
add(result, '\"')
proc putComment(g: var TSrcGen, s: string) = proc putComment(g: var TSrcGen, s: string) =
if s.isNil: return if s.isNil: return
var i = 0 var i = 0
@ -365,10 +339,13 @@ proc atom(g: TSrcGen; n: PNode): string =
of nkEmpty: result = "" of nkEmpty: result = ""
of nkIdent: result = n.ident.s of nkIdent: result = n.ident.s
of nkSym: result = n.sym.name.s of nkSym: result = n.sym.name.s
of nkStrLit: result = makeNimString(n.strVal) of nkStrLit: result = ""; result.addQuoted(n.strVal)
of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"' of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"'
of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\"" of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\""
of nkCharLit: result = "\'"; result.addNimChar chr(int(n.intVal)); result.add '\'' of nkCharLit:
result = "\'"
result.addEscapedChar(chr(int(n.intVal)));
result.add '\''
of nkIntLit: result = litAux(g, n, n.intVal, 4) of nkIntLit: result = litAux(g, n, n.intVal, 4)
of nkInt8Lit: result = litAux(g, n, n.intVal, 1) & "\'i8" of nkInt8Lit: result = litAux(g, n, n.intVal, 1) & "\'i8"
of nkInt16Lit: result = litAux(g, n, n.intVal, 2) & "\'i16" of nkInt16Lit: result = litAux(g, n, n.intVal, 2) & "\'i16"

View file

@ -429,7 +429,7 @@ proc reorder*(graph: ModuleGraph, n: PNode, module: PSym, cache: IdentCache): PN
if n.hasForbiddenPragma: if n.hasForbiddenPragma:
return n return n
var includedFiles = initIntSet() var includedFiles = initIntSet()
let mpath = module.fileIdx.FileIndex.toFullPath let mpath = module.fileIdx.toFullPath
let n = expandIncludes(graph, module, n, mpath, let n = expandIncludes(graph, module, n, mpath,
includedFiles, cache).splitSections includedFiles, cache).splitSections
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)

View file

@ -915,7 +915,7 @@ proc handleSymbolFile*(module: PSym; cache: IdentCache): PRodReader =
module.id = getID() module.id = getID()
return nil return nil
idgen.loadMaxIds(options.gProjectPath / options.gProjectName) idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
let fileIdx = FileIndex module.fileIdx let fileIdx = module.fileIdx
discard checkDep(fileIdx, cache) discard checkDep(fileIdx, cache)
if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile") if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile")
result = gMods[fileIdx.int32].rd result = gMods[fileIdx.int32].rd

View file

@ -26,7 +26,7 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) =
setResult(a, result) setResult(a, result)
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
config: ConfigRef = nil): PEvalContext = config: ConfigRef): PEvalContext =
# For Nimble we need to export 'setupVM'. # For Nimble we need to export 'setupVM'.
result = newCtx(module, cache) result = newCtx(module, cache)
result.mode = emRepl result.mode = emRepl
@ -128,7 +128,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
cbconf getCommand: cbconf getCommand:
setResult(a, options.command) setResult(a, options.command)
cbconf switch: cbconf switch:
processSwitch(a.getString 0, a.getString 1, passPP, module.info) processSwitch(a.getString 0, a.getString 1, passPP, module.info, config)
cbconf hintImpl: cbconf hintImpl:
processSpecificNote(a.getString 0, wHint, passPP, module.info, processSpecificNote(a.getString 0, wHint, passPP, module.info,
a.getString 1) a.getString 1)
@ -150,7 +150,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
options.cppDefine(config, a.getString(0)) options.cppDefine(config, a.getString(0))
proc runNimScript*(cache: IdentCache; scriptName: string; proc runNimScript*(cache: IdentCache; scriptName: string;
freshDefines=true; config: ConfigRef=nil) = freshDefines=true; config: ConfigRef) =
rawMessage(hintConf, scriptName) rawMessage(hintConf, scriptName)
passes.gIncludeFile = includeModule passes.gIncludeFile = includeModule
passes.gImportModule = importModule passes.gImportModule = importModule

View file

@ -101,7 +101,7 @@ proc newOpCall(op: PSym; x: PNode): PNode =
proc destructorCall(c: PContext; op: PSym; x: PNode): PNode = proc destructorCall(c: PContext; op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ.sons[0]) result = newNodeIT(nkCall, x.info, op.typ.sons[0])
result.add(newSymNode(op)) result.add(newSymNode(op))
if newDestructors: if destructor in c.features:
result.add genAddr(c, x) result.add genAddr(c, x)
else: else:
result.add x result.add x
@ -319,7 +319,7 @@ proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
## In the semantic pass this is called in strategic places ## In the semantic pass this is called in strategic places
## to ensure we lift assignment, destructors and moves properly. ## to ensure we lift assignment, destructors and moves properly.
## The later 'destroyer' pass depends on it. ## The later 'destroyer' pass depends on it.
if not newDestructors or not hasDestructor(typ): return if destructor notin c.features or not hasDestructor(typ): return
when false: when false:
# do not produce wrong liftings while we're still instantiating generics: # do not produce wrong liftings while we're still instantiating generics:
# now disabled; breaks topttree.nim! # now disabled; breaks topttree.nim!

View file

@ -434,7 +434,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
"Non-matching candidates for " & renderTree(n) & "\n" & "Non-matching candidates for " & renderTree(n) & "\n" &
candidates) candidates)
result = semResolvedCall(c, n, r) result = semResolvedCall(c, n, r)
elif experimentalMode(c) and canDeref(n): elif implicitDeref in c.features and canDeref(n):
# try to deref the first argument and then try overloading resolution again: # try to deref the first argument and then try overloading resolution again:
# #
# XXX: why is this here? # XXX: why is this here?

View file

@ -130,6 +130,7 @@ type
signatures*: TStrTable signatures*: TStrTable
recursiveDep*: string recursiveDep*: string
suggestionsMade*: bool suggestionsMade*: bool
features*: set[Feature]
inTypeContext*: int inTypeContext*: int
typesWithOps*: seq[(PType, PType)] #\ typesWithOps*: seq[(PType, PType)] #\
# We need to instantiate the type bound ops lazily after # We need to instantiate the type bound ops lazily after
@ -225,7 +226,7 @@ proc newContext*(graph: ModuleGraph; module: PSym; cache: IdentCache): PContext
result.graph = graph result.graph = graph
initStrTable(result.signatures) initStrTable(result.signatures)
result.typesWithOps = @[] result.typesWithOps = @[]
result.features = graph.config.features
proc inclSym(sq: var TSymSeq, s: PSym) = proc inclSym(sq: var TSymSeq, s: PSym) =
var L = len(sq) var L = len(sq)
@ -398,6 +399,3 @@ proc checkMinSonsLen*(n: PNode, length: int) =
proc isTopLevel*(c: PContext): bool {.inline.} = proc isTopLevel*(c: PContext): bool {.inline.} =
result = c.currentScope.depthLevel <= 2 result = c.currentScope.depthLevel <= 2
proc experimentalMode*(c: PContext): bool {.inline.} =
result = gExperimentalMode or sfExperimental in c.module.flags

View file

@ -663,7 +663,7 @@ proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
matches(c, n, nOrig, result) matches(c, n, nOrig, result)
if result.state != csMatch: if result.state != csMatch:
# try to deref the first argument: # try to deref the first argument:
if experimentalMode(c) and canDeref(n): if implicitDeref in c.features and canDeref(n):
n.sons[1] = n.sons[1].tryDeref n.sons[1] = n.sons[1].tryDeref
initCandidate(c, result, t) initCandidate(c, result, t)
matches(c, n, nOrig, result) matches(c, n, nOrig, result)
@ -1452,7 +1452,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
typeMismatch(n.info, lhs.typ, rhsTyp) typeMismatch(n.info, lhs.typ, rhsTyp)
n.sons[1] = fitNode(c, le, rhs, n.info) n.sons[1] = fitNode(c, le, rhs, n.info)
if not newDestructors: if destructor notin c.features:
if tfHasAsgn in lhs.typ.flags and not lhsIsResult and if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
mode != noOverloadedAsgn: mode != noOverloadedAsgn:
return overloadedAsgn(c, lhs, n.sons[1]) return overloadedAsgn(c, lhs, n.sons[1])
@ -1884,7 +1884,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
result.typ = getSysType(tyString) result.typ = getSysType(tyString)
of mParallel: of mParallel:
if not experimentalMode(c): if parallel notin c.features:
localError(n.info, "use the {.experimental.} pragma to enable 'parallel'") localError(n.info, "use the {.experimental.} pragma to enable 'parallel'")
result = setMs(n, s) result = setMs(n, s)
var x = n.lastSon var x = n.lastSon

View file

@ -385,30 +385,9 @@ proc checkNilable(v: PSym) =
include semasgn include semasgn
proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) = proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
# consider this:
# var
# x = 0
# withOverloadedAssignment = foo()
# y = use(withOverloadedAssignment)
# We need to split this into a statement list with multiple 'var' sections
# in order for this transformation to be correct.
let L = identDefs.len let L = identDefs.len
let value = identDefs[L-1] let value = identDefs[L-1]
if value.typ != nil and tfHasAsgn in value.typ.flags and not newDestructors: if result.kind == nkStmtList:
# the spec says we need to rewrite 'var x = T()' to 'var x: T; x = T()':
identDefs.sons[L-1] = emptyNode
if result.kind != nkStmtList:
let oldResult = result
oldResult.add identDefs
result = newNodeI(nkStmtList, result.info)
result.add oldResult
else:
let o = copyNode(orig)
o.add identDefs
result.add o
for i in 0 .. L-3:
result.add overloadedAsgn(c, identDefs[i], value)
elif result.kind == nkStmtList:
let o = copyNode(orig) let o = copyNode(orig)
o.add identDefs o.add identDefs
result.add o result.add o
@ -1267,9 +1246,6 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
gp = newNodeI(nkGenericParams, n.info) gp = newNodeI(nkGenericParams, n.info)
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
#if n.kind == nkDo and not experimentalMode(c):
# localError(n.sons[paramsPos].info,
# "use the {.experimental.} pragma to enable 'do' with parameters")
semParamList(c, n.sons[paramsPos], gp, s) semParamList(c, n.sons[paramsPos], gp, s)
# paramsTypeCheck(c, s.typ) # paramsTypeCheck(c, s.typ)
if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty: if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
@ -1363,27 +1339,26 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
proc semOverride(c: PContext, s: PSym, n: PNode) = proc semOverride(c: PContext, s: PSym, n: PNode) =
case s.name.s.normalize case s.name.s.normalize
of "destroy", "=destroy": of "=destroy":
if newDestructors: let t = s.typ
let t = s.typ var noError = false
var noError = false if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar: var obj = t.sons[1].sons[0]
var obj = t.sons[1].sons[0] while true:
while true: incl(obj.flags, tfHasAsgn)
incl(obj.flags, tfHasAsgn) if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon
if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
elif obj.kind == tyGenericInvocation: obj = obj.sons[0] else: break
else: break if obj.kind in {tyObject, tyDistinct}:
if obj.kind in {tyObject, tyDistinct}: if obj.destructor.isNil:
if obj.destructor.isNil: obj.destructor = s
obj.destructor = s else:
else: localError(n.info, errGenerated,
localError(n.info, errGenerated, "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
"cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) noError = true
noError = true if not noError and sfSystemModule notin s.owner.flags:
if not noError and sfSystemModule notin s.owner.flags: localError(n.info, errGenerated,
localError(n.info, errGenerated, "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
"signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
of "deepcopy", "=deepcopy": of "deepcopy", "=deepcopy":
if s.typ.len == 2 and if s.typ.len == 2 and
@ -1612,9 +1587,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
s.options = gOptions s.options = gOptions
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
if s.name.s[0] in {'.', '('}: if s.name.s[0] in {'.', '('}:
if s.name.s in [".", ".()", ".="] and not experimentalMode(c) and not newDestructors: if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s) message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s)
elif s.name.s == "()" and not experimentalMode(c): elif s.name.s == "()" and callOperator notin c.features:
message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s) message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s)
if n.sons[bodyPos].kind != nkEmpty: if n.sons[bodyPos].kind != nkEmpty:

View file

@ -368,7 +368,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
assert newbody.kind in {tyRef, tyPtr} assert newbody.kind in {tyRef, tyPtr}
assert newbody.lastSon.typeInst == nil assert newbody.lastSon.typeInst == nil
newbody.lastSon.typeInst = result newbody.lastSon.typeInst = result
if newDestructors: if destructor in cl.c.features:
cl.c.typesWithOps.add((newbody, result)) cl.c.typesWithOps.add((newbody, result))
else: else:
typeBound(cl.c, newbody, result, assignment, cl.info) typeBound(cl.c, newbody, result, assignment, cl.info)
@ -545,7 +545,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
else: discard else: discard
proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) = proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
if not newDestructors: return if destructor notin c.features: return
var i = 0 var i = 0
while i < c.typesWithOps.len: while i < c.typesWithOps.len:
let (newty, oldty) = c.typesWithOps[i] let (newty, oldty) = c.typesWithOps[i]

View file

@ -26,7 +26,7 @@ var
# in caas mode, the list of defines and options will be given at start-up? # in caas mode, the list of defines and options will be given at start-up?
# it's enough to check that the previous compilation command is the same? # it's enough to check that the previous compilation command is the same?
proc processCmdLine*(pass: TCmdLinePass, cmd: string) = proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd) var p = parseopt.initOptParser(cmd)
var argsCount = 0 var argsCount = 0
while true: while true:
@ -36,19 +36,19 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
of cmdLongoption, cmdShortOption: of cmdLongoption, cmdShortOption:
if p.key == " ": if p.key == " ":
p.key = "-" p.key = "-"
if processArgument(pass, p, argsCount): break if processArgument(pass, p, argsCount, config): break
else: else:
processSwitch(pass, p) processSwitch(pass, p, config)
of cmdArgument: of cmdArgument:
if processArgument(pass, p, argsCount): break if processArgument(pass, p, argsCount, config): break
if pass == passCmd2: if pass == passCmd2:
if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run": if optRun notin gGlobalOptions and config.arguments.len > 0 and options.command.normalize != "run":
rawMessage(errArgsNeedRunOption, []) rawMessage(errArgsNeedRunOption, [])
proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}) = proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) =
template execute(cmd) = template execute(cmd) =
curCaasCmd = cmd curCaasCmd = cmd
processCmdLine(passCmd2, cmd) processCmdLine(passCmd2, cmd, config)
action(cache) action(cache)
gErrorCounter = 0 gErrorCounter = 0

View file

@ -979,7 +979,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
#result = liftLambdas(prc, result) #result = liftLambdas(prc, result)
when useEffectSystem: trackProc(prc, result) when useEffectSystem: trackProc(prc, result)
result = liftLocalsIfRequested(prc, result) result = liftLocalsIfRequested(prc, result)
if c.needsDestroyPass and newDestructors: if c.needsDestroyPass: #and newDestructors:
result = injectDestructorCalls(prc, result) result = injectDestructorCalls(prc, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
#if prc.name.s == "testbody": #if prc.name.s == "testbody":
@ -996,7 +996,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
when useEffectSystem: trackTopLevelStmt(module, result) when useEffectSystem: trackTopLevelStmt(module, result)
#if n.info ?? "temp.nim": #if n.info ?? "temp.nim":
# echo renderTree(result, {renderIds}) # echo renderTree(result, {renderIds})
if c.needsDestroyPass and newDestructors: if c.needsDestroyPass:
result = injectDestructorCalls(module, result) result = injectDestructorCalls(module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
@ -1007,6 +1007,6 @@ proc transformExpr*(module: PSym, n: PNode): PNode =
var c = openTransf(module, "") var c = openTransf(module, "")
result = processTransf(c, n, module) result = processTransf(c, n, module)
liftDefer(c, result) liftDefer(c, result)
if c.needsDestroyPass and newDestructors: if c.needsDestroyPass:
result = injectDestructorCalls(module, result) result = injectDestructorCalls(module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)

View file

@ -55,7 +55,8 @@ type
wFloatchecks, wNanChecks, wInfChecks, wMoveChecks, wFloatchecks, wNanChecks, wInfChecks, wMoveChecks,
wAssertions, wPatterns, wWarnings, wAssertions, wPatterns, wWarnings,
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
wDeadCodeElim, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wDeadCodeElimUnused, # deprecated, dead code elim always happens
wSafecode, wPackage, wNoForward, wReorder, wNoRewrite,
wPragma, wPragma,
wCompileTime, wNoInit, wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable, wPassc, wPassl, wBorrow, wDiscardable,
@ -143,7 +144,8 @@ const
"assertions", "patterns", "warnings", "hints", "assertions", "patterns", "warnings", "hints",
"optimization", "raises", "writes", "reads", "size", "effects", "tags", "optimization", "raises", "writes", "reads", "size", "effects", "tags",
"deadcodeelim", "safecode", "package", "noforward", "reorder", "norewrite", "deadcodeelim", # deprecated, dead code elim always happens
"safecode", "package", "noforward", "reorder", "norewrite",
"pragma", "pragma",
"compiletime", "noinit", "compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks", "passc", "passl", "borrow", "discardable", "fieldchecks",

View file

@ -35,7 +35,8 @@ Advanced options:
--noLinking compile Nim and generated files but do not link --noLinking compile Nim and generated files but do not link
--noMain do not generate a main procedure --noMain do not generate a main procedure
--genScript generate a compile script (in the 'nimcache' --genScript generate a compile script (in the 'nimcache'
subdirectory named 'compile_$project$scriptext') subdirectory named 'compile_$$project$$scriptext'),
implies --compileOnly
--genDeps generate a '.deps' file containing the dependencies --genDeps generate a '.deps' file containing the dependencies
--os:SYMBOL set the target operating system (cross-compilation) --os:SYMBOL set the target operating system (cross-compilation)
--cpu:SYMBOL set the target processor (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation)
@ -88,5 +89,6 @@ Advanced options:
--parallelBuild:0|1|... perform a parallel build --parallelBuild:0|1|... perform a parallel build
value = number of processors (0 for auto-detect) value = number of processors (0 for auto-detect)
--verbosity:0|1|2|3 set Nim's verbosity level (1 is default) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default)
--experimental enable experimental language features --experimental:$1
enable experimental language feature
-v, --version show detailed version information -v, --version show detailed version information

View file

@ -29,7 +29,6 @@ Options:
--nanChecks:on|off turn NaN checks on|off --nanChecks:on|off turn NaN checks on|off
--infChecks:on|off turn Inf checks on|off --infChecks:on|off turn Inf checks on|off
--nilChecks:on|off turn nil checks on|off --nilChecks:on|off turn nil checks on|off
--deadCodeElim:on|off whole program dead code elimination on|off
--opt:none|speed|size optimize not at all or for speed|size --opt:none|speed|size optimize not at all or for speed|size
Note: use -d:release for a release build! Note: use -d:release for a release build!
--debugger:native|endb use native debugger (gdb) | ENDB (experimental) --debugger:native|endb use native debugger (gdb) | ENDB (experimental)

View file

@ -1397,10 +1397,10 @@ dereferencing operations for reference types:
Automatic dereferencing is also performed for the first argument of a routine Automatic dereferencing is also performed for the first argument of a routine
call. But currently this feature has to be only enabled call. But currently this feature has to be only enabled
via ``{.experimental.}``: via ``{.experimental: "implicitDeref".}``:
.. code-block:: nim .. code-block:: nim
{.experimental.} {.experimental: "implicitDeref".}
proc depth(x: NodeObj): int = ... proc depth(x: NodeObj): int = ...
@ -5588,7 +5588,7 @@ dot operators
------------- -------------
**Note**: Dot operators are still experimental and so need to be enabled **Note**: Dot operators are still experimental and so need to be enabled
via ``{.experimental.}``. via ``{.experimental: "dotOperators".}``.
Nim offers a special family of dot operators that can be used to Nim offers a special family of dot operators that can be used to
intercept and rewrite proc call and field access attempts, referring intercept and rewrite proc call and field access attempts, referring
@ -6768,22 +6768,6 @@ the created global variables within a module is not defined, but all of them
will be initialized after any top-level variables in their originating module will be initialized after any top-level variables in their originating module
and before any variable in a module that imports it. and before any variable in a module that imports it.
deadCodeElim pragma
-------------------
The ``deadCodeElim`` pragma only applies to whole modules: It tells the
compiler to activate (or deactivate) dead code elimination for the module the
pragma appears in.
The ``--deadCodeElim:on`` command line switch has the same effect as marking
every module with ``{.deadCodeElim:on}``. However, for some modules such as
the GTK wrapper it makes sense to *always* turn on dead code elimination -
no matter if it is globally active or not.
Example:
.. code-block:: nim
{.deadCodeElim: on.}
.. ..
NoForward pragma NoForward pragma
@ -6901,17 +6885,12 @@ is uncertain (it may be removed any time).
Example: Example:
.. code-block:: nim .. code-block:: nim
{.experimental.} {.experimental: "parallel".}
type
FooId = distinct int
BarId = distinct int
using
foo: FooId
bar: BarId
proc useUsing(bar, foo) = proc useUsing(bar, foo) =
echo "bar is of type BarId" parallel:
echo "foo is of type FooId" for i in 0..4:
echo "echo in parallel"
Implementation Specific Pragmas Implementation Specific Pragmas
@ -7933,7 +7912,7 @@ Example:
# Compute PI in an inefficient way # Compute PI in an inefficient way
import strutils, math, threadpool import strutils, math, threadpool
{.experimental.} {.experimental: "parallel".}
proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1) proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1)

View file

@ -181,7 +181,7 @@ generated; use the ``--symbolFiles:on`` command line switch to activate them.
Unfortunately due to technical reasons the ``--symbolFiles:on`` needs Unfortunately due to technical reasons the ``--symbolFiles:on`` needs
to *aggregate* some generated C code. This means that the resulting executable to *aggregate* some generated C code. This means that the resulting executable
might contain some cruft even when dead code elimination is turned on. So might contain some cruft even with dead code elimination. So
the final release build should be done with ``--symbolFiles:off``. the final release build should be done with ``--symbolFiles:off``.
Due to the aggregation of C code it is also recommended that each project Due to the aggregation of C code it is also recommended that each project
@ -439,7 +439,7 @@ target.
For example, to generate code for an `AVR`:idx: processor use this command:: For example, to generate code for an `AVR`:idx: processor use this command::
nim c --cpu:avr --os:standalone --deadCodeElim:on --genScript x.nim nim c --cpu:avr --os:standalone --genScript x.nim
For the ``standalone`` target one needs to provide For the ``standalone`` target one needs to provide
a file ``panicoverride.nim``. a file ``panicoverride.nim``.

View file

@ -32,7 +32,7 @@
include "system/inclrtl" include "system/inclrtl"
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
when hostOS == "solaris": when hostOS == "solaris":
{.passl: "-lsocket -lnsl".} {.passl: "-lsocket -lnsl".}

View file

@ -81,7 +81,7 @@
## ##
## theDb.close() ## theDb.close()
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
import strutils, sqlite3 import strutils, sqlite3

View file

@ -13,7 +13,7 @@
## is used. This suffices because Windows' console already provides the ## is used. This suffices because Windows' console already provides the
## wanted functionality. ## wanted functionality.
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
when defined(Windows): when defined(Windows):
proc readLineFromStdin*(prompt: string): TaintedString {. proc readLineFromStdin*(prompt: string): TaintedString {.

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
from posix import SocketHandle from posix import SocketHandle

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
# Get the platform-dependent flags. # Get the platform-dependent flags.
# Structure describing an inotify event. # Structure describing an inotify event.

View file

@ -7,8 +7,6 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim:on.}
from posix import Timespec from posix import Timespec
when defined(macosx) or defined(freebsd) or defined(openbsd) or when defined(macosx) or defined(freebsd) or defined(openbsd) or
@ -61,7 +59,7 @@ const
EV_CLEAR* = 0x0020 ## Clear event state after reporting. EV_CLEAR* = 0x0020 ## Clear event state after reporting.
EV_RECEIPT* = 0x0040 ## Force EV_ERROR on success, data == 0 EV_RECEIPT* = 0x0040 ## Force EV_ERROR on success, data == 0
EV_DISPATCH* = 0x0080 ## Disable event after reporting. EV_DISPATCH* = 0x0080 ## Disable event after reporting.
EV_SYSFLAGS* = 0xF000 ## Reserved by system EV_SYSFLAGS* = 0xF000 ## Reserved by system
EV_DROP* = 0x1000 ## Not should be dropped EV_DROP* = 0x1000 ## Not should be dropped
EV_FLAG1* = 0x2000 ## Filter-specific flag EV_FLAG1* = 0x2000 ## Filter-specific flag
@ -87,10 +85,10 @@ when defined(macosx) or defined(freebsd) or defined(dragonfly):
NOTE_FFAND* = 0x40000000'u32 ## AND fflags NOTE_FFAND* = 0x40000000'u32 ## AND fflags
NOTE_FFOR* = 0x80000000'u32 ## OR fflags NOTE_FFOR* = 0x80000000'u32 ## OR fflags
NOTE_FFCOPY* = 0xc0000000'u32 ## copy fflags NOTE_FFCOPY* = 0xc0000000'u32 ## copy fflags
NOTE_FFCTRLMASK* = 0xc0000000'u32 ## masks for operations NOTE_FFCTRLMASK* = 0xc0000000'u32 ## masks for operations
NOTE_FFLAGSMASK* = 0x00ffffff'u32 NOTE_FFLAGSMASK* = 0x00ffffff'u32
NOTE_TRIGGER* = 0x01000000'u32 ## Cause the event to be triggered NOTE_TRIGGER* = 0x01000000'u32 ## Cause the event to be triggered
## for output. ## for output.
# data/hint flags for EVFILT_{READ|WRITE}, shared with userspace # data/hint flags for EVFILT_{READ|WRITE}, shared with userspace

View file

@ -1,4 +1,4 @@
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
import posix import posix

View file

@ -27,10 +27,10 @@
## resulting C code will just ``#include <XYZ.h>`` and *not* define the ## resulting C code will just ``#include <XYZ.h>`` and *not* define the
## symbols declared here. ## symbols declared here.
# This ensures that we don't accidentally generate #includes for files that # Dead code elimination ensures that we don't accidentally generate #includes
# might not exist on a specific platform! The user will get an error only # for files that might not exist on a specific platform! The user will get an
# if they actualy try to use the missing declaration # error only if they actualy try to use the missing declaration
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
# TODO these constants don't seem to be fetched from a header file for unknown # TODO these constants don't seem to be fetched from a header file for unknown
# platforms - where do they come from and why are they here? # platforms - where do they come from and why are they here?

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
const const
hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
import posix import posix
type type

View file

@ -10,7 +10,7 @@
## Floating-point environment. Handling of floating-point rounding and ## Floating-point environment. Handling of floating-point rounding and
## exceptions (overflow, division by zero, etc.). ## exceptions (overflow, division by zero, etc.).
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
when defined(Posix) and not defined(haiku): when defined(Posix) and not defined(haiku):
{.passl: "-lm".} {.passl: "-lm".}
@ -102,32 +102,33 @@ proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
## represented by object pointed to by `envp` and raise exceptions ## represented by object pointed to by `envp` and raise exceptions
## according to saved exceptions. ## according to saved exceptions.
var FP_RADIX_INTERNAL {. importc: "FLT_RADIX" header: "<float.h>" .} : int const
FLT_RADIX = 2 ## the radix of the exponent representation
template fpRadix* : int = FP_RADIX_INTERNAL FLT_MANT_DIG = 24 ## the number of base FLT_RADIX digits in the mantissa part of a float
FLT_DIG = 6 ## the number of digits of precision of a float
FLT_MIN_EXP = -125 # the minimum value of base FLT_RADIX in the exponent part of a float
FLT_MAX_EXP = 128 # the maximum value of base FLT_RADIX in the exponent part of a float
FLT_MIN_10_EXP = -37 ## the minimum value in base 10 of the exponent part of a float
FLT_MAX_10_EXP = 38 ## the maximum value in base 10 of the exponent part of a float
FLT_MIN = 1.17549435e-38'f32 ## the minimum value of a float
FLT_MAX = 3.40282347e+38'f32 ## the maximum value of a float
FLT_EPSILON = 1.19209290e-07'f32 ## the difference between 1 and the least value greater than 1 of a float
DBL_MANT_DIG = 53 ## the number of base FLT_RADIX digits in the mantissa part of a double
DBL_DIG = 15 ## the number of digits of precision of a double
DBL_MIN_EXP = -1021 ## the minimum value of base FLT_RADIX in the exponent part of a double
DBL_MAX_EXP = 1024 ## the maximum value of base FLT_RADIX in the exponent part of a double
DBL_MIN_10_EXP = -307 ## the minimum value in base 10 of the exponent part of a double
DBL_MAX_10_EXP = 308 ## the maximum value in base 10 of the exponent part of a double
DBL_MIN = 2.2250738585072014E-308 ## the minimal value of a double
DBL_MAX = 1.7976931348623157E+308 ## the minimal value of a double
DBL_EPSILON = 2.2204460492503131E-16 ## the difference between 1 and the least value greater than 1 of a double
template fpRadix* : int = FLT_RADIX
## The (integer) value of the radix used to represent any floating ## The (integer) value of the radix used to represent any floating
## point type on the architecture used to build the program. ## point type on the architecture used to build the program.
var FLT_MANT_DIG {. importc: "FLT_MANT_DIG" header: "<float.h>" .} : int
var FLT_DIG {. importc: "FLT_DIG" header: "<float.h>" .} : int
var FLT_MIN_EXP {. importc: "FLT_MIN_EXP" header: "<float.h>" .} : int
var FLT_MAX_EXP {. importc: "FLT_MAX_EXP" header: "<float.h>" .} : int
var FLT_MIN_10_EXP {. importc: "FLT_MIN_10_EXP" header: "<float.h>" .} : int
var FLT_MAX_10_EXP {. importc: "FLT_MAX_10_EXP" header: "<float.h>" .} : int
var FLT_MIN {. importc: "FLT_MIN" header: "<float.h>" .} : cfloat
var FLT_MAX {. importc: "FLT_MAX" header: "<float.h>" .} : cfloat
var FLT_EPSILON {. importc: "FLT_EPSILON" header: "<float.h>" .} : cfloat
var DBL_MANT_DIG {. importc: "DBL_MANT_DIG" header: "<float.h>" .} : int
var DBL_DIG {. importc: "DBL_DIG" header: "<float.h>" .} : int
var DBL_MIN_EXP {. importc: "DBL_MIN_EXP" header: "<float.h>" .} : int
var DBL_MAX_EXP {. importc: "DBL_MAX_EXP" header: "<float.h>" .} : int
var DBL_MIN_10_EXP {. importc: "DBL_MIN_10_EXP" header: "<float.h>" .} : int
var DBL_MAX_10_EXP {. importc: "DBL_MAX_10_EXP" header: "<float.h>" .} : int
var DBL_MIN {. importc: "DBL_MIN" header: "<float.h>" .} : cdouble
var DBL_MAX {. importc: "DBL_MAX" header: "<float.h>" .} : cdouble
var DBL_EPSILON {. importc: "DBL_EPSILON" header: "<float.h>" .} : cdouble
template mantissaDigits*(T : typedesc[float32]) : int = FLT_MANT_DIG template mantissaDigits*(T : typedesc[float32]) : int = FLT_MANT_DIG
## Number of digits (in base ``floatingPointRadix``) in the mantissa ## Number of digits (in base ``floatingPointRadix``) in the mantissa
## of 32-bit floating-point numbers. ## of 32-bit floating-point numbers.
@ -179,3 +180,11 @@ template maximumPositiveValue*(T : typedesc[float64]) : float64 = DBL_MAX
template epsilon*(T : typedesc[float64]): float64 = DBL_EPSILON template epsilon*(T : typedesc[float64]): float64 = DBL_EPSILON
## The difference between 1.0 and the smallest number greater than ## The difference between 1.0 and the smallest number greater than
## 1.0 that can be represented in a 64-bit floating-point type. ## 1.0 that can be represented in a 64-bit floating-point type.
when isMainModule:
func is_significant(x: float): bool =
if x > minimumPositiveValue(float) and x < maximumPositiveValue(float): true
else: false
doAssert is_significant(10.0)

View file

@ -12,7 +12,7 @@
## **Warning:** This module is deprecated since version 0.14.0. ## **Warning:** This module is deprecated since version 0.14.0.
{.deprecated.} {.deprecated.}
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!

View file

@ -68,7 +68,7 @@
## ``newSocket()``. The difference is that the latter creates a new file ## ``newSocket()``. The difference is that the latter creates a new file
## descriptor. ## descriptor.
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
import nativesockets, os, strutils, parseutils, times, sets, options import nativesockets, os, strutils, parseutils, times, sets, options
export Port, `$`, `==` export Port, `$`, `==`
export Domain, SockType, Protocol export Domain, SockType, Protocol

View file

@ -10,7 +10,7 @@
## This module contains basic operating system facilities like ## This module contains basic operating system facilities like
## retrieving environment variables, reading command line arguments, ## retrieving environment variables, reading command line arguments,
## working with directories, running shell commands, etc. ## working with directories, running shell commands, etc.
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
{.push debugger: off.} {.push debugger: off.}

View file

@ -11,7 +11,7 @@
## ##
## To unpack raw bytes look at the `streams <streams.html>`_ module. ## To unpack raw bytes look at the `streams <streams.html>`_ module.
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!

View file

@ -192,7 +192,7 @@ when not defined(nimscript):
## Initializes the random number generator with a "random" ## Initializes the random number generator with a "random"
## number, i.e. a tickcount. Note: Does not work for NimScript. ## number, i.e. a tickcount. Note: Does not work for NimScript.
let now = times.getTime() let now = times.getTime()
randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanoseconds) randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanosecond)
{.pop.} {.pop.}

View file

@ -19,7 +19,7 @@
include "system/inclrtl" include "system/inclrtl"
import streams import streams
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!

View file

@ -12,7 +12,7 @@
import strutils import strutils
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
proc expandTabs*(s: string, tabSize: int = 8): string {.noSideEffect, proc expandTabs*(s: string, tabSize: int = 8): string {.noSideEffect,
procvar.} = procvar.} =

View file

@ -17,7 +17,7 @@ import parseutils
from math import pow, round, floor, log10 from math import pow, round, floor, log10
from algorithm import reverse from algorithm import reverse
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
{.push debugger:off .} # the user does not want to trace a part {.push debugger:off .} # the user does not want to trace a part
# of the standard library! # of the standard library!
@ -1818,20 +1818,29 @@ proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
dec(L) dec(L)
proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
rtl, extern: "nsuEscape".} = rtl, extern: "nsuEscape", deprecated.} =
## Escapes a string `s`. See `system.addEscapedChar <system.html#addEscapedChar>`_ ## Escapes a string `s`. See `system.addEscapedChar <system.html#addEscapedChar>`_
## for the escaping scheme. ## for the escaping scheme.
## ##
## The resulting string is prefixed with `prefix` and suffixed with `suffix`. ## The resulting string is prefixed with `prefix` and suffixed with `suffix`.
## Both may be empty strings. ## Both may be empty strings.
##
## **Warning:** This procedure is deprecated because it's to easy to missuse.
result = newStringOfCap(s.len + s.len shr 2) result = newStringOfCap(s.len + s.len shr 2)
result.add(prefix) result.add(prefix)
for c in items(s): for c in items(s):
result.addEscapedChar(c) case c
of '\0'..'\31', '\127'..'\255':
add(result, "\\x")
add(result, toHex(ord(c), 2))
of '\\': add(result, "\\\\")
of '\'': add(result, "\\'")
of '\"': add(result, "\\\"")
else: add(result, c)
add(result, suffix) add(result, suffix)
proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
rtl, extern: "nsuUnescape".} = rtl, extern: "nsuUnescape", deprecated.} =
## Unescapes a string `s`. ## Unescapes a string `s`.
## ##
## This complements `escape <#escape>`_ as it performs the opposite ## This complements `escape <#escape>`_ as it performs the opposite
@ -1839,6 +1848,8 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
## ##
## If `s` does not begin with ``prefix`` and end with ``suffix`` a ## If `s` does not begin with ``prefix`` and end with ``suffix`` a
## ValueError exception will be raised. ## ValueError exception will be raised.
##
## **Warning:** This procedure is deprecated because it's to easy to missuse.
result = newStringOfCap(s.len) result = newStringOfCap(s.len)
var i = prefix.len var i = prefix.len
if not s.startsWith(prefix): if not s.startsWith(prefix):

View file

@ -103,7 +103,7 @@ type
Time* = object ## Represents a point in time. Time* = object ## Represents a point in time.
seconds: int64 seconds: int64
nanoseconds: NanosecondRange nanosecond: NanosecondRange
DateTime* = object of RootObj ## Represents a time in different parts. DateTime* = object of RootObj ## Represents a time in different parts.
## Although this type can represent leap ## Although this type can represent leap
@ -159,7 +159,7 @@ type
## This type should be prefered over ``TimeInterval`` unless ## This type should be prefered over ``TimeInterval`` unless
## non-static time units is needed. ## non-static time units is needed.
seconds: int64 seconds: int64
nanoseconds: NanosecondRange nanosecond: NanosecondRange
TimeUnit* = enum ## Different units of time. TimeUnit* = enum ## Different units of time.
Nanoseconds, Microseconds, Milliseconds, Seconds, Minutes, Hours, Days, Weeks, Months, Years Nanoseconds, Microseconds, Milliseconds, Seconds, Minutes, Hours, Days, Weeks, Months, Years
@ -223,21 +223,21 @@ proc normalize[T: Duration|Time](seconds, nanoseconds: int64): T =
## a ``Duration`` or ``Time``. A normalized ``Duration|Time`` has a ## a ``Duration`` or ``Time``. A normalized ``Duration|Time`` has a
## positive nanosecond part in the range ``NanosecondRange``. ## positive nanosecond part in the range ``NanosecondRange``.
result.seconds = seconds + convert(Nanoseconds, Seconds, nanoseconds) result.seconds = seconds + convert(Nanoseconds, Seconds, nanoseconds)
var nanoseconds = nanoseconds mod convert(Seconds, Nanoseconds, 1) var nanosecond = nanoseconds mod convert(Seconds, Nanoseconds, 1)
if nanoseconds < 0: if nanosecond < 0:
nanoseconds += convert(Seconds, Nanoseconds, 1) nanosecond += convert(Seconds, Nanoseconds, 1)
result.seconds -= 1 result.seconds -= 1
result.nanoseconds = nanoseconds.int result.nanosecond = nanosecond.int
proc initTime*(unix: int64, nanoseconds: NanosecondRange): Time = proc initTime*(unix: int64, nanosecond: NanosecondRange): Time =
## Create a ``Time`` from a unix timestamp and a nanosecond part. ## Create a ``Time`` from a unix timestamp and a nanosecond part.
result.seconds = unix result.seconds = unix
result.nanoseconds = nanoseconds result.nanosecond = nanosecond
proc nanoseconds*(time: Time): NanosecondRange = proc nanosecond*(time: Time): NanosecondRange =
## Get the fractional part of a ``Time`` as the number ## Get the fractional part of a ``Time`` as the number
## of nanoseconds of the second. ## of nanoseconds of the second.
time.nanoseconds time.nanosecond
proc initDuration*(nanoseconds, microseconds, milliseconds, proc initDuration*(nanoseconds, microseconds, milliseconds,
seconds, minutes, hours, days, weeks: int64 = 0): Duration = seconds, minutes, hours, days, weeks: int64 = 0): Duration =
@ -281,7 +281,7 @@ proc milliseconds*(dur: Duration): int {.inline.} =
runnableExamples: runnableExamples:
let dur = initDuration(seconds = 1, milliseconds = 1) let dur = initDuration(seconds = 1, milliseconds = 1)
doAssert dur.milliseconds == 1 doAssert dur.milliseconds == 1
convert(Nanoseconds, Milliseconds, dur.nanoseconds) convert(Nanoseconds, Milliseconds, dur.nanosecond)
proc microseconds*(dur: Duration): int {.inline.} = proc microseconds*(dur: Duration): int {.inline.} =
## Number of whole microseconds represented by the **fractional** ## Number of whole microseconds represented by the **fractional**
@ -289,7 +289,7 @@ proc microseconds*(dur: Duration): int {.inline.} =
runnableExamples: runnableExamples:
let dur = initDuration(seconds = 1, microseconds = 1) let dur = initDuration(seconds = 1, microseconds = 1)
doAssert dur.microseconds == 1 doAssert dur.microseconds == 1
convert(Nanoseconds, Microseconds, dur.nanoseconds) convert(Nanoseconds, Microseconds, dur.nanosecond)
proc nanoseconds*(dur: Duration): int {.inline.} = proc nanoseconds*(dur: Duration): int {.inline.} =
## Number of whole nanoseconds represented by the **fractional** ## Number of whole nanoseconds represented by the **fractional**
@ -297,14 +297,14 @@ proc nanoseconds*(dur: Duration): int {.inline.} =
runnableExamples: runnableExamples:
let dur = initDuration(seconds = 1, nanoseconds = 1) let dur = initDuration(seconds = 1, nanoseconds = 1)
doAssert dur.nanoseconds == 1 doAssert dur.nanoseconds == 1
dur.nanoseconds dur.nanosecond
proc fractional*(dur: Duration): Duration {.inline.} = proc fractional*(dur: Duration): Duration {.inline.} =
## The fractional part of duration, as a duration. ## The fractional part of duration, as a duration.
runnableExamples: runnableExamples:
let dur = initDuration(seconds = 1, nanoseconds = 5) let dur = initDuration(seconds = 1, nanoseconds = 5)
doAssert dur.fractional == initDuration(nanoseconds = 5) doAssert dur.fractional == initDuration(nanoseconds = 5)
initDuration(nanoseconds = dur.nanoseconds) initDuration(nanoseconds = dur.nanosecond)
const DurationZero* = initDuration() ## Zero value for durations. Useful for comparisons. const DurationZero* = initDuration() ## Zero value for durations. Useful for comparisons.
## ##
@ -322,7 +322,7 @@ proc `$`*(dur: Duration): string =
doAssert $initDuration(milliseconds = -1500) == "-1 second and -500 milliseconds" doAssert $initDuration(milliseconds = -1500) == "-1 second and -500 milliseconds"
var parts = newSeq[string]() var parts = newSeq[string]()
var remS = dur.seconds var remS = dur.seconds
var remNs = dur.nanoseconds.int var remNs = dur.nanosecond.int
# Normally ``nanoseconds`` should always be positive, but # Normally ``nanoseconds`` should always be positive, but
# that makes no sense when printing. # that makes no sense when printing.
@ -387,7 +387,7 @@ proc fromWinTime*(win: int64): Time =
proc toWinTime*(t: Time): int64 = proc toWinTime*(t: Time): int64 =
## Convert ``t`` to a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``). ## Convert ``t`` to a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``).
result = t.seconds * rateDiff + epochDiff + t.nanoseconds div 100 result = t.seconds * rateDiff + epochDiff + t.nanosecond div 100
proc isLeapYear*(year: int): bool = proc isLeapYear*(year: int): bool =
## Returns true if ``year`` is a leap year. ## Returns true if ``year`` is a leap year.
@ -473,21 +473,21 @@ proc localZoneInfoFromTz(adjTime: Time): ZonedTime {.tags: [], raises: [], benig
{. pragma: operator, rtl, noSideEffect, benign .} {. pragma: operator, rtl, noSideEffect, benign .}
template subImpl[T: Duration|Time](a: Duration|Time, b: Duration|Time): T = template subImpl[T: Duration|Time](a: Duration|Time, b: Duration|Time): T =
normalize[T](a.seconds - b.seconds, a.nanoseconds - b.nanoseconds) normalize[T](a.seconds - b.seconds, a.nanosecond - b.nanosecond)
template addImpl[T: Duration|Time](a: Duration|Time, b: Duration|Time): T = template addImpl[T: Duration|Time](a: Duration|Time, b: Duration|Time): T =
normalize[T](a.seconds + b.seconds, a.nanoseconds + b.nanoseconds) normalize[T](a.seconds + b.seconds, a.nanosecond + b.nanosecond)
template ltImpl(a: Duration|Time, b: Duration|Time): bool = template ltImpl(a: Duration|Time, b: Duration|Time): bool =
a.seconds < b.seconds or ( a.seconds < b.seconds or (
a.seconds == b.seconds and a.nanoseconds < b.nanoseconds) a.seconds == b.seconds and a.nanosecond < b.nanosecond)
template lqImpl(a: Duration|Time, b: Duration|Time): bool = template lqImpl(a: Duration|Time, b: Duration|Time): bool =
a.seconds <= b.seconds or ( a.seconds < b.seconds or (
a.seconds == b.seconds and a.nanoseconds <= b.seconds) a.seconds == b.seconds and a.nanosecond <= b.nanosecond)
template eqImpl(a: Duration|Time, b: Duration|Time): bool = template eqImpl(a: Duration|Time, b: Duration|Time): bool =
a.seconds == b.seconds and a.nanoseconds == b.nanoseconds a.seconds == b.seconds and a.nanosecond == b.nanosecond
proc `+`*(a, b: Duration): Duration {.operator.} = proc `+`*(a, b: Duration): Duration {.operator.} =
## Add two durations together. ## Add two durations together.
@ -507,7 +507,7 @@ proc `-`*(a: Duration): Duration {.operator.} =
## Reverse a duration. ## Reverse a duration.
runnableExamples: runnableExamples:
doAssert -initDuration(seconds = 1) == initDuration(seconds = -1) doAssert -initDuration(seconds = 1) == initDuration(seconds = -1)
normalize[Duration](-a.seconds, -a.nanoseconds) normalize[Duration](-a.seconds, -a.nanosecond)
proc `<`*(a, b: Duration): bool {.operator.} = proc `<`*(a, b: Duration): bool {.operator.} =
## Note that a duration can be negative, ## Note that a duration can be negative,
@ -530,7 +530,7 @@ proc `*`*(a: int64, b: Duration): Duration {.operator} =
## Multiply a duration by some scalar. ## Multiply a duration by some scalar.
runnableExamples: runnableExamples:
doAssert 5 * initDuration(seconds = 1) == initDuration(seconds = 5) doAssert 5 * initDuration(seconds = 1) == initDuration(seconds = 5)
normalize[Duration](a * b.seconds, a * b.nanoseconds) normalize[Duration](a * b.seconds, a * b.nanosecond)
proc `*`*(a: Duration, b: int64): Duration {.operator} = proc `*`*(a: Duration, b: int64): Duration {.operator} =
## Multiply a duration by some scalar. ## Multiply a duration by some scalar.
@ -544,7 +544,7 @@ proc `div`*(a: Duration, b: int64): Duration {.operator} =
doAssert initDuration(seconds = 3) div 2 == initDuration(milliseconds = 1500) doAssert initDuration(seconds = 3) div 2 == initDuration(milliseconds = 1500)
doAssert initDuration(nanoseconds = 3) div 2 == initDuration(nanoseconds = 1) doAssert initDuration(nanoseconds = 3) div 2 == initDuration(nanoseconds = 1)
let carryOver = convert(Seconds, Nanoseconds, a.seconds mod b) let carryOver = convert(Seconds, Nanoseconds, a.seconds mod b)
normalize[Duration](a.seconds div b, (a.nanoseconds + carryOver) div b) normalize[Duration](a.seconds div b, (a.nanosecond + carryOver) div b)
proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} = proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} =
## Computes the duration between two points in time. ## Computes the duration between two points in time.
@ -600,7 +600,7 @@ proc abs*(a: Duration): Duration =
runnableExamples: runnableExamples:
doAssert initDuration(milliseconds = -1500).abs == doAssert initDuration(milliseconds = -1500).abs ==
initDuration(milliseconds = 1500) initDuration(milliseconds = 1500)
initDuration(seconds = abs(a.seconds), nanoseconds = -a.nanoseconds) initDuration(seconds = abs(a.seconds), nanoseconds = -a.nanosecond)
proc toTime*(dt: DateTime): Time {.tags: [], raises: [], benign.} = proc toTime*(dt: DateTime): Time {.tags: [], raises: [], benign.} =
## Converts a broken-down time structure to ## Converts a broken-down time structure to
@ -650,7 +650,7 @@ proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime =
hour: hour, hour: hour,
minute: minute, minute: minute,
second: second, second: second,
nanosecond: zt.adjTime.nanoseconds, nanosecond: zt.adjTime.nanosecond,
weekday: getDayOfWeek(d, m, y), weekday: getDayOfWeek(d, m, y),
yearday: getDayOfYear(d, m, y), yearday: getDayOfYear(d, m, y),
isDst: zt.isDst, isDst: zt.isDst,
@ -809,7 +809,7 @@ else:
# as a result of offset changes (normally due to dst) # as a result of offset changes (normally due to dst)
let utcUnix = adjTime.seconds + utcOffset let utcUnix = adjTime.seconds + utcOffset
let (finalOffset, dst) = getLocalOffsetAndDst(utcUnix) let (finalOffset, dst) = getLocalOffsetAndDst(utcUnix)
result.adjTime = initTime(utcUnix - finalOffset, adjTime.nanoseconds) result.adjTime = initTime(utcUnix - finalOffset, adjTime.nanosecond)
result.utcOffset = finalOffset result.utcOffset = finalOffset
result.isDst = dst result.isDst = dst
@ -1806,7 +1806,7 @@ proc toSeconds*(time: Time): float {.tags: [], raises: [], benign, deprecated.}
## Returns the time in seconds since the unix epoch. ## Returns the time in seconds since the unix epoch.
## ##
## **Deprecated since v0.18.0:** use ``fromUnix`` instead ## **Deprecated since v0.18.0:** use ``fromUnix`` instead
time.seconds.float + time.nanoseconds / convert(Seconds, Nanoseconds, 1) time.seconds.float + time.nanosecond / convert(Seconds, Nanoseconds, 1)
proc getLocalTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} = proc getLocalTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} =
## Converts the calendar time `time` to broken-time representation, ## Converts the calendar time `time` to broken-time representation,
@ -1853,7 +1853,7 @@ when defined(JS):
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead. ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
let dur = getTime() - start let dur = getTime() - start
result = (convert(Seconds, Milliseconds, dur.seconds) + result = (convert(Seconds, Milliseconds, dur.seconds) +
convert(Nanoseconds, Milliseconds, dur.nanoseconds)).int convert(Nanoseconds, Milliseconds, dur.nanosecond)).int
else: else:
proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], benign.} = proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], benign.} =
when defined(macosx): when defined(macosx):

View file

@ -9,7 +9,7 @@
## This module provides support to handle the Unicode UTF-8 encoding. ## This module provides support to handle the Unicode UTF-8 encoding.
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
include "system/inclrtl" include "system/inclrtl"

View file

@ -12,9 +12,9 @@
import macros, strtabs import macros, strtabs
type type
XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s. XmlNode* = ref XmlNodeObj ## an XML tree consists of ``XmlNode``'s.
XmlNodeKind* = enum ## different kinds of ``PXmlNode``'s XmlNodeKind* = enum ## different kinds of ``XmlNode``'s
xnText, ## a text element xnText, ## a text element
xnElement, ## an element with 0 or more children xnElement, ## an element with 0 or more children
xnCData, ## a CDATA node xnCData, ## a CDATA node
@ -315,9 +315,7 @@ proc newXmlTree*(tag: string, children: openArray[XmlNode],
for i in 0..children.len-1: result.s[i] = children[i] for i in 0..children.len-1: result.s[i] = children[i]
result.fAttr = attributes result.fAttr = attributes
proc xmlConstructor(e: NimNode): NimNode {.compileTime.} = proc xmlConstructor(a: NimNode): NimNode {.compileTime.} =
expectLen(e, 2)
var a = e[1]
if a.kind == nnkCall: if a.kind == nnkCall:
result = newCall("newXmlTree", toStrLit(a[0])) result = newCall("newXmlTree", toStrLit(a[0]))
var attrs = newNimNode(nnkBracket, a) var attrs = newNimNode(nnkBracket, a)
@ -348,7 +346,6 @@ macro `<>`*(x: untyped): untyped =
## ##
## <a href="http://nim-lang.org">Nim rules.</a> ## <a href="http://nim-lang.org">Nim rules.</a>
## ##
let x = callsite()
result = xmlConstructor(x) result = xmlConstructor(x)
proc child*(n: XmlNode, name: string): XmlNode = proc child*(n: XmlNode, name: string): XmlNode =

View file

@ -146,7 +146,7 @@ proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
## # missing it. ## # missing it.
when defined(useNimRtl): when defined(useNimRtl):
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
proc definedInScope*(x: untyped): bool {. proc definedInScope*(x: untyped): bool {.
magic: "DefinedInScope", noSideEffect, deprecated, compileTime.} magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
@ -3933,29 +3933,48 @@ proc addEscapedChar*(s: var string, c: char) {.noSideEffect, inline.} =
## * replaces any ``\`` by ``\\`` ## * replaces any ``\`` by ``\\``
## * replaces any ``'`` by ``\'`` ## * replaces any ``'`` by ``\'``
## * replaces any ``"`` by ``\"`` ## * replaces any ``"`` by ``\"``
## * replaces any other character in the set ``{'\0'..'\31', '\127'..'\255'}`` ## * replaces any ``\a`` by ``\\a``
## * replaces any ``\b`` by ``\\b``
## * replaces any ``\t`` by ``\\t``
## * replaces any ``\n`` by ``\\n``
## * replaces any ``\v`` by ``\\v``
## * replaces any ``\f`` by ``\\f``
## * replaces any ``\c`` by ``\\c``
## * replaces any ``\e`` by ``\\e``
## * replaces any other character not in the set ``{'\21..'\126'}
## by ``\xHH`` where ``HH`` is its hexadecimal value. ## by ``\xHH`` where ``HH`` is its hexadecimal value.
## ##
## The procedure has been designed so that its output is usable for many ## The procedure has been designed so that its output is usable for many
## different common syntaxes. ## different common syntaxes.
## **Note**: This is not correct for producing Ansi C code! ## **Note**: This is not correct for producing Ansi C code!
case c case c
of '\0'..'\31', '\127'..'\255': of '\a': s.add "\\a" # \x07
add(s, "\\x") of '\b': s.add "\\b" # \x08
of '\t': s.add "\\t" # \x09
of '\n': s.add "\\n" # \x0A
of '\v': s.add "\\v" # \x0B
of '\f': s.add "\\f" # \x0C
of '\c': s.add "\\c" # \x0D
of '\e': s.add "\\e" # \x1B
of '\\': s.add("\\\\")
of '\'': s.add("\\'")
of '\"': s.add("\\\"")
of {'\32'..'\126'} - {'\\', '\'', '\"'}: s.add(c)
else:
s.add("\\x")
const HexChars = "0123456789ABCDEF" const HexChars = "0123456789ABCDEF"
let n = ord(c) let n = ord(c)
s.add(HexChars[int((n and 0xF0) shr 4)]) s.add(HexChars[int((n and 0xF0) shr 4)])
s.add(HexChars[int(n and 0xF)]) s.add(HexChars[int(n and 0xF)])
of '\\': add(s, "\\\\")
of '\'': add(s, "\\'")
of '\"': add(s, "\\\"")
else: add(s, c)
proc addQuoted*[T](s: var string, x: T) = proc addQuoted*[T](s: var string, x: T) =
## Appends `x` to string `s` in place, applying quoting and escaping ## Appends `x` to string `s` in place, applying quoting and escaping
## if `x` is a string or char. See ## if `x` is a string or char. See
## `addEscapedChar <system.html#addEscapedChar>`_ ## `addEscapedChar <system.html#addEscapedChar>`_
## for the escaping scheme. ## for the escaping scheme. When `x` is a string, characters in the
## range ``{\128..\255}`` are never escaped so that multibyte UTF-8
## characters are untouched (note that this behavior is different from
## ``addEscapedChar``).
## ##
## The Nim standard library uses this function on the elements of ## The Nim standard library uses this function on the elements of
## collections when producing a string representation of a collection. ## collections when producing a string representation of a collection.
@ -3974,7 +3993,12 @@ proc addQuoted*[T](s: var string, x: T) =
when T is string: when T is string:
s.add("\"") s.add("\"")
for c in x: for c in x:
s.addEscapedChar(c) # Only ASCII chars are escaped to avoid butchering
# multibyte UTF-8 characters.
if c <= 127.char:
s.addEscapedChar(c)
else:
s.add c
s.add("\"") s.add("\"")
elif T is char: elif T is char:
s.add("'") s.add("'")

View file

@ -10,7 +10,7 @@
## This module implements a small wrapper for some needed Win API procedures, ## This module implements a small wrapper for some needed Win API procedures,
## so that the Nim compiler does not depend on the huge Windows module. ## so that the Nim compiler does not depend on the huge Windows module.
{.deadCodeElim:on.} {.deadCodeElim: on.} # dce option deprecated
import dynlib import dynlib

View file

@ -34,7 +34,7 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# **************************************************************************** # ****************************************************************************
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
when defined(windows): when defined(windows):
const dllname = "iup(|30|27|26|25|24).dll" const dllname = "iup(|30|27|26|25|24).dll"

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
{.push, callconv: cdecl.} {.push, callconv: cdecl.}
when defined(Unix): when defined(Unix):

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
when not defined(ODBCVER): when not defined(ODBCVER):
const const

View file

@ -22,7 +22,7 @@
## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim ## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim ## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
const useWinVersion = defined(Windows) or defined(nimdoc) const useWinVersion = defined(Windows) or defined(nimdoc)

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
# The current PCRE version information. # The current PCRE version information.

View file

@ -15,7 +15,7 @@
# connection-protocol. # connection-protocol.
# #
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
when defined(windows): when defined(windows):
const const

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
{.deadCodeElim: on.} {.deadCodeElim: on.} # dce option deprecated
when defined(windows): when defined(windows):
when defined(nimOldDlls): when defined(nimOldDlls):
const Lib = "sqlite3.dll" const Lib = "sqlite3.dll"

View file

@ -518,7 +518,7 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) =
close(requests) close(requests)
close(results) close(results)
proc processCmdLine*(pass: TCmdLinePass, cmd: string) = proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd) var p = parseopt.initOptParser(cmd)
while true: while true:
parseopt.next(p) parseopt.next(p)
@ -562,7 +562,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
gRefresh = true gRefresh = true
of "maxresults": of "maxresults":
suggestMaxResults = parseInt(p.val) suggestMaxResults = parseInt(p.val)
else: processSwitch(pass, p) else: processSwitch(pass, p, config)
of cmdArgument: of cmdArgument:
let a = unixToNativePath(p.key) let a = unixToNativePath(p.key)
if dirExists(a) and not fileExists(a.addFileExt("nim")): if dirExists(a) and not fileExists(a.addFileExt("nim")):
@ -577,7 +577,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
if paramCount() == 0: if paramCount() == 0:
stdout.writeline(Usage) stdout.writeline(Usage)
else: else:
processCmdLine(passCmd1, "") processCmdLine(passCmd1, "", config)
if gMode != mstdin: if gMode != mstdin:
msgs.writelnHook = proc (msg: string) = discard msgs.writelnHook = proc (msg: string) = discard
if gProjectName != "": if gProjectName != "":
@ -616,7 +616,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config) runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config)
extccomp.initVars() extccomp.initVars()
processCmdLine(passCmd2, "") processCmdLine(passCmd2, "", config)
let graph = newModuleGraph(config) let graph = newModuleGraph(config)
graph.suggestMode = true graph.suggestMode = true

View file

@ -14,6 +14,7 @@ GenericT[T] '=' bool
GenericT[T] '=' bool GenericT[T] '=' bool
GenericT[T] '=' bool GenericT[T] '=' bool
GenericT[T] '=' bool''' GenericT[T] '=' bool'''
disabled: "true"
""" """
import typetraits import typetraits

View file

@ -1,6 +1,7 @@
discard """ discard """
output: '''i value 88 output: '''i value 88
2aa''' 2aa'''
disabled: "true"
""" """
import moverload_asgn2 import moverload_asgn2

View file

@ -85,14 +85,20 @@ block:
s.addQuoted('\0') s.addQuoted('\0')
s.addQuoted('\31') s.addQuoted('\31')
s.addQuoted('\127') s.addQuoted('\127')
s.addQuoted('\255') doAssert s == "'\\x00''\\x1F''\\x7F'"
doAssert s == "'\\x00''\\x1F''\\x7F''\\xFF'"
block: block:
var s = "" var s = ""
s.addQuoted('\\') s.addQuoted('\\')
s.addQuoted('\'') s.addQuoted('\'')
s.addQuoted('\"') s.addQuoted('\"')
doAssert s == """'\\''\'''\"'""" doAssert s == """'\\''\'''\"'"""
block:
var s = ""
s.addQuoted("å")
s.addQuoted("ä")
s.addQuoted("ö")
s.addEscapedChar('\xFF')
doAssert s == """"å""ä""ö"\xFF"""
# Test customized element representation # Test customized element representation
type CustomString = object type CustomString = object

View file

@ -4,7 +4,7 @@ type
TOption = enum TOption = enum
optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck, optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck,
optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir, optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir,
optWarns, optHints, optDeadCodeElim, optListCmd, optCompileOnly, optWarns, optHints, optListCmd, optCompileOnly,
optSafeCode, # only allow safe code optSafeCode, # only allow safe code
optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib, optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib,
optGenGuiApp, optStackTrace optGenGuiApp, optStackTrace

View file

@ -0,0 +1,5 @@
discard """
file: "tgenscript.nim"
"""
echo "--genscript"

View file

@ -4,8 +4,6 @@ discard """
# bug #2023 # bug #2023
{.deadCodeElim:on.}
type type
Obj = object Obj = object
iter: iterator (): int8 {.closure.} iter: iterator (): int8 {.closure.}

View file

@ -23,7 +23,6 @@ const Lib = "libchipmunk.so.6.1.1"
when defined(MoreNim): when defined(MoreNim):
{.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".} {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".}
{.deadCodeElim: on.}
from math import sqrt, sin, cos, arctan2 from math import sqrt, sin, cos, arctan2
when defined(CpUseFloat): when defined(CpUseFloat):
{.hint: "CpUseFloat defined; using float32 as float".} {.hint: "CpUseFloat defined; using float32 as float".}

View file

@ -20,7 +20,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
const Lib = "libenet.so.1(|.0.3)" const Lib = "libenet.so.1(|.0.3)"
{.deadCodeElim: on.}
const const
ENET_VERSION_MAJOR* = 1 ENET_VERSION_MAJOR* = 1
ENET_VERSION_MINOR* = 3 ENET_VERSION_MINOR* = 3

View file

@ -1,5 +1,5 @@
import macros import macros
{.deadCodeElim: on.}
#Inline macro.add() to allow for easier nesting #Inline macro.add() to allow for easier nesting
proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} = proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} =
a.add(b) a.add(b)

View file

@ -12,7 +12,7 @@ else:
LibS = "libcsfml-system.so.2.0" LibS = "libcsfml-system.so.2.0"
LibW = "libcsfml-window.so.2.0" LibW = "libcsfml-window.so.2.0"
#{.error: "Platform unsupported".} #{.error: "Platform unsupported".}
{.deadCodeElim: on.}
{.pragma: pf, pure, final.} {.pragma: pf, pure, final.}
type type
PClock* = ptr TClock PClock* = ptr TClock

View file

@ -1,5 +1,5 @@
import sfml import sfml
{.deadCodeElim: on.}
let let
Black*: TColor = color(0, 0, 0) Black*: TColor = color(0, 0, 0)
White*: TColor = color(255, 255, 255) White*: TColor = color(255, 255, 255)

View file

@ -1,2 +1 @@
import sfml, math, strutils import sfml, math, strutils
{.deadCodeElim: on.}

View file

@ -5,7 +5,7 @@ import
sg_gui, sg_assets, sound_buffer, enet_client sg_gui, sg_assets, sound_buffer, enet_client
when defined(profiler): when defined(profiler):
import nimprof import nimprof
{.deadCodeElim: on.}
type type
PPlayer* = ref TPlayer PPlayer* = ref TPlayer
TPlayer* = object TPlayer* = object

View file

@ -2,7 +2,7 @@ import
sfml, sfml_colors, sfml, sfml_colors,
input_helpers, sg_packets input_helpers, sg_packets
from strutils import countlines from strutils import countlines
{.deadCodeElim: on.}
type type
PGuiContainer* = ref TGuiContainer PGuiContainer* = ref TGuiContainer
TGuiContainer* = object of TObject TGuiContainer* = object of TObject

View file

@ -1,5 +1,4 @@
debugger = off debugger = off
deadCodeElim = on
path = ".." path = ".."
path = "../genpacket" path = "../genpacket"
path = "../helpers" path = "../helpers"

View file

@ -10,7 +10,7 @@ const
ExeName = "keineschweine" ExeName = "keineschweine"
ServerDefines = "-d:NoSFML -d:NoChipmunk" ServerDefines = "-d:NoSFML -d:NoChipmunk"
TestBuildDefines = "-d:escapeMenuTest -d:debugWeps -d:showFPS -d:moreNim -d:debugKeys -d:foo -d:recordMode --forceBuild" TestBuildDefines = "-d:escapeMenuTest -d:debugWeps -d:showFPS -d:moreNim -d:debugKeys -d:foo -d:recordMode --forceBuild"
ReleaseDefines = "-d:release --deadCodeElim:on" ReleaseDefines = "-d:release"
ReleaseTestDefines = "-d:debugWeps -d:debugKeys --forceBuild" ReleaseTestDefines = "-d:debugWeps -d:debugKeys --forceBuild"
task "testprofile", "..": task "testprofile", "..":

View file

@ -1,3 +1,2 @@
--os:standalone --os:standalone
--deadCodeElim:on
--gc:none --gc:none

View file

@ -4,7 +4,7 @@ discard """
import threadpool, sequtils import threadpool, sequtils
{.experimental.} {.experimental: "parallel".}
proc linearFind(a: openArray[int]; x, offset: int): int = proc linearFind(a: openArray[int]; x, offset: int): int =
for i, y in a: for i, y in a:

View file

@ -2,13 +2,16 @@ discard """
ccodeCheck: "\\i @'__attribute__((noreturn))' .*" ccodeCheck: "\\i @'__attribute__((noreturn))' .*"
""" """
proc noret1*(i: int) {.noreturn.} = proc noret1*(i: int) {.noreturn.} =
echo i echo i
proc noret2*(i: int): void {.noreturn.} = proc noret2*(i: int): void {.noreturn.} =
echo i echo i
noret1(1)
noret2(2)
var p {.used.}: proc(i: int): int var p {.used.}: proc(i: int): int
doAssert(not compiles( doAssert(not compiles(
p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int

View file

@ -1,6 +1,3 @@
{.deadCodeElim: on.}
proc p1*(x, y: int): int = proc p1*(x, y: int): int =
result = x + y result = x + y

View file

@ -367,6 +367,10 @@ suite "ttimes":
check d(seconds = 0) - d(milliseconds = 1500) == d(milliseconds = -1500) check d(seconds = 0) - d(milliseconds = 1500) == d(milliseconds = -1500)
check d(milliseconds = -1500) == d(seconds = -1, milliseconds = -500) check d(milliseconds = -1500) == d(seconds = -1, milliseconds = -500)
check d(seconds = -1, milliseconds = 500) == d(milliseconds = -500) check d(seconds = -1, milliseconds = 500) == d(milliseconds = -500)
check initDuration(seconds = 1, nanoseconds = 2) <=
initDuration(seconds = 1, nanoseconds = 3)
check (initDuration(seconds = 1, nanoseconds = 3) <=
initDuration(seconds = 1, nanoseconds = 1)).not
test "large/small dates": test "large/small dates":
discard initDateTime(1, mJan, -35_000, 12, 00, 00, utc()) discard initDateTime(1, mJan, -35_000, 12, 00, 00, utc())
@ -413,7 +417,7 @@ suite "ttimes":
test "fromWinTime/toWinTime": test "fromWinTime/toWinTime":
check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0 check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0
check (-1).fromWinTime.nanoseconds == convert(Seconds, Nanoseconds, 1) - 100 check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100
check -1.fromWinTime.toWinTime == -1 check -1.fromWinTime.toWinTime == -1
# One nanosecond is discarded due to differences in time resolution # One nanosecond is discarded due to differences in time resolution
check initTime(0, 101).toWinTime.fromWinTime.nanoseconds == 100 check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100

View file

@ -13,7 +13,7 @@ type
CommitId = distinct string CommitId = distinct string
proc `$`*(id: MachineId): string {.borrow.} proc `$`*(id: MachineId): string {.borrow.}
proc `$`(id: CommitId): string {.borrow.} #proc `$`(id: CommitId): string {.borrow.} # not used
var var
thisMachine: MachineId thisMachine: MachineId

View file

@ -63,6 +63,26 @@ proc compileRodFiles(r: var TResults, cat: Category, options: string) =
test "gtkex1", true test "gtkex1", true
test "gtkex2" test "gtkex2"
# --------------------- flags tests -------------------------------------------
proc flagTests(r: var TResults, cat: Category, options: string) =
# --genscript
const filename = "tests"/"flags"/"tgenscript"
const genopts = " --genscript"
let nimcache = nimcacheDir(filename, genopts, targetC)
testSpec r, makeTest(filename, genopts, cat)
when defined(windows):
testExec r, makeTest(filename, " cmd /c cd " & nimcache &
" && compile_tgenscript.bat", cat)
when defined(linux):
testExec r, makeTest(filename, " sh -c \"cd " & nimcache &
" && sh compile_tgenscript.sh\"", cat)
# Run
testExec r, makeTest(filename, " " & nimcache / "tgenscript", cat)
# --------------------- DLL generation tests ---------------------------------- # --------------------- DLL generation tests ----------------------------------
proc safeCopyFile(src, dest: string) = proc safeCopyFile(src, dest: string) =
@ -323,7 +343,7 @@ var nimbleDir = getEnv("NIMBLE_DIR").string
if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble" if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
let let
nimbleExe = findExe("nimble") nimbleExe = findExe("nimble")
packageDir = nimbleDir / "pkgs" #packageDir = nimbleDir / "pkgs" # not used
packageIndex = nimbleDir / "packages.json" packageIndex = nimbleDir / "packages.json"
proc waitForExitEx(p: Process): int = proc waitForExitEx(p: Process): int =
@ -407,9 +427,9 @@ proc `&.?`(a, b: string): string =
# candidate for the stdlib? # candidate for the stdlib?
result = if b.startswith(a): b else: a & b result = if b.startswith(a): b else: a & b
proc `&?.`(a, b: string): string = #proc `&?.`(a, b: string): string = # not used
# candidate for the stdlib? # candidate for the stdlib?
result = if a.endswith(b): a else: a & b #result = if a.endswith(b): a else: a & b
proc processSingleTest(r: var TResults, cat: Category, options, test: string) = proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
let test = "tests" & DirSep &.? cat.string / test let test = "tests" & DirSep &.? cat.string / test
@ -429,6 +449,8 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
jsTests(r, cat, options) jsTests(r, cat, options)
of "dll": of "dll":
dllTests(r, cat, options) dllTests(r, cat, options)
of "flags":
flagTests(r, cat, options)
of "gc": of "gc":
gcTests(r, cat, options) gcTests(r, cat, options)
of "longgc": of "longgc":

View file

@ -121,7 +121,7 @@ proc generateAllTestsContent(outfile: File, allResults: AllTests,
proc generateHtml*(filename: string, onlyFailing: bool) = proc generateHtml*(filename: string, onlyFailing: bool) =
let let
currentTime = getTime().getLocalTime() currentTime = getTime().local()
timestring = htmlQuote format(currentTime, "yyyy-MM-dd HH:mm:ss 'UTC'zzz") timestring = htmlQuote format(currentTime, "yyyy-MM-dd HH:mm:ss 'UTC'zzz")
var outfile = open(filename, fmWrite) var outfile = open(filename, fmWrite)

View file

@ -16,7 +16,7 @@ import
const const
resultsFile = "testresults.html" resultsFile = "testresults.html"
jsonFile = "testresults.json" #jsonFile = "testresults.json" # not used
Usage = """Usage: Usage = """Usage:
tester [options] command [arguments] tester [options] command [arguments]
@ -150,11 +150,11 @@ proc initResults: TResults =
result.skipped = 0 result.skipped = 0
result.data = "" result.data = ""
proc readResults(filename: string): TResults = #proc readResults(filename: string): TResults = # not used
result = marshal.to[TResults](readFile(filename).string) # result = marshal.to[TResults](readFile(filename).string)
proc writeResults(filename: string, r: TResults) = #proc writeResults(filename: string, r: TResults) = # not used
writeFile(filename, $$r) # writeFile(filename, $$r)
proc `$`(x: TResults): string = proc `$`(x: TResults): string =
result = ("Tests passed: $1 / $3 <br />\n" & result = ("Tests passed: $1 / $3 <br />\n" &
@ -404,6 +404,21 @@ proc testC(r: var TResults, test: TTest) =
if exitCode != 0: given.err = reExitCodesDiffer if exitCode != 0: given.err = reExitCodesDiffer
if given.err == reSuccess: inc(r.passed) if given.err == reSuccess: inc(r.passed)
proc testExec(r: var TResults, test: TTest) =
# runs executable or script, just goes by exit code
inc(r.total)
let (outp, errC) = execCmdEx(test.options.strip())
var given: TSpec
specDefaults(given)
if errC == 0:
given.err = reSuccess
else:
given.err = reExitCodesDiffer
given.msg = outp.string
if given.err == reSuccess: inc(r.passed)
r.addResult(test, targetC, "", given.msg, given.err)
proc makeTest(test, options: string, cat: Category, action = actionCompile, proc makeTest(test, options: string, cat: Category, action = actionCompile,
env: string = ""): TTest = env: string = ""): TTest =
# start with 'actionCompile', will be overwritten in the spec: # start with 'actionCompile', will be overwritten in the spec:

View file

@ -15,7 +15,7 @@ _nim()
return 0 return 0
fi fi
case $prev in case $prev in
--stackTrace|--lineTrace|--threads|-x|--checks|--objChecks|--fieldChecks|--rangeChecks|--boundChecks|--overflowChecks|-a|--assertions|--floatChecks|--nanChecks|--infChecks|--deadCodeElim) --stackTrace|--lineTrace|--threads|-x|--checks|--objChecks|--fieldChecks|--rangeChecks|--boundChecks|--overflowChecks|-a|--assertions|--floatChecks|--nanChecks|--infChecks)
# Options that require on/off # Options that require on/off
[[ "$cur" == "=" ]] && cur="" [[ "$cur" == "=" ]] && cur=""
COMPREPLY=( $(compgen -W 'on off' -- "$cur") ) COMPREPLY=( $(compgen -W 'on off' -- "$cur") )
@ -32,7 +32,7 @@ _nim()
return 0 return 0
;; ;;
*) *)
kw="-r -p= --path= -d= --define= -u= --undef= -f --forceBuild --opt= --app= --stackTrace= --lineTrace= --threads= -x= --checks= --objChecks= --fieldChecks= --rangeChecks= --boundChecks= --overflowChecks= -a= --assertions= --floatChecks= --nanChecks= --infChecks= --deadCodeElim=" kw="-r -p= --path= -d= --define= -u= --undef= -f --forceBuild --opt= --app= --stackTrace= --lineTrace= --threads= -x= --checks= --objChecks= --fieldChecks= --rangeChecks= --boundChecks= --overflowChecks= -a= --assertions= --floatChecks= --nanChecks= --infChecks="
COMPREPLY=( $( compgen -W "${kw}" -- $cur ) ) COMPREPLY=( $( compgen -W "${kw}" -- $cur ) )
_filedir '@(nim)' _filedir '@(nim)'
#$split #$split

View file

@ -60,8 +60,6 @@ _nim() {
'*--infChecks=off[turn Inf checks off]' \ '*--infChecks=off[turn Inf checks off]' \
'*--nilChecks=on[turn nil checks on]' \ '*--nilChecks=on[turn nil checks on]' \
'*--nilChecks=off[turn nil checks off]' \ '*--nilChecks=off[turn nil checks off]' \
'*--deadCodeElim=on[whole program dead code elimination on]' \
'*--deadCodeElim=off[whole program dead code elimination off]' \
'*--opt=none[do not optimize]' \ '*--opt=none[do not optimize]' \
'*--opt=speed[optimize for speed|size - use -d:release for a release build]' \ '*--opt=speed[optimize for speed|size - use -d:release for a release build]' \
'*--opt=size[optimize for size]' \ '*--opt=size[optimize for size]' \

View file

@ -11,7 +11,7 @@ import
os, strutils, parseopt, pegs, re, terminal os, strutils, parseopt, pegs, re, terminal
const const
Version = "1.1" Version = "1.2"
Usage = "nimgrep - Nim Grep Utility Version " & Version & """ Usage = "nimgrep - Nim Grep Utility Version " & Version & """
(c) 2012 Andreas Rumpf (c) 2012 Andreas Rumpf
@ -35,6 +35,8 @@ Options:
--nocolor output will be given without any colours. --nocolor output will be given without any colours.
--oneline show file on each matched line --oneline show file on each matched line
--verbose be verbose: list every processed file --verbose be verbose: list every processed file
--filenames find the pattern in the filenames, not in the contents
of the file
--help, -h shows this help --help, -h shows this help
--version, -v shows the version --version, -v shows the version
""" """
@ -42,7 +44,7 @@ Options:
type type
TOption = enum TOption = enum
optFind, optReplace, optPeg, optRegex, optRecursive, optConfirm, optStdin, optFind, optReplace, optPeg, optRegex, optRecursive, optConfirm, optStdin,
optWord, optIgnoreCase, optIgnoreStyle, optVerbose optWord, optIgnoreCase, optIgnoreStyle, optVerbose, optFilenames
TOptions = set[TOption] TOptions = set[TOption]
TConfirmEnum = enum TConfirmEnum = enum
ceAbort, ceYes, ceAll, ceNo, ceNone ceAbort, ceYes, ceAll, ceNo, ceNone
@ -135,11 +137,14 @@ proc processFile(pattern; filename: string) =
filenameShown = true filenameShown = true
var buffer: string var buffer: string
try: if optFilenames in options:
buffer = system.readFile(filename) buffer = filename
except IOError: else:
echo "cannot open file: ", filename try:
return buffer = system.readFile(filename)
except IOError:
echo "cannot open file: ", filename
return
if optVerbose in options: if optVerbose in options:
stdout.writeLine(filename) stdout.writeLine(filename)
stdout.flushFile() stdout.flushFile()
@ -293,6 +298,7 @@ for kind, key, val in getopt():
of "nocolor": useWriteStyled = false of "nocolor": useWriteStyled = false
of "oneline": oneline = true of "oneline": oneline = true
of "verbose": incl(options, optVerbose) of "verbose": incl(options, optVerbose)
of "filenames": incl(options, optFilenames)
of "help", "h": writeHelp() of "help", "h": writeHelp()
of "version", "v": writeVersion() of "version", "v": writeVersion()
else: writeHelp() else: writeHelp()
@ -304,6 +310,7 @@ when defined(posix):
checkOptions({optFind, optReplace}, "find", "replace") checkOptions({optFind, optReplace}, "find", "replace")
checkOptions({optPeg, optRegex}, "peg", "re") checkOptions({optPeg, optRegex}, "peg", "re")
checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style") checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style")
checkOptions({optFilenames, optReplace}, "filenames", "replace")
if optStdin in options: if optStdin in options:
pattern = ask("pattern [ENTER to exit]: ") pattern = ask("pattern [ENTER to exit]: ")