From a20b4c674e9ee27d0ebb1da0163d7d3664808897 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 9 Feb 2017 20:11:54 +0100 Subject: [PATCH 01/35] sysio: minor improvements --- lib/system/sysio.nim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 9f4944eb0f..115b67c18f 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -67,7 +67,7 @@ proc checkErr(f: File) = {.push stackTrace:off, profiler:off.} proc readBuffer(f: File, buffer: pointer, len: Natural): int = result = c_fread(buffer, 1, len, f) - checkErr(f) + if result != len: checkErr(f) proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int = result = readBuffer(f, addr(a[start]), len) @@ -118,8 +118,9 @@ const proc close*(f: File) = discard c_fclose(f) proc readChar(f: File): char = let x = c_fgetc(f) - if x == -1: raiseEOF() - checkErr(f) + if x < 0: + checkErr(f) + raiseEOF() result = char(x) proc flushFile*(f: File) = discard c_fflush(f) @@ -140,7 +141,7 @@ proc readLine(f: File, line: var TaintedString): bool = # fgets doesn't append an \L c_memset(addr line.string[pos], '\L'.ord, sp) var fgetsSuccess = c_fgets(addr line.string[pos], sp, f) != nil - checkErr(f) + if not fgetsSuccess: checkErr(f) let m = c_memchr(addr line.string[pos], '\L'.ord, sp) if m != nil: # \l found: Could be our own or the one by fgets, in any case, we're done From 03b05bd346c1ecc18d1b7aa9e8731056efd6645a Mon Sep 17 00:00:00 2001 From: Emily Mabrey Date: Thu, 9 Feb 2017 17:18:19 -0500 Subject: [PATCH 02/35] Cleanup and reorganize readme.md Fix typos and grammatical errors while rearranging and cleaning up the readme. Change all links to use the reference style Markdown link for increased maintainability. Make all badges use a consistent flat style that matches the art style of the logo. Replace HTML snippet for logo with valid Markdown link by utilizing the freely available Google API for image resizing. --- readme.md | 229 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 128 insertions(+), 101 deletions(-) diff --git a/readme.md b/readme.md index 6eb85b0a38..f5dc1d6aba 100644 --- a/readme.md +++ b/readme.md @@ -1,146 +1,173 @@ -# Nim [![Build Status](https://travis-ci.org/nim-lang/Nim.svg?branch=devel)](https://travis-ci.org/nim-lang/Nim) +# ![Logo][image-nim-logo] Nim [![Build Status][badge-nim-travisci]][nim-travisci] -This repo contains the Nim compiler, Nim's stdlib, tools and -documentation. For more information about Nim, including downloads -and documentation for the latest release, check out -[Nim's website](http://nim-lang.org). +This repository contains the Nim compiler, Nim's stdlib, tools and documentation. +For more information about Nim, including downloads and documentation for +the latest release, check out [Nim's website][nim-site]. ## Compiling -Compiling the Nim compiler is quite straightforward. Because -the Nim compiler itself is written in the Nim programming language -the C source of an older version of the compiler are needed to bootstrap the -latest version. The C sources are available in a separate -repo [here](http://github.com/nim-lang/csources). - -The compiler currently supports the following platform and architecture -combinations: +The compiler currently officially supports the following platform and +architecture combinations: * Windows (Windows XP or greater) - x86 and x86_64 * Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l - * Mac OS X 10.04 or higher - x86, x86_64 and ppc64 + * Mac OS X (10.04 or greater) - x86, x86_64 and ppc64 -In reality a lot more are supported, however they are not tested regularly. +More platforms are supported, however they are not tested regularly and they +may not be as stable as the above-listed platforms. -To build from source you will need: +Compiling the Nim compiler is quite straightforward. First, the C source of +an older version of the Nim compiler is needed to bootstrap the latest +version because the Nim compiler itself is written in the Nim programming +language. Those C sources are available within the +[``nim-lang/csources``][csources-repo] repository. - * gcc 3.x or later recommended. Other alternatives which may work - are: clang, Visual C++, Intel's C++ compiler - * git or wget +Next, to build from source you will need: -**Note:** When installing ``gcc`` on Ubuntu (and likely other distros) ensure -that the ``build-essentials`` package is installed also. + * A C compiler such as ``gcc`` 3.x/later or an alternative such as ``clang``, + ``Visual C++`` or ``Intel C++``. It is recommended to use ``gcc`` 3.x or + later. + * Either ``git`` or ``wget`` to download the needed source repositories. + * The ``build-essentials`` package when using ``gcc`` on Ubuntu (and likely + other distros as well). -If you are on a fairly modern *nix system, the following steps should work: +Then, if you are on a \*nix system or Windows, the following steps should compile +Nim from source using ``gcc``, ``git`` and the ``koch`` build tool (in the place +of ``sh build.sh`` you should substitute ``build.bat`` on x86 Windows or +``build64.bat`` on x86_64 Windows): ``` $ git clone https://github.com/nim-lang/Nim.git $ cd Nim -$ git clone --depth 1 https://github.com/nim-lang/csources -$ cd csources && sh build.sh -$ cd .. +$ git clone --depth 1 https://github.com/nim-lang/csources.git +$ cd csources +$ sh build.sh +$ cd ../ $ bin/nim c koch $ ./koch boot -d:release ``` -You should then add the ``bin`` directory to your PATH, to make it easily -executable on your system. +Finally, once you have finished the build steps (on Windows, Mac or Linux) you +should add the ``bin`` directory to your PATH. -The above steps can be performed on Windows in a similar fashion, the -``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used -instead of ``build.sh``. +## Koch +``koch`` is the build tool used to build various parts of Nim and to generate +documentation and the website, among other things. The ``koch`` tool can also +be used to run the Nim test suite. -The ``koch`` tool is the Nim build tool, more ``koch`` related options are -documented in [doc/koch.rst](doc/koch.rst). +Assuming that you added Nim's ``bin`` directory to your PATH, you may execute +the tests using ``./koch tests``. The test suite takes a while to run, but you +can run a subset of tests by specifying a category (for example +``./koch tests cat async``). +For more information on the ``koch`` build tool please see the documentation +within the [doc/koch.rst](doc/koch.rst) file. ## Nimble -[Nimble](https://github.com/nim-lang/nimble) is Nim's package manager. For the -source based installations, where you added Nim's ``bin`` directory to your PATH, -the easiest way of installing Nimble is via: - -``` -$ koch nimble -``` +[Nimble][nimble-repo] is Nim's package manager. Assuming that you added Nim's +``bin`` directory to your PATH, you may install Nimble by running ``koch nimble`` +within the root of the cloned repository. ## Community -[![Join the Chat at irc.freenode.net#nim](https://img.shields.io/badge/IRC-join_chat_in_%23nim-blue.svg)](https://webchat.freenode.net/?channels=nim) -[![Join the Gitter channel](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nim-lang/Nim) -[![Get help](https://img.shields.io/badge/Forum-get%20help-4eb899.svg)](http://forum.nim-lang.org) -[![Stackoverflow](https://img.shields.io/badge/stackoverflow-use_%23nim_tag-yellow.svg)](http://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15) -[![Follow @nim_lang!](https://img.shields.io/twitter/follow/nim_lang.svg?style=social)](https://twitter.com/nim_lang) +[![Join the IRC chat][badge-nim-irc]][nim-irc] +[![Join the Gitter chat][badge-nim-gitter]][nim-gitter] +[![Get help][badge-nim-forum-gethelp]][nim-forum] +[![View Nim posts on Stack Overflow][badge-nim-stackoverflow]][nim-stackoverflow-newest] +[![Follow @nim_lang on Twitter][badge-nim-twitter]][nim-twitter] -* The [forum](http://forum.nim-lang.org/) - the best place to ask questions and to discuss Nim. -* [IRC (Freenode#nim)](https://webchat.freenode.net/?channels=nim) - a place to discuss - Nim in real-time, this is also where most development decision get made! -* [Gitter](https://gitter.im/nim-lang/Nim) allows to discuss Nim from your browser, one click to join. - There is a bridge between Gitter and IRC channels. -* [Stackoverflow](http://stackoverflow.com/questions/tagged/nim) +* The [forum][nim-forum] - the best place to ask questions and to discuss Nim. +* [#nim IRC Channel (Freenode)][nim-irc] - a place to discuss Nim in real-time. + Also where most development decisions get made. +* [Gitter][nim-gitter] - an additional place to discuss Nim in real-time. There + is a bridge between Gitter and the IRC channel. +* [Stack Overflow][nim-stackoverflow] - a popular Q/A site for programming related + topics that includes posts about Nim. ## Contributing +[![Contribute to Nim via Gratipay][badge-nim-gratipay]][nim-gratipay] +[![Setup a bounty via Bountysource][badge-nim-bountysource]][nim-bountysource] +[![Donate Bitcoins][badge-nim-bitcoin]][nim-bitcoin] -[![Contribute to Nim via Gratipay!](https://img.shields.io/gratipay/team/nim.svg)](https://gratipay.com/nim/) -[![Bountysource](https://img.shields.io/bountysource/team/nim/activity.svg)](https://www.bountysource.com/teams/nim) - -We welcome everyone's contributions to Nim. No matter how small or large -the contribution is, anything from small spelling fixes to large modules -intended to be included in the standard library are accepted. Before -you get started, you should know the following about this repositories -structure: +We welcome everyone's contributions to Nim independent of how small or how large +they are. Anything from small spelling fixes to large modules intended to +be included in the standard library are welcome and appreciated. Before you get +started contributing, you should familiarize yourself with the repository structure: * ``bin/``, ``build/`` - these directories are empty, but are used when Nim is built. -* ``compiler/`` - the compiler source code, all the Nim source code files in this - directory implement the compiler. This also includes nimfix, and plugins - which live in ``compiler/nimfix`` and ``compiler/plugins`` - respectively. Nimsuggest used to live in the ``compiler`` directory also, - but was moved to https://github.com/nim-lang/nimsuggest. +* ``compiler/`` - the compiler source code. Also includes nimfix, and plugins within + ``compiler/nimfix`` and ``compiler/plugins`` respectively. Nimsuggest was moved to + the [``nim-lang/nimsuggest``][nimsuggest-repo] repository, though it previously also + lived within the ``compiler/`` directory. * ``config/`` - the configuration for the compiler and documentation generator. * ``doc/`` - the documentation files in reStructuredText format. -* ``lib/`` - where the standard library lives. +* ``lib/`` - the standard library, including: * ``pure/`` - modules in the standard library written in pure Nim. - * ``impure/`` - modules in the standard library written in pure Nim which - depend on libraries written in other languages. - * ``wrappers/`` - modules which wrap libraries written in other languages. -* ``tests/`` - contains tests for the compiler and standard library, organised by - category. -* ``tools/`` - the tools including ``niminst`` and ``nimweb``, most of these are invoked - via ``koch``. -* ``web/`` - the Nim website (http://nim-lang.org). -* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website, documentation - and more. + * ``impure/`` - modules in the standard library written in pure Nim with + dependencies written in other languages. + * ``wrappers/`` - modules which wrap dependencies written in other languages. +* ``tests/`` - contains categorized tests for the compiler and standard library. +* ``tools/`` - the tools including ``niminst`` and ``nimweb`` (mostly invoked via + ``koch``). +* ``web/`` - [the Nim website][nim-site]. +* ``koch.nim`` - tool used to bootstrap Nim, generate C sources, build the website, + and generate the documentation. -Most importantly, the ``koch`` tool can be used to run the test suite. To do so compile it first -by executing ``nim c koch``, then execute ``./koch tests``. The test suite takes a while to run, -but you can run specific tests by specifying a category to run, for example ``./koch tests cat async``. +If you are not familiar with making a pull request using GitHub and/or git, please +read [this guide][pull-request-instructions]. -Make sure that the tests all pass before -[submitting your pull request](https://help.github.com/articles/using-pull-requests/). -If you're short on time, you can -just run the tests specific to your change. Just run the category which corresponds to the change -you've made. When you create your pull request, Travis CI will verify that all the tests pass -anyway. +Ideally you should make sure that all tests pass before submitting a pull request. +However, if you are short on time, you can just run the tests specific to your +changes by only running the corresponding categories of tests. Travis CI verifies +that all tests pass before allowing the pull request to be accepted, so only +running specific tests should be harmless. -If you're looking for things to do, take a look at our -[issue tracker](https://github.com/nim-lang/Nim/issues). There is always plenty of issues -labelled [``Easy``](https://github.com/nim-lang/Nim/labels/Easy), these should be a good -starting point if this is your first contribution to Nim. +If you're looking for ways to contribute, please look at our [issue tracker][nim-issues]. +There are always plenty of issues labelled [``Easy``][nim-issues-easy]; these should +be a good starting point for an initial contribution to Nim. -You can also help with the development of Nim by making donations. You can do so -in many ways: +You can also help with the development of Nim by making donations. Donations can be +made using: -* [Gratipay](https://gratipay.com/nim/) -* [Bountysource](https://www.bountysource.com/teams/nim) -* Bitcoin - 1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ +* [Gratipay][nim-gratipay] +* [Bountysource][nim-bountysource] +* [Bitcoin][nim-bitcoin] -Finally, if you have any questions feel free to submit a question on the issue tracker, -on the [Nim forum](http://forum.nim-lang.org), or on IRC. +If you have any questions feel free to submit a question on the +[Nim forum][nim-forum], or via IRC on [the \#nim channel][nim-irc]. ## License -The compiler and the standard library are licensed under the MIT license, -except for some modules where the documentation suggests otherwise. This means -that you can use any license for your own programs developed with Nim, -allowing you to create commercial applications. +The compiler and the standard library are licensed under the MIT license, except +for some modules which explicitly state otherwise. As a result you may use any +compatible license (essentially any license) for your own programs developed with +Nim. You are explicitly permitted to develop commercial applications using Nim. -Read copying.txt for more details. +Please read the copying.txt file for more details. -Copyright (c) 2006-2017 Andreas Rumpf. -All rights reserved. +Copyright © 2006-2017 Andreas Rumpf, all rights reserved. + +[nim-site]: https://nim-lang.org +[nim-forum]: https://forum.nim-lang.org +[nim-issues]: https://github.com/nim-lang/Nim/issues +[nim-issues-easy]: https://github.com/nim-lang/Nim/labels/Easy +[nim-irc]: https://webchat.freenode.net/?channels=nim +[nim-travisci]: https://travis-ci.org/nim-lang/Nim +[nim-twitter]: https://twitter.com/nim_lang +[nim-stackoverflow]: https://stackoverflow.com/questions/tagged/nim +[nim-stackoverflow-newest]: https://stackoverflow.com/questions/tagged/nim?sort=newest&pageSize=15 +[nim-gitter]: https://gitter.im/nim-lang/Nim +[nim-gratipay]: https://gratipay.com/nim/ +[nim-bountysource]: https://www.bountysource.com/teams/nim +[nim-bitcoin]: https://blockchain.info/address/1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ +[nimble-repo]: https://github.com/nim-lang/nimble +[nimsuggest-repo]: https://github.com/nim-lang/nimsuggest +[csources-repo]: https://github.com/nim-lang/csources +[badge-nim-travisci]: https://img.shields.io/travis/nim-lang/Nim/devel.svg?style=flat-square +[badge-nim-irc]: https://img.shields.io/badge/chat-on_irc-blue.svg?style=flat-square +[badge-nim-gitter]: https://img.shields.io/badge/chat-on_gitter-blue.svg?style=flat-square +[badge-nim-forum-gethelp]: https://img.shields.io/badge/Forum-get%20help-4eb899.svg?style=flat-square +[badge-nim-twitter]: https://img.shields.io/twitter/follow/nim_lang.svg?style=social +[badge-nim-stackoverflow]: https://img.shields.io/badge/stackoverflow-nim_tag-yellow.svg?style=flat-square +[badge-nim-gratipay]: https://img.shields.io/gratipay/team/nim.svg?style=flat-square +[badge-nim-bountysource]: https://img.shields.io/bountysource/team/nim/activity.svg?style=flat-square +[badge-nim-bitcoin]: https://img.shields.io/badge/bitcoin-1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ-D69134.svg?style=flat-square +[image-nim-logo]: https://images1-focus-opensocial.googleusercontent.com/gadgets/proxy?url=https://raw.githubusercontent.com/nim-lang/assets/master/Art/logo-crown.png&container=focus&resize_w=36&refresh=21600 +[pull-request-instructions]: https://help.github.com/articles/using-pull-requests/ From 1a7fdb09d923b43c6b4d8d11407730a349d5af76 Mon Sep 17 00:00:00 2001 From: Emily Mabrey Date: Thu, 9 Feb 2017 17:33:19 -0500 Subject: [PATCH 03/35] Make additional minor changes to readme.md Move the community section closer to the top of the readme. Make the reference to the copying.txt file in the license section actually link to that file. Adjust the nimble section to be more clear about how and where to acquire the nimble source. --- readme.md | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/readme.md b/readme.md index f5dc1d6aba..865724b716 100644 --- a/readme.md +++ b/readme.md @@ -4,6 +4,21 @@ This repository contains the Nim compiler, Nim's stdlib, tools and documentation For more information about Nim, including downloads and documentation for the latest release, check out [Nim's website][nim-site]. +## Community +[![Join the IRC chat][badge-nim-irc]][nim-irc] +[![Join the Gitter chat][badge-nim-gitter]][nim-gitter] +[![Get help][badge-nim-forum-gethelp]][nim-forum] +[![View Nim posts on Stack Overflow][badge-nim-stackoverflow]][nim-stackoverflow-newest] +[![Follow @nim_lang on Twitter][badge-nim-twitter]][nim-twitter] + +* The [forum][nim-forum] - the best place to ask questions and to discuss Nim. +* [#nim IRC Channel (Freenode)][nim-irc] - a place to discuss Nim in real-time. + Also where most development decisions get made. +* [Gitter][nim-gitter] - an additional place to discuss Nim in real-time. There + is a bridge between Gitter and the IRC channel. +* [Stack Overflow][nim-stackoverflow] - a popular Q/A site for programming related + topics that includes posts about Nim. + ## Compiling The compiler currently officially supports the following platform and architecture combinations: @@ -15,10 +30,11 @@ architecture combinations: More platforms are supported, however they are not tested regularly and they may not be as stable as the above-listed platforms. -Compiling the Nim compiler is quite straightforward. First, the C source of -an older version of the Nim compiler is needed to bootstrap the latest -version because the Nim compiler itself is written in the Nim programming -language. Those C sources are available within the +Compiling the Nim compiler is quite straightforward if you follow these steps: + +First, the C source of an older version of the Nim compiler is needed to +bootstrap the latest version because the Nim compiler itself is written in the +Nim programming language. Those C sources are available within the [``nim-lang/csources``][csources-repo] repository. Next, to build from source you will need: @@ -55,7 +71,7 @@ documentation and the website, among other things. The ``koch`` tool can also be used to run the Nim test suite. Assuming that you added Nim's ``bin`` directory to your PATH, you may execute -the tests using ``./koch tests``. The test suite takes a while to run, but you +the tests using ``./koch tests``. The tests take a while to run, but you can run a subset of tests by specifying a category (for example ``./koch tests cat async``). @@ -63,24 +79,10 @@ For more information on the ``koch`` build tool please see the documentation within the [doc/koch.rst](doc/koch.rst) file. ## Nimble -[Nimble][nimble-repo] is Nim's package manager. Assuming that you added Nim's -``bin`` directory to your PATH, you may install Nimble by running ``koch nimble`` -within the root of the cloned repository. - -## Community -[![Join the IRC chat][badge-nim-irc]][nim-irc] -[![Join the Gitter chat][badge-nim-gitter]][nim-gitter] -[![Get help][badge-nim-forum-gethelp]][nim-forum] -[![View Nim posts on Stack Overflow][badge-nim-stackoverflow]][nim-stackoverflow-newest] -[![Follow @nim_lang on Twitter][badge-nim-twitter]][nim-twitter] - -* The [forum][nim-forum] - the best place to ask questions and to discuss Nim. -* [#nim IRC Channel (Freenode)][nim-irc] - a place to discuss Nim in real-time. - Also where most development decisions get made. -* [Gitter][nim-gitter] - an additional place to discuss Nim in real-time. There - is a bridge between Gitter and the IRC channel. -* [Stack Overflow][nim-stackoverflow] - a popular Q/A site for programming related - topics that includes posts about Nim. +``nimble`` is Nim's package manager and it can be acquired from the +[``nim-lang/nimble``][nimble-repo] repository. Assuming that you added Nim's +``bin`` directory to your PATH, you may install Nimble from source by running +``koch nimble`` within the root of the cloned repository. ## Contributing [![Contribute to Nim via Gratipay][badge-nim-gratipay]][nim-gratipay] @@ -140,7 +142,7 @@ for some modules which explicitly state otherwise. As a result you may use any compatible license (essentially any license) for your own programs developed with Nim. You are explicitly permitted to develop commercial applications using Nim. -Please read the copying.txt file for more details. +Please read the [copying.txt](copying.txt) file for more details. Copyright © 2006-2017 Andreas Rumpf, all rights reserved. From 69fb2c61520fe11941814996f4758814acf02c80 Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Fri, 10 Feb 2017 11:15:43 +0200 Subject: [PATCH 04/35] Fixed heapqueue.del for last elem (#5363) --- lib/pure/collections/heapqueue.nim | 47 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/lib/pure/collections/heapqueue.nim b/lib/pure/collections/heapqueue.nim index abe20e5568..f86ba1d3f6 100644 --- a/lib/pure/collections/heapqueue.nim +++ b/lib/pure/collections/heapqueue.nim @@ -77,8 +77,10 @@ proc pop*[T](heap: var HeapQueue[T]): T = proc del*[T](heap: var HeapQueue[T], index: int) = ## Removes element at `index`, maintaining the heap invariant. swap(seq[T](heap)[^1], seq[T](heap)[index]) - seq[T](heap).setLen(heap.len - 1) - heap.siftup(index) + let newLen = heap.len - 1 + seq[T](heap).setLen(newLen) + if index < newLen: + heap.siftup(index) proc replace*[T](heap: var HeapQueue[T], item: T): T = ## Pop and return the current smallest value, and add the new item. @@ -101,16 +103,19 @@ proc pushpop*[T](heap: var HeapQueue[T], item: T): T = return item when isMainModule: + proc toSortedSeq[T](h: HeapQueue[T]): seq[T] = + var tmp = h + result = @[] + while tmp.len > 0: + result.add(pop(tmp)) + block: # Simple sanity test var heap = newHeapQueue[int]() let data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] for item in data: push(heap, item) doAssert(heap[0] == 0) - var sort = newSeq[int]() - while heap.len > 0: - sort.add(pop(heap)) - doAssert(sort == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + doAssert(heap.toSortedSeq == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) block: # Test del var heap = newHeapQueue[int]() @@ -121,11 +126,27 @@ when isMainModule: doAssert(heap[0] == 1) heap.del(seq[int](heap).find(7)) - heap.del(seq[int](heap).find(5)) - heap.del(seq[int](heap).find(6)) - heap.del(seq[int](heap).find(2)) + doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 5, 6, 8, 9]) - var sort = newSeq[int]() - while heap.len > 0: - sort.add(pop(heap)) - doAssert(sort == @[1, 3, 4, 8, 9]) + heap.del(seq[int](heap).find(5)) + doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 6, 8, 9]) + + heap.del(seq[int](heap).find(6)) + doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 8, 9]) + + heap.del(seq[int](heap).find(2)) + doAssert(heap.toSortedSeq == @[1, 3, 4, 8, 9]) + + block: # Test del last + var heap = newHeapQueue[int]() + let data = [1, 2, 3] + for item in data: push(heap, item) + + heap.del(2) + doAssert(heap.toSortedSeq == @[1, 2]) + + heap.del(1) + doAssert(heap.toSortedSeq == @[1]) + + heap.del(0) + doAssert(heap.toSortedSeq == @[]) From eb0d510195b5061ed840dc52cbe00cd21085f18a Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Fri, 10 Feb 2017 17:25:22 +0200 Subject: [PATCH 05/35] Removed $ from echo calls (#5368) --- doc/tut1.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/tut1.rst b/doc/tut1.rst index 47cafc7fac..e79214dee0 100644 --- a/doc/tut1.rst +++ b/doc/tut1.rst @@ -361,7 +361,7 @@ iterator: .. code-block:: nim echo "Counting to ten: " for i in countup(1, 10): - echo $i + echo i # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines The built-in `$ `_ operator turns an integer (``int``) and many @@ -374,7 +374,7 @@ Each value is ``echo``-ed. This code does the same: echo "Counting to 10: " var i = 1 while i <= 10: - echo $i + echo i inc(i) # increment i by 1 # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines @@ -383,7 +383,7 @@ Counting down can be achieved as easily (but is less often needed): .. code-block:: nim echo "Counting down from 10 to 1: " for i in countdown(10, 1): - echo $i + echo i # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines Since counting up occurs so often in programs, Nim also has a `.. @@ -827,7 +827,7 @@ Let's return to the boring counting example: .. code-block:: nim echo "Counting to ten: " for i in countup(1, 10): - echo $i + echo i Can a `countup `_ proc be written that supports this loop? Lets try: @@ -1035,15 +1035,15 @@ there is a difference between the ``$`` and ``repr`` outputs: myString = "nim" myInteger = 42 myFloat = 3.14 - echo $myBool, ":", repr(myBool) + echo myBool, ":", repr(myBool) # --> true:true - echo $myCharacter, ":", repr(myCharacter) + echo myCharacter, ":", repr(myCharacter) # --> n:'n' - echo $myString, ":", repr(myString) + echo myString, ":", repr(myString) # --> nim:0x10fa8c050"nim" - echo $myInteger, ":", repr(myInteger) + echo myInteger, ":", repr(myInteger) # --> 42:42 - echo $myFloat, ":", repr(myFloat) + echo myFloat, ":", repr(myFloat) # --> 3.1400000000000001e+00:3.1400000000000001e+00 @@ -1075,7 +1075,7 @@ at runtime by 0, the second by 1 and so on. Example: north, east, south, west var x = south # `x` is of type `Direction`; its value is `south` - echo $x # writes "south" to `stdout` + echo x # writes "south" to `stdout` All comparison operators can be used with enumeration types. @@ -1289,7 +1289,7 @@ value. Here the ``for`` statement is looping over the results from the .. code-block:: nim for i in @[3, 4, 5]: - echo $i + echo i # --> 3 # --> 4 # --> 5 From 9b8150aef1f6a8d48dffc6ac4c5cba9a3f8e24d3 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Feb 2017 00:23:22 +0100 Subject: [PATCH 06/35] sysio: check for IO errors for write operations --- lib/system/sysio.nim | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 115b67c18f..fa1bdbb4e2 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -171,21 +171,23 @@ proc readLine(f: File): TaintedString = proc write(f: File, i: int) = when sizeof(int) == 8: - c_fprintf(f, "%lld", i) + if c_fprintf(f, "%lld", i) < 0: checkErr(f) else: - c_fprintf(f, "%ld", i) + if c_fprintf(f, "%ld", i) < 0: checkErr(f) proc write(f: File, i: BiggestInt) = when sizeof(BiggestInt) == 8: - c_fprintf(f, "%lld", i) + if c_fprintf(f, "%lld", i) < 0: checkErr(f) else: - c_fprintf(f, "%ld", i) + if c_fprintf(f, "%ld", i) < 0: checkErr(f) proc write(f: File, b: bool) = if b: write(f, "true") else: write(f, "false") -proc write(f: File, r: float32) = c_fprintf(f, "%g", r) -proc write(f: File, r: BiggestFloat) = c_fprintf(f, "%g", r) +proc write(f: File, r: float32) = + if c_fprintf(f, "%g", r) < 0: checkErr(f) +proc write(f: File, r: BiggestFloat) = + if c_fprintf(f, "%g", r) < 0: checkErr(f) proc write(f: File, c: char) = discard c_putc(ord(c), f) proc write(f: File, a: varargs[string, `$`]) = From c8ae7164e502b585843c584af65f78f67002830e Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Feb 2017 00:24:22 +0100 Subject: [PATCH 07/35] finish.nim: user has multiple chances to move .7z file to proper location --- tools/finish.nim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/finish.nim b/tools/finish.nim index a9fb444a07..e39062b027 100644 --- a/tools/finish.nim +++ b/tools/finish.nim @@ -209,6 +209,9 @@ proc main() = of Manual: echo "After download, move it to: ", dest if askBool("Download successful? (y/n) "): + while not fileExists("dist" / mingw): + echo "could not find: ", "dist" / mingw + if not askBool("Try again? (y/n) "): break if unzip(): retry = true of Failure: discard of Success: From 36d3fd64da21fe128f92ea49943c9dd834aa6848 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 11 Feb 2017 00:42:12 +0100 Subject: [PATCH 08/35] fixes #5354 --- compiler/semexprs.nim | 10 +++++----- tests/metatype/tfieldaccessor.nim | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 tests/metatype/tfieldaccessor.nim diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 57674735a0..9972585c7b 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1093,11 +1093,11 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = return readTypeParameter(c, ty, i, n.info) of tyObject, tyTuple: if ty.n != nil and ty.n.kind == nkRecList: - for field in ty.n: - if field.sym.name == i: - n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ]) - n.typ.n = copyTree(n) - return n + let field = lookupInRecord(ty.n, i) + if field != nil: + n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ]) + n.typ.n = copyTree(n) + return n else: # echo "TYPE FIELD ACCESS" # debug ty diff --git a/tests/metatype/tfieldaccessor.nim b/tests/metatype/tfieldaccessor.nim new file mode 100644 index 0000000000..7054dd22b9 --- /dev/null +++ b/tests/metatype/tfieldaccessor.nim @@ -0,0 +1,17 @@ +type + Test = object + x: int + case p: bool + of true: + a: int + else: + case q: bool + of true: + b: int + else: + discard + +proc f[T](t: typedesc[T]): int = + 1 + +assert Test.f == 1 From 0d1aa9225a6190f4d54b699ef3a191cbbb3209a4 Mon Sep 17 00:00:00 2001 From: Federico Ceratto Date: Sun, 12 Feb 2017 15:02:50 +0000 Subject: [PATCH 09/35] Make walkDirRec docstring more clear (#5377) --- lib/pure/os.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 4cd3870c7d..92e2958204 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1002,8 +1002,8 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. tags: [ReadDirEffect].} = - ## walks over the directory `dir` and yields for each file in `dir`. The - ## full path for each file is returned. + ## Recursively walks over the directory `dir` and yields for each file in `dir`. + ## The full path for each file is returned. Directories are not returned. ## **Warning**: ## Modifying the directory structure while the iterator ## is traversing may result in undefined behavior! From 636b97745754c69f1709bd9dd295c0de56b87105 Mon Sep 17 00:00:00 2001 From: ionel anton Date: Mon, 13 Feb 2017 03:09:43 -0500 Subject: [PATCH 10/35] Column details for postgres. (#5380) --- lib/impure/db_postgres.nim | 184 +++++++++++++++++++++++--- tests/untestable/tpostgres.nim | 229 +++++++++++++++++++++++++++++++++ 2 files changed, 397 insertions(+), 16 deletions(-) diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index 60bd1f0814..fc587b5df6 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -69,16 +69,14 @@ import db_common export db_common type - DbConn* = PPGconn ## encapsulates a database connection - Row* = seq[string] ## a row of a dataset. NULL database values will be - ## converted to nil. - InstantRow* = tuple[res: PPGresult, line: int32] ## a handle that can be - ## used to get a row's - ## column text on demand + DbConn* = PPGconn ## encapsulates a database connection + Row* = seq[string] ## a row of a dataset. NULL database values will be + ## converted to nil. + InstantRow* = object ## a handle that can be + res: PPGresult ## used to get a row's + line: int ## column text on demand SqlPrepared* = distinct string ## a identifier for the prepared queries - -{.deprecated: [TRow: Row, TDbConn: DbConn, - TSqlPrepared: SqlPrepared].} +{.deprecated: [TRow: Row, TDbConn: DbConn, TSqlPrepared: SqlPrepared].} proc dbError*(db: DbConn) {.noreturn.} = ## raises a DbError exception. @@ -213,7 +211,7 @@ iterator instantRows*(db: DbConn, query: SqlQuery, ## on demand using []. Returned handle is valid only within iterator body. var res = setupQuery(db, query, args) for i in 0..pqNtuples(res)-1: - yield (res: res, line: i) + yield InstantRow(res: res, line: i) pqClear(res) iterator instantRows*(db: DbConn, stmtName: SqlPrepared, @@ -223,16 +221,170 @@ iterator instantRows*(db: DbConn, stmtName: SqlPrepared, ## on demand using []. Returned handle is valid only within iterator body. var res = setupQuery(db, stmtName, args) for i in 0..pqNtuples(res)-1: - yield (res: res, line: i) + yield InstantRow(res: res, line: i) pqClear(res) -proc `[]`*(row: InstantRow, col: int32): string {.inline.} = - ## returns text for given column of the row - $pqgetvalue(row.res, row.line, col) +proc getColumnType(res: PPGresult, col: int) : DbType = + ## returns DbType for given column in the row + ## defined in pg_type.h file in the postgres source code + ## Wire representation for types: http://www.npgsql.org/dev/types.html + var oid = pqftype(res, int32(col)) + ## The integer returned is the internal OID number of the type + case oid + of 16: return DbType(kind: DbTypeKind.dbBool, name: "bool") + of 17: return DbType(kind: DbTypeKind.dbBlob, name: "bytea") -proc len*(row: InstantRow): int32 {.inline.} = + of 21: return DbType(kind: DbTypeKind.dbInt, name: "int2", size: 2) + of 23: return DbType(kind: DbTypeKind.dbInt, name: "int4", size: 4) + of 20: return DbType(kind: DbTypeKind.dbInt, name: "int8", size: 8) + of 1560: return DbType(kind: DbTypeKind.dbBit, name: "bit") + of 1562: return DbType(kind: DbTypeKind.dbInt, name: "varbit") + + of 18: return DbType(kind: DbTypeKind.dbFixedChar, name: "char") + of 19: return DbType(kind: DbTypeKind.dbFixedChar, name: "name") + of 1042: return DbType(kind: DbTypeKind.dbFixedChar, name: "bpchar") + + of 25: return DbType(kind: DbTypeKind.dbVarchar, name: "text") + of 1043: return DbType(kind: DbTypeKind.dbVarChar, name: "varchar") + of 2275: return DbType(kind: DbTypeKind.dbVarchar, name: "cstring") + + of 700: return DbType(kind: DbTypeKind.dbFloat, name: "float4") + of 701: return DbType(kind: DbTypeKind.dbFloat, name: "float8") + + of 790: return DbType(kind: DbTypeKind.dbDecimal, name: "money") + of 1700: return DbType(kind: DbTypeKind.dbDecimal, name: "numeric") + + of 704: return DbType(kind: DbTypeKind.dbTimeInterval, name: "tinterval") + of 702: return DbType(kind: DbTypeKind.dbTimestamp, name: "abstime") + of 703: return DbType(kind: DbTypeKind.dbTimeInterval, name: "reltime") + of 1082: return DbType(kind: DbTypeKind.dbDate, name: "date") + of 1083: return DbType(kind: DbTypeKind.dbTime, name: "time") + of 1114: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamp") + of 1184: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamptz") + of 1186: return DbType(kind: DbTypeKind.dbTimeInterval, name: "interval") + of 1266: return DbType(kind: DbTypeKind.dbTime, name: "timetz") + + of 114: return DbType(kind: DbTypeKind.dbJson, name: "json") + of 142: return DbType(kind: DbTypeKind.dbXml, name: "xml") + of 3802: return DbType(kind: DbTypeKind.dbJson, name: "jsonb") + + of 600: return DbType(kind: DbTypeKind.dbPoint, name: "point") + of 601: return DbType(kind: DbTypeKind.dbLseg, name: "lseg") + of 602: return DbType(kind: DbTypeKind.dbPath, name: "path") + of 603: return DbType(kind: DbTypeKind.dbBox, name: "box") + of 604: return DbType(kind: DbTypeKind.dbPolygon, name: "polygon") + of 628: return DbType(kind: DbTypeKind.dbLine, name: "line") + of 718: return DbType(kind: DbTypeKind.dbCircle, name: "circle") + + of 650: return DbType(kind: DbTypeKind.dbInet, name: "cidr") + of 829: return DbType(kind: DbTypeKind.dbMacAddress, name: "macaddr") + of 869: return DbType(kind: DbTypeKind.dbInet, name: "inet") + + of 2950: return DbType(kind: DbTypeKind.dbVarchar, name: "uuid") + of 3614: return DbType(kind: DbTypeKind.dbVarchar, name: "tsvector") + of 3615: return DbType(kind: DbTypeKind.dbVarchar, name: "tsquery") + of 2970: return DbType(kind: DbTypeKind.dbVarchar, name: "txid_snapshot") + + of 27: return DbType(kind: DbTypeKind.dbComposite, name: "tid") + of 1790: return DbType(kind: DbTypeKind.dbComposite, name: "refcursor") + of 2249: return DbType(kind: DbTypeKind.dbComposite, name: "record") + of 3904: return DbType(kind: DbTypeKind.dbComposite, name: "int4range") + of 3906: return DbType(kind: DbTypeKind.dbComposite, name: "numrange") + of 3908: return DbType(kind: DbTypeKind.dbComposite, name: "tsrange") + of 3910: return DbType(kind: DbTypeKind.dbComposite, name: "tstzrange") + of 3912: return DbType(kind: DbTypeKind.dbComposite, name: "daterange") + of 3926: return DbType(kind: DbTypeKind.dbComposite, name: "int8range") + + of 22: return DbType(kind: DbTypeKind.dbArray, name: "int2vector") + of 30: return DbType(kind: DbTypeKind.dbArray, name: "oidvector") + of 143: return DbType(kind: DbTypeKind.dbArray, name: "xml[]") + of 199: return DbType(kind: DbTypeKind.dbArray, name: "json[]") + of 629: return DbType(kind: DbTypeKind.dbArray, name: "line[]") + of 651: return DbType(kind: DbTypeKind.dbArray, name: "cidr[]") + of 719: return DbType(kind: DbTypeKind.dbArray, name: "circle[]") + of 791: return DbType(kind: DbTypeKind.dbArray, name: "money[]") + of 1000: return DbType(kind: DbTypeKind.dbArray, name: "bool[]") + of 1001: return DbType(kind: DbTypeKind.dbArray, name: "bytea[]") + of 1002: return DbType(kind: DbTypeKind.dbArray, name: "char[]") + of 1003: return DbType(kind: DbTypeKind.dbArray, name: "name[]") + of 1005: return DbType(kind: DbTypeKind.dbArray, name: "int2[]") + of 1006: return DbType(kind: DbTypeKind.dbArray, name: "int2vector[]") + of 1007: return DbType(kind: DbTypeKind.dbArray, name: "int4[]") + of 1008: return DbType(kind: DbTypeKind.dbArray, name: "regproc[]") + of 1009: return DbType(kind: DbTypeKind.dbArray, name: "text[]") + of 1028: return DbType(kind: DbTypeKind.dbArray, name: "oid[]") + of 1010: return DbType(kind: DbTypeKind.dbArray, name: "tid[]") + of 1011: return DbType(kind: DbTypeKind.dbArray, name: "xid[]") + of 1012: return DbType(kind: DbTypeKind.dbArray, name: "cid[]") + of 1013: return DbType(kind: DbTypeKind.dbArray, name: "oidvector[]") + of 1014: return DbType(kind: DbTypeKind.dbArray, name: "bpchar[]") + of 1015: return DbType(kind: DbTypeKind.dbArray, name: "varchar[]") + of 1016: return DbType(kind: DbTypeKind.dbArray, name: "int8[]") + of 1017: return DbType(kind: DbTypeKind.dbArray, name: "point[]") + of 1018: return DbType(kind: DbTypeKind.dbArray, name: "lseg[]") + of 1019: return DbType(kind: DbTypeKind.dbArray, name: "path[]") + of 1020: return DbType(kind: DbTypeKind.dbArray, name: "box[]") + of 1021: return DbType(kind: DbTypeKind.dbArray, name: "float4[]") + of 1022: return DbType(kind: DbTypeKind.dbArray, name: "float8[]") + of 1023: return DbType(kind: DbTypeKind.dbArray, name: "abstime[]") + of 1024: return DbType(kind: DbTypeKind.dbArray, name: "reltime[]") + of 1025: return DbType(kind: DbTypeKind.dbArray, name: "tinterval[]") + of 1027: return DbType(kind: DbTypeKind.dbArray, name: "polygon[]") + of 1040: return DbType(kind: DbTypeKind.dbArray, name: "macaddr[]") + of 1041: return DbType(kind: DbTypeKind.dbArray, name: "inet[]") + of 1263: return DbType(kind: DbTypeKind.dbArray, name: "cstring[]") + of 1115: return DbType(kind: DbTypeKind.dbArray, name: "timestamp[]") + of 1182: return DbType(kind: DbTypeKind.dbArray, name: "date[]") + of 1183: return DbType(kind: DbTypeKind.dbArray, name: "time[]") + of 1185: return DbType(kind: DbTypeKind.dbArray, name: "timestamptz[]") + of 1187: return DbType(kind: DbTypeKind.dbArray, name: "interval[]") + of 1231: return DbType(kind: DbTypeKind.dbArray, name: "numeric[]") + of 1270: return DbType(kind: DbTypeKind.dbArray, name: "timetz[]") + of 1561: return DbType(kind: DbTypeKind.dbArray, name: "bit[]") + of 1563: return DbType(kind: DbTypeKind.dbArray, name: "varbit[]") + of 2201: return DbType(kind: DbTypeKind.dbArray, name: "refcursor[]") + of 2951: return DbType(kind: DbTypeKind.dbArray, name: "uuid[]") + of 3643: return DbType(kind: DbTypeKind.dbArray, name: "tsvector[]") + of 3645: return DbType(kind: DbTypeKind.dbArray, name: "tsquery[]") + of 3807: return DbType(kind: DbTypeKind.dbArray, name: "jsonb[]") + of 2949: return DbType(kind: DbTypeKind.dbArray, name: "txid_snapshot[]") + of 3905: return DbType(kind: DbTypeKind.dbArray, name: "int4range[]") + of 3907: return DbType(kind: DbTypeKind.dbArray, name: "numrange[]") + of 3909: return DbType(kind: DbTypeKind.dbArray, name: "tsrange[]") + of 3911: return DbType(kind: DbTypeKind.dbArray, name: "tstzrange[]") + of 3913: return DbType(kind: DbTypeKind.dbArray, name: "daterange[]") + of 3927: return DbType(kind: DbTypeKind.dbArray, name: "int8range[]") + of 2287: return DbType(kind: DbTypeKind.dbArray, name: "record[]") + + of 705: return DbType(kind: DbTypeKind.dbUnknown, name: "unknown") + else: return DbType(kind: DbTypeKind.dbUnknown, name: $oid) ## Query the system table pg_type to determine exactly which type is referenced. + +proc setColumnInfo(columns: var DbColumns; res: PPGresult; L: int32) = + setLen(columns, L) + for i in 0.. 0 + +doAssert dbCols[22].name == "point_col" +doAssert dbCols[22].typ.kind == DbTypeKind.dbPoint +doAssert dbCols[22].typ.name == "point" + +doAssert dbCols[23].name == "line_col" +doAssert dbCols[23].typ.kind == DbTypeKind.dbLine +doAssert dbCols[23].typ.name == "line" + +doAssert dbCols[24].name == "lseg_col" +doAssert dbCols[24].typ.kind == DbTypeKind.dbLseg +doAssert dbCols[24].typ.name == "lseg" + +doAssert dbCols[25].name == "box_col" +doAssert dbCols[25].typ.kind == DbTypeKind.dbBox +doAssert dbCols[25].typ.name == "box" + +doAssert dbCols[26].name == "path_col" +doAssert dbCols[26].typ.kind == DbTypeKind.dbPath +doAssert dbCols[26].typ.name == "path" + +doAssert dbCols[27].name == "polygon_col" +doAssert dbCols[27].typ.kind == DbTypeKind.dbPolygon +doAssert dbCols[27].typ.name == "polygon" + +doAssert dbCols[28].name == "circle_col" +doAssert dbCols[28].typ.kind == DbTypeKind.dbCircle +doAssert dbCols[28].typ.name == "circle" + +doAssert dbCols[29].name == "cidr_col" +doAssert dbCols[29].typ.kind == DbTypeKind.dbInet +doAssert dbCols[29].typ.name == "cidr" + +doAssert dbCols[30].name == "inet_col" +doAssert dbCols[30].typ.kind == DbTypeKind.dbInet +doAssert dbCols[30].typ.name == "inet" + +doAssert dbCols[31].name == "macaddr_col" +doAssert dbCols[31].typ.kind == DbTypeKind.dbMacAddress +doAssert dbCols[31].typ.name == "macaddr" + +doAssert dbCols[32].name == "bit_col" +doAssert dbCols[32].typ.kind == DbTypeKind.dbBit +doAssert dbCols[32].typ.name == "bit" + +doAssert dbCols[33].name == "varbit_col" +doAssert dbCols[33].typ.kind == DbTypeKind.dbBit +doAssert dbCols[33].typ.name == "bit" + +doAssert dbCols[34].name == "tsvector_col" +doAssert dbCols[34].typ.kind == DbTypeKind.dbVarchar +doAssert dbCols[34].typ.name == "tsvector" + +doAssert dbCols[35].name == "tsquery_col" +doAssert dbCols[35].typ.kind == DbTypeKind.dbVarchar +doAssert dbCols[35].typ.name == "tsquery" + +doAssert dbCols[36].name == "uuid_col" +doAssert dbCols[36].typ.kind == DbTypeKind.dbVarchar +doAssert dbCols[36].typ.name == "uuid" + +doAssert dbCols[37].name == "xml_col" +doAssert dbCols[37].typ.kind == DbTypeKind.dbXml +doAssert dbCols[37].typ.name == "xml" + +doAssert dbCols[38].name == "json_col" +doAssert dbCols[38].typ.kind == DbTypeKind.dbJson +doAssert dbCols[38].typ.name == "json" + +doAssert dbCols[39].name == "array_col" +doAssert dbCols[39].typ.kind == DbTypeKind.dbArray +doAssert dbCols[39].typ.name == "int4[]" + +doAssert dbCols[40].name == "custom_composite_col" +doAssert dbCols[40].typ.kind == DbTypeKind.dbUnknown +doAssert parseInt(dbCols[40].typ.name) > 0 + +doAssert dbCols[41].name == "range_col" +doAssert dbCols[41].typ.kind == DbTypeKind.dbComposite +doAssert dbCols[41].typ.name == "int4range" + echo("All tests succeeded!") db.close() + From ac9c2126e60e3890aabf6db20137330b980004df Mon Sep 17 00:00:00 2001 From: flyx Date: Mon, 13 Feb 2017 11:20:07 +0100 Subject: [PATCH 11/35] Added BiggestUInt (#5378) --- lib/pure/parseutils.nim | 24 ++++++++++++------------ lib/pure/strutils.nim | 2 +- lib/system.nim | 11 +++++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index fb7d72182d..8d53a0360a 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -250,18 +250,18 @@ proc parseInt*(s: string, number: var int, start = 0): int {. elif result != 0: number = int(res) -# overflowChecks doesn't work with uint64 -proc rawParseUInt(s: string, b: var uint64, start = 0): int = +# overflowChecks doesn't work with BiggestUInt +proc rawParseUInt(s: string, b: var BiggestUInt, start = 0): int = var - res = 0'u64 - prev = 0'u64 + res = 0.BiggestUInt + prev = 0.BiggestUInt i = start if s[i] == '+': inc(i) # Allow if s[i] in {'0'..'9'}: b = 0 while s[i] in {'0'..'9'}: prev = res - res = res * 10 + (ord(s[i]) - ord('0')).uint64 + res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt if prev > res: return 0 # overflowChecks emulation inc(i) @@ -269,13 +269,13 @@ proc rawParseUInt(s: string, b: var uint64, start = 0): int = b = res result = i - start -proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {. +proc parseBiggestUInt*(s: string, number: var BiggestUInt, start = 0): int {. rtl, extern: "npuParseBiggestUInt", noSideEffect.} = ## parses an unsigned integer starting at `start` and stores the value ## into `number`. ## Result is the number of processed chars or 0 if there is no integer ## or overflow detected. - var res: uint64 + var res: BiggestUInt # use 'res' for exception safety (don't write to 'number' in case of an # overflow exception): result = rawParseUInt(s, res, start) @@ -287,12 +287,12 @@ proc parseUInt*(s: string, number: var uint, start = 0): int {. ## into `number`. ## Result is the number of processed chars or 0 if there is no integer or ## overflow detected. - var res: uint64 + var res: BiggestUInt result = parseBiggestUInt(s, res, start) - if (sizeof(uint) <= 4) and - (res > 0xFFFF_FFFF'u64): - raise newException(OverflowError, "overflow") - elif result != 0: + when sizeof(BiggestUInt) > sizeof(uint) and sizeof(uint) <= 4: + if res > 0xFFFF_FFFF'u64: + raise newException(OverflowError, "overflow") + if result != 0: number = uint(res) proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 235e66f6ad..9c205a54f2 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -939,7 +939,7 @@ proc parseUInt*(s: string): uint {.noSideEffect, procvar, if L != s.len or L == 0: raise newException(ValueError, "invalid unsigned integer: " & s) -proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar, +proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect, procvar, rtl, extern: "nsuParseBiggestUInt".} = ## Parses a decimal unsigned integer value contained in `s`. ## diff --git a/lib/system.nim b/lib/system.nim index 13ca6eaf70..bab5369f11 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1512,6 +1512,17 @@ type ## compiler supports. Currently this is ``float64``, but it is ## platform-dependant in general. +when defined(JS): + type BiggestUInt* = uint32 + ## is an alias for the biggest unsigned integer type the Nim compiler + ## supports. Currently this is ``uint32`` for JS and ``uint64`` for other + ## targets. +else: + type BiggestUInt* = uint64 + ## is an alias for the biggest unsigned integer type the Nim compiler + ## supports. Currently this is ``uint32`` for JS and ``uint64`` for other + ## targets. + {.deprecated: [TAddress: ByteAddress].} when defined(windows): From 279e4b045133bad59e349520547e5220408b232e Mon Sep 17 00:00:00 2001 From: Anatoly Galiulin Date: Mon, 13 Feb 2017 19:35:40 +0700 Subject: [PATCH 12/35] Fixes #5382 --- lib/impure/re.nim | 2 +- tests/stdlib/tbug5382.nim | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/stdlib/tbug5382.nim diff --git a/lib/impure/re.nim b/lib/impure/re.nim index 9d5d2bdd07..e00f91de17 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -290,7 +290,7 @@ proc find*(buf: cstring, pattern: Regex, matches: var openArray[string], for i in 1..int(res)-1: var a = rawMatches[i * 2] var b = rawMatches[i * 2 + 1] - if a >= 0'i32: matches[i-1] = bufSubstr(buf, int(a), int(b)-1) + if a >= 0'i32: matches[i-1] = bufSubstr(buf, int(a), int(b)) else: matches[i-1] = nil return rawMatches[0] diff --git a/tests/stdlib/tbug5382.nim b/tests/stdlib/tbug5382.nim new file mode 100644 index 0000000000..c86656d32b --- /dev/null +++ b/tests/stdlib/tbug5382.nim @@ -0,0 +1,11 @@ +discard """ + output: ''' +02 +''' +""" +import re + +let regexp = re"^\/([0-9]{2})\.html$" +var matches: array[1, string] +discard "/02.html".find(regexp, matches) +echo matches[0] From 6fa1dba515e514ea9a4ac5850b0188fb6cf95fbf Mon Sep 17 00:00:00 2001 From: Anatoly Galiulin Date: Mon, 13 Feb 2017 19:37:20 +0700 Subject: [PATCH 13/35] Add ``tearDownForeignThreadGc`` function (#5369) --- doc/backends.txt | 8 ++++ lib/system/gc_common.nim | 29 +++++++---- lib/system/threads.nim | 16 ++++++- tests/gc/foreign_thr.nim | 88 ++++++++++++++++++++++++++++++++++ tests/testament/categories.nim | 1 + 5 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 tests/gc/foreign_thr.nim diff --git a/doc/backends.txt b/doc/backends.txt index 5846cce9ba..6446103ed8 100644 --- a/doc/backends.txt +++ b/doc/backends.txt @@ -461,3 +461,11 @@ can then attach a GC to this thread via It is **not** safe to disable the garbage collector and enable it after the call from your background thread even if the code you are calling is short lived. + +Before the thread exits, you should tear down the thread's GC to prevent memory +leaks by calling + +.. code-block:: nim + + system.tearDownForeignThreadGc() + diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index 269514ceb2..6ab6bd9208 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -128,13 +128,7 @@ iterator items(stack: ptr GcStack): ptr GcStack = yield s s = s.next -# There will be problems with GC in foreign threads if `threads` option is off or TLS emulation is enabled -const allowForeignThreadGc = compileOption("threads") and not compileOption("tlsEmulation") - -when allowForeignThreadGc: - var - localGcInitialized {.rtlThreadVar.}: bool - +when declared(threadType): proc setupForeignThreadGc*() {.gcsafe.} = ## Call this if you registered a callback that will be run from a thread not ## under your control. This has a cheap thread-local guard, so the GC for @@ -143,16 +137,33 @@ when allowForeignThreadGc: ## ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off`` ## switches are used - if not localGcInitialized: - localGcInitialized = true + if threadType == ThreadType.None: initAllocator() var stackTop {.volatile.}: pointer setStackBottom(addr(stackTop)) initGC() + threadType = ThreadType.ForeignThread + + proc tearDownForeignThreadGc*() {.gcsafe.} = + ## Call this to tear down the GC, previously initialized by ``setupForeignThreadGc``. + ## If GC has not been previously initialized, or has already been torn down, the + ## call does nothing. + ## + ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off`` + ## switches are used + if threadType != ThreadType.ForeignThread: + return + when declared(deallocOsPages): deallocOsPages() + threadType = ThreadType.None + when declared(gch): zeroMem(addr gch, sizeof(gch)) + else: template setupForeignThreadGc*() = {.error: "setupForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".} + template tearDownForeignThreadGc*() = + {.error: "tearDownForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".} + # ----------------- stack management -------------------------------------- # inspired from Smart Eiffel diff --git a/lib/system/threads.nim b/lib/system/threads.nim index e8b34bf2e4..6e58638e92 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -285,7 +285,19 @@ when useStackMaskHack: when not defined(useNimRtl): when not useStackMaskHack: #when not defined(createNimRtl): initStackBottom() - when declared(initGC): initGC() + when declared(initGC): + initGC() + when not emulatedThreadVars: + type ThreadType {.pure.} = enum + None = 0, + NimThread = 1, + ForeignThread = 2 + var + threadType {.rtlThreadVar.}: ThreadType + + threadType = ThreadType.NimThread + + when emulatedThreadVars: if nimThreadVarsSize() > sizeof(ThreadLocalStorage): @@ -442,6 +454,8 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) = # init the GC for refc/markandsweep setStackBottom(addr(p)) initGC() + when declared(threadType): + threadType = ThreadType.NimThread when declared(registerThread): thrd.stackBottom = addr(thrd) registerThread(thrd) diff --git a/tests/gc/foreign_thr.nim b/tests/gc/foreign_thr.nim new file mode 100644 index 0000000000..88ab951133 --- /dev/null +++ b/tests/gc/foreign_thr.nim @@ -0,0 +1,88 @@ +discard """ + output: ''' +Hello from thread +Hello from thread +Hello from thread +Hello from thread +''' + cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file" +""" +# Copied from stdlib +import strutils + +const + StackGuardSize = 4096 + ThreadStackMask = 1024*256*sizeof(int)-1 + ThreadStackSize = ThreadStackMask+1 - StackGuardSize + +type ThreadFunc = proc() {.thread.} + +when defined(posix): + import posix + + proc runInForeignThread(f: ThreadFunc) = + proc wrapper(p: pointer): pointer {.noconv.} = + let thr = cast[ThreadFunc](p) + setupForeignThreadGc() + thr() + tearDownForeignThreadGc() + setupForeignThreadGc() + thr() + tearDownForeignThreadGc() + result = nil + + var attrs {.noinit.}: PthreadAttr + doAssert pthread_attr_init(addr attrs) == 0 + doAssert pthread_attr_setstacksize(addr attrs, ThreadStackSize) == 0 + var tid: Pthread + doAssert pthread_create(addr tid, addr attrs, wrapper, f) == 0 + doAssert pthread_join(tid, nil) == 0 + +elif defined(windows): + import winlean + type + WinThreadProc = proc (x: pointer): int32 {.stdcall.} + + proc createThread(lpThreadAttributes: pointer, dwStackSize: DWORD, + lpStartAddress: WinThreadProc, + lpParameter: pointer, + dwCreationFlags: DWORD, + lpThreadId: var DWORD): Handle {. + stdcall, dynlib: "kernel32", importc: "CreateThread".} + + proc wrapper(p: pointer): int32 {.stdcall.} = + let thr = cast[ThreadFunc](p) + setupForeignThreadGc() + thr() + tearDownForeignThreadGc() + setupForeignThreadGc() + thr() + tearDownForeignThreadGc() + result = 0'i32 + + proc runInForeignThread(f: ThreadFunc) = + var dummyThreadId: DWORD + var h = createThread(nil, ThreadStackSize.int32, wrapper.WinThreadProc, cast[pointer](f), 0, dummyThreadId) + doAssert h != 0.Handle + doAssert waitForSingleObject(h, -1'i32) == 0.DWORD + +else: + {.fatal: "Unknown system".} + +proc runInNativeThread(f: ThreadFunc) = + proc wrapper(f: ThreadFunc) {.thread.} = + # These operations must be NOP + setupForeignThreadGc() + tearDownForeignThreadGc() + f() + f() + var thr: Thread[ThreadFunc] + createThread(thr, wrapper, f) + joinThread(thr) + +proc f {.thread.} = + var msg = "Hello " & "from thread" + echo msg + +runInForeignThread(f) +runInNativeThread(f) diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 2dc8e33183..0685dd73a7 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -147,6 +147,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) = testSpec r, makeTest("tests/gc" / filename, options & " -d:release --gc:boehm", cat, actionRun) + testWithoutBoehm "foreign_thr" test "gcemscripten" test "growobjcrash" test "gcbench" From 92665e6e9a74995bd108da5bf3668e2c09c8d79c Mon Sep 17 00:00:00 2001 From: Ruslan Mustakov Date: Mon, 13 Feb 2017 19:38:30 +0700 Subject: [PATCH 14/35] Add hash proc for cstrings (#5386) --- lib/pure/hashes.nim | 10 ++++++++++ web/news/e031_version_0_16_2.rst | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 11af811493..17d1c64427 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -127,6 +127,15 @@ proc hash*(x: string): Hash = h = h !& ord(x[i]) result = !$h +proc hash*(x: cstring): Hash = + ## efficient hashing of null-terminated strings + var h: Hash = 0 + var i = 0 + while x[i] != 0.char: + h = h !& ord(x[i]) + inc i + result = !$h + proc hash*(sBuf: string, sPos, ePos: int): Hash = ## efficient hashing of a string buffer, from starting ## position `sPos` to ending position `ePos` @@ -239,6 +248,7 @@ proc hash*[A](x: set[A]): Hash = when isMainModule: doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) ) + doAssert( hash("aa bb aaaa1234") == hash(cstring("aa bb aaaa1234")) ) doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") ) doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") ) let xx = @['H','e','l','l','o'] diff --git a/web/news/e031_version_0_16_2.rst b/web/news/e031_version_0_16_2.rst index 5ee40b772e..2d725028e4 100644 --- a/web/news/e031_version_0_16_2.rst +++ b/web/news/e031_version_0_16_2.rst @@ -18,7 +18,11 @@ Changes affecting backwards compatibility - The IO routines now raise ``EOFError`` for the "end of file" condition. ``EOFError`` is a subtype of ``IOError`` and so it's easier to distinguish between "error during read" and "error due to EOF". - +- A hash procedure has been added for ``cstring`` type in ``hashes`` module. + Previously, hash of a ``cstring`` would be calculated as a hash of the + pointer. Now the hash is calculated from the contents of the string, assuming + ``cstring`` is a null-terminated string. Equal ``string``s and ``cstring``s + produce equal hash value. Library Additions ----------------- From a336bf2395cc7915d669c2e3c0e870bf97f5401e Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Mon, 13 Feb 2017 21:14:29 +0100 Subject: [PATCH 15/35] Fixes parseHeader("foo:") != ("foo", @[""]). Refs #5344. --- lib/pure/httpcore.nim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim index d7f720f66f..aa8f1958d1 100644 --- a/lib/pure/httpcore.nim +++ b/lib/pure/httpcore.nim @@ -206,6 +206,8 @@ proc parseHeader*(line: string): tuple[key: string, value: seq[string]] = inc(i) # skip : if i < len(line): i += parseList(line, result.value, i) + elif result.key.len > 0: + result.value = @[""] else: result.value = @[] @@ -318,4 +320,6 @@ when isMainModule: let (key, value) = parseHeader("foobar: ") test = newHttpHeaders() test[key] = value - doAssert test["foobar"] == "" \ No newline at end of file + doAssert test["foobar"] == "" + + doAssert parseHeader("foobar:") == ("foobar", @[""]) \ No newline at end of file From f0aef9f4e2bba8f87d3060d920f6a470450ce41b Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 14 Feb 2017 14:39:17 +0100 Subject: [PATCH 16/35] compile external .c files with the C compiler, not with C++; refs #5357 --- compiler/extccomp.nim | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 0f283b208b..1b068385af 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -566,16 +566,18 @@ proc needsExeExt(): bool {.inline.} = result = (optGenScript in gGlobalOptions and targetOS == osWindows) or (platform.hostOS == osWindows) -proc getCompilerExe(compiler: TSystemCC): string = - result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler - else: CC[compiler].compilerExe +proc getCompilerExe(compiler: TSystemCC; cfile: string): string = + result = if gCmd == cmdCompileToCpp and not cfile.endsWith(".c"): + CC[compiler].cppCompiler + else: + CC[compiler].compilerExe if result.len == 0: rawMessage(errCompilerDoesntSupportTarget, CC[compiler].name) proc getLinkerExe(compiler: TSystemCC): string = result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe elif gMixedMode and gCmd != cmdCompileToCpp: CC[compiler].cppCompiler - else: compiler.getCompilerExe + else: compiler.getCompilerExe("") proc getCompileCFileCmd*(cfile: Cfile): string = var c = cCompiler @@ -596,7 +598,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string = var options = cFileSpecificOptions(cfile.cname) var exe = getConfigVar(c, ".exe") - if exe.len == 0: exe = c.getCompilerExe + if exe.len == 0: exe = c.getCompilerExe(cfile.cname) if needsExeExt(): exe = addFileExt(exe, "exe") if optGenDynLib in gGlobalOptions and @@ -614,7 +616,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string = compilePattern = joinPath(ccompilerpath, exe) else: includeCmd = "" - compilePattern = c.getCompilerExe + compilePattern = c.getCompilerExe(cfile.cname) var cf = if noAbsolutePaths(): extractFilename(cfile.cname) else: cfile.cname From 57874ed9b8f1fba887083013d277b0ac7f3c5f35 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 14 Feb 2017 14:39:53 +0100 Subject: [PATCH 17/35] C++ codegen: emit 'extern C' for importc'ed functions that we declare a prototype for --- compiler/ccgthreadvars.nim | 4 ++-- compiler/cgen.nim | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 3efddbf307..505b69eabb 100644 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -57,8 +57,8 @@ proc generateThreadLocalStorage(m: BModule) = proc generateThreadVarsSize(m: BModule) = if nimtv != nil: - let externc = if gCmd != cmdCompileToCpp and - sfCompileToCpp in m.module.flags: "extern \"C\"" + let externc = if gCmd == cmdCompileToCpp or + sfCompileToCpp in m.module.flags: "extern \"C\" " else: "" addf(m.s[cfsProcs], "$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n", diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 62ed9ad6e6..63a7cda0e1 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -715,10 +715,13 @@ proc genProcAux(m: BModule, prc: PSym) = add(generatedProc, ~"}$N") add(m.s[cfsProcs], generatedProc) -proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} = - result = sfCompileToCpp in m.module.flags and +proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} = + result = (sfCompileToCpp in m.module.flags and sfCompileToCpp notin sym.getModule().flags and - gCmd != cmdCompileToCpp + gCmd != cmdCompileToCpp) or ( + sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and + sym.magic == mNone and + gCmd == cmdCompileToCpp) proc genProcPrototype(m: BModule, sym: PSym) = useHeader(m, sym) @@ -732,7 +735,7 @@ proc genProcPrototype(m: BModule, sym: PSym) = var header = genProcHeader(m, sym) if sfNoReturn in sym.flags and hasDeclspec in extccomp.CC[cCompiler].props: header = "__declspec(noreturn) " & header - if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym): + if sym.typ.callConv != ccInline and requiresExternC(m, sym): header = "extern \"C\" " & header if sfPure in sym.flags and hasAttribute in CC[cCompiler].props: header.add(" __attribute__((naked))") From 4a8257d99259ddf763bbcf3230545dec5380bbec Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 14 Feb 2017 21:07:28 +0100 Subject: [PATCH 18/35] Update bountysource sponsors. --- web/bountysource.nim.cfg | 1 + web/inactive_sponsors.csv | 33 +++++++++++------- web/sponsors.csv | 72 +++++++++++++++++++++------------------ 3 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 web/bountysource.nim.cfg diff --git a/web/bountysource.nim.cfg b/web/bountysource.nim.cfg new file mode 100644 index 0000000000..521e21de41 --- /dev/null +++ b/web/bountysource.nim.cfg @@ -0,0 +1 @@ +-d:ssl diff --git a/web/inactive_sponsors.csv b/web/inactive_sponsors.csv index d466f3f310..6352bc194e 100644 --- a/web/inactive_sponsors.csv +++ b/web/inactive_sponsors.csv @@ -1,26 +1,40 @@ logo, name, url, this_month, all_time, since, level ,bogen,,0,1010,"Jul 23, 2016",1 ,mikra,,0,400,"Apr 28, 2016",1 -,linkmonitor,,0,180,"Jan 28, 2016",1 +,shkolnick-kun,,0,375,"Jul 6, 2016",1 +,"Chris Heller",,0,350,"May 19, 2016",1 +,linkmonitor,,0,280,"Jan 28, 2016",1 ,avsej,,0,110,"Jun 10, 2016",1 ,WilRubin,,0,100,"Aug 11, 2015",1 ,"Benny Luypaert",,0,100,"Apr 10, 2016",1 -,"Chris Heller",,0,100,"May 19, 2016",1 ,PhilipWitte,,0,100,"Aug 5, 2016",1 +,skunkiferous,,0,100,"Oct 2, 2016",1 +,"Jonathan Arnett",,0,90,"May 20, 2016",1 ,Boxifier,,0,75,"Apr 12, 2016",1 ,iolloyd,,0,75,"Apr 29, 2016",1 +,btbytes,,0,70,"Apr 6, 2016",1 ,rb01,,0,50,"May 4, 2016",1 +,barcharcraz,,0,50,"Jun 2, 2016",1 +,zachaysan,,0,50,"Jun 7, 2016",1 +,kunev,,0,50,"Dec 26, 2016",1 +,iboB,,0,50,"Jan 28, 2017",1 ,TedSinger,,0,45,"Apr 9, 2016",1 +,johnnovak,,0,45,"Apr 30, 2016",1 +,"Matthew Baulch",,0,40,"Jun 7, 2016",1 +,"Matthew Newton",,0,35,"Apr 20, 2016",1 ,martinbbjerregaard,,0,35,"Jun 9, 2016",1 ,RationalG,,0,30,"Jun 17, 2016",1 ,benbve,,0,30,"Jul 12, 2016",1 -,barcharcraz,,0,25,"Jun 2, 2016",1 +,multikatt,,0,30,"Nov 2, 2016",1 ,"Landon Bass",,0,25,"Jun 7, 2016",1 ,jimrichards,,0,25,"Jun 8, 2016",1 ,jjzazuet,,0,25,"Jul 10, 2016",1 -,moigagoo,,0,20,"May 13, 2016",1 ,kteza1,,0,20,"Jun 10, 2016",1 ,tomkeus,,0,20,"Sep 4, 2016",1 +,csoriano89,,0,20,"Sep 7, 2016",1 +,juanjux,,0,20,"Oct 29, 2016",1 +,zagfai,,0,20,"Nov 3, 2016",1 +,hellcoderz,,0,20,"Jan 24, 2017",1 ,mirek,,0,15,"Apr 9, 2016",1 ,DateinAsia,,0,15,"Jul 30, 2016",1 ,rickc,,0,15,"Jul 31, 2016",1 @@ -38,13 +52,6 @@ logo, name, url, this_month, all_time, since, level ,Blumenversand,,0,10,"Jul 21, 2016",1 ,cinnabardk,,0,10,"Aug 6, 2016",1 ,reddec,,0,10,"Aug 31, 2016",1 +,cupen,,0,10,"Nov 21, 2016",1 +,yay,,0,10,"Jan 25, 2017",1 ,niv,,0,5,"Apr 6, 2016",1 -,goniz,,0,5,"Apr 7, 2016",1 -,genunix,,0,5,"Apr 12, 2016",1 -,CynepHy6,,0,5,"Apr 14, 2016",1 -,ivanflorentin,,0,5,"May 3, 2016",1 -,stevenyhw,,0,5,"May 20, 2016",1 -,"Sanjay Singh",,0,5,"Jun 6, 2016",1 -,yuttie,,0,5,"Jun 7, 2016",1 -,hron,,0,5,"Jun 11, 2016",1 -,laszlowaty,,0,5,"Jun 17, 2016",1 diff --git a/web/sponsors.csv b/web/sponsors.csv index 0701575d59..7136808c6a 100644 --- a/web/sponsors.csv +++ b/web/sponsors.csv @@ -1,34 +1,40 @@ logo, name, url, this_month, all_time, since, level -assets/bountysource/secondspectrum.png,Second Spectrum,http://www.secondspectrum.com/,250,1250,"May 5, 2016",250 -assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,"Jun 20, 2016",250 -,shkolnick-kun,https://github.com/shkolnick-kun,75,225,"Jul 6, 2016",75 -,flyx,http://flyx.org,35,210,"Apr 7, 2016",75 -,"Yuriy Glukhov",,25,150,"Apr 6, 2016",25 -,endragor,https://github.com/endragor,25,150,"Apr 7, 2016",25 -,FedericoCeratto,http://firelet.net,25,150,"Apr 7, 2016",25 -,"Adrian Veith",,25,150,"Apr 20, 2016",25 -,skunkiferous,https://github.com/skunkiferous,100,100,"Oct 2, 2016",150 -,euantorano,http://euantorano.co.uk,25,100,"Jun 7, 2016",25 -,xxlabaza,https://github.com/xxlabaza,25,95,"Jun 17, 2016",25 -,btbytes,https://www.btbytes.com/,10,60,"Apr 6, 2016",10 -,niebaopeng,https://github.com/niebaopeng,10,50,"Apr 15, 2016",10 -,"Jonathan Arnett",,10,50,"May 20, 2016",10 -,swalf,https://github.com/swalf,5,45,"May 9, 2016",5 -,zolern,https://github.com/zolern,10,40,"Apr 15, 2016",10 -,"pyloor ",https://schwarz-weiss.cc/,10,40,"May 16, 2016",10 -,zachaysan,http://venn.lc,10,40,"Jun 7, 2016",10 -,"Matthew Baulch",,10,40,"Jun 7, 2016",10 -,"Oskari Timperi",,10,40,"Jun 8, 2016",10 -,"Handojo Goenadi",,5,35,"Apr 19, 2016",5 -,"Matthew Newton",,5,30,"Apr 20, 2016",5 -,johnnovak,http://www.johnnovak.net/,5,30,"Apr 29, 2016",5 -,RyanMarcus,http://rmarcus.info,5,15,"Jul 19, 2016",5 -,lenzenmi,https://github.com/lenzenmi,5,15,"Jul 28, 2016",5 -,cpunion,https://github.com/cpunion,10,10,"Sep 9, 2016",10 -,pandada8,https://github.com/pandada8,5,10,"Aug 12, 2016",5 -,abeaumont,http://alfredobeaumont.org/blog,5,10,"Aug 12, 2016",5 -,"Svend Knudsen",,1,6,"Apr 11, 2016",1 -,"Michael D. Sklaroff",,1,6,"Apr 27, 2016",1 -,csoriano89,https://github.com/csoriano89,5,5,"Sep 7, 2016",5 -,nicck,,1,2,"Aug 9, 2016",1 -,campbellr,,1,1,"Sep 4, 2016",1 +assets/bountysource/secondspectrum.png,Second Spectrum,http://www.secondspectrum.com/,250,2250,"May 5, 2016",250 +assets/bountysource/xored.svg,"Xored Software, Inc.",http://xored.com/,250,1000,250,2000,"Jun 20, 2016",250 +,Varriount,https://github.com/Varriount,250,750,"Nov 18, 2016",250 +,flyx,http://flyx.org,35,350,"Apr 7, 2016",75 +,"Yuriy Glukhov",,25,250,"Apr 6, 2016",25 +,endragor,https://github.com/endragor,25,250,"Apr 7, 2016",25 +,FedericoCeratto,http://firelet.net,25,250,"Apr 7, 2016",25 +,"Adrian Veith",,25,250,"Apr 20, 2016",25 +,euantorano,http://euantorano.co.uk,25,200,"Jun 7, 2016",25 +,xxlabaza,https://github.com/xxlabaza,25,170,"Jun 17, 2016",25 +,devted,https://github.com/devted,25,100,"Oct 19, 2016",25 +,"pyloor ",https://schwarz-weiss.cc/,10,95,"May 16, 2016",10 +,niebaopeng,https://github.com/niebaopeng,10,90,"Apr 15, 2016",10 +,zolern,https://github.com/zolern,10,80,"Apr 15, 2016",10 +,"Oskari Timperi",,10,80,"Jun 8, 2016",10 +,jcosborn,https://github.com/jcosborn,25,75,"Nov 21, 2016",25 +,swalf,https://github.com/swalf,5,65,"May 9, 2016",5 +,"Handojo Goenadi",,5,55,"Apr 19, 2016",5 +,cpunion,https://github.com/cpunion,10,50,"Sep 9, 2016",10 +,D-L,https://github.com/D-L,5,50,"Apr 7, 2016",5 +,moigagoo,http://sloth-ci.com,10,40,"May 13, 2016",10 +,enthus1ast,http://code0.xyz/,10,40,"Oct 28, 2016",10 +,RyanMarcus,http://rmarcus.info,5,35,"Jul 19, 2016",5 +,lenzenmi,https://github.com/lenzenmi,5,35,"Jul 28, 2016",5 +,"Christian Bagley",,10,30,"Oct 11, 2016",10 +,pandada8,https://github.com/pandada8,5,30,"Aug 12, 2016",5 +,abeaumont,http://alfredobeaumont.org/blog,5,30,"Aug 12, 2016",5 +,opendragon,http://www.opendragon.com,25,25,"Jan 18, 2017",25 +,"Eric Raible",,10,20,"Dec 23, 2016",10 +,zefciu,http://pythonista.net,10,20,"Dec 29, 2016",10 +,"Andrey ",https://github.com/Andrey,5,20,"Oct 10, 2016",5 +,syrol,https://github.com/syrol,5,10,"Dec 12, 2016",5 +,"Svend Knudsen",,1,10,"Apr 11, 2016",1 +,"Michael D. Sklaroff",,1,10,"Apr 27, 2016",1 +,nicck,,1,6,"Aug 9, 2016",1 +,cnygaard,,5,5,"Jan 17, 2017",5 +,Aldrog,,5,5,"Feb 11, 2017",5 +,mpachecofaulk55,,5,5,"Feb 11, 2017",5 +,campbellr,,1,5,"Sep 4, 2016",1 From 4c683e90ece19e0f9b2833daf4d4f783ab186718 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Tue, 14 Feb 2017 21:09:49 +0100 Subject: [PATCH 19/35] Fix rst parse problem in version 0.16.2 news. --- web/news/e031_version_0_16_2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/news/e031_version_0_16_2.rst b/web/news/e031_version_0_16_2.rst index 2d725028e4..171e4cef12 100644 --- a/web/news/e031_version_0_16_2.rst +++ b/web/news/e031_version_0_16_2.rst @@ -21,8 +21,8 @@ Changes affecting backwards compatibility - A hash procedure has been added for ``cstring`` type in ``hashes`` module. Previously, hash of a ``cstring`` would be calculated as a hash of the pointer. Now the hash is calculated from the contents of the string, assuming - ``cstring`` is a null-terminated string. Equal ``string``s and ``cstring``s - produce equal hash value. + ``cstring`` is a null-terminated string. Equal ``string`` and ``cstring`` + values produce an equal hash value. Library Additions ----------------- From 55782205a4bcbe8584fbb96425ae530a302be15f Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Wed, 15 Feb 2017 14:18:45 +0200 Subject: [PATCH 20/35] Fix appveyor.yml shows green, when failed. (#5396) --- appveyor.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 87640b1923..ea98b8507e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,10 +7,7 @@ cache: # - i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z matrix: - fast_finish: true # set this flag to immediately finish build once one of the jobs fails. - allow_failures: - - platform: x64 -# - platform: x86 + fast_finish: true environment: matrix: From 95abf30fae3d1d91e1980fa9a5a46e7319201cd8 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 15 Feb 2017 15:35:15 +0100 Subject: [PATCH 21/35] compiler debug proc: also output node flags --- compiler/astalgo.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index affbdffd96..226d5ee42c 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -388,6 +388,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int; [istr, makeYamlString($n.kind)] addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) if maxRecDepth != 0: + addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)]) case n.kind of nkCharLit..nkUInt64Lit: addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)]) From 1811e51ff5dc0213a5abfd0f2bb32729f40c0344 Mon Sep 17 00:00:00 2001 From: araq Date: Wed, 15 Feb 2017 22:09:16 +0100 Subject: [PATCH 22/35] fixes #5392 --- lib/system/sysio.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index fa1bdbb4e2..7444661e37 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -215,7 +215,10 @@ proc rawFileSize(file: File): int = discard c_fseek(file, clong(oldPos), 0) proc endOfFile(f: File): bool = - result = c_feof(f) != 0 + var c = c_fgetc(f) + discard c_ungetc(c, f) + return c < 0'i32 + #result = c_feof(f) != 0 proc readAllFile(file: File, len: int): string = # We acquire the filesize beforehand and hope it doesn't change. From 5b5bd3811b5f6e7841128527cb098b23b373e7a6 Mon Sep 17 00:00:00 2001 From: araq Date: Wed, 15 Feb 2017 22:10:31 +0100 Subject: [PATCH 23/35] koch: don't build downloader tool, it is not ready --- koch.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/koch.nim b/koch.nim index 825b360a0a..109dcc3f1c 100644 --- a/koch.nim +++ b/koch.nim @@ -223,8 +223,9 @@ proc bundleWinTools() = copyExe("tools/finish".exe, "finish".exe) removeFile("tools/finish".exe) nimexec("c -o:bin/vccexe.exe tools/vccenv/vccexe") - nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " & - r"--path:..\ui tools\downloader.nim") + when false: + nimexec(r"c --cc:vcc --app:gui -o:bin\downloader.exe -d:ssl --noNimblePath " & + r"--path:..\ui tools\downloader.nim") proc zip(args: string) = bundleNimbleSrc() From 97e26967f1f37a33edf6877cedfc9854fabab5eb Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 00:43:14 +0100 Subject: [PATCH 24/35] fixes #5383 --- compiler/ast.nim | 3 +-- compiler/sem.nim | 15 +++++++++++++++ compiler/semdata.nim | 10 ++++++++++ compiler/semexprs.nim | 3 ++- compiler/seminst.nim | 7 ++++--- compiler/semstmts.nim | 1 + compiler/semtempl.nim | 2 +- compiler/semtypes.nim | 9 +++++---- compiler/transf.nim | 5 ++++- tests/template/tgensymregression.nim | 13 +++++++++++++ tests/template/tparams_gensymed.nim | 9 ++++----- 11 files changed, 60 insertions(+), 17 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 8fbec64cf1..4ea68dc996 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym = ## Generic instantiations are owned by their originating generic ## symbol. This proc skips such owners and goes straight to the owner ## of the generic itself (the module or the enclosing proc). - result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags == - {sfFromGeneric}: + result = if s.kind in skProcKinds and sfFromGeneric in s.flags: s.owner.owner else: s.owner diff --git a/compiler/sem.nim b/compiler/sem.nim index dbf2376357..961d9fa75e 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -168,6 +168,16 @@ proc commonType*(x, y: PType): PType = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) +proc getGenSym(c: PContext; s: PSym): PSym = + var it = c.p + while it != nil: + result = get(it, s) + if result != nil: + #echo "got from table ", result.name.s, " ", result.info + return result + it = it.next + result = s + proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii @@ -178,6 +188,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = if result.kind != kind: localError(n.info, "cannot use symbol of kind '" & $result.kind & "' as a '" & $kind & "'") + if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}: + # declarative context, so produce a fresh gensym: + result = copySym(result) + result.ast = n.sym.ast + put(c.p, n.sym, result) # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 20fd1d9be5..845efd25a0 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -39,6 +39,7 @@ type next*: PProcCon # used for stacking procedure contexts wasForwarded*: bool # whether the current proc has a separate header bracketExpr*: PNode # current bracket expression (for ^ support) + mapping*: TIdTable TInstantiationPair* = object genericSym*: PSym @@ -147,6 +148,15 @@ proc lastOptionEntry*(c: PContext): POptionEntry = proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next +proc put*(p: PProcCon; key, val: PSym) = + if p.mapping.data == nil: initIdTable(p.mapping) + #echo "put into table ", key.info + p.mapping.idTablePut(key, val) + +proc get*(p: PProcCon; key: PSym): PSym = + if p.mapping.data == nil: return nil + result = PSym(p.mapping.idTableGet(key)) + proc newOptionEntry*(): POptionEntry = new(result) result.options = gOptions diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9972585c7b..542d7b4e39 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType, return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) #echo "came here: returned nil" -proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = +proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = + let s = getGenSym(c, sym) case s.kind of skConst: markUsed(n.info, s) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 9c57be0231..1a96b4bc60 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -106,15 +106,16 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = #if n.kind == nkSym and sfGenSym in n.sym.flags: # if n.sym.owner != orig: # echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner - if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and + if n.kind == nkSym and sfGenSym in n.sym.flags: # and # (n.sym.owner == orig or n.sym.owner.kind in {skPackage}): let s = n.sym var x = PSym(idTableGet(symMap, s)) - if x == nil: + if x != nil: + n.sym = x + when false: x = copySym(s, false) x.owner = owner idTablePut(symMap, s, x) - n.sym = x else: for i in 0 .. Date: Thu, 16 Feb 2017 01:43:12 +0100 Subject: [PATCH 25/35] make more tests green --- compiler/semfold.nim | 5 ++++- compiler/transf.nim | 10 ++++++---- tests/overload/tprefer_tygenericinst.nim | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 05e398c9a3..7a65462ec2 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -628,7 +628,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of {skProc, skMethod}: result = n of skType: - result = newSymNodeTypeDesc(s, n.info) + # XXX gensym'ed symbols can come here and cannot be resolved. This is + # dirty, but correct. + if s.typ != nil: + result = newSymNodeTypeDesc(s, n.info) of skGenericParam: if s.typ.kind == tyStatic: if s.typ.n != nil: diff --git a/compiler/transf.nim b/compiler/transf.nim index cbd1f15e34..2103d48bf9 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -869,10 +869,12 @@ proc transform(c: PTransf, n: PNode): PTransNode = else: result = transformSons(c, n) of nkIdentDefs, nkConstDef: - result = n.PTransNode - #transformSons(c, n) - let L = n.len-1 - result[L] = transform(c, n.sons[L]) + when true: + result = transformSons(c, n) + else: + result = n.PTransNode + let L = n.len-1 + result[L] = transform(c, n.sons[L]) # XXX comment handling really sucks: if importantComments(): PNode(result).comment = n.comment diff --git a/tests/overload/tprefer_tygenericinst.nim b/tests/overload/tprefer_tygenericinst.nim index 9787af06b9..56541c7e8b 100644 --- a/tests/overload/tprefer_tygenericinst.nim +++ b/tests/overload/tprefer_tygenericinst.nim @@ -19,7 +19,7 @@ when true: q(B()) # This call reported as ambiguous. # bug #2219 -template testPred(a: expr) = +template testPred(a: untyped) = block: type A = object of RootObj type B = object of A From 01c785e0aa2f2b7f36aa51c34bbedfbf2e74fb39 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 10:39:40 +0100 Subject: [PATCH 26/35] make tests green again --- compiler/seminst.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 1a96b4bc60..acaade4949 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -112,10 +112,12 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = var x = PSym(idTableGet(symMap, s)) if x != nil: n.sym = x - when false: + elif s.owner.kind == skPackage: + #echo "copied this ", s.name.s x = copySym(s, false) x.owner = owner idTablePut(symMap, s, x) + n.sym = x else: for i in 0 .. Date: Wed, 15 Feb 2017 15:35:15 +0100 Subject: [PATCH 27/35] compiler debug proc: also output node flags --- compiler/astalgo.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index affbdffd96..226d5ee42c 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -388,6 +388,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int; [istr, makeYamlString($n.kind)] addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)]) if maxRecDepth != 0: + addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)]) case n.kind of nkCharLit..nkUInt64Lit: addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)]) From 71026cec6e28d89677be0b5b3db4f8f79ee4bb3e Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 00:43:14 +0100 Subject: [PATCH 28/35] fixes #5383 --- compiler/ast.nim | 3 +-- compiler/sem.nim | 15 +++++++++++++++ compiler/semdata.nim | 10 ++++++++++ compiler/semexprs.nim | 3 ++- compiler/seminst.nim | 7 ++++--- compiler/semstmts.nim | 1 + compiler/semtempl.nim | 2 +- compiler/semtypes.nim | 9 +++++---- compiler/transf.nim | 5 ++++- tests/template/tgensymregression.nim | 13 +++++++++++++ tests/template/tparams_gensymed.nim | 9 ++++----- 11 files changed, 60 insertions(+), 17 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 8fbec64cf1..4ea68dc996 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1541,8 +1541,7 @@ proc skipGenericOwner*(s: PSym): PSym = ## Generic instantiations are owned by their originating generic ## symbol. This proc skips such owners and goes straight to the owner ## of the generic itself (the module or the enclosing proc). - result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags == - {sfFromGeneric}: + result = if s.kind in skProcKinds and sfFromGeneric in s.flags: s.owner.owner else: s.owner diff --git a/compiler/sem.nim b/compiler/sem.nim index dbf2376357..961d9fa75e 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -168,6 +168,16 @@ proc commonType*(x, y: PType): PType = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) +proc getGenSym(c: PContext; s: PSym): PSym = + var it = c.p + while it != nil: + result = get(it, s) + if result != nil: + #echo "got from table ", result.name.s, " ", result.info + return result + it = it.next + result = s + proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii @@ -178,6 +188,11 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = if result.kind != kind: localError(n.info, "cannot use symbol of kind '" & $result.kind & "' as a '" & $kind & "'") + if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}: + # declarative context, so produce a fresh gensym: + result = copySym(result) + result.ast = n.sym.ast + put(c.p, n.sym, result) # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 20fd1d9be5..845efd25a0 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -39,6 +39,7 @@ type next*: PProcCon # used for stacking procedure contexts wasForwarded*: bool # whether the current proc has a separate header bracketExpr*: PNode # current bracket expression (for ^ support) + mapping*: TIdTable TInstantiationPair* = object genericSym*: PSym @@ -147,6 +148,15 @@ proc lastOptionEntry*(c: PContext): POptionEntry = proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next +proc put*(p: PProcCon; key, val: PSym) = + if p.mapping.data == nil: initIdTable(p.mapping) + #echo "put into table ", key.info + p.mapping.idTablePut(key, val) + +proc get*(p: PProcCon; key: PSym): PSym = + if p.mapping.data == nil: return nil + result = PSym(p.mapping.idTableGet(key)) + proc newOptionEntry*(): POptionEntry = new(result) result.options = gOptions diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9972585c7b..542d7b4e39 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -922,7 +922,8 @@ proc readTypeParameter(c: PContext, typ: PType, return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) #echo "came here: returned nil" -proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = +proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = + let s = getGenSym(c, sym) case s.kind of skConst: markUsed(n.info, s) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 9c57be0231..1a96b4bc60 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -106,15 +106,16 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = #if n.kind == nkSym and sfGenSym in n.sym.flags: # if n.sym.owner != orig: # echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner - if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and + if n.kind == nkSym and sfGenSym in n.sym.flags: # and # (n.sym.owner == orig or n.sym.owner.kind in {skPackage}): let s = n.sym var x = PSym(idTableGet(symMap, s)) - if x == nil: + if x != nil: + n.sym = x + when false: x = copySym(s, false) x.owner = owner idTablePut(symMap, s, x) - n.sym = x else: for i in 0 .. Date: Thu, 16 Feb 2017 11:15:27 +0100 Subject: [PATCH 29/35] fixes #5402 --- compiler/ccgexprs.nim | 9 ++++--- tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim | 26 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 95a7beada5..6f7e83c186 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -220,7 +220,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = optAsgnLoc(src, t, field), newflags) proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags, - t: PNode) = + t: PNode, typ: PType) = if t == nil: return let newflags = if src.s == OnStatic: @@ -232,10 +232,11 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags, case t.kind of nkSym: let field = t.sym + if field.loc.r == nil: fillObjectFields(p.module, typ) genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r), optAsgnLoc(src, field.typ, field.loc.r), newflags) of nkRecList: - for child in items(t): genOptAsgnObject(p, dest, src, newflags, child) + for child in items(t): genOptAsgnObject(p, dest, src, newflags, child, typ) else: discard proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = @@ -315,9 +316,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = genGenericAsgn(p, dest, src, flags) elif needsComplexAssignment(ty): if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4: - discard getTypeDesc(p.module, dest.t) + discard getTypeDesc(p.module, ty) internalAssert ty.n != nil - genOptAsgnObject(p, dest, src, flags, ty.n) + genOptAsgnObject(p, dest, src, flags, ty.n, ty) else: genGenericAsgn(p, dest, src, flags) else: diff --git a/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim new file mode 100644 index 0000000000..919dc3fc19 --- /dev/null +++ b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim @@ -0,0 +1,26 @@ +discard """ + output: '''false''' +""" + +# bug #5402 + +import lists + +type + Container[T] = ref object + obj: T + + ListOfContainers[T] = ref object + list: DoublyLinkedList[Container[T]] + +proc contains[T](this: ListOfContainers[T], obj: T): bool = + for item in this.list.items(): + if item.obj == obj: return true + return false + +proc newListOfContainers[T](): ListOfContainers[T] = + new(result) + result.list = initDoublyLinkedList[Container[T]]() + +let q = newListOfContainers[int64]() +echo q.contains(123) From 61181702d5cf68e4b7a97cac352b395d37ddb702 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 11:35:15 +0100 Subject: [PATCH 30/35] fixes #5399 --- compiler/semfold.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 7a65462ec2..749deded11 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -659,7 +659,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = localError(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof") result = nil - elif skipTypes(a.typ, typedescInst).kind in + elif skipTypes(a.typ, typedescInst+{tyRange}).kind in IntegralTypes+NilableTypes+{tySet}: #{tyArray,tyObject,tyTuple}: result = newIntNodeT(getSize(a.typ), n) From 0440aea69158dfde7e315d547f8f2ed474a705c0 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 21:30:54 +0100 Subject: [PATCH 31/35] fixes #5405 --- compiler/sem.nim | 10 ---------- compiler/semdata.nim | 20 ++++++++++++++++++++ compiler/sigmatch.nim | 2 ++ tests/template/tgensymregression.nim | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 961d9fa75e..fc7736b079 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -168,16 +168,6 @@ proc commonType*(x, y: PType): PType = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) -proc getGenSym(c: PContext; s: PSym): PSym = - var it = c.p - while it != nil: - result = get(it, s) - if result != nil: - #echo "got from table ", result.name.s, " ", result.info - return result - it = it.next - result = s - proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 845efd25a0..77a530a150 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -157,6 +157,26 @@ proc get*(p: PProcCon; key: PSym): PSym = if p.mapping.data == nil: return nil result = PSym(p.mapping.idTableGet(key)) +proc getGenSym*(c: PContext; s: PSym): PSym = + if sfGenSym notin s.flags: return s + var it = c.p + while it != nil: + result = get(it, s) + if result != nil: + #echo "got from table ", result.name.s, " ", result.info + return result + it = it.next + result = s + +proc considerGenSyms*(c: PContext; n: PNode) = + if n.kind == nkSym: + let s = getGenSym(c, n.sym) + if n.sym != s: + n.sym = s + else: + for i in 0.. Date: Thu, 16 Feb 2017 22:50:21 +0100 Subject: [PATCH 32/35] fixes #5400 --- compiler/ccgstmts.nim | 7 +++++-- tests/errmsgs/tproper_stacktrace3.nim | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 tests/errmsgs/tproper_stacktrace3.nim diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 45d675f64a..02119d63e1 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -1103,8 +1103,8 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) = genAssignment(p, a, tmp, {}) proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = - genLineDir(p, e) if e.sons[0].kind == nkSym and sfGoto in e.sons[0].sym.flags: + genLineDir(p, e) genGotoVar(p, e.sons[1]) elif not fieldDiscriminantCheckNeeded(p, e): var a: TLoc @@ -1114,8 +1114,11 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = initLocExpr(p, e.sons[0], a) if fastAsgn: incl(a.flags, lfNoDeepCopy) assert(a.t != nil) - loadInto(p, e.sons[0], e.sons[1], a) + let ri = e.sons[1] + genLineDir(p, ri) + loadInto(p, e.sons[0], ri, a) else: + genLineDir(p, e) asgnFieldDiscriminant(p, e) proc genStmts(p: BProc, t: PNode) = diff --git a/tests/errmsgs/tproper_stacktrace3.nim b/tests/errmsgs/tproper_stacktrace3.nim new file mode 100644 index 0000000000..c292fa0920 --- /dev/null +++ b/tests/errmsgs/tproper_stacktrace3.nim @@ -0,0 +1,23 @@ +discard """ + outputsub: '''tproper_stacktrace3.nim(21) main''' + exitcode: 1 +""" + +# bug #5400 + +type Container = object + val: int + +proc actualResolver(x: ptr Container): ptr Container = x + +template resolve(): untyped = actualResolver(db) + +proc myfail(): int = + doAssert false + +proc main() = + var db: ptr Container = nil + # actualResolver(db).val = myfail() # actualResolver is not included in stack trace. + resolve().val = myfail() # resolve template is included in stack trace. + +main() From 5d4ed1117de41e0907536437292688d77aa6f01b Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 22:53:32 +0100 Subject: [PATCH 33/35] distros.nim: brew usually doesn't require 'sudo' --- lib/pure/distros.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim index ff30f61341..8964976305 100644 --- a/lib/pure/distros.nim +++ b/lib/pure/distros.nim @@ -225,7 +225,7 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) = else: result = (" install " & p, true) else: - result = ("brew install " & p, true) + result = ("brew install " & p, false) proc foreignDep*(foreignPackageName: string) = ## Registers 'foreignPackageName' to the internal list of foreign deps. From 9534a5d6328e6e4df94d4a8f038a388dfdf56c49 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 16 Feb 2017 22:59:07 +0100 Subject: [PATCH 34/35] fixes #5391 --- compiler/trees.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/trees.nim b/compiler/trees.nim index 7208f7d7b4..79a460aa0e 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -38,7 +38,7 @@ proc exprStructuralEquivalent*(a, b: PNode; strictSymEquality=false): bool = # don't go nuts here: same symbol as string is enough: result = a.sym.name.id == b.sym.name.id of nkIdent: result = a.ident.id == b.ident.id - of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal + of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal of nkEmpty, nkNilLit, nkType: result = true From e9767d8809a0ff4df83ffff1836937db3c2885bf Mon Sep 17 00:00:00 2001 From: fenekku Date: Fri, 17 Feb 2017 02:26:49 -0500 Subject: [PATCH 35/35] Fix reverse on empty openArray (#5407) Reversing an empty `openArray` would raise a RangeError. For instance for `a: seq[int] = @[]`, we have `a.high` return `-1` but `-1` is not a `Natural`. Leaving the array as-is is the expected behaviour. --- lib/pure/algorithm.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 739cdc16bb..bc39f153bf 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -46,7 +46,7 @@ proc reverse*[T](a: var openArray[T], first, last: Natural) = proc reverse*[T](a: var openArray[T]) = ## reverses the array `a`. - reverse(a, 0, a.high) + reverse(a, 0, max(0, a.high)) proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] = ## returns the reverse of the array `a[first..last]`.