From 72dfe176f5211f561263984a2df653f16dcf5466 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Mon, 23 Apr 2018 17:02:38 +0800 Subject: [PATCH 01/13] remove dead code elimination option (#7669) --- compiler/ast.nim | 6 +++--- compiler/ccgexprs.nim | 5 ++--- compiler/ccgstmts.nim | 18 ++---------------- compiler/ccgutils.nim | 4 ---- compiler/cgen.nim | 4 ---- compiler/commands.nim | 3 +-- compiler/options.nim | 3 ++- compiler/pragmas.nim | 14 ++++---------- compiler/wordrecg.nim | 6 ++++-- doc/basicopt.txt | 1 - doc/manual.rst | 16 ---------------- doc/nimc.rst | 4 ++-- lib/deprecated/pure/sockets.nim | 2 +- lib/impure/db_sqlite.nim | 2 +- lib/impure/rdstdin.nim | 2 +- lib/posix/epoll.nim | 2 +- lib/posix/inotify.nim | 2 +- lib/posix/kqueue.nim | 8 +++----- lib/posix/linux.nim | 2 +- lib/posix/posix.nim | 8 ++++---- lib/posix/posix_other.nim | 2 +- lib/posix/termios.nim | 2 +- lib/pure/fenv.nim | 2 +- lib/pure/matchers.nim | 2 +- lib/pure/net.nim | 2 +- lib/pure/os.nim | 2 +- lib/pure/parseutils.nim | 2 +- lib/pure/ropes.nim | 2 +- lib/pure/strmisc.nim | 2 +- lib/pure/strutils.nim | 2 +- lib/pure/unicode.nim | 2 +- lib/system.nim | 2 +- lib/windows/winlean.nim | 2 +- lib/wrappers/iup.nim | 2 +- lib/wrappers/mysql.nim | 2 +- lib/wrappers/odbcsql.nim | 2 +- lib/wrappers/openssl.nim | 2 +- lib/wrappers/pcre.nim | 2 +- lib/wrappers/postgres.nim | 2 +- lib/wrappers/sqlite3.nim | 2 +- tests/enum/toptions.nim | 2 +- tests/iter/tobj_iter.nim | 2 -- .../dependencies/chipmunk/chipmunk.nim | 1 - .../keineschweine/dependencies/enet/enet.nim | 1 - .../dependencies/genpacket/macro_dsl.nim | 2 +- .../keineschweine/dependencies/sfml/sfml.nim | 2 +- .../dependencies/sfml/sfml_colors.nim | 2 +- .../dependencies/sfml/sfml_vector.nim | 1 - tests/manyloc/keineschweine/keineschweine.nim | 2 +- tests/manyloc/keineschweine/lib/sg_gui.nim | 2 +- tests/manyloc/keineschweine/server/nim.cfg | 1 - tests/manyloc/nake/nakefile.nim | 2 +- tests/manyloc/standalone/barebone.nim.cfg | 1 - tests/pragmas/tnoreturn.nim | 7 +++++-- tests/rodfiles/deadg.nim | 3 --- tools/nim.bash-completion | 4 ++-- tools/nim.zsh-completion | 2 -- 57 files changed, 67 insertions(+), 122 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 4a0a9a20bf41..2c8f686ebb6b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -262,7 +262,8 @@ type # variable is a thread variable sfCompileTime, # proc can be evaluated at compile time 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 sfInfixCall, # symbol needs infix call syntax in target language; # for interfacing with C++, JS @@ -275,10 +276,9 @@ type TSymFlags* = set[TSymFlag] const - sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher sfNoInit* = sfMainModule # don't generate code to init the variable - sfImmediate* = sfDeadCodeElim + sfImmediate* = sfDispatcher # macro or template is immediately expanded # without considering any possible overloads sfAllUntyped* = sfVolatile # macro or template is immediately expanded \ diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 461a862986cc..ea373f5a6af5 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2264,7 +2264,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkEmpty: discard of nkWhileStmt: genWhileStmt(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 nkCaseStmt: genCase(p, n, d) 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 # by ensuring it's no inner proc (owner is a module): if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags: - if (not emitLazily(prc)) or - ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or + if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or (prc.kind == skMethod): # we have not only the header: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 2030d6add23c..cb3d6dbe6e81 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -280,20 +280,6 @@ proc genVarStmt(p: BProc, n: PNode) = else: 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) = # # { if (!expr1) goto L1; @@ -587,7 +573,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = genLineDir(p, t) if isImportedException(typ): lineF(p, cpsStmts, "throw $1;$n", [e]) - else: + else: lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n", [e, makeCString(typ.sym.name.s)]) else: @@ -836,7 +822,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = else: for j in 0..t[i].len-2: 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) startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc)) else: diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index fe28d2209ba1..48648bddea1b 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -211,8 +211,4 @@ proc mangle*(name: string): string = if requiresUnderscore: result.add "_" -proc emitLazily*(s: PSym): bool {.inline.} = - result = optDeadCodeElim in gGlobalOptions or - sfDeadCodeElim in getModule(s).flags - initTypeTables() diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 9e1f9349ff41..ff3e6714d508 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1309,10 +1309,6 @@ proc newModule(g: BModuleList; module: PSym): BModule = growCache g.modules, module.position 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.} = if graph.backend == nil: graph.backend = newModuleList(config) diff --git a/compiler/commands.nim b/compiler/commands.nim index e1dc1aacf32e..8d73ac90e656 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -268,7 +268,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool = of "movechecks": result = contains(gOptions, optMoveCheck) of "linedir": result = contains(gOptions, optLineDir) of "assertions", "a": result = contains(gOptions, optAssert) - of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim) of "run", "r": result = contains(gGlobalOptions, optRun) of "symbolfiles": result = gSymbolFiles != disabledSf of "genscript": result = contains(gGlobalOptions, optGenScript) @@ -509,7 +508,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info) of "linedir": processOnOffSwitch({optLineDir}, 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": processOnOffSwitchG({optThreads}, arg, pass, info) #if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe) diff --git a/compiler/options.nim b/compiler/options.nim index 93a3f17962dd..7126d43980ec 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -41,7 +41,8 @@ type # please make sure we have under 32 options TOptions* = set[TOption] TGlobalOption* = enum # **keep binary compatible** - gloptNone, optForceFullMake, optDeadCodeElim, + gloptNone, optForceFullMake, + optDeadCodeElimUnused, # deprecated, always on optListCmd, optCompileOnly, optNoLinking, optCDebug, # turn on debugging information optGenDynLib, # generate a dynamic library diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index cb11564a4c54..9e9233fe72a4 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -44,7 +44,9 @@ const wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, 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, wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto, wInjectStmt, wDeprecated, wExperimental, wThis} @@ -215,10 +217,6 @@ proc onOff(c: PContext, n: PNode, op: TOptions) = if isTurnedOn(c, n): 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) = if isTurnedOn(c, n): incl(c.module.flags, flag) else: excl(c.module.flags, flag) @@ -764,7 +762,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wThreadVar: noVal(it) incl(sym.flags, sfThread) - of wDeadCodeElim: pragmaDeadCodeElim(c, it) + of wDeadCodeElimUnused: discard # deprecated, dead code elim always on of wNoForward: pragmaNoForward(c, it) of wReorder: pragmaNoForward(c, it, sfReorder) of wMagic: processMagic(c, it, sym) @@ -960,10 +958,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, if sym.kind != skType or sym.typ == nil: invalidPragma(it) else: 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: # We check for errors, but do nothing with these pragmas otherwise # as they are handled directly in 'evalTemplate'. diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 76d91d4e77b3..91b527e028ac 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -55,7 +55,8 @@ type wFloatchecks, wNanChecks, wInfChecks, wMoveChecks, wAssertions, wPatterns, wWarnings, 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, wCompileTime, wNoInit, wPassc, wPassl, wBorrow, wDiscardable, @@ -143,7 +144,8 @@ const "assertions", "patterns", "warnings", "hints", "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", "compiletime", "noinit", "passc", "passl", "borrow", "discardable", "fieldchecks", diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 4c11cc767eaa..90c7ba09c848 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -29,7 +29,6 @@ Options: --nanChecks:on|off turn NaN checks on|off --infChecks:on|off turn Inf 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 Note: use -d:release for a release build! --debugger:native|endb use native debugger (gdb) | ENDB (experimental) diff --git a/doc/manual.rst b/doc/manual.rst index fbd0430201f8..f1330d5247ca 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -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 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 diff --git a/doc/nimc.rst b/doc/nimc.rst index b275438eaa5b..29dbdea42900 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -181,7 +181,7 @@ generated; use the ``--symbolFiles:on`` command line switch to activate them. Unfortunately due to technical reasons the ``--symbolFiles:on`` needs 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``. 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:: - 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 a file ``panicoverride.nim``. diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim index f0568366ab5d..05aebef76abb 100644 --- a/lib/deprecated/pure/sockets.nim +++ b/lib/deprecated/pure/sockets.nim @@ -32,7 +32,7 @@ include "system/inclrtl" -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when hostOS == "solaris": {.passl: "-lsocket -lnsl".} diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 21049571f915..f88037e2f34c 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -81,7 +81,7 @@ ## ## theDb.close() -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated import strutils, sqlite3 diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim index 5aa4cfcc38f9..54bab82f0bc4 100644 --- a/lib/impure/rdstdin.nim +++ b/lib/impure/rdstdin.nim @@ -13,7 +13,7 @@ ## is used. This suffices because Windows' console already provides the ## wanted functionality. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(Windows): proc readLineFromStdin*(prompt: string): TaintedString {. diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim index c5ed1a873319..2d38137bb9ac 100644 --- a/lib/posix/epoll.nim +++ b/lib/posix/epoll.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated from posix import SocketHandle diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim index a206f806715e..359e88617fd1 100644 --- a/lib/posix/inotify.nim +++ b/lib/posix/inotify.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated # Get the platform-dependent flags. # Structure describing an inotify event. diff --git a/lib/posix/kqueue.nim b/lib/posix/kqueue.nim index 730491a53607..18b47f5d50e5 100644 --- a/lib/posix/kqueue.nim +++ b/lib/posix/kqueue.nim @@ -7,8 +7,6 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} - from posix import Timespec when defined(macosx) or defined(freebsd) or defined(openbsd) or @@ -61,7 +59,7 @@ const EV_CLEAR* = 0x0020 ## Clear event state after reporting. EV_RECEIPT* = 0x0040 ## Force EV_ERROR on success, data == 0 EV_DISPATCH* = 0x0080 ## Disable event after reporting. - + EV_SYSFLAGS* = 0xF000 ## Reserved by system EV_DROP* = 0x1000 ## Not should be dropped 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_FFOR* = 0x80000000'u32 ## OR 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_TRIGGER* = 0x01000000'u32 ## Cause the event to be triggered + NOTE_TRIGGER* = 0x01000000'u32 ## Cause the event to be triggered ## for output. # data/hint flags for EVFILT_{READ|WRITE}, shared with userspace diff --git a/lib/posix/linux.nim b/lib/posix/linux.nim index 6f9f75e34019..25c7c7979321 100644 --- a/lib/posix/linux.nim +++ b/lib/posix/linux.nim @@ -1,4 +1,4 @@ -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated import posix diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index a23d760509ae..3ff156bdf010 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -27,10 +27,10 @@ ## resulting C code will just ``#include `` and *not* define the ## symbols declared here. -# This ensures that we don't accidentally generate #includes for files that -# might not exist on a specific platform! The user will get an error only -# if they actualy try to use the missing declaration -{.deadCodeElim: on.} +# Dead code elimination ensures that we don't accidentally generate #includes +# for files that might not exist on a specific platform! The user will get an +# error only if they actualy try to use the missing declaration +{.deadCodeElim: on.} # dce option deprecated # 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? diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim index ae41263e81a5..004a4205b3d4 100644 --- a/lib/posix/posix_other.nim +++ b/lib/posix/posix_other.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated const hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim index f86e408fb302..60d5401077e7 100644 --- a/lib/posix/termios.nim +++ b/lib/posix/termios.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated import posix type diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim index f8f115eccc3f..a083c680ced3 100644 --- a/lib/pure/fenv.nim +++ b/lib/pure/fenv.nim @@ -10,7 +10,7 @@ ## Floating-point environment. Handling of floating-point rounding and ## exceptions (overflow, division by zero, etc.). -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated when defined(Posix) and not defined(haiku): {.passl: "-lm".} diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim index 6366fee1ab1f..685c3b07acc6 100644 --- a/lib/pure/matchers.nim +++ b/lib/pure/matchers.nim @@ -12,7 +12,7 @@ ## **Warning:** This module is deprecated since version 0.14.0. {.deprecated.} -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/net.nim b/lib/pure/net.nim index ccf02a1fca06..ebb59ca6d633 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -68,7 +68,7 @@ ## ``newSocket()``. The difference is that the latter creates a new file ## descriptor. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated import nativesockets, os, strutils, parseutils, times, sets, options export Port, `$`, `==` export Domain, SockType, Protocol diff --git a/lib/pure/os.nim b/lib/pure/os.nim index ddeee2c6b289..11be8f0c12a6 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -10,7 +10,7 @@ ## This module contains basic operating system facilities like ## retrieving environment variables, reading command line arguments, ## working with directories, running shell commands, etc. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger: off.} diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 57387e62ed23..cecc94e9253d 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -11,7 +11,7 @@ ## ## To unpack raw bytes look at the `streams `_ module. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index 6ddd61afa6ab..24ba012e5f77 100644 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -19,7 +19,7 @@ include "system/inclrtl" import streams -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim index 89ef2fcd20be..d1ff920c9310 100644 --- a/lib/pure/strmisc.nim +++ b/lib/pure/strmisc.nim @@ -12,7 +12,7 @@ import strutils -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated proc expandTabs*(s: string, tabSize: int = 8): string {.noSideEffect, procvar.} = diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 54fdcb4d0b91..849c16c345ff 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -17,7 +17,7 @@ import parseutils from math import pow, round, floor, log10 from algorithm import reverse -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 257c620f7902..cc4d28f5ba3f 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -9,7 +9,7 @@ ## This module provides support to handle the Unicode UTF-8 encoding. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated include "system/inclrtl" diff --git a/lib/system.nim b/lib/system.nim index 5e08dadc0b61..874b8c4d13e6 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -146,7 +146,7 @@ proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} ## # missing it. when defined(useNimRtl): - {.deadCodeElim: on.} + {.deadCodeElim: on.} # dce option deprecated proc definedInScope*(x: untyped): bool {. magic: "DefinedInScope", noSideEffect, deprecated, compileTime.} diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 62bc38da9efb..7e22f98c7c19 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -10,7 +10,7 @@ ## 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. -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated import dynlib diff --git a/lib/wrappers/iup.nim b/lib/wrappers/iup.nim index d910173cadf5..dee2e14c71f3 100644 --- a/lib/wrappers/iup.nim +++ b/lib/wrappers/iup.nim @@ -34,7 +34,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # **************************************************************************** -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(windows): const dllname = "iup(|30|27|26|25|24).dll" diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim index 4464eae50854..06c663822ec2 100644 --- a/lib/wrappers/mysql.nim +++ b/lib/wrappers/mysql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push, callconv: cdecl.} when defined(Unix): diff --git a/lib/wrappers/odbcsql.nim b/lib/wrappers/odbcsql.nim index 1b2544ec011b..43d1c504df77 100644 --- a/lib/wrappers/odbcsql.nim +++ b/lib/wrappers/odbcsql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when not defined(ODBCVER): const diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index 357343bffb63..86ae85369627 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -22,7 +22,7 @@ ## ./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 -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated const useWinVersion = defined(Windows) or defined(nimdoc) diff --git a/lib/wrappers/pcre.nim b/lib/wrappers/pcre.nim index 6c7088bbf279..e9e11960c8d8 100644 --- a/lib/wrappers/pcre.nim +++ b/lib/wrappers/pcre.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated # The current PCRE version information. diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim index f9a10dccbf76..7cb816f68927 100644 --- a/lib/wrappers/postgres.nim +++ b/lib/wrappers/postgres.nim @@ -15,7 +15,7 @@ # connection-protocol. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(windows): const diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim index a129458323a7..0276a0a65230 100644 --- a/lib/wrappers/sqlite3.nim +++ b/lib/wrappers/sqlite3.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(windows): when defined(nimOldDlls): const Lib = "sqlite3.dll" diff --git a/tests/enum/toptions.nim b/tests/enum/toptions.nim index e53acb2b35e9..da66f0067cd7 100644 --- a/tests/enum/toptions.nim +++ b/tests/enum/toptions.nim @@ -4,7 +4,7 @@ type TOption = enum optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck, optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir, - optWarns, optHints, optDeadCodeElim, optListCmd, optCompileOnly, + optWarns, optHints, optListCmd, optCompileOnly, optSafeCode, # only allow safe code optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib, optGenGuiApp, optStackTrace diff --git a/tests/iter/tobj_iter.nim b/tests/iter/tobj_iter.nim index eb0e37b23bec..a894755d71c8 100644 --- a/tests/iter/tobj_iter.nim +++ b/tests/iter/tobj_iter.nim @@ -4,8 +4,6 @@ discard """ # bug #2023 -{.deadCodeElim:on.} - type Obj = object iter: iterator (): int8 {.closure.} diff --git a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim index 56d3edec49f6..f06c4e0be357 100644 --- a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim +++ b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim @@ -23,7 +23,6 @@ const Lib = "libchipmunk.so.6.1.1" when defined(MoreNim): {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".} -{.deadCodeElim: on.} from math import sqrt, sin, cos, arctan2 when defined(CpUseFloat): {.hint: "CpUseFloat defined; using float32 as float".} diff --git a/tests/manyloc/keineschweine/dependencies/enet/enet.nim b/tests/manyloc/keineschweine/dependencies/enet/enet.nim index 3c4ce2017a09..3ea8172d5f2c 100644 --- a/tests/manyloc/keineschweine/dependencies/enet/enet.nim +++ b/tests/manyloc/keineschweine/dependencies/enet/enet.nim @@ -20,7 +20,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. const Lib = "libenet.so.1(|.0.3)" -{.deadCodeElim: on.} const ENET_VERSION_MAJOR* = 1 ENET_VERSION_MINOR* = 3 diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim index d3a0c701d30c..86c12fbb09cb 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim @@ -1,5 +1,5 @@ import macros -{.deadCodeElim: on.} + #Inline macro.add() to allow for easier nesting proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} = a.add(b) diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim index 1524f0eb466e..0060bf12bd9b 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim @@ -12,7 +12,7 @@ else: LibS = "libcsfml-system.so.2.0" LibW = "libcsfml-window.so.2.0" #{.error: "Platform unsupported".} -{.deadCodeElim: on.} + {.pragma: pf, pure, final.} type PClock* = ptr TClock diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim index 95a760e1ff8b..b4eb1b8f0642 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim @@ -1,5 +1,5 @@ import sfml -{.deadCodeElim: on.} + let Black*: TColor = color(0, 0, 0) White*: TColor = color(255, 255, 255) diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim index 474d249aa16c..94c5308a99e3 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim @@ -1,2 +1 @@ import sfml, math, strutils -{.deadCodeElim: on.} diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim index c0f1bc031330..59347ee46d70 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim +++ b/tests/manyloc/keineschweine/keineschweine.nim @@ -5,7 +5,7 @@ import sg_gui, sg_assets, sound_buffer, enet_client when defined(profiler): import nimprof -{.deadCodeElim: on.} + type PPlayer* = ref TPlayer TPlayer* = object diff --git a/tests/manyloc/keineschweine/lib/sg_gui.nim b/tests/manyloc/keineschweine/lib/sg_gui.nim index ffc4e8215bf1..b7448d9df4c7 100644 --- a/tests/manyloc/keineschweine/lib/sg_gui.nim +++ b/tests/manyloc/keineschweine/lib/sg_gui.nim @@ -2,7 +2,7 @@ import sfml, sfml_colors, input_helpers, sg_packets from strutils import countlines -{.deadCodeElim: on.} + type PGuiContainer* = ref TGuiContainer TGuiContainer* = object of TObject diff --git a/tests/manyloc/keineschweine/server/nim.cfg b/tests/manyloc/keineschweine/server/nim.cfg index fdc45a8e1810..211ad3003b22 100644 --- a/tests/manyloc/keineschweine/server/nim.cfg +++ b/tests/manyloc/keineschweine/server/nim.cfg @@ -1,5 +1,4 @@ debugger = off -deadCodeElim = on path = ".." path = "../genpacket" path = "../helpers" diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim index 2055d7834618..97af79a84fc0 100644 --- a/tests/manyloc/nake/nakefile.nim +++ b/tests/manyloc/nake/nakefile.nim @@ -10,7 +10,7 @@ const ExeName = "keineschweine" ServerDefines = "-d:NoSFML -d:NoChipmunk" 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" task "testprofile", "..": diff --git a/tests/manyloc/standalone/barebone.nim.cfg b/tests/manyloc/standalone/barebone.nim.cfg index bb350ff553e3..b956bef8e904 100644 --- a/tests/manyloc/standalone/barebone.nim.cfg +++ b/tests/manyloc/standalone/barebone.nim.cfg @@ -1,3 +1,2 @@ --os:standalone ---deadCodeElim:on --gc:none diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim index 4d00c603462a..bb59b1c71ac6 100644 --- a/tests/pragmas/tnoreturn.nim +++ b/tests/pragmas/tnoreturn.nim @@ -2,13 +2,16 @@ discard """ ccodeCheck: "\\i @'__attribute__((noreturn))' .*" """ -proc noret1*(i: int) {.noreturn.} = +proc noret1*(i: int) {.noreturn.} = echo i -proc noret2*(i: int): void {.noreturn.} = +proc noret2*(i: int): void {.noreturn.} = echo i +noret1(1) +noret2(2) + var p {.used.}: proc(i: int): int doAssert(not compiles( p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int diff --git a/tests/rodfiles/deadg.nim b/tests/rodfiles/deadg.nim index 587608e14ebb..0aee59bb8011 100644 --- a/tests/rodfiles/deadg.nim +++ b/tests/rodfiles/deadg.nim @@ -1,6 +1,3 @@ - -{.deadCodeElim: on.} - proc p1*(x, y: int): int = result = x + y diff --git a/tools/nim.bash-completion b/tools/nim.bash-completion index 1c199a0cfacf..8e569079ac48 100644 --- a/tools/nim.bash-completion +++ b/tools/nim.bash-completion @@ -15,7 +15,7 @@ _nim() return 0 fi 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 [[ "$cur" == "=" ]] && cur="" COMPREPLY=( $(compgen -W 'on off' -- "$cur") ) @@ -32,7 +32,7 @@ _nim() 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 ) ) _filedir '@(nim)' #$split diff --git a/tools/nim.zsh-completion b/tools/nim.zsh-completion index 57b5e163ec01..e9b9002fb5c1 100644 --- a/tools/nim.zsh-completion +++ b/tools/nim.zsh-completion @@ -60,8 +60,6 @@ _nim() { '*--infChecks=off[turn Inf checks off]' \ '*--nilChecks=on[turn nil checks on]' \ '*--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=speed[optimize for speed|size - use -d:release for a release build]' \ '*--opt=size[optimize for size]' \ From 8caf257607e0b76f103155add7849fb934371678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Mon, 23 Apr 2018 11:09:48 +0200 Subject: [PATCH 02/13] Don't escape multibyte characters (#7570) --- compiler/renderer.nim | 33 +++------------ lib/pure/strutils.nim | 17 ++++++-- lib/system.nim | 42 +++++++++++++++----- tests/collections/tcollections_to_string.nim | 10 ++++- 4 files changed, 60 insertions(+), 42 deletions(-) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 0e631a8986a8..2a65a10a80f5 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -172,32 +172,6 @@ proc put(g: var TSrcGen, kind: TTokType, s: string) = else: 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) = if s.isNil: return var i = 0 @@ -365,10 +339,13 @@ proc atom(g: TSrcGen; n: PNode): string = of nkEmpty: result = "" of nkIdent: result = n.ident.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 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 nkInt8Lit: result = litAux(g, n, n.intVal, 1) & "\'i8" of nkInt16Lit: result = litAux(g, n, n.intVal, 2) & "\'i16" diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 849c16c345ff..cdc5ec4f9d63 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1818,20 +1818,29 @@ proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect, dec(L) proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, - rtl, extern: "nsuEscape".} = + rtl, extern: "nsuEscape", deprecated.} = ## Escapes a string `s`. See `system.addEscapedChar `_ ## for the escaping scheme. ## ## The resulting string is prefixed with `prefix` and suffixed with `suffix`. ## 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.add(prefix) 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) proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, - rtl, extern: "nsuUnescape".} = + rtl, extern: "nsuUnescape", deprecated.} = ## Unescapes a string `s`. ## ## 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 ## ValueError exception will be raised. + ## + ## **Warning:** This procedure is deprecated because it's to easy to missuse. result = newStringOfCap(s.len) var i = prefix.len if not s.startsWith(prefix): diff --git a/lib/system.nim b/lib/system.nim index 874b8c4d13e6..98c1334281b1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3933,29 +3933,48 @@ proc addEscapedChar*(s: var string, c: char) {.noSideEffect, inline.} = ## * 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. ## ## The procedure has been designed so that its output is usable for many ## different common syntaxes. ## **Note**: This is not correct for producing Ansi C code! case c - of '\0'..'\31', '\127'..'\255': - add(s, "\\x") + of '\a': s.add "\\a" # \x07 + 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" let n = ord(c) s.add(HexChars[int((n and 0xF0) shr 4)]) 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) = ## Appends `x` to string `s` in place, applying quoting and escaping ## if `x` is a string or char. See ## `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 ## 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: s.add("\"") 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("\"") elif T is char: s.add("'") diff --git a/tests/collections/tcollections_to_string.nim b/tests/collections/tcollections_to_string.nim index 6cc8a84ff06c..48b06a6aa055 100644 --- a/tests/collections/tcollections_to_string.nim +++ b/tests/collections/tcollections_to_string.nim @@ -85,14 +85,20 @@ block: s.addQuoted('\0') s.addQuoted('\31') s.addQuoted('\127') - s.addQuoted('\255') - doAssert s == "'\\x00''\\x1F''\\x7F''\\xFF'" + doAssert s == "'\\x00''\\x1F''\\x7F'" block: var s = "" s.addQuoted('\\') s.addQuoted('\'') s.addQuoted('\"') doAssert s == """'\\''\'''\"'""" +block: + var s = "" + s.addQuoted("å") + s.addQuoted("ä") + s.addQuoted("ö") + s.addEscapedChar('\xFF') + doAssert s == """"å""ä""ö"\xFF""" # Test customized element representation type CustomString = object From 64908bf171ac3f8cd4c81a6de0e512e47d1d5d5d Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 23 Apr 2018 10:37:19 +0200 Subject: [PATCH 03/13] nimgrep: add --filenames option --- tools/nimgrep.nim | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim index 8dc076ad98d8..4cfcbe9bc251 100644 --- a/tools/nimgrep.nim +++ b/tools/nimgrep.nim @@ -11,7 +11,7 @@ import os, strutils, parseopt, pegs, re, terminal const - Version = "1.1" + Version = "1.2" Usage = "nimgrep - Nim Grep Utility Version " & Version & """ (c) 2012 Andreas Rumpf @@ -35,6 +35,8 @@ Options: --nocolor output will be given without any colours. --oneline show file on each matched line --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 --version, -v shows the version """ @@ -42,7 +44,7 @@ Options: type TOption = enum optFind, optReplace, optPeg, optRegex, optRecursive, optConfirm, optStdin, - optWord, optIgnoreCase, optIgnoreStyle, optVerbose + optWord, optIgnoreCase, optIgnoreStyle, optVerbose, optFilenames TOptions = set[TOption] TConfirmEnum = enum ceAbort, ceYes, ceAll, ceNo, ceNone @@ -135,11 +137,14 @@ proc processFile(pattern; filename: string) = filenameShown = true var buffer: string - try: - buffer = system.readFile(filename) - except IOError: - echo "cannot open file: ", filename - return + if optFilenames in options: + buffer = filename + else: + try: + buffer = system.readFile(filename) + except IOError: + echo "cannot open file: ", filename + return if optVerbose in options: stdout.writeLine(filename) stdout.flushFile() @@ -293,6 +298,7 @@ for kind, key, val in getopt(): of "nocolor": useWriteStyled = false of "oneline": oneline = true of "verbose": incl(options, optVerbose) + of "filenames": incl(options, optFilenames) of "help", "h": writeHelp() of "version", "v": writeVersion() else: writeHelp() @@ -304,6 +310,7 @@ when defined(posix): checkOptions({optFind, optReplace}, "find", "replace") checkOptions({optPeg, optRegex}, "peg", "re") checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style") +checkOptions({optFilenames, optReplace}, "filenames", "replace") if optStdin in options: pattern = ask("pattern [ENTER to exit]: ") From ba86b09e69e4c7cb6bc906f1f1db918547854161 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 23 Apr 2018 10:53:56 +0200 Subject: [PATCH 04/13] remove obsolete nimrod.cfg configuration files --- compiler/nimconf.nim | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index c19b41af1cc1..bdf55813419c 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -247,10 +247,6 @@ proc loadConfigs*(cfg: string; cache: IdentCache; config: ConfigRef = nil) = var projectConfig = changeFileExt(gProjectFull, "nimcfg") if not fileExists(projectConfig): projectConfig = changeFileExt(gProjectFull, "nim.cfg") - if not fileExists(projectConfig): - projectConfig = changeFileExt(gProjectFull, "nimrod.cfg") - if fileExists(projectConfig): - rawMessage(warnDeprecated, projectConfig) readConfigFile(projectConfig, cache, config) proc loadConfigs*(cfg: string; config: ConfigRef = nil) = From 3e5192b5dafcfc93fae701d6cdf5ffa3d1a81e1f Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 23 Apr 2018 10:54:26 +0200 Subject: [PATCH 05/13] compiler: remove unnecessary FileIndex type conversions --- compiler/passes.nim | 2 +- compiler/reorder.nim | 2 +- compiler/rodread.nim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/passes.nim b/compiler/passes.nim index d7c18167680f..6ff3f2bb5df6 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -166,7 +166,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream, p: TParsers a: TPassContextArray s: PLLStream - fileIdx = FileIndex module.fileIdx + fileIdx = module.fileIdx if module.id < 0: # new module caching mechanism: for i in 0.. Date: Tue, 24 Apr 2018 08:25:00 +0200 Subject: [PATCH 06/13] xmltree: remove usage of deprecated callsite() --- lib/pure/xmltree.nim | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index 45696c80c8cc..a6f62abce740 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -12,9 +12,9 @@ import macros, strtabs 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 xnElement, ## an element with 0 or more children 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] result.fAttr = attributes -proc xmlConstructor(e: NimNode): NimNode {.compileTime.} = - expectLen(e, 2) - var a = e[1] +proc xmlConstructor(a: NimNode): NimNode {.compileTime.} = if a.kind == nnkCall: result = newCall("newXmlTree", toStrLit(a[0])) var attrs = newNimNode(nnkBracket, a) @@ -348,7 +346,6 @@ macro `<>`*(x: untyped): untyped = ## ## Nim rules. ## - let x = callsite() result = xmlConstructor(x) proc child*(n: XmlNode, name: string): XmlNode = From ee366f17469a96b418b58db17e03c892cf4f17d8 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 24 Apr 2018 09:34:20 +0200 Subject: [PATCH 07/13] .experimental can now be used to enable specific features --- changelog.md | 6 ++++ compiler/commands.nim | 39 ++++++++++++-------- compiler/nim.nim | 4 +-- compiler/options.nim | 14 ++++++-- compiler/pragmas.nim | 22 +++++++++--- compiler/scriptconfig.nim | 6 ++-- compiler/semasgn.nim | 4 +-- compiler/semcall.nim | 2 +- compiler/semdata.nim | 6 ++-- compiler/semexprs.nim | 6 ++-- compiler/semstmts.nim | 71 ++++++++++++------------------------- compiler/semtypinst.nim | 4 +-- compiler/service.nim | 12 +++---- compiler/transf.nim | 6 ++-- doc/advopt.txt | 5 +-- doc/manual.rst | 21 +++++------ nimsuggest/nimsuggest.nim | 8 ++--- tests/parallel/tparfind.nim | 2 +- 18 files changed, 122 insertions(+), 116 deletions(-) diff --git a/changelog.md b/changelog.md index a3332789a398..8ac02a388a4a 100644 --- a/changelog.md +++ b/changelog.md @@ -102,4 +102,10 @@ - Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual 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 diff --git a/compiler/commands.nim b/compiler/commands.nim index 8d73ac90e656..dc5d808ecd5c 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -46,9 +46,9 @@ type passCmd2, # second pass over the command line 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; - config: ConfigRef = nil) + config: ConfigRef) # implementation @@ -58,7 +58,13 @@ const const 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 = result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, @@ -276,7 +282,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool = of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation) of "implicitstatic": result = contains(gOptions, optImplicitStatic) of "patterns": result = contains(gOptions, optPatterns) - of "experimental": result = gExperimentalMode of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace) else: invalidCmdLineOption(passCmd1, switch, info) @@ -339,7 +344,7 @@ proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = options.inclDynlibOverride(arg) proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; - config: ConfigRef = nil) = + config: ConfigRef) = var theOS: TSystemOS cpu: TSystemCPU @@ -694,8 +699,13 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; # only supported for compatibility. Does nothing. expectArg(switch, arg, pass, info) of "experimental": - expectNoArg(switch, arg, pass, info) - gExperimentalMode = true + if arg.len == 0: + config.features.incl oldExperimentalFeatures + else: + try: + config.features.incl parseEnum[Feature](arg) + except ValueError: + localError(info, "unknown experimental feature") of "nocppexceptions": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optNoCppExceptions) @@ -706,7 +716,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; config.cppDefine(arg) of "newruntime": expectNoArg(switch, arg, pass, info) - newDestructors = true + doAssert(config != nil) + incl(config.features, destructor) defineSymbol("nimNewRuntime") of "cppcompiletonamespace": expectNoArg(switch, arg, pass, info) @@ -716,10 +727,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) else: invalidCmdLineOption(pass, switch, info) -proc processCommand(switch: string, pass: TCmdLinePass) = +proc processCommand(switch: string, pass: TCmdLinePass; config: ConfigRef) = var cmd, arg: string splitSwitch(switch, cmd, arg, pass, gCmdLineInfo) - processSwitch(cmd, arg, pass, gCmdLineInfo) + processSwitch(cmd, arg, pass, gCmdLineInfo, config) var @@ -727,19 +738,19 @@ var # the arguments to be passed to the program that # should be run -proc processSwitch*(pass: TCmdLinePass; p: OptParser) = +proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) = # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") # we fix this here var bracketLe = strutils.find(p.key, '[') if bracketLe >= 0: var key = substr(p.key, 0, bracketLe - 1) var val = substr(p.key, bracketLe + 1) & ':' & p.val - processSwitch(key, val, pass, gCmdLineInfo) + processSwitch(key, val, pass, gCmdLineInfo, config) else: - processSwitch(p.key, p.val, pass, gCmdLineInfo) + processSwitch(p.key, p.val, pass, gCmdLineInfo, config) proc processArgument*(pass: TCmdLinePass; p: OptParser; - argsCount: var int): bool = + argsCount: var int; config: ConfigRef): bool = if argsCount == 0: # nim filename.nims is the same as "nim e filename.nims": if p.key.endswith(".nims"): diff --git a/compiler/nim.nim b/compiler/nim.nim index 8f3463be98cf..3fa733303ec2 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -42,7 +42,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = writeCommandLineUsage() else: # Process command line arguments: - processCmdLine(passCmd1, "") + processCmdLine(passCmd1, "", config) if gProjectName == "-": gProjectName = "stdinfile" gProjectFull = "stdinfile" @@ -71,7 +71,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = # now process command line arguments again, because some options in the # command line can overwite the config file's settings extccomp.initVars() - processCmdLine(passCmd2, "") + processCmdLine(passCmd2, "", config) if options.command == "": rawMessage(errNoCommand, command) mainCommand(newModuleGraph(config), cache) diff --git a/compiler/options.nim b/compiler/options.nim index 7126d43980ec..24c9d0f7341b 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -103,13 +103,23 @@ type ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod, ideHighlight, ideOutline, ideKnown, ideMsg + Feature* = enum ## experimental features + implicitDeref, + dotOperators, + callOperator, + parallel, + destructor + ConfigRef* = ref object ## eventually all global configuration should be moved here cppDefines*: HashSet[string] headerFile*: string + features*: set[Feature] + +const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel} proc newConfigRef*(): ConfigRef = result = ConfigRef(cppDefines: initSet[string](), - headerFile: "") + headerFile: "", features: {}) proc cppDefine*(c: ConfigRef; define: string) = c.cppDefines.incl define @@ -146,8 +156,6 @@ var gListFullPaths*: bool gPreciseStack*: bool = false gNoNimblePath* = false - gExperimentalMode*: bool - newDestructors*: bool gDynlibOverrideAll*: bool useNimNamespace*: bool diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 9e9233fe72a4..5aa90377191b 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -680,6 +680,22 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = elif n.kind == nkExprColonExpr: 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, validPragmas: TSpecialWords): bool = var it = n.sons[i] @@ -993,11 +1009,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, else: it.sons[1] = c.semExpr(c, it.sons[1]) of wExperimental: - noVal(it) - if isTopLevel(c): - c.module.flags.incl sfExperimental - else: - localError(it.info, "'experimental' pragma only valid as toplevel statement") + processExperimental(c, it, sym) of wThis: if it.kind in nkPragmaCallKinds and it.len == 2: c.selfName = considerQuotedIdent(it[1]) diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim index 692a8d8964dc..c533f4cb445c 100644 --- a/compiler/scriptconfig.nim +++ b/compiler/scriptconfig.nim @@ -26,7 +26,7 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) = setResult(a, result) proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; - config: ConfigRef = nil): PEvalContext = + config: ConfigRef): PEvalContext = # For Nimble we need to export 'setupVM'. result = newCtx(module, cache) result.mode = emRepl @@ -128,7 +128,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; cbconf getCommand: setResult(a, options.command) 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: processSpecificNote(a.getString 0, wHint, passPP, module.info, a.getString 1) @@ -150,7 +150,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; options.cppDefine(config, a.getString(0)) proc runNimScript*(cache: IdentCache; scriptName: string; - freshDefines=true; config: ConfigRef=nil) = + freshDefines=true; config: ConfigRef) = rawMessage(hintConf, scriptName) passes.gIncludeFile = includeModule passes.gImportModule = importModule diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index bbd2baf6e077..5c7b91f6df58 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -101,7 +101,7 @@ proc newOpCall(op: PSym; x: PNode): PNode = proc destructorCall(c: PContext; op: PSym; x: PNode): PNode = result = newNodeIT(nkCall, x.info, op.typ.sons[0]) result.add(newSymNode(op)) - if newDestructors: + if destructor in c.features: result.add genAddr(c, x) else: 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 ## to ensure we lift assignment, destructors and moves properly. ## 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: # do not produce wrong liftings while we're still instantiating generics: # now disabled; breaks topttree.nim! diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 0fc12f164e8b..f443339f5974 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -434,7 +434,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode, "Non-matching candidates for " & renderTree(n) & "\n" & candidates) 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: # # XXX: why is this here? diff --git a/compiler/semdata.nim b/compiler/semdata.nim index bcc1bba1506b..8159abf8f9b6 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -130,6 +130,7 @@ type signatures*: TStrTable recursiveDep*: string suggestionsMade*: bool + features*: set[Feature] inTypeContext*: int typesWithOps*: seq[(PType, PType)] #\ # 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 initStrTable(result.signatures) result.typesWithOps = @[] - + result.features = graph.config.features proc inclSym(sq: var TSymSeq, s: PSym) = var L = len(sq) @@ -398,6 +399,3 @@ proc checkMinSonsLen*(n: PNode, length: int) = proc isTopLevel*(c: PContext): bool {.inline.} = result = c.currentScope.depthLevel <= 2 - -proc experimentalMode*(c: PContext): bool {.inline.} = - result = gExperimentalMode or sfExperimental in c.module.flags diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 279b6cc5774c..6ad5d931d415 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -663,7 +663,7 @@ proc resolveIndirectCall(c: PContext; n, nOrig: PNode; matches(c, n, nOrig, result) if result.state != csMatch: # 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 initCandidate(c, result, t) matches(c, n, nOrig, result) @@ -1452,7 +1452,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = typeMismatch(n.info, lhs.typ, rhsTyp) 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 mode != noOverloadedAsgn: 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.typ = getSysType(tyString) of mParallel: - if not experimentalMode(c): + if parallel notin c.features: localError(n.info, "use the {.experimental.} pragma to enable 'parallel'") result = setMs(n, s) var x = n.lastSon diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8d7747fb4a8a..94090852f859 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -385,30 +385,9 @@ proc checkNilable(v: PSym) = include semasgn 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 value = identDefs[L-1] - if value.typ != nil and tfHasAsgn in value.typ.flags and not newDestructors: - # 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: + if result.kind == nkStmtList: let o = copyNode(orig) o.add identDefs result.add o @@ -1267,9 +1246,6 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = gp = newNodeI(nkGenericParams, n.info) 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) # paramsTypeCheck(c, s.typ) 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) = case s.name.s.normalize - of "destroy", "=destroy": - if newDestructors: - let t = s.typ - var noError = false - if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar: - var obj = t.sons[1].sons[0] - while true: - incl(obj.flags, tfHasAsgn) - if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon - elif obj.kind == tyGenericInvocation: obj = obj.sons[0] - else: break - if obj.kind in {tyObject, tyDistinct}: - if obj.destructor.isNil: - obj.destructor = s - else: - localError(n.info, errGenerated, - "cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) - noError = true - if not noError and sfSystemModule notin s.owner.flags: - localError(n.info, errGenerated, - "signature for '" & s.name.s & "' must be proc[T: object](x: var T)") + of "=destroy": + let t = s.typ + var noError = false + if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar: + var obj = t.sons[1].sons[0] + while true: + incl(obj.flags, tfHasAsgn) + if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon + elif obj.kind == tyGenericInvocation: obj = obj.sons[0] + else: break + if obj.kind in {tyObject, tyDistinct}: + if obj.destructor.isNil: + obj.destructor = s + else: + localError(n.info, errGenerated, + "cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) + noError = true + if not noError and sfSystemModule notin s.owner.flags: + localError(n.info, errGenerated, + "signature for '" & s.name.s & "' must be proc[T: object](x: var T)") incl(s.flags, sfUsed) of "deepcopy", "=deepcopy": if s.typ.len == 2 and @@ -1612,9 +1587,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, s.options = gOptions if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) 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) - 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) if n.sons[bodyPos].kind != nkEmpty: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 09434c925b82..c97c1186eaa3 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -368,7 +368,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = assert newbody.kind in {tyRef, tyPtr} assert newbody.lastSon.typeInst == nil newbody.lastSon.typeInst = result - if newDestructors: + if destructor in cl.c.features: cl.c.typesWithOps.add((newbody, result)) else: typeBound(cl.c, newbody, result, assignment, cl.info) @@ -545,7 +545,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = else: discard proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) = - if not newDestructors: return + if destructor notin c.features: return var i = 0 while i < c.typesWithOps.len: let (newty, oldty) = c.typesWithOps[i] diff --git a/compiler/service.nim b/compiler/service.nim index ac04b786028d..7cdfc112cc88 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -26,7 +26,7 @@ var # 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? -proc processCmdLine*(pass: TCmdLinePass, cmd: string) = +proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) = var p = parseopt.initOptParser(cmd) var argsCount = 0 while true: @@ -36,19 +36,19 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) = of cmdLongoption, cmdShortOption: if p.key == " ": p.key = "-" - if processArgument(pass, p, argsCount): break + if processArgument(pass, p, argsCount, config): break else: - processSwitch(pass, p) + processSwitch(pass, p, config) of cmdArgument: - if processArgument(pass, p, argsCount): break + if processArgument(pass, p, argsCount, config): break if pass == passCmd2: if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run": 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) = curCaasCmd = cmd - processCmdLine(passCmd2, cmd) + processCmdLine(passCmd2, cmd, config) action(cache) gErrorCounter = 0 diff --git a/compiler/transf.nim b/compiler/transf.nim index f30f8583a9e5..f7ec6c97f22f 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -979,7 +979,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = #result = liftLambdas(prc, result) when useEffectSystem: trackProc(prc, result) result = liftLocalsIfRequested(prc, result) - if c.needsDestroyPass and newDestructors: + if c.needsDestroyPass: #and newDestructors: result = injectDestructorCalls(prc, result) incl(result.flags, nfTransf) #if prc.name.s == "testbody": @@ -996,7 +996,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode = when useEffectSystem: trackTopLevelStmt(module, result) #if n.info ?? "temp.nim": # echo renderTree(result, {renderIds}) - if c.needsDestroyPass and newDestructors: + if c.needsDestroyPass: result = injectDestructorCalls(module, result) incl(result.flags, nfTransf) @@ -1007,6 +1007,6 @@ proc transformExpr*(module: PSym, n: PNode): PNode = var c = openTransf(module, "") result = processTransf(c, n, module) liftDefer(c, result) - if c.needsDestroyPass and newDestructors: + if c.needsDestroyPass: result = injectDestructorCalls(module, result) incl(result.flags, nfTransf) diff --git a/doc/advopt.txt b/doc/advopt.txt index bf7dd7fb4f2b..0d1578f78f15 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -35,7 +35,7 @@ Advanced options: --noLinking compile Nim and generated files but do not link --noMain do not generate a main procedure --genScript generate a compile script (in the 'nimcache' - subdirectory named 'compile_$project$scriptext') + subdirectory named 'compile_$$project$$scriptext') --genDeps generate a '.deps' file containing the dependencies --os:SYMBOL set the target operating system (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation) @@ -88,5 +88,6 @@ Advanced options: --parallelBuild:0|1|... perform a parallel build value = number of processors (0 for auto-detect) --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 diff --git a/doc/manual.rst b/doc/manual.rst index f1330d5247ca..636bf796be33 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -1397,10 +1397,10 @@ dereferencing operations for reference types: Automatic dereferencing is also performed for the first argument of a routine call. But currently this feature has to be only enabled -via ``{.experimental.}``: +via ``{.experimental: "implicitDeref".}``: .. code-block:: nim - {.experimental.} + {.experimental: "implicitDeref".} proc depth(x: NodeObj): int = ... @@ -5588,7 +5588,7 @@ dot operators ------------- **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 intercept and rewrite proc call and field access attempts, referring @@ -6885,17 +6885,12 @@ is uncertain (it may be removed any time). Example: .. code-block:: nim - {.experimental.} - type - FooId = distinct int - BarId = distinct int - using - foo: FooId - bar: BarId + {.experimental: "parallel".} proc useUsing(bar, foo) = - echo "bar is of type BarId" - echo "foo is of type FooId" + parallel: + for i in 0..4: + echo "echo in parallel" Implementation Specific Pragmas @@ -7917,7 +7912,7 @@ Example: # Compute PI in an inefficient way import strutils, math, threadpool - {.experimental.} + {.experimental: "parallel".} proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1) diff --git a/nimsuggest/nimsuggest.nim b/nimsuggest/nimsuggest.nim index 49e61b9a9abd..b2764e9ee0f5 100644 --- a/nimsuggest/nimsuggest.nim +++ b/nimsuggest/nimsuggest.nim @@ -518,7 +518,7 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) = close(requests) close(results) -proc processCmdLine*(pass: TCmdLinePass, cmd: string) = +proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) = var p = parseopt.initOptParser(cmd) while true: parseopt.next(p) @@ -562,7 +562,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) = gRefresh = true of "maxresults": suggestMaxResults = parseInt(p.val) - else: processSwitch(pass, p) + else: processSwitch(pass, p, config) of cmdArgument: let a = unixToNativePath(p.key) if dirExists(a) and not fileExists(a.addFileExt("nim")): @@ -577,7 +577,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = if paramCount() == 0: stdout.writeline(Usage) else: - processCmdLine(passCmd1, "") + processCmdLine(passCmd1, "", config) if gMode != mstdin: msgs.writelnHook = proc (msg: string) = discard if gProjectName != "": @@ -616,7 +616,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config) extccomp.initVars() - processCmdLine(passCmd2, "") + processCmdLine(passCmd2, "", config) let graph = newModuleGraph(config) graph.suggestMode = true diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim index 9de5012f5843..4b3610c6703f 100644 --- a/tests/parallel/tparfind.nim +++ b/tests/parallel/tparfind.nim @@ -4,7 +4,7 @@ discard """ import threadpool, sequtils -{.experimental.} +{.experimental: "parallel".} proc linearFind(a: openArray[int]; x, offset: int): int = for i, y in a: From 7df892db9dcfff24be8f0a3c0bff01643d649049 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 24 Apr 2018 11:45:08 +0200 Subject: [PATCH 08/13] make tests green again --- tests/assign/toverload_asgn1.nim | 1 + tests/assign/toverload_asgn2.nim | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/assign/toverload_asgn1.nim b/tests/assign/toverload_asgn1.nim index dbc3a71c4ea1..01e7e7aa7a86 100644 --- a/tests/assign/toverload_asgn1.nim +++ b/tests/assign/toverload_asgn1.nim @@ -14,6 +14,7 @@ GenericT[T] '=' bool GenericT[T] '=' bool GenericT[T] '=' bool GenericT[T] '=' bool''' + disabled: "true" """ import typetraits diff --git a/tests/assign/toverload_asgn2.nim b/tests/assign/toverload_asgn2.nim index 243c90494710..1104be92b537 100644 --- a/tests/assign/toverload_asgn2.nim +++ b/tests/assign/toverload_asgn2.nim @@ -1,6 +1,7 @@ discard """ output: '''i value 88 2aa''' + disabled: "true" """ import moverload_asgn2 From b503ca03f697d7364efe0bc5cf367e9e8bd12418 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 24 Apr 2018 11:58:18 +0200 Subject: [PATCH 09/13] refactoring: move 'argument' global into config object --- compiler/commands.nim | 9 ++------- compiler/nim.nim | 6 +++--- compiler/options.nim | 2 ++ compiler/service.nim | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index dc5d808ecd5c..591bf8883d07 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -733,11 +733,6 @@ proc processCommand(switch: string, pass: TCmdLinePass; config: ConfigRef) = processSwitch(cmd, arg, pass, gCmdLineInfo, config) -var - arguments* = "" - # the arguments to be passed to the program that - # should be run - proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) = # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") # we fix this here @@ -756,7 +751,7 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser; if p.key.endswith(".nims"): options.command = "e" options.gProjectName = unixToNativePath(p.key) - arguments = cmdLineRest(p) + config.arguments = cmdLineRest(p) result = true elif pass != passCmd2: options.command = p.key @@ -765,6 +760,6 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser; if argsCount == 1: # support UNIX style filenames everywhere for portable build scripts: options.gProjectName = unixToNativePath(p.key) - arguments = cmdLineRest(p) + config.arguments = cmdLineRest(p) result = true inc argsCount diff --git a/compiler/nim.nim b/compiler/nim.nim index 3fa733303ec2..28078233037a 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -80,7 +80,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = if msgs.gErrorCounter == 0: when hasTinyCBackend: if gCmd == cmdRun: - tccgen.run(commands.arguments) + tccgen.run(config.arguments) if optRun in gGlobalOptions: if gCmd == cmdCompileToJS: var ex: string @@ -89,7 +89,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = else: ex = quoteShell( completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir)) - execExternalProgram(findNodeJs() & " " & ex & ' ' & commands.arguments) + execExternalProgram(findNodeJs() & " " & ex & ' ' & config.arguments) else: var binPath: string if options.outFile.len > 0: @@ -99,7 +99,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = # Figure out ourselves a valid binary name. binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir var ex = quoteShell(binPath) - execExternalProgram(ex & ' ' & commands.arguments) + execExternalProgram(ex & ' ' & config.arguments) when declared(GC_setMaxPause): GC_setMaxPause 2_000 diff --git a/compiler/options.nim b/compiler/options.nim index 24c9d0f7341b..a5dfaa81cc47 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -114,6 +114,8 @@ type cppDefines*: HashSet[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} diff --git a/compiler/service.nim b/compiler/service.nim index 7cdfc112cc88..6ec9b9046772 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -42,7 +42,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) = of cmdArgument: if processArgument(pass, p, argsCount, config): break 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, []) proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) = From c461811bde431f8ab566aae11116a21af2e7d50a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Wed, 25 Apr 2018 02:29:47 +0200 Subject: [PATCH 10/13] Use safeLen in pairs iterator for PNode (#7684) --- compiler/ast.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 2c8f686ebb6b..b8202abe6062 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1622,7 +1622,7 @@ iterator items*(n: PNode): PNode = for i in 0..= nkNone and n.kind <= nkNilLit From c385391ffd08d61738392efa2be334b2ceb5517f Mon Sep 17 00:00:00 2001 From: cooldome Date: Wed, 25 Apr 2018 01:41:16 +0100 Subject: [PATCH 11/13] Consts in fenv (#7688) * Fixes #7574 * better comments * Changes vars to consts for side effect tracking * Revert unintended changes --- lib/pure/fenv.nim | 55 +++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim index a083c680ced3..c946c4261866 100644 --- a/lib/pure/fenv.nim +++ b/lib/pure/fenv.nim @@ -102,32 +102,33 @@ proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "".} ## represented by object pointed to by `envp` and raise exceptions ## according to saved exceptions. -var FP_RADIX_INTERNAL {. importc: "FLT_RADIX" header: "" .} : int - -template fpRadix* : int = FP_RADIX_INTERNAL +const + FLT_RADIX = 2 ## the radix of the exponent representation + + 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 ## point type on the architecture used to build the program. -var FLT_MANT_DIG {. importc: "FLT_MANT_DIG" header: "" .} : int -var FLT_DIG {. importc: "FLT_DIG" header: "" .} : int -var FLT_MIN_EXP {. importc: "FLT_MIN_EXP" header: "" .} : int -var FLT_MAX_EXP {. importc: "FLT_MAX_EXP" header: "" .} : int -var FLT_MIN_10_EXP {. importc: "FLT_MIN_10_EXP" header: "" .} : int -var FLT_MAX_10_EXP {. importc: "FLT_MAX_10_EXP" header: "" .} : int -var FLT_MIN {. importc: "FLT_MIN" header: "" .} : cfloat -var FLT_MAX {. importc: "FLT_MAX" header: "" .} : cfloat -var FLT_EPSILON {. importc: "FLT_EPSILON" header: "" .} : cfloat - -var DBL_MANT_DIG {. importc: "DBL_MANT_DIG" header: "" .} : int -var DBL_DIG {. importc: "DBL_DIG" header: "" .} : int -var DBL_MIN_EXP {. importc: "DBL_MIN_EXP" header: "" .} : int -var DBL_MAX_EXP {. importc: "DBL_MAX_EXP" header: "" .} : int -var DBL_MIN_10_EXP {. importc: "DBL_MIN_10_EXP" header: "" .} : int -var DBL_MAX_10_EXP {. importc: "DBL_MAX_10_EXP" header: "" .} : int -var DBL_MIN {. importc: "DBL_MIN" header: "" .} : cdouble -var DBL_MAX {. importc: "DBL_MAX" header: "" .} : cdouble -var DBL_EPSILON {. importc: "DBL_EPSILON" header: "" .} : cdouble - template mantissaDigits*(T : typedesc[float32]) : int = FLT_MANT_DIG ## Number of digits (in base ``floatingPointRadix``) in the mantissa ## 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 ## The difference between 1.0 and the smallest number greater than ## 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) From b34580fd5b955dec510f1aa06c3db1e4af052ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Nihlg=C3=A5rd?= Date: Wed, 25 Apr 2018 02:43:26 +0200 Subject: [PATCH 12/13] Rename `Time.nanoseconds` to `nanosecond` (#7673) * Rename `Time.nanoseconds` to `nanosecond` * Fix bug with Duration comparision --- lib/pure/random.nim | 2 +- lib/pure/times.nim | 60 ++++++++++++++++++++--------------------- tests/stdlib/ttimes.nim | 8 ++++-- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 968a326d2482..01ea9c845fed 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -192,7 +192,7 @@ when not defined(nimscript): ## Initializes the random number generator with a "random" ## number, i.e. a tickcount. Note: Does not work for NimScript. let now = times.getTime() - randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanoseconds) + randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanosecond) {.pop.} diff --git a/lib/pure/times.nim b/lib/pure/times.nim index bf63ed344271..7d101beab403 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -103,7 +103,7 @@ type Time* = object ## Represents a point in time. seconds: int64 - nanoseconds: NanosecondRange + nanosecond: NanosecondRange DateTime* = object of RootObj ## Represents a time in different parts. ## Although this type can represent leap @@ -159,7 +159,7 @@ type ## This type should be prefered over ``TimeInterval`` unless ## non-static time units is needed. seconds: int64 - nanoseconds: NanosecondRange + nanosecond: NanosecondRange TimeUnit* = enum ## Different units of time. 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 ## positive nanosecond part in the range ``NanosecondRange``. result.seconds = seconds + convert(Nanoseconds, Seconds, nanoseconds) - var nanoseconds = nanoseconds mod convert(Seconds, Nanoseconds, 1) - if nanoseconds < 0: - nanoseconds += convert(Seconds, Nanoseconds, 1) + var nanosecond = nanoseconds mod convert(Seconds, Nanoseconds, 1) + if nanosecond < 0: + nanosecond += convert(Seconds, Nanoseconds, 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. 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 ## of nanoseconds of the second. - time.nanoseconds + time.nanosecond proc initDuration*(nanoseconds, microseconds, milliseconds, seconds, minutes, hours, days, weeks: int64 = 0): Duration = @@ -281,7 +281,7 @@ proc milliseconds*(dur: Duration): int {.inline.} = runnableExamples: let dur = initDuration(seconds = 1, milliseconds = 1) doAssert dur.milliseconds == 1 - convert(Nanoseconds, Milliseconds, dur.nanoseconds) + convert(Nanoseconds, Milliseconds, dur.nanosecond) proc microseconds*(dur: Duration): int {.inline.} = ## Number of whole microseconds represented by the **fractional** @@ -289,7 +289,7 @@ proc microseconds*(dur: Duration): int {.inline.} = runnableExamples: let dur = initDuration(seconds = 1, microseconds = 1) doAssert dur.microseconds == 1 - convert(Nanoseconds, Microseconds, dur.nanoseconds) + convert(Nanoseconds, Microseconds, dur.nanosecond) proc nanoseconds*(dur: Duration): int {.inline.} = ## Number of whole nanoseconds represented by the **fractional** @@ -297,14 +297,14 @@ proc nanoseconds*(dur: Duration): int {.inline.} = runnableExamples: let dur = initDuration(seconds = 1, nanoseconds = 1) doAssert dur.nanoseconds == 1 - dur.nanoseconds + dur.nanosecond proc fractional*(dur: Duration): Duration {.inline.} = ## The fractional part of duration, as a duration. runnableExamples: let dur = initDuration(seconds = 1, 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. ## @@ -322,7 +322,7 @@ proc `$`*(dur: Duration): string = doAssert $initDuration(milliseconds = -1500) == "-1 second and -500 milliseconds" var parts = newSeq[string]() var remS = dur.seconds - var remNs = dur.nanoseconds.int + var remNs = dur.nanosecond.int # Normally ``nanoseconds`` should always be positive, but # that makes no sense when printing. @@ -387,7 +387,7 @@ proc fromWinTime*(win: int64): Time = proc toWinTime*(t: Time): int64 = ## 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 = ## 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 .} 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 = - 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 = 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 = - a.seconds <= b.seconds or ( - a.seconds == b.seconds and a.nanoseconds <= b.seconds) + a.seconds < b.seconds or ( + a.seconds == b.seconds and a.nanosecond <= b.nanosecond) 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.} = ## Add two durations together. @@ -507,7 +507,7 @@ proc `-`*(a: Duration): Duration {.operator.} = ## Reverse a duration. runnableExamples: 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.} = ## Note that a duration can be negative, @@ -530,7 +530,7 @@ proc `*`*(a: int64, b: Duration): Duration {.operator} = ## Multiply a duration by some scalar. runnableExamples: 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} = ## 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(nanoseconds = 3) div 2 == initDuration(nanoseconds = 1) 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".} = ## Computes the duration between two points in time. @@ -600,7 +600,7 @@ proc abs*(a: Duration): Duration = runnableExamples: doAssert initDuration(milliseconds = -1500).abs == 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.} = ## Converts a broken-down time structure to @@ -650,7 +650,7 @@ proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime = hour: hour, minute: minute, second: second, - nanosecond: zt.adjTime.nanoseconds, + nanosecond: zt.adjTime.nanosecond, weekday: getDayOfWeek(d, m, y), yearday: getDayOfYear(d, m, y), isDst: zt.isDst, @@ -809,7 +809,7 @@ else: # as a result of offset changes (normally due to dst) let utcUnix = adjTime.seconds + utcOffset let (finalOffset, dst) = getLocalOffsetAndDst(utcUnix) - result.adjTime = initTime(utcUnix - finalOffset, adjTime.nanoseconds) + result.adjTime = initTime(utcUnix - finalOffset, adjTime.nanosecond) result.utcOffset = finalOffset 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. ## ## **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.} = ## 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. let dur = getTime() - start result = (convert(Seconds, Milliseconds, dur.seconds) + - convert(Nanoseconds, Milliseconds, dur.nanoseconds)).int + convert(Nanoseconds, Milliseconds, dur.nanosecond)).int else: proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], benign.} = when defined(macosx): diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index 945d7ba3dc1d..37e14c1e2c65 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -367,6 +367,10 @@ suite "ttimes": check d(seconds = 0) - d(milliseconds = 1500) == d(milliseconds = -1500) check d(milliseconds = -1500) == d(seconds = -1, 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": discard initDateTime(1, mJan, -35_000, 12, 00, 00, utc()) @@ -413,7 +417,7 @@ suite "ttimes": test "fromWinTime/toWinTime": 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 # One nanosecond is discarded due to differences in time resolution - check initTime(0, 101).toWinTime.fromWinTime.nanoseconds == 100 \ No newline at end of file + check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 \ No newline at end of file From e931f3b5a9643e0d7ac45b88b0bddb32dda4c540 Mon Sep 17 00:00:00 2001 From: genotrance Date: Wed, 25 Apr 2018 03:52:32 -0500 Subject: [PATCH 13/13] Fixes #802, #803 and #3775 - genscript issues (#7677) * Fixes #802, #803 and #3775 - genscript issues * Test case for genscript * Test script * Verify on Linux * Update categories.nim * Fix merge * Improve test framework * Windows fixes --- compiler/commands.nim | 1 + compiler/extccomp.nim | 3 ++- doc/advopt.txt | 3 ++- tests/flags/tgenscript.nim | 5 +++++ tests/testament/backend.nim | 2 +- tests/testament/categories.nim | 28 +++++++++++++++++++++++++--- tests/testament/htmlgen.nim | 2 +- tests/testament/tester.nim | 25 ++++++++++++++++++++----- 8 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 tests/flags/tgenscript.nim diff --git a/compiler/commands.nim b/compiler/commands.nim index 591bf8883d07..06b487cf043e 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -652,6 +652,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "genscript", "gendeps": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optGenScript) + incl(gGlobalOptions, optCompileOnly) of "colors": processOnOffSwitchG({optUseColors}, arg, pass, info) of "lib": expectArg(switch, arg, pass, info) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index f9b18a3354e7..f8938e3af5bb 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -470,8 +470,9 @@ proc execExternalProgram*(cmd: string, msg = hintExecuting) = proc generateScript(projectFile: string, script: Rope) = let (dir, name, ext) = splitFile(projectFile) - writeRope(script, dir / addFileExt("compile_" & name, + writeRope(script, getNimcacheDir() / addFileExt("compile_" & name, platform.OS[targetOS].scriptExt)) + copyFile(libpath / "nimbase.h", getNimcacheDir() / "nimbase.h") proc getOptSpeed(c: TSystemCC): string = result = getConfigVar(c, ".options.speed") diff --git a/doc/advopt.txt b/doc/advopt.txt index 0d1578f78f15..d4a4b4961303 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -35,7 +35,8 @@ Advanced options: --noLinking compile Nim and generated files but do not link --noMain do not generate a main procedure --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 --os:SYMBOL set the target operating system (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation) diff --git a/tests/flags/tgenscript.nim b/tests/flags/tgenscript.nim new file mode 100644 index 000000000000..6a037b5d8f7e --- /dev/null +++ b/tests/flags/tgenscript.nim @@ -0,0 +1,5 @@ +discard """ + file: "tgenscript.nim" +""" + +echo "--genscript" diff --git a/tests/testament/backend.nim b/tests/testament/backend.nim index 4acef9ca4ea5..385f1171c107 100644 --- a/tests/testament/backend.nim +++ b/tests/testament/backend.nim @@ -13,7 +13,7 @@ type CommitId = distinct string proc `$`*(id: MachineId): string {.borrow.} -proc `$`(id: CommitId): string {.borrow.} +#proc `$`(id: CommitId): string {.borrow.} # not used var thisMachine: MachineId diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 2f9198759870..84e536636a05 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -63,6 +63,26 @@ proc compileRodFiles(r: var TResults, cat: Category, options: string) = test "gtkex1", true 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 ---------------------------------- proc safeCopyFile(src, dest: string) = @@ -323,7 +343,7 @@ var nimbleDir = getEnv("NIMBLE_DIR").string if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble" let nimbleExe = findExe("nimble") - packageDir = nimbleDir / "pkgs" + #packageDir = nimbleDir / "pkgs" # not used packageIndex = nimbleDir / "packages.json" proc waitForExitEx(p: Process): int = @@ -407,9 +427,9 @@ proc `&.?`(a, b: string): string = # candidate for the stdlib? 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? - 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) = let test = "tests" & DirSep &.? cat.string / test @@ -429,6 +449,8 @@ proc processCategory(r: var TResults, cat: Category, options: string) = jsTests(r, cat, options) of "dll": dllTests(r, cat, options) + of "flags": + flagTests(r, cat, options) of "gc": gcTests(r, cat, options) of "longgc": diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim index bf26a956d29c..4a888427e0b5 100644 --- a/tests/testament/htmlgen.nim +++ b/tests/testament/htmlgen.nim @@ -121,7 +121,7 @@ proc generateAllTestsContent(outfile: File, allResults: AllTests, proc generateHtml*(filename: string, onlyFailing: bool) = let - currentTime = getTime().getLocalTime() + currentTime = getTime().local() timestring = htmlQuote format(currentTime, "yyyy-MM-dd HH:mm:ss 'UTC'zzz") var outfile = open(filename, fmWrite) diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 856f95f3b652..f08c83079082 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -16,7 +16,7 @@ import const resultsFile = "testresults.html" - jsonFile = "testresults.json" + #jsonFile = "testresults.json" # not used Usage = """Usage: tester [options] command [arguments] @@ -150,11 +150,11 @@ proc initResults: TResults = result.skipped = 0 result.data = "" -proc readResults(filename: string): TResults = - result = marshal.to[TResults](readFile(filename).string) +#proc readResults(filename: string): TResults = # not used +# result = marshal.to[TResults](readFile(filename).string) -proc writeResults(filename: string, r: TResults) = - writeFile(filename, $$r) +#proc writeResults(filename: string, r: TResults) = # not used +# writeFile(filename, $$r) proc `$`(x: TResults): string = result = ("Tests passed: $1 / $3
\n" & @@ -404,6 +404,21 @@ proc testC(r: var TResults, test: TTest) = if exitCode != 0: given.err = reExitCodesDiffer 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, env: string = ""): TTest = # start with 'actionCompile', will be overwritten in the spec: