From baa77387d7b9ecda84a58af2fed515cb32cb2a5b Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 5 Aug 2018 03:15:40 -0700 Subject: fixes #8215; remove reference to old doc command which was deprecated (#8418) --- doc/docgen.rst | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'doc') diff --git a/doc/docgen.rst b/doc/docgen.rst index d196b3a18..fa23bdc79 100644 --- a/doc/docgen.rst +++ b/doc/docgen.rst @@ -97,24 +97,9 @@ Partial Output:: proc helloWorld(times: int) {.raises: [], tags: [].} ... -The full output can be seen here: `docgen_sample2.html `_. - -The older version of the ``doc`` command, now renamed ``doc0`` runs before -semantic checking which means it lacks some of the things ``doc`` will output. - -The ``doc0`` command:: - nim doc0 sample - -Partial Output:: - ... - proc helloWorld*(times: int) - ... - -Output can be viewed in full here: `docgen_sample.html `_. -As you can see, the tool has extracted less information than what the ``doc`` -command provides, such as pragmas attached implicitly by the compiler. This type -of information is not available from looking at the AST (Abstract Syntax Tree) -prior to semantic checking, which is why ``doc0`` doesn't show it. +The full output can be seen here: `docgen_sample.html `_. +It runs after semantic checking, and includes pragmas attached implicitly by the +compiler. JSON -- cgit 1.4.1-2-gfad0 From e067a7681fd8db93e51fa65569829b8c485c6bfe Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 6 Aug 2018 23:38:29 +0200 Subject: 'nimcache' defaults to ~/.cache on Posix; cleaned up documentation --- changelog.md | 13 ++++++++----- compiler/options.nim | 14 ++++++++++++-- doc/backends.txt | 13 ++++++------- doc/nimc.rst | 35 ++++++++++++----------------------- 4 files changed, 38 insertions(+), 37 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index 4c19abfc0..56830628a 100644 --- a/changelog.md +++ b/changelog.md @@ -20,7 +20,7 @@ - The parser now warns about inconsistent spacing around binary operators as these can easily be confused with unary operators. This warning will likely become an error in the future. -- The ``'c`` and ``'C'`` prefix for octal literals is now deprecated to +- The ``'c`` and ``'C'`` suffix for octal literals is now deprecated to bring the language in line with the standard library (e.g. ``parseOct``). - The dot style for import paths (e.g ``import path.to.module`` instead of ``import path/to/module``) has been deprecated. @@ -67,6 +67,9 @@ - The undocumented ``#? braces`` parsing mode was removed. - The undocumented PHP backend was removed. +- The default location of ``nimcache`` for the native code targets was + changed. Read [the compiler user guide](https://nim-lang.org/docs/nimc.html#generated-c-code-directory) + for more information. ### Library additions @@ -91,7 +94,7 @@ - ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt`` - Added the proc ``flush`` for memory mapped files. - Added the ``MemMapFileStream``. -- Added ``macros.copyLineInfo`` to copy lineInfo from other node +- Added ``macros.copyLineInfo`` to copy lineInfo from other node. ### Library changes @@ -161,11 +164,11 @@ - The command syntax now supports keyword arguments after the first comma. - Thread-local variables can now be declared inside procs. This implies all - the effects of the `global` pragma. + the effects of the ``global`` pragma. -- Nim now supports `except` clause in the export statement. +- Nim now supports ``except`` clause in the export statement. -- Range float types, example `range[0.0 .. Inf]`. More details in language manual. +- Range float types, example ``range[0.0 .. Inf]``. More details in language manual. ### Tool changes diff --git a/compiler/options.nim b/compiler/options.nim index 7d7327d28..4931b4330 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -480,9 +480,19 @@ proc disableNimblePath*(conf: ConfigRef) = include packagehandling +proc getOsCacheDir(): string = + when defined(posix): + result = getHomeDir() / ".cache" + else: + result = getHomeDir() / genSubDir + proc getNimcacheDir*(conf: ConfigRef): string = - result = if conf.nimcacheDir.len > 0: conf.nimcacheDir - else: shortenDir(conf, conf.projectPath) / genSubDir + result = if conf.nimcacheDir.len > 0: + conf.nimcacheDir + elif conf.cmd == cmdCompileToJS: + shortenDir(conf, conf.projectPath) / genSubDir + else: getOsCacheDir() / conf.projectName & + (if isDefined(conf, "release"): "_r" else: "_d") proc pathSubs*(conf: ConfigRef; p, config: string): string = let home = removeTrailingDirSep(os.getHomeDir()) diff --git a/doc/backends.txt b/doc/backends.txt index b7f5308ab..13ef7bf4d 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -65,7 +65,6 @@ The JavaScript target --------------------- Nim can also generate `JavaScript`:idx: code through the ``js`` command. -However, the JavaScript code generator is experimental! Nim targets JavaScript 1.5 which is supported by any widely used browser. Since JavaScript does not have a portable means to include another module, @@ -77,7 +76,7 @@ available. This includes: * manual memory management (``alloc``, etc.) * casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.) * file management -* most modules of the Standard library +* most modules of the standard library * proper 64 bit integer arithmetic * unsigned integer arithmetic @@ -87,9 +86,8 @@ However, the modules `strutils `_, `math `_, and To compile a Nim module into a ``.js`` file use the ``js`` command; the default is a ``.js`` file that is supposed to be referenced in an ``.html`` -file. However, you can also run the code with `nodejs`:idx:, a `software -platform for easily building fast, scalable network applications -`_:: +file. However, you can also run the code with `nodejs`:idx: +(``_):: nim js -d:nodejs -r examples/hallo.nim @@ -330,8 +328,9 @@ Nimcache naming logic The `nimcache`:idx: directory is generated during compilation and will hold either temporary or final files depending on your backend target. The default -name for the directory is ``nimcache`` but you can use the ``--nimcache`` -`compiler switch `_ to change it. +name for the directory depends on the used backend and on your OS but you can +use the ``--nimcache`` `compiler switch `_ to +change it. Nimcache and C like targets ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/nimc.rst b/doc/nimc.rst index 0939f67e8..277c88ec1 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -157,38 +157,27 @@ the first matching file is used. Generated C code directory -------------------------- The generated files that Nim produces all go into a subdirectory called -``nimcache`` in your project directory. This makes it easy to delete all +``nimcache``. Its full path is + +- ``~/.cache/$projectname(_r|_d)`` on Posix +- ``$HOME/nimcache/$projectname(_r|_d)`` on Windows. + +The ``_r`` suffix is used for release builds, ``_d`` is for debug builds. + +This makes it easy to delete all generated files. Files generated in this directory follow a naming logic which you can read about in the `Nim Backend Integration document `_. +The ``--nimcache`` +`compiler switch `_ can be used to +to change the ``nimcache`` directory. + However, the generated C code is not platform independent. C code generated for Linux does not compile on Windows, for instance. The comment on top of the C file lists the OS, CPU and CC the file has been compiled for. -Compilation cache -================= - -**Warning**: The compilation cache is still highly experimental! - -The ``nimcache`` directory may also contain so called `rod`:idx: -or `symbol files`:idx:. These files are pre-compiled modules that are used by -the compiler to perform `incremental compilation`:idx:. This means that only -modules that have changed since the last compilation (or the modules depending -on them etc.) are re-compiled. However, per default no symbol files are -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 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 -resides in its own directory so that the generated ``nimcache`` directory -is not shared between different projects. - - Compiler Selection ================== -- cgit 1.4.1-2-gfad0 From ef9dd464668d08520bdcd549836b4a7551e3b601 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 6 Aug 2018 23:38:29 +0200 Subject: 'nimcache' defaults to ~/.cache on Posix; cleaned up documentation --- changelog.md | 11 +++++++---- compiler/options.nim | 14 ++++++++++++-- doc/backends.txt | 13 ++++++------- doc/nimc.rst | 35 ++++++++++++----------------------- 4 files changed, 37 insertions(+), 36 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index c1e7bd09c..9ab7a0b72 100644 --- a/changelog.md +++ b/changelog.md @@ -20,7 +20,7 @@ - The parser now warns about inconsistent spacing around binary operators as these can easily be confused with unary operators. This warning will likely become an error in the future. -- The ``'c`` and ``'C'`` prefix for octal literals is now deprecated to +- The ``'c`` and ``'C'`` suffix for octal literals is now deprecated to bring the language in line with the standard library (e.g. ``parseOct``). - The dot style for import paths (e.g ``import path.to.module`` instead of ``import path/to/module``) has been deprecated. @@ -67,6 +67,9 @@ - The undocumented ``#? braces`` parsing mode was removed. - The undocumented PHP backend was removed. +- The default location of ``nimcache`` for the native code targets was + changed. Read [the compiler user guide](https://nim-lang.org/docs/nimc.html#generated-c-code-directory) + for more information. ### Library additions @@ -162,11 +165,11 @@ - The command syntax now supports keyword arguments after the first comma. - Thread-local variables can now be declared inside procs. This implies all - the effects of the `global` pragma. + the effects of the ``global`` pragma. -- Nim now supports `except` clause in the export statement. +- Nim now supports ``except`` clause in the export statement. -- Range float types, example `range[0.0 .. Inf]`. More details in language manual. +- Range float types, example ``range[0.0 .. Inf]``. More details in language manual. ### Tool changes diff --git a/compiler/options.nim b/compiler/options.nim index 7d7327d28..4931b4330 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -480,9 +480,19 @@ proc disableNimblePath*(conf: ConfigRef) = include packagehandling +proc getOsCacheDir(): string = + when defined(posix): + result = getHomeDir() / ".cache" + else: + result = getHomeDir() / genSubDir + proc getNimcacheDir*(conf: ConfigRef): string = - result = if conf.nimcacheDir.len > 0: conf.nimcacheDir - else: shortenDir(conf, conf.projectPath) / genSubDir + result = if conf.nimcacheDir.len > 0: + conf.nimcacheDir + elif conf.cmd == cmdCompileToJS: + shortenDir(conf, conf.projectPath) / genSubDir + else: getOsCacheDir() / conf.projectName & + (if isDefined(conf, "release"): "_r" else: "_d") proc pathSubs*(conf: ConfigRef; p, config: string): string = let home = removeTrailingDirSep(os.getHomeDir()) diff --git a/doc/backends.txt b/doc/backends.txt index b7f5308ab..13ef7bf4d 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -65,7 +65,6 @@ The JavaScript target --------------------- Nim can also generate `JavaScript`:idx: code through the ``js`` command. -However, the JavaScript code generator is experimental! Nim targets JavaScript 1.5 which is supported by any widely used browser. Since JavaScript does not have a portable means to include another module, @@ -77,7 +76,7 @@ available. This includes: * manual memory management (``alloc``, etc.) * casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.) * file management -* most modules of the Standard library +* most modules of the standard library * proper 64 bit integer arithmetic * unsigned integer arithmetic @@ -87,9 +86,8 @@ However, the modules `strutils `_, `math `_, and To compile a Nim module into a ``.js`` file use the ``js`` command; the default is a ``.js`` file that is supposed to be referenced in an ``.html`` -file. However, you can also run the code with `nodejs`:idx:, a `software -platform for easily building fast, scalable network applications -`_:: +file. However, you can also run the code with `nodejs`:idx: +(``_):: nim js -d:nodejs -r examples/hallo.nim @@ -330,8 +328,9 @@ Nimcache naming logic The `nimcache`:idx: directory is generated during compilation and will hold either temporary or final files depending on your backend target. The default -name for the directory is ``nimcache`` but you can use the ``--nimcache`` -`compiler switch `_ to change it. +name for the directory depends on the used backend and on your OS but you can +use the ``--nimcache`` `compiler switch `_ to +change it. Nimcache and C like targets ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/nimc.rst b/doc/nimc.rst index 0939f67e8..277c88ec1 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -157,38 +157,27 @@ the first matching file is used. Generated C code directory -------------------------- The generated files that Nim produces all go into a subdirectory called -``nimcache`` in your project directory. This makes it easy to delete all +``nimcache``. Its full path is + +- ``~/.cache/$projectname(_r|_d)`` on Posix +- ``$HOME/nimcache/$projectname(_r|_d)`` on Windows. + +The ``_r`` suffix is used for release builds, ``_d`` is for debug builds. + +This makes it easy to delete all generated files. Files generated in this directory follow a naming logic which you can read about in the `Nim Backend Integration document `_. +The ``--nimcache`` +`compiler switch `_ can be used to +to change the ``nimcache`` directory. + However, the generated C code is not platform independent. C code generated for Linux does not compile on Windows, for instance. The comment on top of the C file lists the OS, CPU and CC the file has been compiled for. -Compilation cache -================= - -**Warning**: The compilation cache is still highly experimental! - -The ``nimcache`` directory may also contain so called `rod`:idx: -or `symbol files`:idx:. These files are pre-compiled modules that are used by -the compiler to perform `incremental compilation`:idx:. This means that only -modules that have changed since the last compilation (or the modules depending -on them etc.) are re-compiled. However, per default no symbol files are -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 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 -resides in its own directory so that the generated ``nimcache`` directory -is not shared between different projects. - - Compiler Selection ================== -- cgit 1.4.1-2-gfad0 From a2c5ffba0cd82b5677fa57612f7dcb7af2348f45 Mon Sep 17 00:00:00 2001 From: alaviss Date: Thu, 9 Aug 2018 15:50:36 +0700 Subject: Uses XDG_CACHE_HOME if available (#8585) * compiler/options: use XDG_CACHE_HOME if set * doc/nimc: update documentation --- compiler/options.nim | 2 +- doc/nimc.rst | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/compiler/options.nim b/compiler/options.nim index be9342085..44519ea22 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -482,7 +482,7 @@ include packagehandling proc getOsCacheDir(): string = when defined(posix): - result = getHomeDir() / ".cache" + result = string getEnv("XDG_CACHE_HOME", getHomeDir() / ".cache") else: result = getHomeDir() / genSubDir diff --git a/doc/nimc.rst b/doc/nimc.rst index 277c88ec1..fca5b273c 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -159,7 +159,8 @@ Generated C code directory The generated files that Nim produces all go into a subdirectory called ``nimcache``. Its full path is -- ``~/.cache/$projectname(_r|_d)`` on Posix +- ``$XDG_CACHE_HOME/$projectname(_r|_d)`` or ``~/.cache/$projectname(_r|_d)`` + on Posix - ``$HOME/nimcache/$projectname(_r|_d)`` on Windows. The ``_r`` suffix is used for release builds, ``_d`` is for debug builds. -- cgit 1.4.1-2-gfad0 From b4e5c9d075d9c2ef6192749b02738966b3dc943d Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 9 Aug 2018 20:31:40 +0200 Subject: deprecate the .this pragma --- changelog.md | 4 ++++ compiler/idents.nim | 37 ++++++++++++-------------------- compiler/modulegraphs.nim | 54 +++++++++++++++++++++++------------------------ compiler/pragmas.nim | 2 ++ doc/manual.rst | 2 ++ 5 files changed, 48 insertions(+), 51 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index 9ab7a0b72..426b63b7e 100644 --- a/changelog.md +++ b/changelog.md @@ -170,6 +170,10 @@ - Nim now supports ``except`` clause in the export statement. - Range float types, example ``range[0.0 .. Inf]``. More details in language manual. +- The ``{.this.}`` pragma has been deprecated. It never worked within generics and + we found the resulting code harder to read than the more explicit ``obj.field`` + syntax. + ### Tool changes diff --git a/compiler/idents.nim b/compiler/idents.nim index 0a2f2d5cf..58800b73d 100644 --- a/compiler/idents.nim +++ b/compiler/idents.nim @@ -30,14 +30,7 @@ type wordCounter: int idAnon*, idDelegator*, emptyIdent*: PIdent -when false: - var - legacy: IdentCache - -proc resetIdentCache*() = - when false: - for i in low(legacy.buckets)..high(legacy.buckets): - legacy.buckets[i] = nil +proc resetIdentCache*() = discard proc cmpIgnoreStyle*(a, b: cstring, blen: int): int = if a[0] != b[0]: return 1 @@ -73,11 +66,9 @@ proc cmpExact(a, b: cstring, blen: int): int = if result == 0: if a[i] != '\0': result = 1 -{.this: self.} - -proc getIdent*(self: IdentCache; identifier: cstring, length: int, h: Hash): PIdent = - var idx = h and high(buckets) - result = buckets[idx] +proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIdent = + var idx = h and high(ic.buckets) + result = ic.buckets[idx] var last: PIdent = nil var id = 0 while result != nil: @@ -85,8 +76,8 @@ proc getIdent*(self: IdentCache; identifier: cstring, length: int, h: Hash): PId if last != nil: # make access to last looked up identifier faster: last.next = result.next - result.next = buckets[idx] - buckets[idx] = result + result.next = ic.buckets[idx] + ic.buckets[idx] = result return elif cmpIgnoreStyle(cstring(result.s), identifier, length) == 0: assert((id == 0) or (id == result.id)) @@ -97,20 +88,20 @@ proc getIdent*(self: IdentCache; identifier: cstring, length: int, h: Hash): PId result.h = h result.s = newString(length) for i in countup(0, length - 1): result.s[i] = identifier[i] - result.next = buckets[idx] - buckets[idx] = result + result.next = ic.buckets[idx] + ic.buckets[idx] = result if id == 0: - inc(wordCounter) - result.id = -wordCounter + inc(ic.wordCounter) + result.id = -ic.wordCounter else: result.id = id -proc getIdent*(self: IdentCache; identifier: string): PIdent = - result = getIdent(cstring(identifier), len(identifier), +proc getIdent*(ic: IdentCache; identifier: string): PIdent = + result = getIdent(ic, cstring(identifier), len(identifier), hashIgnoreStyle(identifier)) -proc getIdent*(self: IdentCache; identifier: string, h: Hash): PIdent = - result = getIdent(cstring(identifier), len(identifier), h) +proc getIdent*(ic: IdentCache; identifier: string, h: Hash): PIdent = + result = getIdent(ic, cstring(identifier), len(identifier), h) proc newIdentCache*(): IdentCache = result = IdentCache() diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 334cd1ae6..1eecc4176 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -65,10 +65,8 @@ type proc hash*(x: FileIndex): Hash {.borrow.} -{.this: g.} - proc stopCompile*(g: ModuleGraph): bool {.inline.} = - result = doStopCompile != nil and doStopCompile() + result = g.doStopCompile != nil and g.doStopCompile() proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym = result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo(), {}) @@ -98,44 +96,44 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph = result.cacheTables = initTable[string, BTree[string, PNode]]() proc resetAllModules*(g: ModuleGraph) = - initStrTable(packageSyms) - deps = initIntSet() - modules = @[] - importStack = @[] - inclToMod = initTable[FileIndex, FileIndex]() - usageSym = nil - owners = @[] - methods = @[] - initStrTable(compilerprocs) - initStrTable(exposed) + initStrTable(g.packageSyms) + g.deps = initIntSet() + g.modules = @[] + g.importStack = @[] + g.inclToMod = initTable[FileIndex, FileIndex]() + g.usageSym = nil + g.owners = @[] + g.methods = @[] + initStrTable(g.compilerprocs) + initStrTable(g.exposed) proc getModule*(g: ModuleGraph; fileIdx: FileIndex): PSym = - if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len: - result = modules[fileIdx.int32] + if fileIdx.int32 >= 0 and fileIdx.int32 < g.modules.len: + result = g.modules[fileIdx.int32] proc dependsOn(a, b: int): int {.inline.} = (a shl 15) + b proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) = assert m.position == m.info.fileIndex.int32 addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false) - if suggestMode: - deps.incl m.position.dependsOn(dep.int) + if g.suggestMode: + g.deps.incl m.position.dependsOn(dep.int) # we compute the transitive closure later when quering the graph lazily. # this improves efficiency quite a lot: #invalidTransitiveClosure = true proc addIncludeDep*(g: ModuleGraph; module, includeFile: FileIndex) = addModuleDep(g.incr, g.config, module, includeFile, isIncludeFile = true) - discard hasKeyOrPut(inclToMod, includeFile, module) + discard hasKeyOrPut(g.inclToMod, includeFile, module) proc parentModule*(g: ModuleGraph; fileIdx: FileIndex): FileIndex = ## returns 'fileIdx' if the file belonging to this index is ## directly used as a module or else the module that first ## references this include file. - if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len and modules[fileIdx.int32] != nil: + if fileIdx.int32 >= 0 and fileIdx.int32 < g.modules.len and g.modules[fileIdx.int32] != nil: result = fileIdx else: - result = inclToMod.getOrDefault(fileIdx) + result = g.inclToMod.getOrDefault(fileIdx) proc transitiveClosure(g: var IntSet; n: int) = # warshall's algorithm @@ -147,22 +145,22 @@ proc transitiveClosure(g: var IntSet; n: int) = g.incl i.dependsOn(j) proc markDirty*(g: ModuleGraph; fileIdx: FileIndex) = - let m = getModule fileIdx + let m = g.getModule fileIdx if m != nil: incl m.flags, sfDirty proc markClientsDirty*(g: ModuleGraph; fileIdx: FileIndex) = # we need to mark its dependent modules D as dirty right away because after # nimsuggest is done with this module, the module's dirty flag will be # cleared but D still needs to be remembered as 'dirty'. - if invalidTransitiveClosure: - invalidTransitiveClosure = false - transitiveClosure(deps, modules.len) + if g.invalidTransitiveClosure: + g.invalidTransitiveClosure = false + transitiveClosure(g.deps, g.modules.len) # every module that *depends* on this file is also dirty: - for i in 0i32.. Date: Fri, 10 Aug 2018 01:20:14 +0200 Subject: deprecated regionized pointers --- changelog.md | 3 ++ compiler/semtypes.nim | 2 ++ doc/manual.rst | 62 ------------------------------------- lib/pure/concurrency/threadpool.nim | 6 ++-- tests/parallel/tptr_to_ref.nim | 4 +-- 5 files changed, 9 insertions(+), 68 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index 426b63b7e..a77c57631 100644 --- a/changelog.md +++ b/changelog.md @@ -173,6 +173,9 @@ - The ``{.this.}`` pragma has been deprecated. It never worked within generics and we found the resulting code harder to read than the more explicit ``obj.field`` syntax. +- "Memory regions" for pointer types have been deprecated, they were hardly used + anywhere. Note that this has **nothing** to do with the ``--gc:regions`` switch + of managing memory. ### Tool changes diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 972c8c709..99f2cf20d 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -193,6 +193,8 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin { tyError, tyObject}: message c.config, n[i].info, errGenerated, "region needs to be an object type" + else: + message(c.config, n.info, warnDeprecated, "region for pointer types") addSonSkipIntLit(result, region) addSonSkipIntLit(result, t) if tfPartial in result.flags: diff --git a/doc/manual.rst b/doc/manual.rst index 460468fe5..7aeec7390 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -1507,68 +1507,6 @@ non nilable pointers. The details of this analysis are still to be specified here. -Memory regions --------------- - -The types ``ref`` and ``ptr`` can get an optional ``region`` annotation. -A region has to be an object type. - -Regions are very useful to separate user space and kernel memory in the -development of OS kernels: - -.. code-block:: nim - type - Kernel = object - Userspace = object - - var a: Kernel ptr Stat - var b: Userspace ptr Stat - - # the following does not compile as the pointer types are incompatible: - a = b - -As the example shows ``ptr`` can also be used as a binary -operator, ``region ptr T`` is a shortcut for ``ptr[region, T]``. - -In order to make generic code easier to write ``ptr T`` is a subtype -of ``ptr[R, T]`` for any ``R``. - -Furthermore the subtype relation of the region object types is lifted to -the pointer types: If ``A <: B`` then ``ptr[A, T] <: ptr[B, T]``. This can be -used to model subregions of memory. As a special typing rule ``ptr[R, T]`` is -not compatible to ``pointer`` to prevent the following from compiling: - -.. code-block:: nim - # from system - proc dealloc(p: pointer) - - # wrap some scripting language - type - PythonsHeap = object - PyObjectHeader = object - rc: int - typ: pointer - PyObject = ptr[PythonsHeap, PyObjectHeader] - - proc createPyObject(): PyObject {.importc: "...".} - proc destroyPyObject(x: PyObject) {.importc: "...".} - - var foo = createPyObject() - # type error here, how convenient: - dealloc(foo) - - -Future directions: - -* Memory regions might become available for ``string`` and ``seq`` too. -* Builtin regions like ``private``, ``global`` and ``local`` might be - useful for an OpenCL target. -* Builtin "regions" can model ``lent`` and ``unique`` pointers. -* An assignment operator can be attached to a region so that proper write - barriers can be generated. This would imply that the GC can be implemented - completely in user-space. - - Procedural type --------------- A procedural type is internally a pointer to a procedure. ``nil`` is diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 6ec71e912..826e42b6c 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -89,8 +89,6 @@ proc closeBarrier(b: ptr Barrier) {.compilerProc.} = # ---------------------------------------------------------------------------- type - foreign* = object ## a region that indicates the pointer comes from a - ## foreign thread heap. AwaitInfo = object cv: Semaphore idx: int @@ -231,10 +229,10 @@ proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) = action(fv.blob) finished(fv) -proc unsafeRead*[T](fv: FlowVar[ref T]): foreign ptr T = +proc unsafeRead*[T](fv: FlowVar[ref T]): ptr T = ## blocks until the value is available and then returns this value. await(fv) - result = cast[foreign ptr T](fv.data) + result = cast[ptr T](fv.data) proc `^`*[T](fv: FlowVar[ref T]): ref T = ## blocks until the value is available and then returns this value. diff --git a/tests/parallel/tptr_to_ref.nim b/tests/parallel/tptr_to_ref.nim index fee210dcd..ae02c16e5 100644 --- a/tests/parallel/tptr_to_ref.nim +++ b/tests/parallel/tptr_to_ref.nim @@ -11,7 +11,7 @@ type Killer* = object lock: Lock bailed {.guard: lock.}: bool - processes {.guard: lock.}: array[0..MAX_WORKERS-1, foreign ptr Process] + processes {.guard: lock.}: array[0..MAX_WORKERS-1, ptr Process] # Hold a lock for a statement. template hold(lock: Lock, body: untyped) = @@ -32,7 +32,7 @@ proc initKiller*(): Killer = var killer = initKiller() # remember that a process has been launched, killing it if we have bailed. -proc launched*(process: foreign ptr Process): int {.gcsafe.} = +proc launched*(process: ptr Process): int {.gcsafe.} = result = killer.processes.high + 1 killer.lock.hold: if killer.bailed: -- cgit 1.4.1-2-gfad0 From 43f634db8dfac4fb13c8454958d35e776410dac1 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Fri, 10 Aug 2018 00:20:14 -0700 Subject: fixes #8519; implements T.distinctBase to reverse T = distinct A (#8531) --- doc/manual.rst | 3 ++- lib/pure/sugar.nim | 38 ++++++++++++++++++++++++++++++++++++++ tests/stdlib/tsugar.nim | 29 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/stdlib/tsugar.nim (limited to 'doc') diff --git a/doc/manual.rst b/doc/manual.rst index abdc4ce69..de0a13143 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -1673,7 +1673,8 @@ A ``distinct`` type is new type derived from a `base type`:idx: that is incompatible with its base type. In particular, it is an essential property of a distinct type that it **does not** imply a subtype relation between it and its base type. Explicit type conversions from a distinct type to its -base type and vice versa are allowed. +base type and vice versa are allowed. See also ``distinctBase`` to get the +reverse operation. Modelling currencies diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim index 258b40191..8ded552d9 100644 --- a/lib/pure/sugar.nim +++ b/lib/pure/sugar.nim @@ -198,3 +198,41 @@ macro dump*(x: typed): untyped = let r = quote do: debugEcho `s`, " = ", `x` return r + +# TODO: consider exporting this in macros.nim +proc freshIdentNodes(ast: NimNode): NimNode = + # Replace NimIdent and NimSym by a fresh ident node + # see also https://github.com/nim-lang/Nim/pull/8531#issuecomment-410436458 + proc inspect(node: NimNode): NimNode = + case node.kind: + of nnkIdent, nnkSym: + result = ident($node) + of nnkEmpty, nnkLiterals: + result = node + else: + result = node.kind.newTree() + for child in node: + result.add inspect(child) + result = inspect(ast) + +macro distinctBase*(T: typedesc): untyped = + ## reverses ``type T = distinct A``; works recursively. + runnableExamples: + type T = distinct int + doAssert distinctBase(T) is int + doAssert: not compiles(distinctBase(int)) + type T2 = distinct T + doAssert distinctBase(T2) is int + + let typeNode = getTypeImpl(T) + expectKind(typeNode, nnkBracketExpr) + if typeNode[0].typeKind != ntyTypeDesc: + error "expected typeDesc, got " & $typeNode[0] + var typeSym = typeNode[1] + typeSym = getTypeImpl(typeSym) + if typeSym.typeKind != ntyDistinct: + error "type is not distinct" + typeSym = typeSym[0] + while typeSym.typeKind == ntyDistinct: + typeSym = getTypeImpl(typeSym)[0] + typeSym.freshIdentNodes diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim new file mode 100644 index 000000000..a870bf6fe --- /dev/null +++ b/tests/stdlib/tsugar.nim @@ -0,0 +1,29 @@ +discard """ + file: "tsugar.nim" + output: "" +""" +import sugar +import macros + +block distinctBase: + block: + type + Foo[T] = distinct seq[T] + var a: Foo[int] + doAssert a.type.distinctBase is seq[int] + + block: + # simplified from https://github.com/nim-lang/Nim/pull/8531#issuecomment-410436458 + macro uintImpl(bits: static[int]): untyped = + if bits >= 128: + let inner = getAST(uintImpl(bits div 2)) + result = newTree(nnkBracketExpr, ident("UintImpl"), inner) + else: + result = ident("uint64") + + type + BaseUint = UintImpl or SomeUnsignedInt + UintImpl[Baseuint] = object + Uint[bits: static[int]] = distinct uintImpl(bits) + + doAssert Uint[128].distinctBase is UintImpl[uint64] -- cgit 1.4.1-2-gfad0 From 1d63a8fe4a21d71ab2d8cfb7d1540bdc09d02c29 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 10 Aug 2018 09:21:46 +0200 Subject: update the 'float' spec; refs #8589 --- doc/manual.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/manual.rst b/doc/manual.rst index 7aeec7390..c0cde5140 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -769,8 +769,8 @@ Pre-defined floating point types The following floating point types are pre-defined: ``float`` - the generic floating point type; its size is platform dependent - (the compiler chooses the processor's fastest floating point type). + the generic floating point type; its size used to be platform dependent, + but now it is always mapped to ``float64``. This type should be used in general. floatXX -- cgit 1.4.1-2-gfad0 From 1d78ba64b4761de88817a2e5748a456679cb2bab Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 10 Aug 2018 11:40:01 +0200 Subject: rework the exception hierarchy; refs #8363 --- changelog.md | 4 ++ doc/exception_hierarchy_fragment.txt | 28 ---------- doc/manual.rst | 9 ++- lib/pure/smtp.nim | 6 +- lib/system.nim | 104 +++++++++++------------------------ 5 files changed, 45 insertions(+), 106 deletions(-) delete mode 100644 doc/exception_hierarchy_fragment.txt (limited to 'doc') diff --git a/changelog.md b/changelog.md index f06041b34..5a28fc7ff 100644 --- a/changelog.md +++ b/changelog.md @@ -177,6 +177,10 @@ anywhere. Note that this has **nothing** to do with the ``--gc:regions`` switch of managing memory. +- The exception hierarchy was slightly reworked, ``SystemError`` was renamed to + ``Error`` and is the new base class for any exception that is guaranteed to + be catchable. This change should have minimal impact on most existing Nim code. + ### Tool changes diff --git a/doc/exception_hierarchy_fragment.txt b/doc/exception_hierarchy_fragment.txt deleted file mode 100644 index a02d9ccef..000000000 --- a/doc/exception_hierarchy_fragment.txt +++ /dev/null @@ -1,28 +0,0 @@ -* `Exception `_ - * `AccessViolationError `_ - * `ArithmeticError `_ - * `DivByZeroError `_ - * `OverflowError `_ - * `AssertionError `_ - * `DeadThreadError `_ - * `FloatingPointError `_ - * `FloatDivByZeroError `_ - * `FloatInexactError `_ - * `FloatInvalidOpError `_ - * `FloatOverflowError `_ - * `FloatUnderflowError `_ - * `FieldError `_ - * `IndexError `_ - * `ObjectAssignmentError `_ - * `ObjectConversionError `_ - * `ValueError `_ - * `KeyError `_ - * `ReraiseError `_ - * `RangeError `_ - * `OutOfMemoryError `_ - * `ResourceExhaustedError `_ - * `StackOverflowError `_ - * `SystemError `_ - * `IOError `_ - * `OSError `_ - * `LibraryError `_ diff --git a/doc/manual.rst b/doc/manual.rst index c0cde5140..6ce72e2e1 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -3968,9 +3968,12 @@ exception. Exception hierarchy ------------------- -The exception tree is defined in the `system `_ module: - -.. include:: exception_hierarchy_fragment.txt +The exception tree is defined in the `system `_ module. +Every exception inherits from ``system.Exception``. Exceptions that indicate +programming bugs inherit from ``system.Defect`` (which is a subtype of ``Exception``) +and are stricly speaking not catchable as they can also be mapped to an operation +that terminates the whole process. Exceptions that indicate any other runtime error +that can be caught inherit from ``system.Error`` (which is a subtype of ``Exception``). Imported exceptions diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim index c2c674b84..d9b863a52 100644 --- a/lib/pure/smtp.nim +++ b/lib/pure/smtp.nim @@ -119,8 +119,7 @@ proc newSmtp*(useSsl = false, debug=false, when compiledWithSsl: sslContext.wrapSocket(result.sock) else: - raise newException(SystemError, - "SMTP module compiled without SSL support") + {.error: "SMTP module compiled without SSL support".} proc newAsyncSmtp*(useSsl = false, debug=false, sslContext = defaultSslContext): AsyncSmtp = @@ -133,8 +132,7 @@ proc newAsyncSmtp*(useSsl = false, debug=false, when compiledWithSsl: sslContext.wrapSocket(result.sock) else: - raise newException(SystemError, - "SMTP module compiled without SSL support") + {.error: "SMTP module compiled without SSL support".} proc quitExcpt(smtp: AsyncSmtp, msg: string): Future[void] = var retFuture = newFuture[void]() diff --git a/lib/system.nim b/lib/system.nim index 3a82299ac..531363eb1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -484,141 +484,103 @@ type raise_id: uint # set when exception is raised up: ref Exception # used for stacking exceptions. Not exported! - SystemError* = object of Exception ## \ - ## Abstract class for exceptions that the runtime system raises. - ## - ## See the full `exception hierarchy `_. - IOError* = object of SystemError ## \ + Defect* = object of Exception ## \ + ## Abstract base class for all exceptions that Nim's runtime raises + ## but that are strictly uncatchable as they can also be mapped to + ## a ``quit`` / ``trap`` / ``exit`` operation. + + Error* = object of Exception ## \ + ## Abstract class for all exceptions that are catchable. + IOError* = object of Error ## \ ## Raised if an IO error occurred. - ## - ## See the full `exception hierarchy `_. EOFError* = object of IOError ## \ ## Raised if an IO "end of file" error occurred. - ## - ## See the full `exception hierarchy `_. - OSError* = object of SystemError ## \ + OSError* = object of Error ## \ ## Raised if an operating system service failed. - ## - ## See the full `exception hierarchy `_. errorCode*: int32 ## OS-defined error code describing this error. LibraryError* = object of OSError ## \ ## Raised if a dynamic library could not be loaded. - ## - ## See the full `exception hierarchy `_. - ResourceExhaustedError* = object of SystemError ## \ + ResourceExhaustedError* = object of Error ## \ ## Raised if a resource request could not be fulfilled. - ## - ## See the full `exception hierarchy `_. - ArithmeticError* = object of Exception ## \ + ArithmeticError* = object of Defect ## \ ## Raised if any kind of arithmetic error occurred. - ## - ## See the full `exception hierarchy `_. DivByZeroError* = object of ArithmeticError ## \ ## Raised for runtime integer divide-by-zero errors. - ## - ## See the full `exception hierarchy `_. OverflowError* = object of ArithmeticError ## \ ## Raised for runtime integer overflows. ## ## This happens for calculations whose results are too large to fit in the - ## provided bits. See the full `exception hierarchy `_. - AccessViolationError* = object of Exception ## \ + ## provided bits. + AccessViolationError* = object of Defect ## \ ## Raised for invalid memory access errors - ## - ## See the full `exception hierarchy `_. - AssertionError* = object of Exception ## \ + AssertionError* = object of Defect ## \ ## Raised when assertion is proved wrong. ## - ## Usually the result of using the `assert() template <#assert>`_. See the - ## full `exception hierarchy `_. - ValueError* = object of Exception ## \ + ## Usually the result of using the `assert() template <#assert>`_. + ValueError* = object of Defect ## \ ## Raised for string and object conversion errors. KeyError* = object of ValueError ## \ ## Raised if a key cannot be found in a table. ## ## Mostly used by the `tables `_ module, it can also be raised ## by other collection modules like `sets `_ or `strtabs - ## `_. See the full `exception hierarchy `_. - OutOfMemError* = object of SystemError ## \ + ## `_. + OutOfMemError* = object of Defect ## \ ## Raised for unsuccessful attempts to allocate memory. - ## - ## See the full `exception hierarchy `_. - IndexError* = object of Exception ## \ + IndexError* = object of Defect ## \ ## Raised if an array index is out of bounds. - ## - ## See the full `exception hierarchy `_. - FieldError* = object of Exception ## \ + FieldError* = object of Defect ## \ ## Raised if a record field is not accessible because its dicriminant's ## value does not fit. - ## - ## See the full `exception hierarchy `_. - RangeError* = object of Exception ## \ + RangeError* = object of Defect ## \ ## Raised if a range check error occurred. - ## - ## See the full `exception hierarchy `_. - StackOverflowError* = object of SystemError ## \ + StackOverflowError* = object of Defect ## \ ## Raised if the hardware stack used for subroutine calls overflowed. - ## - ## See the full `exception hierarchy `_. - ReraiseError* = object of Exception ## \ + ReraiseError* = object of Defect ## \ ## Raised if there is no exception to reraise. - ## - ## See the full `exception hierarchy `_. - ObjectAssignmentError* = object of Exception ## \ + ObjectAssignmentError* = object of Defect ## \ ## Raised if an object gets assigned to its parent's object. - ## - ## See the full `exception hierarchy `_. - ObjectConversionError* = object of Exception ## \ + ObjectConversionError* = object of Defect ## \ ## Raised if an object is converted to an incompatible object type. ## You can use ``of`` operator to check if conversion will succeed. - ## - ## See the full `exception hierarchy `_. - FloatingPointError* = object of Exception ## \ + FloatingPointError* = object of Defect ## \ ## Base class for floating point exceptions. - ## - ## See the full `exception hierarchy `_. FloatInvalidOpError* = object of FloatingPointError ## \ ## Raised by invalid operations according to IEEE. ## - ## Raised by ``0.0/0.0``, for example. See the full `exception - ## hierarchy `_. + ## Raised by ``0.0/0.0``, for example. FloatDivByZeroError* = object of FloatingPointError ## \ ## Raised by division by zero. ## - ## Divisor is zero and dividend is a finite nonzero number. See the full - ## `exception hierarchy `_. + ## Divisor is zero and dividend is a finite nonzero number. FloatOverflowError* = object of FloatingPointError ## \ ## Raised for overflows. ## ## The operation produced a result that exceeds the range of the exponent. - ## See the full `exception hierarchy `_. FloatUnderflowError* = object of FloatingPointError ## \ ## Raised for underflows. ## ## The operation produced a result that is too small to be represented as a - ## normal number. See the full `exception hierarchy `_. + ## normal number. FloatInexactError* = object of FloatingPointError ## \ ## Raised for inexact results. ## ## The operation produced a result that cannot be represented with infinite ## precision -- for example: ``2.0 / 3.0, log(1.1)`` ## - ## **NOTE**: Nim currently does not detect these! See the full - ## `exception hierarchy `_. - DeadThreadError* = object of Exception ## \ + ## **NOTE**: Nim currently does not detect these! + DeadThreadError* = object of Defect ## \ ## Raised if it is attempted to send a message to a dead thread. - ## - ## See the full `exception hierarchy `_. - NilAccessError* = object of SystemError ## \ + NilAccessError* = object of Defect ## \ ## Raised on dereferences of ``nil`` pointers. ## ## This is only raised if the ``segfaults.nim`` module was imported! when defined(nimNewRuntime): type - MoveError* = object of SystemError ## \ + MoveError* = object of Defect ## \ ## Raised on attempts to re-sink an already consumed ``sink`` parameter. when defined(js) or defined(nimdoc): -- cgit 1.4.1-2-gfad0 From ba6601b149e77be52973209fbcea5a799f1ebf24 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 10 Aug 2018 12:09:51 +0200 Subject: fixes #8599 --- compiler/options.nim | 2 +- doc/nimc.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/compiler/options.nim b/compiler/options.nim index ef2b6023a..537a550f8 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -482,7 +482,7 @@ include packagehandling proc getOsCacheDir(): string = when defined(posix): - result = string getEnv("XDG_CACHE_HOME", getHomeDir() / ".cache") + result = getEnv("XDG_CACHE_HOME", getHomeDir() / ".cache") / "nim" else: result = getHomeDir() / genSubDir diff --git a/doc/nimc.rst b/doc/nimc.rst index fca5b273c..a33be39e6 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -159,7 +159,7 @@ Generated C code directory The generated files that Nim produces all go into a subdirectory called ``nimcache``. Its full path is -- ``$XDG_CACHE_HOME/$projectname(_r|_d)`` or ``~/.cache/$projectname(_r|_d)`` +- ``$XDG_CACHE_HOME/nim/$projectname(_r|_d)`` or ``~/.cache/nim/$projectname(_r|_d)`` on Posix - ``$HOME/nimcache/$projectname(_r|_d)`` on Windows. -- cgit 1.4.1-2-gfad0 From 4cf1e3eb4b77e4afd5047397b05726756c2de598 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 10 Aug 2018 15:31:53 +0200 Subject: rename SystemError to CatchableError in order to avoid breaking Nimble and probably lots of other code --- changelog.md | 2 +- doc/manual.rst | 3 ++- lib/system.nim | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index 5a28fc7ff..f48f7e024 100644 --- a/changelog.md +++ b/changelog.md @@ -178,7 +178,7 @@ of managing memory. - The exception hierarchy was slightly reworked, ``SystemError`` was renamed to - ``Error`` and is the new base class for any exception that is guaranteed to + ``CatchableError`` and is the new base class for any exception that is guaranteed to be catchable. This change should have minimal impact on most existing Nim code. diff --git a/doc/manual.rst b/doc/manual.rst index 6ce72e2e1..6ea82b78c 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -3973,7 +3973,8 @@ Every exception inherits from ``system.Exception``. Exceptions that indicate programming bugs inherit from ``system.Defect`` (which is a subtype of ``Exception``) and are stricly speaking not catchable as they can also be mapped to an operation that terminates the whole process. Exceptions that indicate any other runtime error -that can be caught inherit from ``system.Error`` (which is a subtype of ``Exception``). +that can be caught inherit from ``system.CatchableError`` +(which is a subtype of ``Exception``). Imported exceptions diff --git a/lib/system.nim b/lib/system.nim index 531363eb1..b92dd58d6 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -489,18 +489,18 @@ type ## but that are strictly uncatchable as they can also be mapped to ## a ``quit`` / ``trap`` / ``exit`` operation. - Error* = object of Exception ## \ + CatchableError* = object of Exception ## \ ## Abstract class for all exceptions that are catchable. - IOError* = object of Error ## \ + IOError* = object of CatchableError ## \ ## Raised if an IO error occurred. EOFError* = object of IOError ## \ ## Raised if an IO "end of file" error occurred. - OSError* = object of Error ## \ + OSError* = object of CatchableError ## \ ## Raised if an operating system service failed. errorCode*: int32 ## OS-defined error code describing this error. LibraryError* = object of OSError ## \ ## Raised if a dynamic library could not be loaded. - ResourceExhaustedError* = object of Error ## \ + ResourceExhaustedError* = object of CatchableError ## \ ## Raised if a resource request could not be fulfilled. ArithmeticError* = object of Defect ## \ ## Raised if any kind of arithmetic error occurred. -- cgit 1.4.1-2-gfad0 From 6a0751e81a31d08d8b31a434018176adcdd989d7 Mon Sep 17 00:00:00 2001 From: DrSlump Date: Mon, 13 Aug 2018 11:24:58 +0200 Subject: Fixes #7586: Adds documentation for hints --- doc/nimc.rst | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'doc') diff --git a/doc/nimc.rst b/doc/nimc.rst index fca5b273c..9c81d912f 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -68,6 +68,46 @@ User Some user defined warning. ========================== ============================================ +List of hints +------------- + +Each hint can be activated individually with ``--hint[NAME]:on|off`` or in a +``push`` pragma. + +========================== ============================================ +Name Description +========================== ============================================ +CC Shows when the C compiler is called. +CodeBegin +CodeEnd +CondTrue +Conf A config file was loaded. +ConvToBaseNotNeeded +ConvFromXtoItselfNotNeeded +Dependency +Exec Program is executed. +ExprAlwaysX +ExtendedContext +GCStats Dumps statistics about the Garbage Collector. +GlobalVar Shows global variables declarations. +LineTooLong Line exceeds the maximum length. +Link Linking phase. +Name +Path Search paths modifications. +Pattern +Performance +Processing Artifact being compiled. +QuitCalled +Source The source line that triggered a diagnostic + message. +StackTrace +Success, SuccessX Successful compilation of a library or a binary. +User +UserRaw +XDeclaredButNotUsed Unused symbols in the code. +========================== ============================================ + + Verbosity levels ---------------- -- cgit 1.4.1-2-gfad0 From f960523b466f3e32ab29968a18c51e3843abc3c9 Mon Sep 17 00:00:00 2001 From: Araq Date: Mon, 13 Aug 2018 20:12:13 +0200 Subject: document the new --nilseqs:on switch --- changelog.md | 2 +- doc/advopt.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index f48f7e024..b84cf16a1 100644 --- a/changelog.md +++ b/changelog.md @@ -155,7 +155,7 @@ More details in language manual. - ``nil`` for strings/seqs is finally gone. Instead the default value for - these is ``"" / @[]``. + these is ``"" / @[]``. Use ``--nilseqs:on`` for a transition period. - Accessing the binary zero terminator in Nim's native strings is now invalid. Internally a Nim string still has the trailing zero for diff --git a/doc/advopt.txt b/doc/advopt.txt index 685c8127d..150025509 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -68,6 +68,8 @@ Advanced options: --oldNewlines:on|off turn on|off the old behaviour of "\n" --laxStrings:on|off when turned on, accessing the zero terminator in strings is allowed; only for backwards compatibility + --nilseqs:on|off allow 'nil' for strings/seqs for + backwards compatibility --skipCfg do not read the general configuration file --skipUserCfg do not read the user's configuration file --skipParentCfg do not read the parent dirs' configuration files -- cgit 1.4.1-2-gfad0 From 83c89197f3fda783819cd0c5de06561c3e6f3616 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 14 Aug 2018 01:28:04 +0200 Subject: renames threadpool.await to blockUntil; refs #7853 --- changelog.md | 4 ++++ doc/manual.rst | 6 ++--- doc/spawn.txt | 6 ++--- lib/pure/concurrency/threadpool.nim | 48 ++++++++++++++++++------------------- tests/parallel/twaitany.nim | 4 ++-- 5 files changed, 36 insertions(+), 32 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index b84cf16a1..e2203e602 100644 --- a/changelog.md +++ b/changelog.md @@ -63,6 +63,10 @@ - ``lineInfoObj`` now returns absolute path instead of project path. It's used by ``lineInfo``, ``check``, ``expect``, ``require``, etc. +- `threadpool`'s `await` and derivatives have been renamed to `blockUntil` + to avoid confusions with `await` from the `async` macro. + + #### Breaking changes in the compiler - The undocumented ``#? braces`` parsing mode was removed. diff --git a/doc/manual.rst b/doc/manual.rst index ea2b74a75..db610f8f8 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -7877,7 +7877,7 @@ that ``spawn`` takes is restricted: ``spawn`` executes the passed expression on the thread pool and returns a `data flow variable`:idx: ``FlowVar[T]`` that can be read from. The reading -with the ``^`` operator is **blocking**. However, one can use ``awaitAny`` to +with the ``^`` operator is **blocking**. However, one can use ``blockUntilAny`` to wait on multiple flow variables at the same time: .. code-block:: nim @@ -7888,10 +7888,10 @@ wait on multiple flow variables at the same time: var responses = newSeq[FlowVarBase](3) for i in 0..2: responses[i] = spawn tellServer(Update, "key", "value") - var index = awaitAny(responses) + var index = blockUntilAny(responses) assert index >= 0 responses.del(index) - discard awaitAny(responses) + discard blockUntilAny(responses) Data flow variables ensure that no data races are possible. Due to technical limitations not every type ``T`` is possible in diff --git a/doc/spawn.txt b/doc/spawn.txt index 522c94464..ab667ff48 100644 --- a/doc/spawn.txt +++ b/doc/spawn.txt @@ -25,7 +25,7 @@ Spawn statement A standalone ``spawn`` statement is a simple construct. It executes the passed expression on the thread pool and returns a `data flow variable`:idx: ``FlowVar[T]`` that can be read from. The reading with the ``^`` operator is -**blocking**. However, one can use ``awaitAny`` to wait on multiple flow +**blocking**. However, one can use ``blockUntilAny`` to wait on multiple flow variables at the same time: .. code-block:: nim @@ -36,10 +36,10 @@ variables at the same time: var responses = newSeq[FlowVarBase](3) for i in 0..2: responses[i] = spawn tellServer(Update, "key", "value") - var index = awaitAny(responses) + var index = blockUntilAny(responses) assert index >= 0 responses.del(index) - discard awaitAny(responses) + discard blockUntilAny(responses) Data flow variables ensure that no data races are possible. Due to technical limitations not every type ``T`` is possible in diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 826e42b6c..f3b13fac5 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -30,7 +30,7 @@ proc destroySemaphore(cv: var Semaphore) {.inline.} = deinitCond(cv.c) deinitLock(cv.L) -proc await(cv: var Semaphore) = +proc blockUntil(cv: var Semaphore) = acquire(cv.L) while cv.counter <= 0: wait(cv.c, cv.L) @@ -81,7 +81,7 @@ proc closeBarrier(b: ptr Barrier) {.compilerProc.} = fence() b.interest = true fence() - while b.left != b.entered: await(b.cv) + while b.left != b.entered: blockUntil(b.cv) destroySemaphore(b.cv) {.pop.} @@ -97,7 +97,7 @@ type FlowVarBaseObj = object of RootObj ready, usesSemaphore, awaited: bool cv: Semaphore #\ - # for 'awaitAny' support + # for 'blockUntilAny' support ai: ptr AwaitInfo idx: int data: pointer # we incRef and unref it to keep it alive; note this MUST NOT @@ -128,12 +128,12 @@ type q: ToFreeQueue readyForTask: Semaphore -proc await*(fv: FlowVarBase) = +proc blockUntil*(fv: FlowVarBase) = ## waits until the value for the flowVar arrives. Usually it is not necessary ## to call this explicitly. if fv.usesSemaphore and not fv.awaited: fv.awaited = true - await(fv.cv) + blockUntil(fv.cv) destroySemaphore(fv.cv) proc selectWorker(w: ptr Worker; fn: WorkerProc; data: pointer): bool = @@ -141,7 +141,7 @@ proc selectWorker(w: ptr Worker; fn: WorkerProc; data: pointer): bool = w.data = data w.f = fn signal(w.taskArrived) - await(w.taskStarted) + blockUntil(w.taskStarted) result = true proc cleanFlowVars(w: ptr Worker) = @@ -176,11 +176,11 @@ proc attach(fv: FlowVarBase; i: int): bool = release(fv.cv.L) proc finished(fv: FlowVarBase) = - doAssert fv.ai.isNil, "flowVar is still attached to an 'awaitAny'" + doAssert fv.ai.isNil, "flowVar is still attached to an 'blockUntilAny'" # we have to protect against the rare cases where the owner of the flowVar # simply disregards the flowVar and yet the "flowVar" has not yet written # anything to it: - await(fv) + blockUntil(fv) if fv.data.isNil: return let owner = cast[ptr Worker](fv.owner) let q = addr(owner.q) @@ -189,7 +189,7 @@ proc finished(fv: FlowVarBase) = #echo "EXHAUSTED!" release(q.lock) wakeupWorkerToProcessQueue(owner) - await(q.empty) + blockUntil(q.empty) acquire(q.lock) q.data[q.len] = cast[pointer](fv.data) inc q.len @@ -220,7 +220,7 @@ proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) = ## to ``action``. Note that due to Nim's parameter passing semantics this ## means that ``T`` doesn't need to be copied and so ``awaitAndThen`` can ## sometimes be more efficient than ``^``. - await(fv) + blockUntil(fv) when T is string or T is seq: action(cast[T](fv.data)) elif T is ref: @@ -231,29 +231,29 @@ proc awaitAndThen*[T](fv: FlowVar[T]; action: proc (x: T) {.closure.}) = proc unsafeRead*[T](fv: FlowVar[ref T]): ptr T = ## blocks until the value is available and then returns this value. - await(fv) + blockUntil(fv) result = cast[ptr T](fv.data) proc `^`*[T](fv: FlowVar[ref T]): ref T = ## blocks until the value is available and then returns this value. - await(fv) + blockUntil(fv) let src = cast[ref T](fv.data) deepCopy result, src proc `^`*[T](fv: FlowVar[T]): T = ## blocks until the value is available and then returns this value. - await(fv) + blockUntil(fv) when T is string or T is seq: # XXX closures? deepCopy? result = cast[T](fv.data) else: result = fv.blob -proc awaitAny*(flowVars: openArray[FlowVarBase]): int = +proc blockUntilAny*(flowVars: openArray[FlowVarBase]): int = ## awaits any of the given flowVars. Returns the index of one flowVar for - ## which a value arrived. A flowVar only supports one call to 'awaitAny' at - ## the same time. That means if you awaitAny([a,b]) and awaitAny([b,c]) the second - ## call will only await 'c'. If there is no flowVar left to be able to wait + ## which a value arrived. A flowVar only supports one call to 'blockUntilAny' at + ## the same time. That means if you blockUntilAny([a,b]) and blockUntilAny([b,c]) the second + ## call will only blockUntil 'c'. If there is no flowVar left to be able to wait ## on, -1 is returned. ## **Note**: This results in non-deterministic behaviour and should be avoided. var ai: AwaitInfo @@ -269,7 +269,7 @@ proc awaitAny*(flowVars: openArray[FlowVarBase]): int = inc conflicts if conflicts < flowVars.len: if result < 0: - await(ai.cv) + blockUntil(ai.cv) result = ai.idx for i in 0 .. flowVars.high: discard cas(addr flowVars[i].ai, addr ai, nil) @@ -326,7 +326,7 @@ proc slave(w: ptr Worker) {.thread.} = w.ready = true readyWorker = w signal(gSomeReady) - await(w.taskArrived) + blockUntil(w.taskArrived) # XXX Somebody needs to look into this (why does this assertion fail # in Visual Studio?) when not defined(vcc) and not defined(tcc): assert(not w.ready) @@ -351,7 +351,7 @@ proc distinguishedSlave(w: ptr Worker) {.thread.} = else: w.ready = true signal(w.readyForTask) - await(w.taskArrived) + blockUntil(w.taskArrived) assert(not w.ready) w.f(w, w.data) if w.q.len != 0: w.cleanFlowVars @@ -499,7 +499,7 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} = # on the current thread instead. var self = addr(workersData[localThreadId-1]) fn(self, data) - await(self.taskStarted) + blockUntil(self.taskStarted) return if isSlave: @@ -524,7 +524,7 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} = inc numSlavesWaiting - await(gSomeReady) + blockUntil(gSomeReady) if isSlave: withLock numSlavesLock: @@ -542,7 +542,7 @@ proc nimSpawn4(fn: WorkerProc; data: pointer; id: ThreadId) {.compilerProc.} = release(distinguishedLock) while true: if selectWorker(addr(distinguishedData[id]), fn, data): break - await(distinguishedData[id].readyForTask) + blockUntil(distinguishedData[id].readyForTask) proc sync*() = @@ -555,7 +555,7 @@ proc sync*() = if not allReady: break allReady = allReady and workersData[i].ready if allReady: break - await(gSomeReady) + blockUntil(gSomeReady) inc toRelease for i in 0 ..< toRelease: diff --git a/tests/parallel/twaitany.nim b/tests/parallel/twaitany.nim index 69136a3b6..fcabf691e 100644 --- a/tests/parallel/twaitany.nim +++ b/tests/parallel/twaitany.nim @@ -18,12 +18,12 @@ var results: seq[int] = @[] for i in 0 .. durations.high: tasks.add spawn timer(durations[i]) -var index = awaitAny(tasks) +var index = blockUntilAny(tasks) while index != -1: results.add ^cast[FlowVar[int]](tasks[index]) tasks.del(index) #echo repr results - index = awaitAny(tasks) + index = blockUntilAny(tasks) doAssert results.len == 5 doAssert 1000 in results -- cgit 1.4.1-2-gfad0 From da41fc18018058e01ac11132f7ff29651e3fdaa7 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 15 Aug 2018 17:45:57 +0200 Subject: put the new for loop macros under an experimental switch named 'forLoopMacros' --- compiler/options.nim | 6 ++++-- compiler/semstmts.nim | 5 +++-- doc/manual.rst | 5 +++++ tests/macros/tforloop_macro1.nim | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/compiler/options.nim b/compiler/options.nim index 6de32bfad..bc5545488 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -111,14 +111,16 @@ type ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod, ideHighlight, ideOutline, ideKnown, ideMsg - Feature* = enum ## experimental features + Feature* = enum ## experimental features; DO NOT RENAME THESE! implicitDeref, dotOperators, callOperator, parallel, destructor, notnil, - dynamicBindSym + dynamicBindSym, + forLoopMacros + #caseStmtMacros SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index b1e39d2db..7eb915dad 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -720,8 +720,9 @@ proc handleForLoopMacro(c: PContext; n: PNode): PNode = proc semFor(c: PContext, n: PNode): PNode = checkMinSonsLen(n, 3, c.config) var length = sonsLen(n) - result = handleForLoopMacro(c, n) - if result != nil: return result + if forLoopMacros in c.features: + result = handleForLoopMacro(c, n) + if result != nil: return result openScope(c) result = n n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) diff --git a/doc/manual.rst b/doc/manual.rst index db610f8f8..935db34ac 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -5380,6 +5380,7 @@ type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop: :test: "nim c $1" import macros + {.experimental: "forLoopMacros".} macro enumerate(x: ForLoopStmt): untyped = expectKind x, nnkForStmt @@ -5406,6 +5407,10 @@ type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop: echo a2, " ", b2 +Currently for loop macros must be enabled explicitly +via ``{.experimental: "forLoopMacros".}``. + + Special Types ============= diff --git a/tests/macros/tforloop_macro1.nim b/tests/macros/tforloop_macro1.nim index a8f45c7ac..49918563d 100644 --- a/tests/macros/tforloop_macro1.nim +++ b/tests/macros/tforloop_macro1.nim @@ -12,7 +12,7 @@ discard """ """ import macros - +{.experimental: "forLoopMacros".} macro mymacro(): untyped = result = newLit([1, 2, 3]) -- cgit 1.4.1-2-gfad0 From 1061e26bc997cd3b74c6b08862ad7145039f2550 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Thu, 16 Aug 2018 00:16:49 +0200 Subject: implements 'case statement macros' in order to encourage the development of pattern matching mechanisms that are not terrible to look at --- changelog.md | 14 ++-- compiler/options.nim | 4 +- compiler/semstmts.nim | 181 ++++++++++++++++++++++++++++++-------------------- doc/manual.rst | 52 +++++++++++++++ 4 files changed, 172 insertions(+), 79 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index e2203e602..5437f16ac 100644 --- a/changelog.md +++ b/changelog.md @@ -95,7 +95,7 @@ - Added the procs ``rationals.`div```, ``rationals.`mod```, ``rationals.floorDiv`` and ``rationals.floorMod`` for rationals. - Added the proc ``math.prod`` for product of elements in openArray. - Added the proc ``parseBinInt`` to parse a binary integer from a string, which returns the value. -- ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt`` +- ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt``. - Added the proc ``flush`` for memory mapped files. - Added the ``MemMapFileStream``. - Added ``macros.copyLineInfo`` to copy lineInfo from other node. @@ -138,7 +138,13 @@ - ``func`` is now an alias for ``proc {.noSideEffect.}``. - In order to make ``for`` loops and iterators more flexible to use Nim now supports so called "for-loop macros". See - the `manual `_ for more details. + the [manual](manual.html#macros-for-loop-macros) for more details. + This feature enables a Python-like generic ``enumerate`` implementation. + +- Case statements can now be rewritten via macros. See the [manual]() for more information. + This feature enables custom pattern matchers. + + - the `typedesc` special type has been renamed to just `type`. - `static` and `type` are now also modifiers similar to `ref` and `ptr`. They denote the special types `static[T]` and `type[T]`. @@ -171,7 +177,7 @@ - Thread-local variables can now be declared inside procs. This implies all the effects of the ``global`` pragma. -- Nim now supports ``except`` clause in the export statement. +- Nim now supports the ``except`` clause in the export statement. - Range float types, example ``range[0.0 .. Inf]``. More details in language manual. - The ``{.this.}`` pragma has been deprecated. It never worked within generics and @@ -219,6 +225,6 @@ - macros.bindSym now capable to accepts not only literal string or string constant expression. bindSym enhancement make it also can accepts computed string or ident node inside macros / compile time functions / static blocks. Only in templates / regular code it retains it's old behavior. - This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch + This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch. ### Bugfixes diff --git a/compiler/options.nim b/compiler/options.nim index bc5545488..1873d9d5b 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -119,8 +119,8 @@ type destructor, notnil, dynamicBindSym, - forLoopMacros - #caseStmtMacros + forLoopMacros, + caseStmtMacros SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 7eb915dad..170ac799e 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -178,71 +178,6 @@ proc semIf(c: PContext, n: PNode): PNode = result.kind = nkIfExpr result.typ = typ -proc semCase(c: PContext, n: PNode): PNode = - result = n - checkMinSonsLen(n, 2, c.config) - openScope(c) - n.sons[0] = semExprWithType(c, n.sons[0]) - var chckCovered = false - var covered: BiggestInt = 0 - var typ = commonTypeBegin - var hasElse = false - let caseTyp = skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}) - case caseTyp.kind - of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool: - chckCovered = true - of tyFloat..tyFloat128, tyString, tyError: - discard - else: - localError(c.config, n.info, errSelectorMustBeOfCertainTypes) - return - for i in countup(1, sonsLen(n) - 1): - var x = n.sons[i] - when defined(nimsuggest): - if c.config.ideCmd == ideSug and exactEquals(c.config.m.trackPos, x.info) and caseTyp.kind == tyEnum: - suggestEnum(c, x, caseTyp) - case x.kind - of nkOfBranch: - checkMinSonsLen(x, 2, c.config) - semCaseBranch(c, n, x, i, covered) - var last = sonsLen(x)-1 - x.sons[last] = semExprBranchScope(c, x.sons[last]) - typ = commonType(typ, x.sons[last]) - of nkElifBranch: - chckCovered = false - checkSonsLen(x, 2, c.config) - openScope(c) - x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0])) - x.sons[1] = semExprBranch(c, x.sons[1]) - typ = commonType(typ, x.sons[1]) - closeScope(c) - of nkElse: - chckCovered = false - checkSonsLen(x, 1, c.config) - x.sons[0] = semExprBranchScope(c, x.sons[0]) - typ = commonType(typ, x.sons[0]) - hasElse = true - else: - illFormedAst(x, c.config) - if chckCovered: - if covered == toCover(c, n.sons[0].typ): - hasElse = true - else: - localError(c.config, n.info, "not all cases are covered") - closeScope(c) - if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: - for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon) - # propagate any enforced VoidContext: - if typ == c.enforceVoidContext: - result.typ = c.enforceVoidContext - else: - for i in 1..n.len-1: - var it = n.sons[i] - let j = it.len-1 - if not endsInNoReturn(it.sons[j]): - it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info) - result.typ = typ - proc semTry(c: PContext, n: PNode): PNode = var check = initIntSet() @@ -683,29 +618,28 @@ proc isTrivalStmtExpr(n: PNode): bool = return false result = true -proc handleForLoopMacro(c: PContext; n: PNode): PNode = - let iterExpr = n[^2] - if iterExpr.kind in nkCallKinds: +proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string): PNode = + if selector.kind in nkCallKinds: # we transform # n := for a, b, c in m(x, y, z): Y # to # m(n) - let forLoopStmt = magicsys.getCompilerProc(c.graph, "ForLoopStmt") - if forLoopStmt == nil: return + let maType = magicsys.getCompilerProc(c.graph, magicType) + if maType == nil: return - let headSymbol = iterExpr[0] + let headSymbol = selector[0] var o: TOverloadIter var match: PSym = nil var symx = initOverloadIter(o, c, headSymbol) while symx != nil: if symx.kind in {skTemplate, skMacro}: - if symx.typ.len == 2 and symx.typ[1] == forLoopStmt.typ: + if symx.typ.len == 2 and symx.typ[1] == maType.typ: if match == nil: match = symx else: localError(c.config, n.info, errAmbiguousCallXYZ % [ getProcHeader(c.config, match), - getProcHeader(c.config, symx), $iterExpr]) + getProcHeader(c.config, symx), $selector]) symx = nextOverloadIter(o, c, headSymbol) if match == nil: return @@ -717,6 +651,38 @@ proc handleForLoopMacro(c: PContext; n: PNode): PNode = of skTemplate: result = semTemplateExpr(c, callExpr, match, {}) else: result = nil +proc handleForLoopMacro(c: PContext; n: PNode): PNode = + result = handleStmtMacro(c, n, n[^2], "ForLoopStmt") + +proc handleCaseStmtMacro(c: PContext; n: PNode): PNode = + # n[0] has been sem'checked and has a type. We use this to resolve + # 'match(n[0])' but then we pass 'n' to the 'match' macro. This seems to + # be the best solution. + var toResolve = newNodeI(nkCall, n.info) + toResolve.add newIdentNode(getIdent(c.cache, "match"), n.info) + toResolve.add n[0] + + var errors: CandidateErrors + var r = resolveOverloads(c, toResolve, toResolve, {skTemplate, skMacro}, {}, + errors, false) + if r.state == csMatch: + var match = r.calleeSym + markUsed(c.config, n[0].info, match, c.graph.usageSym) + styleCheckUse(n[0].info, match) + + # but pass 'n' to the 'match' macro, not 'n[0]': + r.call.sons[1] = n + let toExpand = semResolvedCall(c, r, r.call, {}) + case match.kind + of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, {}) + of skTemplate: result = semTemplateExpr(c, toExpand, match, {}) + else: result = nil + # this would be the perfectly consistent solution with 'for loop macros', + # but it kinda sucks for pattern matching as the matcher is not attached to + # a type then: + when false: + result = handleStmtMacro(c, n, n[0], "CaseStmt") + proc semFor(c: PContext, n: PNode): PNode = checkMinSonsLen(n, 3, c.config) var length = sonsLen(n) @@ -758,6 +724,75 @@ proc semFor(c: PContext, n: PNode): PNode = result.typ = c.enforceVoidContext closeScope(c) +proc semCase(c: PContext, n: PNode): PNode = + result = n + checkMinSonsLen(n, 2, c.config) + openScope(c) + n.sons[0] = semExprWithType(c, n.sons[0]) + var chckCovered = false + var covered: BiggestInt = 0 + var typ = commonTypeBegin + var hasElse = false + let caseTyp = skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc}) + case caseTyp.kind + of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool: + chckCovered = true + of tyFloat..tyFloat128, tyString, tyError: + discard + else: + if caseStmtMacros in c.features: + result = handleCaseStmtMacro(c, n) + if result != nil: return result + + localError(c.config, n.info, errSelectorMustBeOfCertainTypes) + return + for i in countup(1, sonsLen(n) - 1): + var x = n.sons[i] + when defined(nimsuggest): + if c.config.ideCmd == ideSug and exactEquals(c.config.m.trackPos, x.info) and caseTyp.kind == tyEnum: + suggestEnum(c, x, caseTyp) + case x.kind + of nkOfBranch: + checkMinSonsLen(x, 2, c.config) + semCaseBranch(c, n, x, i, covered) + var last = sonsLen(x)-1 + x.sons[last] = semExprBranchScope(c, x.sons[last]) + typ = commonType(typ, x.sons[last]) + of nkElifBranch: + chckCovered = false + checkSonsLen(x, 2, c.config) + openScope(c) + x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0])) + x.sons[1] = semExprBranch(c, x.sons[1]) + typ = commonType(typ, x.sons[1]) + closeScope(c) + of nkElse: + chckCovered = false + checkSonsLen(x, 1, c.config) + x.sons[0] = semExprBranchScope(c, x.sons[0]) + typ = commonType(typ, x.sons[0]) + hasElse = true + else: + illFormedAst(x, c.config) + if chckCovered: + if covered == toCover(c, n.sons[0].typ): + hasElse = true + else: + localError(c.config, n.info, "not all cases are covered") + closeScope(c) + if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: + for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon) + # propagate any enforced VoidContext: + if typ == c.enforceVoidContext: + result.typ = c.enforceVoidContext + else: + for i in 1..n.len-1: + var it = n.sons[i] + let j = it.len-1 + if not endsInNoReturn(it.sons[j]): + it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info) + result.typ = typ + proc semRaise(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1, c.config) diff --git a/doc/manual.rst b/doc/manual.rst index 935db34ac..bb2650799 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -5411,6 +5411,58 @@ Currently for loop macros must be enabled explicitly via ``{.experimental: "forLoopMacros".}``. +Case statement macros +--------------------- + +A macro that needs to be called `match`:idx: can be used to +rewrite ``case`` statements in order to +implement `pattern matching`:idx: for certain types. The following +example implements a simplistic form of pattern matching for tuples, +leveraging the existing equality operator for tuples (as provided in + ``system.==``): + +.. code-block:: nim + :test: "nim c $1" + + {.experimental: "caseStmtMacros".} + + import macros + + macro match(n: tuple): untyped = + result = newTree(nnkIfStmt) + let selector = n[0] + for i in 1 ..< n.len: + let it = n[i] + case it.kind + of nnkElse, nnkElifBranch, nnkElifExpr, nnkElseExpr: + result.add it + of nnkOfBranch: + for j in 0..it.len-2: + let cond = newCall("==", selector, it[j]) + result.add newTree(nnkElifBranch, cond, it[^1]) + else: + error "'match' cannot handle this node", it + echo repr result + + case ("foo", 78) + of ("foo", 78): echo "yes" + of ("bar", 88): echo "no" + else: discard + + +Currently case statement macros must be enabled explicitly +via ``{.experimental: "caseStmtMacros".}``. + +``match`` macros are subject to overload resolution. First the +``case``'s selector expression is used to determine which ``match`` +macro to call. To this macro is then the complete ``case`` statement +body is passed and the macro is evaluated. + +In other words, the macro needs to transform the full ``case`` statement +but only the statement's selector expression is used to determine which +``macro`` to call. + + Special Types ============= -- cgit 1.4.1-2-gfad0 From 3ca8ebe778cb82cdbd97d7a9a00015bbeed1a696 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Thu, 16 Aug 2018 18:43:25 +0200 Subject: fixes #8653 --- changelog.md | 3 +++ compiler/nimconf.nim | 4 ++-- doc/nimc.rst | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/changelog.md b/changelog.md index 441b09042..73d526136 100644 --- a/changelog.md +++ b/changelog.md @@ -227,4 +227,7 @@ compile time functions / static blocks. Only in templates / regular code it retains it's old behavior. This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch. +- On Posix systems the global system wide configuration is now put under ``/etc/nim/nim.cfg``, + it used to be ``/etc/nim.cfg``. Usually it does not exist, however. + ### Bugfixes diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index d3b4645dc..cb7e52cf7 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -228,8 +228,8 @@ proc getSystemConfigPath(conf: ConfigRef; filename: string): string = let p = getPrefixDir(conf) result = joinPath([p, "config", filename]) when defined(unix): - if not existsFile(result): result = joinPath([p, "etc", filename]) - if not existsFile(result): result = "/etc/" & filename + if not existsFile(result): result = joinPath([p, "etc/nim", filename]) + if not existsFile(result): result = "/etc/nim/" & filename proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) = setDefaultLibpath(conf) diff --git a/doc/nimc.rst b/doc/nimc.rst index 31df4b6f7..0682fac03 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -154,7 +154,7 @@ passed as a command line argument to the compiler. The ``nim`` executable processes configuration files in the following directories (in this order; later files overwrite previous settings): -1) ``$nim/config/nim.cfg``, ``/etc/nim.cfg`` (UNIX) or ``%NIMROD%/config/nim.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option. +1) ``$nim/config/nim.cfg``, ``/etc/nim/nim.cfg`` (UNIX) or ``%NIM%/config/nim.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option. 2) ``$HOME/.config/nim.cfg`` (POSIX) or ``%APPDATA%/nim.cfg`` (Windows). This file can be skipped with the ``--skipUserCfg`` command line option. 3) ``$parentDir/nim.cfg`` where ``$parentDir`` stands for any parent directory of the project file's path. These files can be skipped with the ``--skipParentCfg`` command line option. 4) ``$projectDir/nim.cfg`` where ``$projectDir`` stands for the project file's path. This file can be skipped with the ``--skipProjCfg`` command line option. -- cgit 1.4.1-2-gfad0