From 6a29fbf240e9395588dcf048ddd3037144c52e12 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 11 Sep 2014 21:00:25 +0200 Subject: [PATCH 01/41] be explicit about single letter options --- doc/basicopt.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/basicopt.txt b/doc/basicopt.txt index fdb0e36e1..390623828 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -35,3 +35,5 @@ Options: -r, --run run the compiled program with given arguments --advanced show advanced command line switches -h, --help show this help + +Note: Even single letter options require the colon: -p:PATH. From f99c40f61bc47f98390aab42f686fcb697dc9ce8 Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Thu, 25 Sep 2014 23:29:02 +0200 Subject: [PATCH 02/41] Improve setjmp()/longjmp() performance. Exception handling for the C backend used setjmp()/longjmp() unconditionally. However, on POSIX systems, these functions save and restore the signal mask, adding considerable overhead to exception handling, even where no exceptions are involved. The compiler and library now try to use either _setjmp()/_longjmp() or sigsetjmp()/siglongjmp() where possible, marked by the defines "nimRawSetjmp" and "nimSigSetjmp", respectively. The define "nimStdSetjmp" can be used to revert to setjmp()/longjmp() instead. --- compiler/ccgstmts.nim | 9 ++++++++- compiler/cgen.nim | 2 +- compiler/condsyms.nim | 2 ++ lib/system/ansi_c.nim | 21 +++++++++++++++++---- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index cb9eebb32..8b0a8e9bb 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -832,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = discard cgsym(p.module, "E_Base") linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint) linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint) - linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + if isDefined("nimStdSetjmp"): + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + elif isDefined("nimSigSetjmp"): + linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint) + elif isDefined("nimRawSetjmp"): + linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint) + else: + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) add(p.nestedTryStmts, t) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 315b55801..359fa3309 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -13,7 +13,7 @@ import ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, - times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, + times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, semparallel diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index dc61d2f89..a2d8b3564 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -136,3 +136,5 @@ proc initDefines*() = declareSymbol("emulatedthreadvars") if platform.OS[targetOS].props.contains(ospLacksThreadVars): defineSymbol("emulatedthreadvars") + if isDefined("posix"): + defineSymbol("nimRawSetjmp") diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index e012697ae..673d55582 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -78,10 +78,23 @@ when defined(macosx): else: template SIGBUS: expr = SIGSEGV -proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. - header: "", importc: "longjmp".} -proc c_setjmp(jmpb: C_JmpBuf): cint {. - header: "", importc: "setjmp".} +when defined(nimSigSetjmp) and not defined(nimStdSetjmp): + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "", importc: "siglongjmp".} + template c_setjmp(jmpb: C_JmpBuf): cint = + proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {. + header: "", importc: "sigsetjmp".} + c_sigsetjmp(jmpb, 0) +elif defined(nimRawSetjmp) and not defined(nimStdSetjmp): + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "", importc: "_longjmp".} + proc c_setjmp(jmpb: C_JmpBuf): cint {. + header: "", importc: "_setjmp".} +else: + proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. + header: "", importc: "longjmp".} + proc c_setjmp(jmpb: C_JmpBuf): cint {. + header: "", importc: "setjmp".} proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. importc: "signal", header: "".} From cb6441e73d976dcf59b1e55236887fe5d3a1d6ec Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Sat, 27 Sep 2014 18:05:30 +0200 Subject: [PATCH 03/41] Use _setjmp()/_longjmp() only on BSD-like systems for now. --- compiler/condsyms.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index a2d8b3564..238dbf5c7 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -136,5 +136,7 @@ proc initDefines*() = declareSymbol("emulatedthreadvars") if platform.OS[targetOS].props.contains(ospLacksThreadVars): defineSymbol("emulatedthreadvars") - if isDefined("posix"): + case targetOS + of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx: defineSymbol("nimRawSetjmp") + else: discard From b234d311d49df927b709891f5f640b90cf982ee4 Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 28 Sep 2014 15:35:35 -0400 Subject: [PATCH 04/41] Disable git hashing in the version command --- compiler/commands.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index c15cc674c..87e94d9c9 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) = platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name])) - const gitHash = gorge("git log -n 1 --format=%H") + discard """const gitHash = gorge("git log -n 1 --format=%H") if gitHash.strip.len == 40: - msgWriteln("git hash: " & gitHash) + msgWriteln("git hash: " & gitHash)""" msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas & From 93d55c077ffc9b9df381b4f921a16960c7141f19 Mon Sep 17 00:00:00 2001 From: Varriount Date: Sun, 28 Sep 2014 15:47:09 -0400 Subject: [PATCH 05/41] Updated Version Number --- compiler/nversion.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/nversion.nim b/compiler/nversion.nim index 3c868ed2a..bd1f79ac6 100644 --- a/compiler/nversion.nim +++ b/compiler/nversion.nim @@ -14,7 +14,7 @@ const MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets? VersionMajor* = 0 VersionMinor* = 9 - VersionPatch* = 5 + VersionPatch* = 6 VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch RodFileVersion* = "1215" # modify this if the rod-format changes! From 55c78af9c0a7a63683ee49044ece0667f699adc8 Mon Sep 17 00:00:00 2001 From: Clay Sweetser Date: Wed, 1 Oct 2014 18:14:06 -0400 Subject: [PATCH 06/41] Fixes #1529 --- compiler/procfind.nim | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 0354d585d..9f52cc117 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = var it: TIdentIter result = initIdentIter(it, scope.symbols, fn.name) while result != nil: - if result.kind in skProcKinds and - sameType(result.typ, fn.typ, flags): return + if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags): + case equalParams(result.typ.n, fn.typ.n) + of paramsEqual: + return + of paramsIncompatible: + localError(fn.info, errNotOverloadable, fn.name.s) + return + of paramsNotEqual: + discard result = nextIdentIter(it, scope.symbols) From 3df37a79237be4ac16c745a1c500d029b7d8ff1b Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Sun, 5 Oct 2014 00:26:22 +0200 Subject: [PATCH 07/41] Fixed missing color definion --- doc/nimdoc.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/nimdoc.css b/doc/nimdoc.css index 6154f0b2e..e3bab07de 100644 --- a/doc/nimdoc.css +++ b/doc/nimdoc.css @@ -16,6 +16,11 @@ customize this style sheet. Andreas Rumpf */ +body { + color: black; + background: white; +} + /* used to remove borders from tables and images */ .borderless, table.borderless td, table.borderless th { border: 0 } From 1da251523fb5e09d1edcd1ff37c2c993ec26273b Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 5 Oct 2014 02:22:48 +0200 Subject: [PATCH 08/41] added 'nim*Setjmp' conditional symbols --- compiler/condsyms.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 238dbf5c7..2c493c7d0 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -69,6 +69,8 @@ const reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize debugExecProcesses pcreDll useLipzipSrc preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime + + nimSigSetjmp nimStdSetjmp nimRawSetjmp """.split proc initDefines*() = From 54f6280d7659ce057a64cd9878a17c26065a7321 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Date: Tue, 7 Oct 2014 17:02:50 -0400 Subject: [PATCH 09/41] Update cpuinfo.nim sys/types.h needed for macosx and freebsd sys/param.h needed for openbsd and netbsd --- lib/pure/concurrency/cpuinfo.nim | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index dfa819f64..cd8e5b14a 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -18,15 +18,22 @@ when not defined(windows): when defined(linux): import linux + +when defined(freebsd) or defined(macosx): + {.emit:"#include ".} + +when defined(openbsd) or defined(netbsd): + {.emit:"#include ".} when defined(macosx) or defined(bsd): + {.emit:"#include ".} const CTL_HW = 6 HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, a: var csize, b: pointer, c: int): cint {. - importc: "sysctl", header: "".} + importc: "sysctl".} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. From fa3545c092522a43517669387ad2a953a4a2fd04 Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Fri, 10 Oct 2014 23:24:28 +0200 Subject: [PATCH 10/41] Raise exception on adding a non-existent file to a zip archive --- lib/impure/zipfiles.nim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim index 1726449d8..63b8a843d 100644 --- a/lib/impure/zipfiles.nim +++ b/lib/impure/zipfiles.nim @@ -56,6 +56,11 @@ proc addFile*(z: var TZipArchive, dest, src: string) = ## Adds the file `src` to the archive `z` with the name `dest`. `dest` ## may contain a path that will be created. assert(z.mode != fmRead) + if not fileExists(src): + var e: ref EIO + new(e) + e.msg = "File does not exist" + raise e var zipsrc = zip_source_file(z.w, src, 0, -1) if zipsrc == nil: #echo("Dest: " & dest) From d526e051c516ced3533f421637ca2ea3c11e03db Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Sat, 11 Oct 2014 00:20:49 +0200 Subject: [PATCH 11/41] Code more cleaner --- lib/impure/zipfiles.nim | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim index 63b8a843d..b9f89dda0 100644 --- a/lib/impure/zipfiles.nim +++ b/lib/impure/zipfiles.nim @@ -57,10 +57,7 @@ proc addFile*(z: var TZipArchive, dest, src: string) = ## may contain a path that will be created. assert(z.mode != fmRead) if not fileExists(src): - var e: ref EIO - new(e) - e.msg = "File does not exist" - raise e + raise newException(EIO, "File '" & src & "' does not exist") var zipsrc = zip_source_file(z.w, src, 0, -1) if zipsrc == nil: #echo("Dest: " & dest) From 6c9730b3534927ac2bdd4ec7c77e0d37bba7aa2e Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 12:25:15 +0200 Subject: [PATCH 12/41] fixes #1551 --- compiler/semexprs.nim | 5 +++++ lib/pure/concurrency/threadpool.nim | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ff445ecd0..46e6f1ab3 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1614,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType; initIdTable(bindings) bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t) result = c.semGenerateInstance(c, sym, bindings, info) + # since it's an instantiation, we unmark it as a compilerproc. Otherwise + # codegen would fail: + if sfCompilerProc in result.flags: + result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC} + result.loc.r = nil proc setMs(n: PNode, s: PSym): PNode = result = n diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index e0a2ac678..f46822d94 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -95,7 +95,7 @@ type FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]' FlowVarBaseObj = object of TObject - ready, usesCondVar: bool + ready, usesCondVar, awaited: bool cv: CondVar #\ # for 'awaitAny' support ai: ptr AwaitInfo @@ -129,8 +129,8 @@ type proc await*(fv: FlowVarBase) = ## waits until the value for the flowVar arrives. Usually it is not necessary ## to call this explicitly. - if fv.usesCondVar: - fv.usesCondVar = false + if fv.usesCondVar and not fv.awaited: + fv.awaited = true await(fv.cv) destroyCondVar(fv.cv) From 753d18d66c978b192b5c4fcf9b86c755c3fa9266 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 13:16:51 +0200 Subject: [PATCH 13/41] minor cleanup for cpuinfo --- lib/pure/concurrency/cpuinfo.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index cd8e5b14a..bd10a416f 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -26,14 +26,13 @@ when defined(openbsd) or defined(netbsd): {.emit:"#include ".} when defined(macosx) or defined(bsd): - {.emit:"#include ".} const CTL_HW = 6 HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, a: var csize, b: pointer, c: int): cint {. - importc: "sysctl".} + importc: "sysctl", header: "".} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. From 028a62e2bae3944a489904ae2d926408fc3f46ec Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 13:20:00 +0200 Subject: [PATCH 14/41] documentation updates --- doc/manual.txt | 21 +++++++++++++ web/news.txt | 85 +++++++++++++++++++++++++++----------------------- 2 files changed, 67 insertions(+), 39 deletions(-) diff --git a/doc/manual.txt b/doc/manual.txt index 7b713bf93..6aed72ce7 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -5039,6 +5039,27 @@ first implementation to play with a language feature before a nicer syntax to access the feature becomes available. +deprecated pragma +----------------- + +The deprecated pragma is used to mark a symbol as deprecated: + +.. code-block:: nimrod + proc p() {.deprecated.} + var x {.deprecated.}: char + +It can also be used as a statement. Then it takes a list of *renamings*. The +upcoming ``nimfix`` tool can automatically update the code and perform these +renamings: + +.. code-block:: nimrod + type + File = object + Stream = ref object + {.deprecated: [TFile: File, PStream: Stream].} + + + noSideEffect pragma ------------------- The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side diff --git a/web/news.txt b/web/news.txt index 2d7086be6..efef33e42 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,51 +2,58 @@ News ==== -.. - 2014-06-29 Version 0.9.6 released - ================================= +2014-10-11 Version 0.9.6 released +================================= - Changes affecting backwards compatibility - ----------------------------------------- +**Note: This is the last release of Nimrod. The language has been renamed to +Nim. Nim slightly breaks compatibility.** - - ``spawn`` now uses an elaborate self-adapting thread pool and as such - has been moved into its own module. So to use it, you now have to import - ``threadpool``. - - The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is - now considered for implicit early binding. - - ``c2nim`` moved into its own repository and is now a Babel package. - - ``pas2nim`` moved into its own repository and is now a Babel package. - - ``system.$`` for floating point types now produces a human friendly string - representation. - - ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour - of the new ``TUri`` type in the ``uri`` module. - - The ``destructor`` pragma has been deprecated. Use the ``override`` pragma - instead. The destructor's name has to be ``destroy`` now. - - ``lambda`` is not a keyword anymore. - - **system.defined has been split into system.defined and system.declared**. - You have to use ``--symbol`` to declare new conditional symbols that can be - set via ``--define``. - - ``--threadanalysis:on`` is now the default. To make your program compile - you can disable it but this is only a temporary solution as this option - will disappear soon! - +This is a maintenance release. The upcoming 0.10.0 release has all +the new features and exciting developments. - Language Additions - ------------------ - - There is a new ``parallel`` statement for safe fork&join parallel computing. - +Changes affecting backwards compatibility +----------------------------------------- - Library Additions - ----------------- +- ``spawn`` now uses an elaborate self-adapting thread pool and as such + has been moved into its own module. So to use it, you now have to import + ``threadpool``. +- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is + now considered for implicit early binding. +- ``c2nim`` moved into its own repository and is now a Babel package. +- ``pas2nim`` moved into its own repository and is now a Babel package. +- ``system.$`` for floating point types now produces a human friendly string + representation. +- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour + of the new ``TUri`` type in the ``uri`` module. +- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma + instead. The destructor's name has to be ``destroy`` now. +- ``lambda`` is not a keyword anymore. +- **system.defined has been split into system.defined and system.declared**. + You have to use ``--symbol`` to declare new conditional symbols that can be + set via ``--define``. +- ``--threadanalysis:on`` is now the default. To make your program compile + you can disable it but this is only a temporary solution as this option + will disappear soon! - - Added module ``cpuinfo``. - - Added module ``threadpool``. - - ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. - - Added ``algorithm.reversed`` - - Added ``uri.combine`` and ``uri.parseUri``. - - Some sockets procedures now support a ``SafeDisconn`` flag which causes - them to handle disconnection errors and not raise them. + +Language Additions +------------------ + +- This version introduces the new ``deprecated`` pragma statement that is used + to handle the upcoming massive amount of symbol renames. + + +Library Additions +----------------- + +- Added module ``cpuinfo``. +- Added module ``threadpool``. +- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``. +- Added ``algorithm.reversed`` +- Added ``uri.combine`` and ``uri.parseUri``. +- Some sockets procedures now support a ``SafeDisconn`` flag which causes + them to handle disconnection errors and not raise them. 2014-04-21 Version 0.9.4 released From 661c51682a9a842e6da181a2a52dae0ec40c0002 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 20:31:24 +0200 Subject: [PATCH 15/41] backported .deprecated statement --- compiler/ast.nim | 23 ++++--- compiler/condsyms.nim | 7 ++- compiler/lookups.nim | 136 +++++++++++++++++++++++++----------------- compiler/pragmas.nim | 113 ++++++++++++++++++++--------------- compiler/sempass2.nim | 20 +------ compiler/wordrecg.nim | 4 +- 6 files changed, 169 insertions(+), 134 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 7ad294695..0c828a6d9 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this @@ -291,6 +291,8 @@ const sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't # require RC ops + sfCompileToCpp* = sfInfixCall # compile the module as C++ code + sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code const # getting ready for the future expr/stmt merge @@ -476,7 +478,7 @@ type # and first phase symbol lookup in generics skConditional, # symbol for the preprocessor (may become obsolete) skDynLib, # symbol represents a dynamic library; this is used - # internally; it does not exist in Nimrod code + # internally; it does not exist in Nim code skParam, # a parameter skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()`` skTemp, # a temporary variable (introduced by compiler) @@ -501,7 +503,8 @@ type skStub, # symbol is a stub and not yet loaded from the ROD # file (it is loaded on demand, which may # mean: never) - skPackage # symbol is a package (used for canonicalization) + skPackage, # symbol is a package (used for canonicalization) + skAlias # an alias (needs to be resolved immediately) TSymKinds* = set[TSymKind] const @@ -678,7 +681,7 @@ type heapRoot*: PRope # keeps track of the enclosing heap object that # owns this location (required by GC algorithms # employing heap snapshots or sliding views) - a*: int # location's "address", i.e. slot for temporaries + a*: int # ---------------- end of backend information ------------------------------ @@ -731,8 +734,9 @@ type # check for the owner when touching 'usedGenerics'. usedGenerics*: seq[PInstantiation] tab*: TStrTable # interface table for modules + of skLet, skVar, skField: + guard*: PSym else: nil - magic*: TMagic typ*: PType name*: PIdent @@ -872,7 +876,7 @@ const tyProc, tyString, tyError} ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator, skClosureIterator, - skMacro, skTemplate, skConverter, skEnumField, skLet, skStub} + skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfDotSetter, nfDotField, nfIsRef} @@ -1162,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode, result.sons = @[name, pattern, genericParams, params, pragmas, exceptions, body] - proc newType(kind: TTypeKind, owner: PSym): PType = new(result) result.kind = kind @@ -1172,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType = result.id = getID() when debugIds: registerId(result) - #if result.id < 2000 then - # MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) + #if result.id < 2000: + # messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) proc mergeLoc(a: var TLoc, b: TLoc) = if a.k == low(a.k): a.k = b.k @@ -1229,6 +1232,8 @@ proc copySym(s: PSym, keepId: bool = false): PSym = result.position = s.position result.loc = s.loc result.annex = s.annex # BUGFIX + if result.kind in {skVar, skLet, skField}: + result.guard = s.guard proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = result = newSym(s.kind, newIdent, s.owner, info) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 2c493c7d0..6d144ad96 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -60,7 +60,7 @@ const quick release debug useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler - nodejs kwin + nodejs kwin nimfix usesysassert usegcassert tinyC useFFI useStdoutAsStdmsg createNimRtl @@ -70,7 +70,7 @@ const debugExecProcesses pcreDll useLipzipSrc preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime - nimSigSetjmp nimStdSetjmp nimRawSetjmp + nimStdSetjmp nimRawSetjmp nimSigSetjmp """.split proc initDefines*() = @@ -87,6 +87,7 @@ proc initDefines*() = defineSymbol("nimnewshared") defineSymbol("nimrequiresnimframe") defineSymbol("nimparsebiggestfloatmagic") + defineSymbol("nimalias") # add platform specific symbols: for c in low(CPU)..high(CPU): diff --git a/compiler/lookups.nim b/compiler/lookups.nim index aee64f52f..d486585ef 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this @@ -11,7 +11,7 @@ import intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, - renderer, wordrecg, idgen + renderer, wordrecg, idgen, nimfix.prettybase proc ensureNoMissingOrUnusedSymbols(scope: PScope) @@ -40,11 +40,8 @@ proc considerQuotedIdent*(n: PNode): PIdent = template addSym*(scope: PScope, s: PSym) = strTableAdd(scope.symbols, s) -proc addUniqueSym*(scope: PScope, s: PSym): TResult = - if strTableIncl(scope.symbols, s): - result = Failure - else: - result = Success +proc addUniqueSym*(scope: PScope, s: PSym): bool = + result = not strTableIncl(scope.symbols, s) proc openScope*(c: PContext): PScope {.discardable.} = result = PScope(parent: c.currentScope, @@ -65,6 +62,17 @@ iterator walkScopes*(scope: PScope): PScope = yield current current = current.parent +proc skipAlias*(s: PSym; n: PNode): PSym = + if s == nil or s.kind != skAlias: + result = s + else: + result = s.owner + if gCmd == cmdPretty: + prettybase.replaceDeprecated(n.info, s, result) + else: + message(n.info, warnDeprecated, "use " & result.name.s & " instead; " & + s.name.s) + proc localSearchInScope*(c: PContext, s: PIdent): PSym = result = strTableGet(c.currentScope.symbols, s) @@ -139,14 +147,14 @@ proc wrongRedefinition*(info: TLineInfo, s: string) = localError(info, errAttemptToRedefine, s) proc addDecl*(c: PContext, sym: PSym) = - if c.currentScope.addUniqueSym(sym) == Failure: + if not c.currentScope.addUniqueSym(sym): wrongRedefinition(sym.info, sym.name.s) proc addPrelimDecl*(c: PContext, sym: PSym) = discard c.currentScope.addUniqueSym(sym) proc addDeclAt*(scope: PScope, sym: PSym) = - if scope.addUniqueSym(sym) == Failure: + if not scope.addUniqueSym(sym): wrongRedefinition(sym.info, sym.name.s) proc addInterfaceDeclAux(c: PContext, sym: PSym) = @@ -163,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) = if fn.kind notin OverloadableSyms: internalError(fn.info, "addOverloadableSymAt") return - var check = strTableGet(scope.symbols, fn.name) + let check = strTableGet(scope.symbols, fn.name) if check != nil and check.kind notin OverloadableSyms: wrongRedefinition(fn.info, fn.name.s) else: @@ -179,20 +187,41 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) = addOverloadableSymAt(scope, sym) addInterfaceDeclAux(c, sym) +when defined(nimfix): + import strutils + + # when we cannot find the identifier, retry with a changed identifer: + proc altSpelling(x: PIdent): PIdent = + case x.s[0] + of 'A'..'Z': result = getIdent(toLower(x.s[0]) & x.s.substr(1)) + of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1)) + else: result = x + + template fixSpelling(n: PNode; ident: PIdent; op: expr) = + let alt = ident.altSpelling + result = op(c, alt).skipAlias(n) + if result != nil: + prettybase.replaceDeprecated(n.info, ident, alt) + return result +else: + template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard + proc lookUp*(c: PContext, n: PNode): PSym = # Looks up a symbol. Generates an error in case of nil. case n.kind of nkIdent: - result = searchInScopes(c, n.ident) - if result == nil: + result = searchInScopes(c, n.ident).skipAlias(n) + if result == nil: + fixSpelling(n, n.ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, n.ident.s) result = errorSym(c, n) of nkSym: result = n.sym of nkAccQuoted: var ident = considerQuotedIdent(n) - result = searchInScopes(c, ident) + result = searchInScopes(c, ident).skipAlias(n) if result == nil: + fixSpelling(n, ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, ident.s) result = errorSym(c, n) else: @@ -206,36 +235,38 @@ type TLookupFlag* = enum checkAmbiguity, checkUndeclared -proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = +proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = case n.kind of nkIdent, nkAccQuoted: var ident = considerQuotedIdent(n) - result = searchInScopes(c, ident) - if result == nil and checkUndeclared in flags: + result = searchInScopes(c, ident).skipAlias(n) + if result == nil and checkUndeclared in flags: + fixSpelling(n, ident, searchInScopes) localError(n.info, errUndeclaredIdentifier, ident.s) result = errorSym(c, n) - elif checkAmbiguity in flags and result != nil and - contains(c.ambiguousSymbols, result.id): + elif checkAmbiguity in flags and result != nil and + contains(c.ambiguousSymbols, result.id): localError(n.info, errUseQualifier, ident.s) of nkSym: result = n.sym - if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id): + if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id): localError(n.info, errUseQualifier, n.sym.name.s) - of nkDotExpr: + of nkDotExpr: result = nil var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared}) - if (m != nil) and (m.kind == skModule): + if m != nil and m.kind == skModule: var ident: PIdent = nil - if n.sons[1].kind == nkIdent: + if n.sons[1].kind == nkIdent: ident = n.sons[1].ident - elif n.sons[1].kind == nkAccQuoted: + elif n.sons[1].kind == nkAccQuoted: ident = considerQuotedIdent(n.sons[1]) - if ident != nil: - if m == c.module: - result = strTableGet(c.topLevelScope.symbols, ident) - else: - result = strTableGet(m.tab, ident) - if result == nil and checkUndeclared in flags: + if ident != nil: + if m == c.module: + result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n) + else: + result = strTableGet(m.tab, ident).skipAlias(n) + if result == nil and checkUndeclared in flags: + fixSpelling(n.sons[1], ident, searchInScopes) localError(n.sons[1].info, errUndeclaredIdentifier, ident.s) result = errorSym(c, n.sons[1]) elif n.sons[1].kind == nkSym: @@ -256,7 +287,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = o.scope = c.currentScope o.mode = oimNoQualifier while true: - result = initIdentIter(o.it, o.scope.symbols, ident) + result = initIdentIter(o.it, o.scope.symbols, ident).skipAlias(n) if result != nil: break else: @@ -277,11 +308,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = if ident != nil: if o.m == c.module: # a module may access its private members: - result = initIdentIter(o.it, c.topLevelScope.symbols, ident) + result = initIdentIter(o.it, c.topLevelScope.symbols, + ident).skipAlias(n) o.mode = oimSelfModule - else: - result = initIdentIter(o.it, o.m.tab, ident) - else: + else: + result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n) + else: localError(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1])) result = errorSym(c, n.sons[1]) @@ -307,18 +339,18 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = result = nil of oimNoQualifier: if o.scope != nil: - result = nextIdentIter(o.it, o.scope.symbols) + result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break - result = initIdentIter(o.it, o.scope.symbols, o.it.name) + result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n) # BUGFIX: o.it.name <-> n.ident else: result = nil of oimSelfModule: - result = nextIdentIter(o.it, c.topLevelScope.symbols) + result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n) of oimOtherModule: - result = nextIdentIter(o.it, o.m.tab) + result = nextIdentIter(o.it, o.m.tab).skipAlias(n) of oimSymChoice: if o.symChoiceIndex < sonsLen(n): result = n.sons[o.symChoiceIndex].sym @@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = o.mode = oimSymChoiceLocalLookup o.scope = c.currentScope result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) of oimSymChoiceLocalLookup: - result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice) + result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n) while result == nil: o.scope = o.scope.parent if o.scope == nil: break result = firstIdentExcluding(o.it, o.scope.symbols, - n.sons[0].sym.name, o.inSymChoice) + n.sons[0].sym.name, o.inSymChoice).skipAlias(n) if result != nil and result.kind == skStub: loadStub(result) -when false: - proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode, - flags = {checkUndeclared}): PSym = - var o: TOverloadIter - result = initOverloadIter(o, c, n) - var a = result - while a != nil: - if sfImmediate in a.flags: return a - a = nextOverloadIter(o, c, n) - if result == nil and checkUndeclared in flags: - localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s) - result = errorSym(c, n) +proc pickSym*(c: PContext, n: PNode; kind: TSymKind; + flags: TSymFlags = {}): PSym = + var o: TOverloadIter + var a = initOverloadIter(o, c, n) + while a != nil: + if a.kind == kind and flags <= a.flags: + return a + a = nextOverloadIter(o, c, n) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 024401b86..d73494c6e 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1,6 +1,6 @@ # # -# The Nimrod Compiler +# The Nim Compiler # (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this @@ -24,7 +24,7 @@ const wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, - wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe, + wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, wOverride} converterPragmas* = procPragmas methodPragmas* = procPragmas @@ -36,8 +36,8 @@ const iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, - wTags, wUses, wOperator, wGcSafe} - exprPragmas* = {wLine} + wTags, wLocks, wGcSafe} + exprPragmas* = {wLine, wLocks} stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, @@ -45,27 +45,27 @@ const wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto, - wInjectStmt} + wInjectStmt, wDeprecated} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, - wRaises, wUses, wTags, wGcSafe} + wRaises, wLocks, wTags, wGcSafe} typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wBorrow, wGcSafe} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, - wImportCpp, wImportObjC, wError} + wImportCpp, wImportObjC, wError, wGuard} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, - wGensym, wInject, wCodegenDecl} + wGensym, wInject, wCodegenDecl, wGuard} constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject} letPragmas* = varPragmas procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, - wThread, wRaises, wUses, wTags, wGcSafe} + wThread, wRaises, wLocks, wTags, wGcSafe} allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) @@ -128,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) = incl(s.flags, sfImportc) incl(s.flags, sfInfixCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToCpp) proc processImportObjC(s: PSym, extname: string) = setExternName(s, extname) incl(s.flags, sfImportc) incl(s.flags, sfNamedParamCall) excl(s.flags, sfForward) + let m = s.getModule() + incl(m.flags, sfCompileToObjC) proc newEmptyStrNode(n: PNode): PNode {.noinline.} = result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) @@ -514,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = else: invalidPragma(n) -proc pragmaUses(c: PContext, n: PNode) = - proc processExc(c: PContext, x: PNode): PNode = - if x.kind in {nkAccQuoted, nkIdent, nkSym, - nkOpenSymChoice, nkClosedSymChoice}: - if considerQuotedIdent(x).s == "*": - return newSymNode(ast.anyGlobal) - result = c.semExpr(c, x) - if result.kind != nkSym or sfGlobal notin result.sym.flags: - localError(x.info, "'$1' is not a global variable" % result.renderTree) - result = newSymNode(ast.anyGlobal) - - if n.kind == nkExprColonExpr: - let it = n.sons[1] - if it.kind notin {nkCurly, nkBracket}: - n.sons[1] = processExc(c, it) - else: - for i in 0 .. % high(int16): localError(it.info, errPowerOfTwoExpected) else: - sym.typ.align = align - of wSize: + sym.typ.align = align.int16 + of wSize: if sym.typ == nil: invalidPragma(it) var size = expectIntLit(c, it) if not isPowerOfTwo(size) or size <= 0 or size > 8: @@ -648,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, processDynLib(c, it, sym) of wCompilerproc: noVal(it) # compilerproc may not get a string! - if sfFromGeneric notin sym.flags: - makeExternExport(sym, "$1", it.info) - incl(sym.flags, sfCompilerProc) - incl(sym.flags, sfUsed) # suppress all those stupid warnings - registerCompilerProc(sym) - of wProcVar: + if sfFromGeneric notin sym.flags: markCompilerProc(sym) + of wProcVar: noVal(it) incl(sym.flags, sfProcvar) - of wDeprecated: - noVal(it) - if sym != nil: incl(sym.flags, sfDeprecated) + of wDeprecated: + if it.kind == nkExprColonExpr: deprecatedStmt(c, it) + elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: noVal(it) @@ -789,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if sym == nil: invalidPragma(it) of wLine: pragmaLine(c, it) of wRaises, wTags: pragmaRaisesOrTags(c, it) - of wUses: pragmaUses(c, it) - of wOperator: - if sym == nil: invalidPragma(it) - else: sym.position = expectIntLit(c, it) + of wGuard: + if sym == nil or sym.kind notin {skVar, skLet, skField}: + invalidPragma(it) + else: + sym.guard = pragmaGuard(c, it, sym.kind) of wInjectStmt: if it.kind != nkExprColonExpr: localError(it.info, errExprExpected) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index acc2425f1..da4adcf49 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) = if n.sons[namePos].kind != nkSym: return documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects) documentEffect(n, n.sons[pragmasPos], wTags, tagEffects) - documentEffect(n, n.sons[pragmasPos], wUses, usesEffects) template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {} @@ -335,10 +334,6 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true - when trackGlobals: - let usesSpec = effectSpec(pragma, wUses) - mergeUses(tracked, usesSpec, n) - proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv if paramType != nil and tfNotNil in paramType.flags and @@ -641,10 +636,6 @@ proc checkMethodEffects*(disp, branch: PSym) = if not isNil(tagsSpec): checkRaisesSpec(tagsSpec, actual.sons[tagEffects], "can have an unlisted effect: ", hints=off, subtypeRelation) - let usesSpec = effectSpec(p, wUses) - if not isNil(usesSpec): - checkRaisesSpec(usesSpec, actual.sons[usesEffects], - "may use an unlisted global variable: ", hints=off, symbolPredicate) if sfThread in disp.flags and notGcSafe(branch.typ): localError(branch.info, "base method is GC-safe, but '$1' is not" % branch.name.s) @@ -656,16 +647,13 @@ proc setEffectsForProcType*(t: PType, n: PNode) = let raisesSpec = effectSpec(n, wRaises) tagsSpec = effectSpec(n, wTags) - usesSpec = effectSpec(n, wUses) - if not isNil(raisesSpec) or not isNil(tagsSpec) or not isNil(usesSpec): + if not isNil(raisesSpec) or not isNil(tagsSpec): internalAssert effects.len == 0 newSeq(effects.sons, effectListLen) if not isNil(raisesSpec): effects.sons[exceptionEffects] = raisesSpec if not isNil(tagsSpec): effects.sons[tagEffects] = tagsSpec - if not isNil(usesSpec): - effects.sons[usesEffects] = usesSpec proc initEffects(effects: PNode; s: PSym; t: var TEffects) = newSeq(effects.sons, effectListLen) @@ -710,12 +698,6 @@ proc trackProc*(s: PSym, body: PNode) = # after the check, use the formal spec: effects.sons[tagEffects] = tagsSpec - when trackGlobals: - let usesSpec = effectSpec(p, wUses) - if not isNil(usesSpec): - checkRaisesSpec(usesSpec, t.uses, - "uses an unlisted global variable: ", hints=on, symbolPredicate) - effects.sons[usesEffects] = usesSpec if optThreadAnalysis in gGlobalOptions: if sfThread in s.flags and t.gcUnsafe: #localError(s.info, warnGcUnsafe2, s.name.s) diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 96056eb6f..d81031917 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -64,7 +64,7 @@ type wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, - wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wUses, + wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, wAuto, wBool, wCatch, wChar, wClass, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, @@ -147,7 +147,7 @@ const "computedgoto", "injectstmt", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", - "guard", "uses", + "guard", "locks", "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", From 34e96e37a12083e64be3842f5fc76fd795328e4a Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 20:51:41 +0200 Subject: [PATCH 16/41] added missing nimfix files --- compiler/nimfix/nimfix.nim | 106 +++++++++++++++++++++++ compiler/nimfix/nimfix.nim.cfg | 17 ++++ compiler/nimfix/pretty.nim | 152 +++++++++++++++++++++++++++++++++ compiler/nimfix/prettybase.nim | 93 ++++++++++++++++++++ 4 files changed, 368 insertions(+) create mode 100644 compiler/nimfix/nimfix.nim create mode 100644 compiler/nimfix/nimfix.nim.cfg create mode 100644 compiler/nimfix/pretty.nim create mode 100644 compiler/nimfix/prettybase.nim diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim new file mode 100644 index 000000000..e561b6d4d --- /dev/null +++ b/compiler/nimfix/nimfix.nim @@ -0,0 +1,106 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code. + +import strutils, os, parseopt +import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf, + extccomp, condsyms, lists + +const Usage = """ +Nimfix - Tool to patch Nim code +Usage: + nimfix [options] projectflie.nim + +Options: + --overwriteFiles:on|off overwrite the original nim files. + DEFAULT is ON! + --wholeProject overwrite every processed file. + --checkExtern:on|off style check also extern names + --styleCheck:on|off|auto performs style checking for identifiers + and suggests an alternative spelling; + 'auto' corrects the spelling. + +In addition, all command line options of Nim are supported. +""" + +proc mainCommand = + #msgs.gErrorMax = high(int) # do not stop after first error + registerPass verbosePass + registerPass semPass + gCmd = cmdPretty + appendStr(searchPaths, options.libpath) + if gProjectFull.len != 0: + # current path is always looked first for modules + prependStr(searchPaths, gProjectPath) + + compileProject() + pretty.overwriteFiles() + +proc processCmdLine*(pass: TCmdLinePass, cmd: string) = + var p = parseopt.initOptParser(cmd) + var argsCount = 0 + gOnlyMainfile = true + while true: + parseopt.next(p) + case p.kind + of cmdEnd: break + of cmdLongoption, cmdShortOption: + case p.key.normalize + of "overwritefiles": + case p.val.normalize + of "on": gOverWrite = true + of "off": gOverWrite = false + else: localError(gCmdLineInfo, errOnOrOffExpected) + of "checkextern": + case p.val.normalize + of "on": gCheckExtern = true + of "off": gCheckExtern = false + else: localError(gCmdLineInfo, errOnOrOffExpected) + of "stylecheck": + case p.val.normalize + of "off": gStyleCheck = StyleCheck.None + of "on": gStyleCheck = StyleCheck.Warn + of "auto": gStyleCheck = StyleCheck.Auto + else: localError(gCmdLineInfo, errOnOrOffExpected) + of "wholeproject": gOnlyMainfile = false + else: + processSwitch(pass, p) + of cmdArgument: + options.gProjectName = unixToNativePath(p.key) + # if processArgument(pass, p, argsCount): break + +proc handleCmdLine() = + if paramCount() == 0: + stdout.writeln(Usage) + else: + processCmdLine(passCmd1, "") + if gProjectName != "": + try: + gProjectFull = canonicalizePath(gProjectName) + except OSError: + gProjectFull = gProjectName + var p = splitFile(gProjectFull) + gProjectPath = p.dir + gProjectName = p.name + else: + gProjectPath = getCurrentDir() + loadConfigs(DefaultConfig) # load all config files + # now process command line arguments again, because some options in the + # command line can overwite the config file's settings + extccomp.initVars() + processCmdLine(passCmd2, "") + mainCommand() + +when compileOption("gc", "v2") or compileOption("gc", "refc"): + GC_disableMarkAndSweep() + +condsyms.initDefines() +defineSymbol "nimfix" +handleCmdline() diff --git a/compiler/nimfix/nimfix.nim.cfg b/compiler/nimfix/nimfix.nim.cfg new file mode 100644 index 000000000..31a41e080 --- /dev/null +++ b/compiler/nimfix/nimfix.nim.cfg @@ -0,0 +1,17 @@ +# Special configuration file for the Nim project +# gc:markAndSweep + +hint[XDeclaredButNotUsed]:off +path:"$projectPath/../.." + +path:"$lib/packages/docutils" +path:"$nim/compiler" + +define:useStdoutAsStdmsg +symbol:nimfix +define:nimfix + +cs:partial +#define:useNodeIds +define:booting +define:noDocgen diff --git a/compiler/nimfix/pretty.nim b/compiler/nimfix/pretty.nim new file mode 100644 index 000000000..acac574af --- /dev/null +++ b/compiler/nimfix/pretty.nim @@ -0,0 +1,152 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements the code "prettifier". This is part of the toolchain +## to convert Nim code into a consistent style. + +import + strutils, os, options, ast, astalgo, msgs, ropes, idents, + intsets, strtabs, semdata, prettybase + +type + StyleCheck* {.pure.} = enum None, Warn, Auto + +var + gOverWrite* = true + gStyleCheck*: StyleCheck + gCheckExtern*, gOnlyMainfile*: bool + +proc overwriteFiles*() = + let doStrip = options.getConfigVar("pretty.strip").normalize == "on" + for i in 0 .. high(gSourceFiles): + if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and + (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx): + let newFile = if gOverWrite: gSourceFiles[i].fullpath + else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim") + try: + var f = open(newFile, fmWrite) + for line in gSourceFiles[i].lines: + if doStrip: + f.write line.strip(leading = false, trailing = true) + else: + f.write line + f.write(gSourceFiles[i].newline) + f.close + except IOError: + rawMessage(errCannotOpenFile, newFile) + +proc `=~`(s: string, a: openArray[string]): bool = + for x in a: + if s.startsWith(x): return true + +proc beautifyName(s: string, k: TSymKind): string = + # minimal set of rules here for transition: + # GC_ is allowed + + let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'}) + if allUpper and k in {skConst, skEnumField, skType}: return s + result = newStringOfCap(s.len) + var i = 0 + case k + of skType, skGenericParam: + # Types should start with a capital unless builtins like 'int' etc.: + if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string", + "char", "byte", "bool", "openArray", "seq", "array", "void", + "pointer", "float", "csize", "cdouble", "cchar", "cschar", + "cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any", + "range", "openarray", "varargs", "set", "cfloat" + ]: + result.add s[i] + else: + result.add toUpper(s[i]) + of skConst, skEnumField: + # for 'const' we keep how it's spelt; either upper case or lower case: + result.add s[0] + else: + # as a special rule, don't transform 'L' to 'l' + if s.len == 1 and s[0] == 'L': result.add 'L' + elif '_' in s: result.add(s[i]) + else: result.add toLower(s[0]) + inc i + while i < s.len: + if s[i] == '_': + if i > 0 and s[i-1] in {'A'..'Z'}: + # don't skip '_' as it's essential for e.g. 'GC_disable' + result.add('_') + inc i + result.add s[i] + else: + inc i + result.add toUpper(s[i]) + elif allUpper: + result.add toLower(s[i]) + else: + result.add s[i] + inc i + +proc replaceInFile(info: TLineInfo; newName: string) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = min(info.col.int, line.len) + if first < 0: return + #inc first, skipIgnoreCase(line, "proc ", first) + while first > 0 and line[first-1] in prettybase.Letters: dec first + if first < 0: return + if line[first] == '`': inc first + + let last = first+identLen(line, first)-1 + if differ(line, first, last, newName): + # last-first+1 != newName.len or + var x = line.substr(0, first-1) & newName & line.substr(last+1) + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true + +proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) = + let beau = beautifyName(s, k) + if s != beau: + if gStyleCheck == StyleCheck.Auto: + sym.name = getIdent(beau) + replaceInFile(info, beau) + else: + message(info, hintName, beau) + +proc styleCheckDefImpl(info: TLineInfo; s: PSym; k: TSymKind) = + # operators stay as they are: + if k in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: return + if k in {skType, skGenericParam} and sfAnon in s.flags: return + if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern: + checkStyle(info, s.name.s, k, s) + +template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) = + when defined(nimfix): + if gStyleCheck != StyleCheck.None: styleCheckDefImpl(info, s, k) + +template styleCheckDef*(info: TLineInfo; s: PSym) = + styleCheckDef(info, s, s.kind) +template styleCheckDef*(s: PSym) = + styleCheckDef(s.info, s, s.kind) + +proc styleCheckUseImpl(info: TLineInfo; s: PSym) = + if info.fileIndex < 0: return + # we simply convert it to what it looks like in the definition + # for consistency + + # operators stay as they are: + if s.kind in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: + return + if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return + let newName = s.name.s + + replaceInFile(info, newName) + #if newName == "File": writeStackTrace() + +template styleCheckUse*(info: TLineInfo; s: PSym) = + when defined(nimfix): + if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s) diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim new file mode 100644 index 000000000..8e0f5db6d --- /dev/null +++ b/compiler/nimfix/prettybase.nim @@ -0,0 +1,93 @@ +# +# +# The Nim Compiler +# (c) Copyright 2014 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +import ast, msgs, strutils, idents, lexbase, streams +from os import splitFile + +type + TSourceFile* = object + lines*: seq[string] + dirty*, isNimfixFile*: bool + fullpath*, newline*: string + fileIdx*: int32 + +var + gSourceFiles*: seq[TSourceFile] = @[] + +proc loadFile*(info: TLineInfo) = + let i = info.fileIndex + if i >= gSourceFiles.len: + gSourceFiles.setLen(i+1) + if gSourceFiles[i].lines.isNil: + gSourceFiles[i].fileIdx = info.fileIndex + gSourceFiles[i].lines = @[] + let path = info.toFullPath + gSourceFiles[i].fullpath = path + gSourceFiles[i].isNimfixFile = path.splitFile.ext == ".nimfix" + # we want to die here for IOError: + for line in lines(path): + gSourceFiles[i].lines.add(line) + # extract line ending of the file: + var lex: TBaseLexer + open(lex, newFileStream(path, fmRead)) + var pos = lex.bufpos + while true: + case lex.buf[pos] + of '\c': + gSourceFiles[i].newline = "\c\L" + break + of '\L', '\0': + gSourceFiles[i].newline = "\L" + break + else: discard + inc pos + close(lex) + +const + Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'} + +proc identLen*(line: string, start: int): int = + while start+result < line.len and line[start+result] in Letters: + inc result + +proc differ*(line: string, a, b: int, x: string): bool = + let y = line[a..b] + result = cmpIgnoreStyle(y, x) == 0 and y != x + +proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = min(info.col.int, line.len) + if first < 0: return + #inc first, skipIgnoreCase(line, "proc ", first) + while first > 0 and line[first-1] in Letters: dec first + if first < 0: return + if line[first] == '`': inc first + + let last = first+identLen(line, first)-1 + if cmpIgnoreStyle(line[first..last], oldSym.s) == 0: + var x = line.substr(0, first-1) & newSym.s & line.substr(last+1) + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true + #if newSym.s == "File": writeStackTrace() + +proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = + replaceDeprecated(info, oldSym.name, newSym.name) + +proc replaceComment*(info: TLineInfo) = + loadFile(info) + + let line = gSourceFiles[info.fileIndex].lines[info.line-1] + var first = info.col.int + if line[first] != '#': inc first + + var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape + system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) + gSourceFiles[info.fileIndex].dirty = true From 399c985b62b35e7d81149ceef5d9a51fdeac35ed Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Oct 2014 21:44:35 +0200 Subject: [PATCH 17/41] fixes recent regression --- lib/pure/concurrency/cpuinfo.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index bd10a416f..8d7f28f8e 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -26,13 +26,16 @@ when defined(openbsd) or defined(netbsd): {.emit:"#include ".} when defined(macosx) or defined(bsd): + # we HAVE to emit param.h before sysctl.h so we cannot use .header here + # either. The amount of archaic bullshit in Poonix based OSes is just insane. + {.emit:"#include ".} const CTL_HW = 6 HW_AVAILCPU = 25 HW_NCPU = 3 proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, a: var csize, b: pointer, c: int): cint {. - importc: "sysctl", header: "".} + importc: "sysctl", nodecl.} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. From ca4c64dd72646abec1b9683bb422f8cb2ca81ad7 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 12 Oct 2014 03:13:12 +0200 Subject: [PATCH 18/41] zipfile generation works again --- koch.nim | 6 ++++-- tools/niminst/niminst.nim | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/koch.nim b/koch.nim index dff6ede98..b7cf65ff7 100644 --- a/koch.nim +++ b/koch.nim @@ -84,9 +84,11 @@ proc csource(args: string) = exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" % [args, NimrodVersion, compileNimInst, findNim()]) -proc zip(args: string) = - exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" % +proc zip(args: string) = + exec("$3 cc -r $2 --var:version=$1 scripts compiler/nimrod.ini" % [NimrodVersion, compileNimInst, findNim()]) + exec("$# --var:version=$# zip compiler/nimrod.ini" % + ["tools/niminst/niminst".exe, NimrodVersion]) proc buildTool(toolname, args: string) = exec("$# cc $# $#" % [findNim(), args, toolname]) diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index bf8a7a84f..50b3dacc3 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -503,9 +503,9 @@ when haveZipLib: else: n = c.outdir / n var z: TZipArchive if open(z, n, fmWrite): - addFile(z, proj / buildBatFile32, buildBatFile32) - addFile(z, proj / buildBatFile64, buildBatFile64) - addFile(z, proj / buildShFile, buildShFile) + addFile(z, proj / buildBatFile32, "build" / buildBatFile32) + addFile(z, proj / buildBatFile64, "build" / buildBatFile64) + addFile(z, proj / buildShFile, "build" / buildShFile) addFile(z, proj / installShFile, installShFile) addFile(z, proj / deinstallShFile, deinstallShFile) for f in walkFiles(c.libpath / "lib/*.h"): @@ -513,7 +513,7 @@ when haveZipLib: for osA in 1..c.oses.len: for cpuA in 1..c.cpus.len: var dir = buildDir(osA, cpuA) - for k, f in walkDir(dir): + for k, f in walkDir("build" / dir): if k == pcFile: addFile(z, proj / dir / extractFilename(f), f) for cat in items({fcConfig..fcOther, fcUnix}): From b7befd69ba0051c1db44a37c8c3e06c48990a9b1 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 12 Oct 2014 14:18:17 +0200 Subject: [PATCH 19/41] updated news.txt slightly --- web/news.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/news.txt b/web/news.txt index efef33e42..27262309e 100644 --- a/web/news.txt +++ b/web/news.txt @@ -2,13 +2,13 @@ News ==== -2014-10-11 Version 0.9.6 released +2014-10-12 Version 0.9.6 released ================================= **Note: This is the last release of Nimrod. The language has been renamed to Nim. Nim slightly breaks compatibility.** -This is a maintenance release. The upcoming 0.10.0 release has all +This is a maintenance release. The upcoming 0.10.0 release has the new features and exciting developments. From 60431944654f3914fb695c48c8579beeddd1084a Mon Sep 17 00:00:00 2001 From: Simon Krauter Date: Tue, 14 Oct 2014 23:32:28 +0200 Subject: [PATCH 20/41] Fixed missing color definion in docs CSS --- config/nimdoc.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg index dc241db50..9db52a84d 100644 --- a/config/nimdoc.cfg +++ b/config/nimdoc.cfg @@ -93,6 +93,11 @@ doc.file = """ $title