Compare commits

...

190 Commits

Author SHA1 Message Date
narimiran
b6d96cafc8 bump the version to 0.19.4 2019-01-31 09:46:55 +01:00
Miran
74275112a5 fixes #2796 (#10500) [backport]
(cherry picked from commit 9ac0cbdd51)
2019-01-31 08:29:40 +01:00
Araq
3ffa9b2e78 fixes #9149 [backport]
(cherry picked from commit 07a0a61875)
2019-01-31 08:28:30 +01:00
Neelesh Chandola
3959b2fd24 Fixes https://github.com/nim-lang/Nim/issues/8484 (#10470) [backport]
(cherry picked from commit 2b0ed9995d)
2019-01-31 08:28:08 +01:00
Miran
d53e3db0eb fix #10287 (#10448) 2019-01-25 10:04:54 +01:00
Christian Lyder Jacobsen
2853aeda8e Use hexadecimal in json escaping (#10437) [backport]
(cherry picked from commit 8313e5f24e)
2019-01-25 10:02:03 +01:00
narimiran
818b23ce7b include missing modules in lib.rst 2019-01-25 10:01:28 +01:00
Miran
a89534eb96 fix #9556 (#10445) 2019-01-25 09:59:53 +01:00
Araq
81fd1147db fixes #8294 [backport]
(cherry picked from commit 27e366eaec)
2019-01-25 09:56:34 +01:00
Jjp137
9047fb7738 lib.rst: fix a typo (#10308) 2019-01-25 09:56:08 +01:00
Ico Doornekamp
00fcaefaab Fixes #10263; [backport]
(cherry picked from commit efa4b9adaa)
2019-01-23 16:07:13 +01:00
LemonBoy
1932da018f Restore the docstring during the .async. transform (#10404) [backport]
Fixes #9816

(cherry picked from commit 792dbed57e)
2019-01-22 09:42:07 +01:00
genotrance
031de094f0 Fix gorge caching (#10407)
(cherry picked from commit 4b1e227531)
2019-01-22 06:31:50 +01:00
Oscar Nihlgård
ba68025ce5 Support system.reset in vm (#10400)
(cherry picked from commit a4cdd25b19)
2019-01-22 06:31:28 +01:00
LemonBoy
56b26966c8 Make the registered passes local to the ModuleGraph (#9259)
Closes #9068

(cherry picked from commit b97a7dbf3d)
2019-01-21 08:39:18 +01:00
narimiran
e8aaec0153 [backport] fix documentation leak to os.nim[ci skip]
(cherry picked from commit 29e0a792ff)
2019-01-14 09:34:22 +01:00
Araq
e21b578740 fixes #10075 [backport]
(cherry picked from commit aa7ad88978)
2019-01-14 09:18:27 +01:00
Araq
98cdfe073e fixes #10271 [backport]
(cherry picked from commit 451377f737)
2019-01-14 09:18:19 +01:00
alaviss
efa75215e6 system/strmantle: avoid leaking docs to system.nim [ci skip] (#10233)
thanks @timotheecour for spotting this

(cherry picked from commit 20402579a2)
2019-01-14 09:16:07 +01:00
Leonardo Cecchi
dd8192fc1d Fix ODBC SQL Error string decoding (#10207) [backport]
ODBC Errors were presented to the users as a sequence of characters.
I.e.:

    >test_oracle.exe

    Error: ['H', 'Y', '0', '0', '0', '\x00', '\x00', ...]

    test_oracle.nim(15)      test_oracle
    test_oracle.nim(8)       test_oracle
    db_odbc.nim(534)         open
    db_odbc.nim(168)         dbError
    Error: unhandled exception: ODBC Error [DbError]

This patch fix the string decoding, creating a real string:

    >test_oracle.exe

    Error: HY000 [Oracle][ODBC][Ora]ORA-12541: TNS:no listener

    test_oracle.nim(15)      test_oracle
    test_oracle.nim(8)       test_oracle
    db_odbc.nim(534)         open
    db_odbc.nim(168)         dbError
    Error: unhandled exception: ODBC Error [DbError]

(cherry picked from commit b7be67349b)
2019-01-14 09:15:17 +01:00
narimiran
6b775905b6 remove float128 from the manual, fixes #10213 [ci skip]
(cherry picked from commit 258952832f)
2019-01-09 11:05:41 +01:00
Ico Doornekamp
187cc9f6bd Added examples to strtabs module (#10160)
(cherry picked from commit be9d1280ae)
2019-01-09 11:04:27 +01:00
alaviss
5499ec084c fix system.nim documentations (#10168)
* system: fix nimGC_getStackBottom doc
* system/helpers: avoid leaking docs to system

(cherry picked from commit be0a4d1342)
2019-01-09 11:02:43 +01:00
Araq
81c9bee285 fixes #10188
(cherry picked from commit 5101b6befd)
2019-01-09 11:01:51 +01:00
Araq
5fc78d86b7 runnableExamples: compile and test them as a single file; fixes #9300 2019-01-09 11:00:40 +01:00
Araq
ecdcded294 koch.nim: speed up tests for the 'testinstall' target for the nightly builds (these tests are also covered by the other CIs)
(cherry picked from commit e6cbf9e790)
2019-01-04 16:36:16 +01:00
Miran
82818d23b1 [backport] correctly document toInt, fixes #2764 [ci skip] (#10176)
(cherry picked from commit 77166ba795)
2019-01-04 16:34:32 +01:00
alaviss
1134f85faa os.walkDir: correctly evaluate paths when relative = true [0.19] (#10173) 2019-01-03 16:35:14 +01:00
Araq
32d7fa35a9 fixes #9728
(cherry picked from commit 4929f74023)
2019-01-03 13:36:31 +01:00
Ico Doornekamp
f90ebaf6f3 Add link to tutorial part III to docs.rst (#10157) [ci skip]
(cherry picked from commit 31b8bc7866)
2019-01-03 09:50:43 +01:00
Araq
2e22bf4f5f tut3: improved the wording
(cherry picked from commit 1cc8b7814d)
2019-01-03 09:50:05 +01:00
Arne Döring
0e2bfe3e6b added a new macro tutorial (#9588)
(cherry picked from commit 30480605c1)
2019-01-03 09:49:56 +01:00
Araq
e4767ef8d5 fixes #9889, fixes #9886
(cherry picked from commit 7a66616d74)
2019-01-02 11:39:49 +01:00
Araq
8d3cadbc94 tar.xz building: also ship with the moved testament tool
(cherry picked from commit 00f84d3d22)
2019-01-02 10:39:49 +01:00
narimiran
7beea1642d Revert "os.walkDir: correctly evaluate paths when relative = true"
This reverts commit 123c568236.
2018-12-31 11:20:10 +01:00
narimiran
a23b5c9265 Revert "Undefine some symbols and globalOptions when processing nimscript (#9945) [backport]"
This reverts commit 90b4648a99.
2018-12-31 11:17:27 +01:00
alaviss
3b2e151d3e config/nim.cfg: disable tlsEmulation on Haiku (#10092) [backport]
As of hrev52662, TLS support in Haiku is usable again. This has since
been backported to R1/Beta1, so we can flip the switch upstream.

(cherry picked from commit ca0ef62c9e)
2018-12-29 10:52:33 +01:00
Araq
0b9d158d11 fixes #10033 [backport]
(cherry picked from commit bdb67201b2)
2018-12-29 10:52:09 +01:00
alaviss
123c568236 os.walkDir: correctly evaluate paths when relative = true 2018-12-29 10:51:43 +01:00
Araq
98bf23fe08 fixes #10058 [backport]
(cherry picked from commit 23448a96cc)
2018-12-29 10:47:49 +01:00
Andreas Rumpf
d02bf88f21 GC: avoid pathological behaviour; fixes #10040 [backport] 2018-12-29 10:47:20 +01:00
Neelesh Chandola
90b4648a99 Undefine some symbols and globalOptions when processing nimscript (#9945) [backport]
* Undefine some symbols when processing nimscript
* Undefine taintMode when processing nimscript
* Reload .cfg configuration

(cherry picked from commit bb85869237)
2018-12-29 10:45:33 +01:00
Jacek Sieka
a29ab5e65f allow uints to appear in deep constant expressions
(cherry picked from commit db51eb3e32)
2018-12-15 10:43:23 +01:00
Timothee Cour
c16fa63f5e fix #9872: setLen now works properly at CT [backport]
(cherry picked from commit f838b1e6c1)
2018-12-15 10:24:54 +01:00
Araq
28946ed9f6 fixes #9864 [backport]
(cherry picked from commit af815c3c18)
2018-12-15 10:07:15 +01:00
Araq
f0a78b8ef1 hotfix: discriminants can be of size 8 bytes [backport]
(cherry picked from commit 24106ade8f)
2018-12-15 10:07:03 +01:00
Timothee Cour
c0e741778f fix #9832 (fixup) (#9859)
(cherry picked from commit d502ddea9e)
2018-12-15 10:06:45 +01:00
Timothee Cour
c3319fcad5 fixes #9832 (#9841) [backport]
(cherry picked from commit 05769020d3)
2018-12-15 10:06:25 +01:00
Andreas Rumpf
7572d40b23 enables .raises: [] via a .push (#9834) [backport]
(cherry picked from commit c74226f4c1)
2018-12-15 09:41:22 +01:00
Josh Goebel
fa01531b8c fix outdated example to invoke Nim from C
- resolves #8139

(cherry picked from commit dace2a0999)
2018-11-28 17:50:36 +01:00
Andreas Rumpf
e091c99514 don't crash where there is an unknown statement pragma [backport]
(cherry picked from commit 93cf0ef52e)
2018-11-28 17:49:45 +01:00
pgkos
a8b20e8129 fixes #9800 (#9804) [backport]
* fixes #9800
* add tests for #9800

(cherry picked from commit 518c72e57a)
2018-11-28 17:49:33 +01:00
alaviss
b53d726c57 don't raise exception in the default handler 2018-11-24 21:53:35 +01:00
narimiran
ff66aae380 disable tasyncssl on appveyor 2018-11-24 20:16:12 +01:00
Yuriy Glukhov
219942658b Fixes 9716 [backport] 2018-11-24 17:35:24 +01:00
Ștefan Talpalaru
7dfb2a8cd3 fix segfault when calling shallow() on an empty string (#9782) [backport]
shallow() casts its string argument to a seq and then tries to access
its fields. Guess what happens when that string is nil, which seems to
be the representation of an empty string (both the default value and an
explicitly assigned "").

Segfault encountered when running "ntags -R ." on a large project. The relevant line:
a1c62c38e5/ntags.nim (lines-125)

(cherry picked from commit f8fa94cb20)
2018-11-24 12:21:04 +01:00
ishowta
9fcdc14527 Empty check in shallow [backport] (#9676) 2018-11-24 12:20:35 +01:00
cooldome
ad554a2013 Fixes discard bug in cpp codegen (#9747) [backport]
Fixes discard bug in cpp codegen

(cherry picked from commit 9b9f5dee0b)
2018-11-24 12:17:32 +01:00
Yuriy Glukhov
43b3582952 Fixed yield in nkObjConstr. Fixes #9694 [backport] (#9744)
* Fixed yield in nkObjConstr. Fixes #9694
* Separate expr lowering from state splitting, introduce a clear lowering internal error

(cherry picked from commit 5a2290f788)
2018-11-24 12:17:21 +01:00
cooldome
64a4c72392 Of operator in vm fixes [backport] (#9717)
* fixes #9701
*  fixes #9702
* optimize of statement to bool

(cherry picked from commit 8c1083d3b7)
2018-11-24 12:15:43 +01:00
Andreas Rumpf
fa3017f6bb nimpretty: fixes #9673 [backport]
(cherry picked from commit 532647171e)
2018-11-24 12:15:12 +01:00
Andreas Rumpf
172e95be50 nimpretty: explicit --indent option; fixes #9502; refs #9510 [backport]
(cherry picked from commit d1fe195dcc)
2018-11-24 12:15:05 +01:00
Andreas Rumpf
7d88738068 parser/grammar sync; fixes #9608 [backport]
(cherry picked from commit 4e94f49065)
2018-11-24 12:14:18 +01:00
Andreas Rumpf
5f7679cb50 nim check fix; fixes #9609 [backport]
(cherry picked from commit 1c73db08b8)
2018-11-24 12:14:09 +01:00
Andreas Rumpf
4cece52524 Nimscript: fixes #9246 [backport]
(cherry picked from commit 73c306258b)
2018-11-24 12:13:36 +01:00
Miran
3ef686011d Merge tests into a larger file (part 8 of ∞) (#9583)
* merge tuple tests

* merge trmacros tests

* merge template tests

(cherry picked from commit 66a76d3165)
2018-11-24 12:13:20 +01:00
Araq
f0e196e674 make more tests green 2018-11-04 13:28:02 +01:00
Araq
c514fd5b27 manually backported the fix to #9322 2018-11-04 13:27:45 +01:00
LemonBoy
1355dd1884 Fix transformation of yield in inline context (#9135)
When the loop variables are part of the envP block it is not safe to use
a nkFastAsgn.

Fixes #2656

(cherry picked from commit f98a3056c6)
2018-11-04 13:16:28 +01:00
Araq
fcbe611899 make some tests green again 2018-11-04 13:16:21 +01:00
Araq
b0217beadf preparations for version 0.19.2 2018-11-04 10:03:50 +01:00
LemonBoy
d37ec666d7 cherry pick 2018-11-04 09:02:03 +01:00
Araq
da1569afb6 fixes #9507
(cherry picked from commit eb2e494a52)
2018-11-04 08:47:34 +01:00
Neelesh Chandola
abf02b5f28 Fixes #9556 (#9604) [backport]
(cherry picked from commit 7a15d2d04b)
2018-11-03 07:28:51 +01:00
Miran
e68775f94d delete unused issue_template.md
The templates in .github/ISSUE_TEMPLATE are used.

(cherry picked from commit 3806e5640a)
2018-11-03 07:28:34 +01:00
Araq
98103b5433 docgen: fixes #9432 [backport]
(cherry picked from commit 48f73aaa1c)
2018-11-03 07:27:53 +01:00
Araq
20c6ec0a22 docgen: make tests green again [backport]
(cherry picked from commit 8f28be0dd8)
2018-11-03 07:27:20 +01:00
Araq
be6f0108f3 docgen: fixes #9169 [backport]
(cherry picked from commit eb03684c57)
2018-11-03 07:26:41 +01:00
Arne Döring
ae26351a0e changelog entry
(cherry picked from commit 80843373ba)
2018-11-01 18:08:38 +01:00
Arne Döring
899ce95420 fix typo
(cherry picked from commit 84db658eb4)
2018-11-01 18:08:25 +01:00
Miran
e214241bd3 Change documentation details (closes #5525) (#9542)
(cherry picked from commit 313bbf5b9b)
2018-11-01 18:08:00 +01:00
Araq
257d62efc9 docgen: fixes #9235 [backport]
(cherry picked from commit c9e8b899ed)
2018-11-01 18:07:49 +01:00
Araq
ea2309a99f contributing guide: document the new [backport] convention
(cherry picked from commit b138e89772)
2018-11-01 18:07:39 +01:00
Araq
8172ac8c0b system.nim: workaround for the fixed documentation generator
(cherry picked from commit 1dd1d66f16)
2018-11-01 18:07:13 +01:00
Araq
78f9a55287 nre: don't use the deprecated import syntax
(cherry picked from commit 895ac5bec4)
2018-11-01 18:06:57 +01:00
Arne Döring
758c20dc84 fixes #9557
(cherry picked from commit e653121633)
2018-11-01 18:06:42 +01:00
B3liever
1a9b954cd9 Fix names set and get procs in macros
(cherry picked from commit fb75e3bb49)
2018-11-01 18:06:32 +01:00
Ian
801c102881 #9348 Merge some small test files (#9561)
* Consolidated types issue tests
* Consolidated vm issue tests

(cherry picked from commit 5ddeead29c)
2018-11-01 18:03:51 +01:00
Araq
5d3756ed3f fixes #7667; underlying issue is that dot calls in generics have no concept of 'friend' symbols, will be addressed later
(cherry picked from commit e44df5dca6)
2018-11-01 18:03:28 +01:00
narimiran
939ffc3615 more examples for mod and div, plus corrections [ci skip]
(cherry picked from commit 80b78b50d0)
2018-11-01 18:03:16 +01:00
Clyybber
20b6c47d3f actually do ceiling division, not a similar operation
Co-Authored-By: flaviut <tamasflaviu@gmail.com>
(cherry picked from commit 2aa7eeda39)
2018-11-01 18:03:05 +01:00
Neelesh Chandola
c756983795 Fixes #9525 (#9526)
(cherry picked from commit 95cc1abdc7)
2018-11-01 18:02:56 +01:00
xzfc
c8786ad197 Fix strscans.scanp (#9518)
* strscans: fix typo

* strscans: fix #9240

* strscans: add tests

(cherry picked from commit 95a60dc780)
2018-11-01 18:02:33 +01:00
Araq
aa1def75c0 make tests\benchmarks programs compile again
(cherry picked from commit c804b606f9)
2018-11-01 18:02:07 +01:00
narimiran
2f48d2175b Closes #6986
(cherry picked from commit f4149ae535)
2018-11-01 18:01:58 +01:00
Flaviu Tamas
71d9a1f289 Eliminate floating point arithmatic in nre
Integer division is already hard enough on your CPU, using floating
point here is WAY slower and can just as effectivly be done using
integers. This is important because matchImpl tends to be in the center
of very hot loops (like split()).

(cherry picked from commit 9ca1c2c930)
2018-11-01 18:01:44 +01:00
Andrii Riabushenko
2333645fbd update changelog 2018-11-01 18:01:29 +01:00
citycide
171721bf49 docs: clarify asyncCheck vs waitFor
(cherry picked from commit 4362ba7293)
2018-11-01 18:00:26 +01:00
Andreas Rumpf
45655332e8 nimpretty tester: strengthen the comparison, do not use strip
(cherry picked from commit dd252ce640)
2018-11-01 18:00:11 +01:00
Andreas Rumpf
961d8bdf2f nimpretty: fixes #9506
(cherry picked from commit 03005fde99)
2018-11-01 18:00:03 +01:00
Araq
fb9aa0c821 correct tnoop test case 2018-11-01 17:59:26 +01:00
Araq
c53046223f nimpretty: fixes #9500
(cherry picked from commit 87d60b2a4b)
2018-11-01 17:58:44 +01:00
Araq
6977a743f3 nimpretty: fixes #9504
(cherry picked from commit 0afca3dd6b)
2018-11-01 17:58:33 +01:00
Andreas Rumpf
6844d679fc nimpretty: fixes #9499
(cherry picked from commit 5fd2827ab6)
2018-11-01 17:58:17 +01:00
Andreas Rumpf
4b06f19b71 stdlib: documenation updates, the exception names have been changed
(cherry picked from commit 223e92b83a)
2018-11-01 17:58:07 +01:00
Andreas Rumpf
f8c341e31f make tests green again
(cherry picked from commit f5a2c6e19d)
2018-11-01 17:57:30 +01:00
Andreas Rumpf
d6124ccbad parsutils: minor doc improvements
(cherry picked from commit 9331f06c0b)
2018-11-01 17:57:15 +01:00
Araq
522896f488 nimpretty: closes #9484
(cherry picked from commit e7e75224a2)
2018-11-01 17:57:03 +01:00
Araq
427aa63a66 nimpretty: test for idempotence; fixes #9483
(cherry picked from commit 06a6433db7)
2018-11-01 17:56:53 +01:00
genotrance
01b36cce1e Make Windows cross-compilation simpler (#9485)
(cherry picked from commit 8500076651)
2018-11-01 17:56:42 +01:00
Araq
db68353848 nimpretty: fixes #8078
(cherry picked from commit 3ee53a7c8e)
2018-11-01 17:56:34 +01:00
Araq
8196fd6f73 nimpretty: fixes #9398
(cherry picked from commit e3a0415650)
2018-11-01 17:56:04 +01:00
Araq
5f1280194e closes #9400
(cherry picked from commit 72370c8dfa)
2018-11-01 17:55:54 +01:00
Araq
1b2c8317e0 nimpretty: minor bug fix
(cherry picked from commit 695074214b)
2018-11-01 17:55:43 +01:00
loongw
80a9ac1400 \#include "windows.h" instead of "Windows.h" (#9475)
This fixes #9474

(cherry picked from commit 4841fc5356)
2018-11-01 17:55:31 +01:00
recloser
fdce2e0188 Fix printing and comparing uninitialized strings
(cherry picked from commit 2b03bed2db)
2018-11-01 17:55:20 +01:00
Vindaar
5e48d4050e add test case
(cherry picked from commit 557fa85e02)
2018-11-01 17:55:12 +01:00
Vindaar
a482e5735d fixes #9456 by only calling c_fclose if non nil
(cherry picked from commit e190f485ae)
2018-11-01 17:54:44 +01:00
Oscar Nihlgård
b864c89479 Fix times 32-bit issue
(cherry picked from commit 81f5427ed4)
2018-11-01 17:54:28 +01:00
Timothee Cour
8f5a127e5c [doc] add tips to doc/contributing.rst: git, code review, CI (#9429) 2018-11-01 17:53:51 +01:00
Miran
614059d6de Update issue templates
Create `bug report` and `feature request` templates.

(cherry picked from commit fc625091e0)
2018-11-01 17:52:41 +01:00
Arne Döring
6a6b77190c Create issue_template.md
(cherry picked from commit d26beedfb1)
2018-11-01 17:52:33 +01:00
Miran
38b391ff62 merge stdlib tests (#9439)
(cherry picked from commit 9fb212cfdf)
2018-11-01 17:52:04 +01:00
jcosborn
42056874d1 added test for #4674 (#9438)
(cherry picked from commit 3b1ade0350)
2018-11-01 17:51:51 +01:00
Timothee Cour
4424fe0acc fixes #9376: old changelogs should be kept instead of erased (#9428)
(cherry picked from commit 162e7ee5b5)
2018-11-01 17:51:41 +01:00
Timothee Cour
6515810a2e [doc] start of best practices section in contributing.rst (#9415)
(cherry picked from commit 15dbd973de)
2018-11-01 17:51:33 +01:00
Araq
c1a6ebf40d closes #6220
(cherry picked from commit c64391e30b)
2018-11-01 17:51:16 +01:00
Araq
8f8f3ba12f closes #5321
(cherry picked from commit 4644484fb7)
2018-11-01 17:50:53 +01:00
Vindaar
58726f9b81 fix #9394 by replacing fmt with strutils.% (#9417)
* fix #9394 by replacing `fmt` with normal string append

Until issue #7632 is fixed, use string append.

* use `strutils.%` instead of normal string add

(cherry picked from commit 82a1576263)
2018-11-01 17:50:38 +01:00
LemonBoy
8a356fafb7 Make the swap procs safe for unaligned input ptrs (#9210)
* Make the swap procs safe for unaligned input ptrs

The copy to a temporary local variable is often elided by a sufficiently
smart compiler when it can prove the input pointer is aligned.

Refs #9206

* Explain why copyMem is used

(cherry picked from commit 1fe949b9d5)
2018-11-01 17:50:28 +01:00
Timothee Cour
624d05c73f [nimscript] document currentSourcePath in thisDir (#9402)
(cherry picked from commit 7d8e281239)
2018-11-01 17:50:03 +01:00
Araq
b65b360ac2 tests: disable flaky tests for now; closes #9421
(cherry picked from commit 381498b0db)
2018-11-01 17:49:55 +01:00
Araq
0d5355b5fd intern.rst: minor formating improvements
(cherry picked from commit 03a05ca456)
2018-11-01 17:49:38 +01:00
Bo Lingen
8637ca6983 docs(lib): update Nimble notes since package list is not inline anymore (#9397)
(cherry picked from commit 458aab0b10)
2018-11-01 17:49:17 +01:00
Miran
a65ac85e4a make some tests faster (#9413)
* remove duplicated slow test

* smaller `convex hull`

* smaller sleep

* faster `trtree`

* smaller sleep in `tfuturestream`

(cherry picked from commit 95504caa31)
2018-11-01 17:48:56 +01:00
Araq
13a8765afc make thavlak and tmarkerproc_regression tests take fewer iterations in order to speedup the CIs
(cherry picked from commit 81e33b9d87)
2018-11-01 17:48:32 +01:00
Araq
64f5c96685 nimpretty: fixes #9384
(cherry picked from commit bd9d5787f0)
2018-11-01 17:48:17 +01:00
technicallyagd
aac04585ea Elaborate on source code filter usage in the documentation. (#9407)
* Elaborate on source code filter usage.
Also gives it an abbreviation, SCF.

* Fix the code block formatting

* Trim off the unintended usage with import.

(cherry picked from commit 88adf77569)
2018-11-01 17:48:06 +01:00
Yuriy Glukhov
7cf698442a No setjump in GC for emscripten/wasm (#9386)
(cherry picked from commit dc72cf7564)
2018-11-01 17:47:57 +01:00
PMunch
b70b633e8e Fixes #9364 and add moduleDescription to jsondoc (#9396)
This fixes `jsondoc0` so that it has comments in the output as described
by the documentation. It also fixes `jsondoc`/`jsondoc2` as it stored
it's output in a file with an html extension. Along with this it also
adds a new field `moduleDescription` to `jsondoc`/`jsondoc2` which
contains the module description.

(cherry picked from commit db95fad6fa)
2018-11-01 17:47:27 +01:00
Miran
3ed61da6c1 improve error message, closes #2361 (#9387)
* improve error message

* use single % operation

(cherry picked from commit e8cf289bee)
2018-11-01 17:47:20 +01:00
Federico Ceratto
25ce980fe1 Update example (#9395)
(cherry picked from commit afc453beff)
2018-11-01 17:47:10 +01:00
Kaushal Modi
7e1d411279 Update config.nims search path in docs (#9388)
Related: https://github.com/nim-lang/Nim/pull/8682

Also mention the "nim help" command to list all available tasks.

(cherry picked from commit 3e9f506923)
2018-11-01 17:47:02 +01:00
Andreas Rumpf
90d18b75c2 fixes #9244
(cherry picked from commit b340f677eb)
2018-11-01 17:46:31 +01:00
eqperes
2e2a2754a4 Some documentation added to strutils (#9379)
* wip documentation strutils

* some runnableExamples in strutils

* assert -> doAssert

* corrected doc for abbrev; some more runnable examples

* runnableExamples for join

* fix c&p error

* corrections

(cherry picked from commit afd9d8dd8d)
2018-11-01 17:46:22 +01:00
Andreas Rumpf
6ad4022b5e nimpretty: added an new simple test
(cherry picked from commit 480d228603)
2018-11-01 17:46:12 +01:00
Andreas Rumpf
e0eda28a99 nimpretty: fixes #9144
(cherry picked from commit 778e4d1775)
2018-11-01 17:44:54 +01:00
Andreas Rumpf
06b1d17134 nimpretty: add #!nimpretty on/off directives
(cherry picked from commit f3c0703b7d)
2018-11-01 17:44:48 +01:00
Andreas Rumpf
754e11de3e nimpretty: fixes #8626
(cherry picked from commit ed38079b9b)
2018-11-01 17:44:23 +01:00
Andreas Rumpf
3340e46310 nimpretty: render r-strings properly, fixes #9236
(cherry picked from commit 89ba0f8592)
2018-11-01 17:44:09 +01:00
Araq
4f432688a3 system.nim: fixes typo
(cherry picked from commit fe091997aa)
2018-11-01 17:43:46 +01:00
Miran
ee18699609 merge macros tests (#9367) 2018-11-01 17:43:26 +01:00
Andreas Rumpf
ae80f763b3 unicode: added strip, align, alignLeft, repeat procs; refs #6301
(cherry picked from commit 8960efa340)
2018-11-01 17:40:29 +01:00
Andreas Rumpf
48d3b26c21 unicode: add split procs; refs #6301 2018-11-01 17:39:58 +01:00
Andreas Rumpf
2818661ffe struils: don't use the deprecated accumulateResult
(cherry picked from commit 152c7d99c3)
2018-11-01 17:38:05 +01:00
Miran
325ca8cae6 Merge tests into a larger file (part 3 of ∞: generics) (#9347)
* merge generics issues tests
* merge tgeneric
* merge test with local imports
* merge tcan tests
* merge matcher tests
* more issue tests merged
* one more tcan test
* merge various small tests into one file
* add a test for #3717

(cherry picked from commit 9f8b93641e)
2018-11-01 17:37:48 +01:00
Vindaar
ed4a7b7f66 add issue #5707 as test case (#9361)
(cherry picked from commit afd5abdfc2)
2018-11-01 17:37:33 +01:00
Josh Goebel
5b3b091cd1 Fix type in docs (#9362)
(cherry picked from commit 38454c6951)
2018-11-01 17:37:20 +01:00
Federico Ceratto
64da338a8b Update makefile and buildsh templates for riscv64 (#9351)
(cherry picked from commit e435dbd35e)
2018-11-01 17:36:25 +01:00
Miran
e718dc75c5 Merge tests into a larger file (part 2 of ∞) (#9335)
* merge controlflow tests

* merge distinct tests

* merge enum tests

* merge fields tests

* merge implicit tests

* merge iter issues tests

(cherry picked from commit 3c9fcc4c30)
2018-11-01 17:36:14 +01:00
Tomohiro
495585bc1e manual: Fix links to Parallel & Spawn (#9342)
(cherry picked from commit eb4272ba1c)
2018-11-01 17:36:02 +01:00
eqperes
7de3bcfb8e Proposed solution for issue #8919 (#9280)
* Proposed solution for issue #8919

* count sub/subs must be non-empty

(cherry picked from commit 14925ee8b6)
2018-11-01 17:35:29 +01:00
Jacek Sieka
7cf3944c38 Testament pre parallel (#9137)
* testament: move to root dir (it's not a test)

* osproc: fix process index passed to afterRunEvent for parallel runs

it was passing the index of the process, not index of all commands

* testament: complete file move

(cherry picked from commit 97738a4f28)
2018-11-01 17:35:08 +01:00
Miran
44f5c7e90f Merge tests into a larger file (part 1 of ∞) (#9318)
* merge actiontable tests

* merge arithm tests

* merge array tests

* merge assign tests

* merge bind tests

* merge casestmt tests

* merge closure tests

* merge cnt seq tests

* merge collections tests

* merge concept issues tests

* merge concept tests

* fix failing tests

* smaller outputs

Use `doAssert` where possible.

* fix wrong output

* split `tcomputedgoto`

* revert merging concepts

* fix failing test

(cherry picked from commit 7f18d7cbc1)
2018-11-01 17:34:33 +01:00
Tomohiro
faa9e7a582 manual: Remove stmt or expr template related text from manual (#9321)
(cherry picked from commit d2b04a8bc7)
2018-11-01 17:33:17 +01:00
Araq
596524d2ec fixes #9306
(cherry picked from commit 8ab6fa1be2)
2018-11-01 17:32:41 +01:00
Andrea Ferretti
fde803745e Clarify that term rewriting macros are applied recursively (#9305)
Fixes https://github.com/nim-lang/Nim/issues/9288 fixes https://github.com/nim-lang/Nim/issues/8376 and fixes https://github.com/nim-lang/Nim/issues/2901

(cherry picked from commit 160f8599c6)
2018-11-01 17:32:32 +01:00
eqperes
8a9680e3a2 compile date and compile time tz written in doc (#9283)
(cherry picked from commit 00c4aba828)
2018-11-01 17:32:21 +01:00
Oscar Nihlgård
291d7499a4 Fix OrderedSet.excl (#9287)
(cherry picked from commit eade49d7a7)
2018-11-01 17:31:56 +01:00
Timothee Cour
b5bb48dbd2 fix #9295 (#9299)
(cherry picked from commit 0aac5c9725)
2018-11-01 17:31:36 +01:00
xzfc
73a7d1456c Fix tests on NixOS (#9209) (#9285)
* Replace `/bin/sleep` with just `sleep`, i.e. use environment variable
  `$PATH` to locate binary.
* Replace `/usr/share/zoneinfo` with `$TZDIR` when it is defined,
  fallback to hardcoded path otherwise. This is the same behavior that
  Glibc2 normally have, see man 3 tzset.

(cherry picked from commit 8ed3dac1dc)
2018-11-01 17:31:25 +01:00
eqperes
65c2f19cff Documentation improved for math module 2018-11-01 17:30:51 +01:00
manterolat
a5aad7ff59 Fixes #9154 (#9193)
(cherry picked from commit 16a941a642)
2018-11-01 17:29:20 +01:00
Miran
0714de4f3b Iter test: closes #3819 (#9272)
(cherry picked from commit 462bff48b2)
2018-11-01 17:29:10 +01:00
Timothee Cour
41e2f6b7bc fix #9264 regression (#9265)
(cherry picked from commit 77f836b403)
2018-11-01 17:28:57 +01:00
Miran
46f0c7c554 better docs for tables module (#9221)
* better docs for `tables` module

* lower case for the first sentence in docs

(cherry picked from commit 98a8868cb4)
2018-11-01 17:28:42 +01:00
Timothee Cour
b0618ffe17 fix tests/generics/t8694.nim: runnableExamples were not run because of #9216 (#9262)
(cherry picked from commit 63c00d7be9)
2018-11-01 17:28:26 +01:00
Kaushal Modi
d1114d0995 Do not encode the anchors in docs (id attr in a tags) (#9261)
Update the tests too.

Fixes https://github.com/nim-lang/Nim/issues/9232.

(cherry picked from commit c6dfbfc2cf)
2018-11-01 17:28:15 +01:00
hlaaf
8120d8bede Separate high/low/len docs for each overload (#8816)
(cherry picked from commit c68ea019f9)
2018-11-01 17:27:53 +01:00
Dominik Picheta
7ff17aff5f Fixes #8994. FutureStream read procedure data loss no longer occurs. (#9183)
* Fixes #8994. FutureStream read procedure data loss no longer occurs.

* Optimises the fix for #8994.

(cherry picked from commit 21ecf64d24)
2018-11-01 17:27:35 +01:00
Yasuhiro Horimoto
f2a44aa8cf Fixes #8841 (#9101)
Modify comments for readChar and peekChar to the same as the comment for them in the source code.

(cherry picked from commit fe19670c52)
2018-11-01 17:27:28 +01:00
technicallyagd
1e1a43dd23 Fixes some minor typos in nimsuggest.rst (#9223)
* Fix Minor typo in nimsuggest.rst

* Fixes two more typo in nimsuggest.rst

(cherry picked from commit 85187d4ba3)
2018-11-01 17:27:10 +01:00
LemonBoy
0f080fdce3 Fix range type construction in the VM (#9205)
The `range[X,Y]` representation is wrong, we use `range[X .. Y]`
instead.

Fixes #9194

(cherry picked from commit 8a1055adce)
2018-11-01 17:26:50 +01:00
cooldome
221c67b880 fixes #9222 (#9224)
(cherry picked from commit 036c52f0b6)
2018-11-01 17:26:15 +01:00
Timothee Cour
2923eb08ab [os] clarify docs for existsDir (#9212)
* Update os.nim

* Update os.nim

(cherry picked from commit 73e6b229aa)
2018-11-01 17:26:06 +01:00
LemonBoy
ddd54a3413 Prevent the construction of recursive tyStatic types (#9256)
Fixes #9255

(cherry picked from commit b8d2f79ef0)
2018-11-01 17:25:51 +01:00
Dheepak Krishnamurthy
ffeb3c6cec Add checks for except: body blocks (#9191)
(cherry picked from commit 70018aa683)
2018-11-01 17:25:30 +01:00
jcosborn
82896abcbe fixes #4435 (#9185)
(cherry picked from commit dd65986795)
2018-11-01 17:25:07 +01:00
Juan Carlos
4e9686d1a9 HTMLGen Update, Add runnableExamples, Add HTML Tags center, details, dialog, marquee, picture, slot, summary (#9252)
(cherry picked from commit bc557e4c6a)
2018-11-01 17:24:04 +01:00
LemonBoy
d29fc8c693 Replace the sha1 implementation w/ a working one (#9242)
As #9239 points out the old implementation had some serious flaws.
The new implementation is a port of the MIT-licensed one used by
Chromium OS and has been tested against the FIPS-provided vectors and by
generating huge files like the ones mentioned in the issue above.

While I tried my best to take into account the existence of BE machines
the code has only been tested on a LE one.

(cherry picked from commit 18023c023d)
2018-11-01 17:23:49 +01:00
510 changed files with 13259 additions and 8930 deletions

45
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,45 @@
---
name: Bug report
about: You found an unexpected behaviour? Use this template.
---
<!-- Think about the title, twice. -->
<!-- Summarize the Problem here, keep it simple. -->
<!-- e.g. `echo` outputs the wrong string. -->
### Example
<!-- This should be a source code block.
```nim
echo "Hello World!"
```
-->
### Current Output
<!--
```
Hola mundo!
```
-->
### Expected Output
<!--
```
Hello World!
```
-->
### Possible Solution
<!--- Have you found a possible solution? Post it here. -->
### Additional Information
<!--- For Example:
A link to a project where the issue is relevant.
A link to a related issue or discussion.
-->

View File

@@ -0,0 +1,23 @@
---
name: Feature request
about: You want to suggest a new feature? Use this template.
---
### Summary
<!--- Short summary of your proposed feature -->
### Description
<!--- Describe your solution, what problem does it fix? -->
### Alternatives
<!--- Are there any alternatives you've considered? -->
### Additional Information
<!--- For Example:
A link to a project where the issue is relevant.
A link to a related issue or discussion.
-->

View File

@@ -53,8 +53,8 @@ test-windows:
<<: *win_set_path_def
script:
- call ci\deps.bat
- nim c --taintMode:on tests\testament\tester
- tests\testament\tester.exe --pedantic all
- nim c --taintMode:on testament\tester
- testament\tester.exe --pedantic all
tags:
- windows
- fast

View File

@@ -42,11 +42,11 @@ script:
#- nimble install sdl1
#- nimble install jester@#head -y
#- nimble install niminst
- nim c --taintMode:on -d:nimCoroutines tests/testament/tester
- tests/testament/tester --pedantic all -d:nimCoroutines
- nim c --taintMode:on -d:nimCoroutines testament/tester
- testament/tester --pedantic all -d:nimCoroutines
- nim c -o:bin/nimpretty nimpretty/nimpretty.nim
- nim c -r nimpretty/tester.nim
- ./koch docs
- ./koch docs --git.commit:devel
- ./koch csource
- ./koch nimsuggest
- nim c -r nimsuggest/tester

View File

@@ -53,11 +53,11 @@ build_script:
# - nimble install opengl -y
# - nimble install sdl1 -y
# - nimble install jester@#head -y
- nim c --taintMode:on -d:nimCoroutines --os:genode -d:posix --compileOnly tests/testament/tester
- nim c --taintMode:on -d:nimCoroutines tests/testament/tester
- nim c --taintMode:on -d:nimCoroutines --os:genode -d:posix --compileOnly testament/tester
- nim c --taintMode:on -d:nimCoroutines testament/tester
test_script:
- tests\testament\tester --pedantic all -d:nimCoroutines
- testament\tester --pedantic all -d:nimCoroutines
- nim c -r nimdoc\tester
# - koch csource
# - koch zip

View File

@@ -1,253 +1,12 @@
## v0.19.X - XX/XX/2018
## v0.19.2 - 2018-11-04
### Changes affecting backwards compatibility
This is a bugfix release of version 0.19.0. No new features or breaking changes.
The most important bugfixes are:
- The stdlib module ``future`` has been renamed to ``sugar``.
- ``macros.callsite`` is now deprecated. Since the introduction of ``varargs``
parameters this became unnecessary.
- Anonymous tuples with a single element can now be written as ``(1,)`` with a
trailing comma. The underlying AST is ``nnkTupleConstr(newLit 1)`` for this
example. ``nnkTupleConstr`` is a new node kind your macros need to be able
to deal with!
- Indexing into a ``cstring`` for the JS target is now mapped
to ``charCodeAt``.
- Assignments that would "slice" an object into its supertype are now prevented
at runtime. Use ``ref object`` with inheritance rather than ``object`` with
inheritance to prevent this issue.
- The ``not nil`` type annotation now has to be enabled explicitly
via ``{.experimental: "notnil"}`` as we are still not pleased with how this
feature works with Nim's containers.
- The parser now warns about inconsistent spacing around binary operators as
these can easily be confused with unary operators. This warning will likely
become an error in the future.
- The ``'c`` and ``'C'`` suffix for octal literals is now deprecated to
bring the language in line with the standard library (e.g. ``parseOct``).
- The dot style for import paths (e.g ``import path.to.module`` instead of
``import path/to/module``) has been deprecated.
- ``spawn`` can handle the empty seqs/strings that are internally
represented as ``nil``.
- The most pressing bugs of the documentation generator have been fixed.
- async streaming of the httpclient has been fixed.
#### Breaking changes in the standard library
- ``re.split`` for empty regular expressions now yields every character in
the string which is what other programming languages chose to do.
- The returned tuple of ``system.instantiationInfo`` now has a third field
containing the column of the instantiation.
- ``cookies.setCookie`` no longer assumes UTC for the expiration date.
- ``strutils.formatEng`` does not distinguish between ``nil`` and ``""``
strings anymore for its ``unit`` parameter. Instead the space is controlled
by a new parameter ``useUnitSpace``.
- The ``times.parse`` and ``times.format`` procs have been rewritten.
The proc signatures are the same so it should generally not break anything.
However, the new implementation is a bit stricter, which is a breaking change.
For example ``parse("2017-01-01 foo", "yyyy-MM-dd")`` will now raise an error.
- ``proc `-`*(a, b: Time): int64`` in the ``times`` module has changed return type
to ``times.Duration`` in order to support higher time resolutions.
The proc is no longer deprecated.
- The ``times.Timezone`` is now an immutable ref-type that must be initialized
with an explicit constructor (``newTimezone``).
- ``posix.Timeval.tv_sec`` has changed type to ``posix.Time``.
- ``math.`mod` `` for floats now behaves the same as ``mod`` for integers
(previously it used floor division like Python). Use ``math.floorMod`` for the old behavior.
- For string inputs, ``unicode.isUpper`` and ``unicode.isLower`` now require a
second mandatory parameter ``skipNonAlpha``.
- For string inputs, ``strutils.isUpperAscii`` and ``strutils.isLowerAscii`` now
require a second mandatory parameter ``skipNonAlpha``.
- ``osLastError`` is now marked with ``sideEffect``
- The procs ``parseHexInt`` and ``parseOctInt`` now fail on empty strings
and strings containing only valid prefixes, e.g. "0x" for hex integers.
- ``terminal.setCursorPos`` and ``terminal.setCursorXPos`` now work correctly
with 0-based coordinates on POSIX (previously, you needed to use
1-based coordinates on POSIX for correct behaviour; the Windows behaviour
was always correct).
- ``lineInfoObj`` now returns absolute path instead of project path.
It's used by ``lineInfo``, ``check``, ``expect``, ``require``, etc.
- ``net.sendTo`` no longer returns an int and now raises an ``OSError``.
- `threadpool`'s `await` and derivatives have been renamed to `blockUntil`
to avoid confusions with `await` from the `async` macro.
#### Breaking changes in the compiler
- The undocumented ``#? braces`` parsing mode was removed.
- The undocumented PHP backend was removed.
- The default location of ``nimcache`` for the native code targets was
changed. Read [the compiler user guide](https://nim-lang.org/docs/nimc.html#generated-c-code-directory)
for more information.
### Library additions
- ``re.split`` now also supports the ``maxsplit`` parameter for consistency
with ``strutils.split``.
- Added ``system.toOpenArray`` in order to support zero-copy slicing
operations. This is currently not yet available for the JavaScript target.
- Added ``getCurrentDir``, ``findExe``, ``cpDir`` and ``mvDir`` procs to
``nimscript``.
- The ``times`` module now supports up to nanosecond time resolution when available.
- Added the type ``times.Duration`` for representing fixed durations of time.
- Added the proc ``times.convert`` for converting between different time units,
e.g days to seconds.
- Added the proc ``algorithm.binarySearch[T, K]`` with the ```cmp``` parameter.
- Added the proc ``algorithm.upperBound``.
- Added inverse hyperbolic functions, ``math.arcsinh``, ``math.arccosh`` and ``math.arctanh`` procs.
- Added cotangent, secant and cosecant procs ``math.cot``, ``math.sec`` and ``math.csc``; and their hyperbolic, inverse and inverse hyperbolic functions, ``math.coth``, ``math.sech``, ``math.csch``, ``math.arccot``, ``math.arcsec``, ``math.arccsc``, ``math.arccoth``, ``math.arcsech`` and ``math.arccsch`` procs.
- Added the procs ``math.floorMod`` and ``math.floorDiv`` for floor based integer division.
- Added the procs ``rationals.`div```, ``rationals.`mod```, ``rationals.floorDiv`` and ``rationals.floorMod`` for rationals.
- Added the proc ``math.prod`` for product of elements in openArray.
- Added the proc ``parseBinInt`` to parse a binary integer from a string, which returns the value.
- ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt``.
- Added the proc ``flush`` for memory mapped files.
- Added the ``MemMapFileStream``.
- Added a simple interpreting event parser template ``eventParser`` to the ``pegs`` module.
- Added ``macros.copyLineInfo`` to copy lineInfo from other node.
- Added ``system.ashr`` an arithmetic right shift for integers.
### Library changes
- ``macros.astGenRepr``, ``macros.lispRepr`` and ``macros.treeRepr``
now escapes the content of string literals consistently.
- ``macros.NimSym`` and ``macros.NimIdent`` is now deprecated in favor
of the more general ``NimNode``.
- ``macros.getImpl`` now includes the pragmas of types, instead of omitting them.
- ``macros.hasCustomPragma`` and ``macros.getCustomPragmaVal`` now
also support ``ref`` and ``ptr`` types, pragmas on types and variant
fields.
- ``system.SomeReal`` is now called ``SomeFloat`` for consistency and
correctness.
- ``algorithm.smartBinarySearch`` and ``algorithm.binarySearch`` is
now joined in ``binarySearch``. ``smartbinarySearch`` is now
deprecated.
- The `terminal` module now exports additional procs for generating ANSI color
codes as strings.
- Added the parameter ``val`` for the ``CritBitTree[int].inc`` proc.
- An exception raised from a ``test`` block of ``unittest`` now shows its type in
error message.
- The ``compiler/nimeval`` API was rewritten to simplify the "compiler as an
API". Using the Nim compiler and its VM as a scripting engine has never been
easier. See ``tests/compilerapi/tcompilerapi.nim`` for an example of how to
use the Nim VM in a native Nim application.
- Added the parameter ``val`` for the ``CritBitTree[T].incl`` proc.
- The proc ``tgamma`` was renamed to ``gamma``. ``tgamma`` is deprecated.
- The ``pegs`` module now exports getters for the fields of its ``Peg`` and ``NonTerminal``
object types. ``Peg``s with child nodes now have the standard ``items`` and ``pairs``
iterators.
- The ``accept`` socket procedure defined in the ``net`` module can now accept
a nil socket.
### Language additions
- Dot calls combined with explicit generic instantiations can now be written
as ``x.y[:z]`` which is transformed into ``y[z](x)`` by the parser.
- ``func`` is now an alias for ``proc {.noSideEffect.}``.
- In order to make ``for`` loops and iterators more flexible to use Nim now
supports so called "for-loop macros". See
the [manual](manual.html#macros-for-loop-macros) for more details.
This feature enables a Python-like generic ``enumerate`` implementation.
- Case statements can now be rewritten via macros. See the [manual](manual.html#macros-case-statement-macros) for more information.
This feature enables custom pattern matchers.
- the `typedesc` special type has been renamed to just `type`.
- `static` and `type` are now also modifiers similar to `ref` and `ptr`.
They denote the special types `static[T]` and `type[T]`.
- Forcing compile-time evaluation with `static` now supports specifying
the desired target type (as a concrete type or as a type class)
- The `type` operator now supports checking that the supplied expression
matches an expected type constraint.
### Language changes
- The `importcpp` pragma now allows importing the listed fields of generic
C++ types. Support for numeric parameters have also been added through
the use of `static[T]` types.
(#6415)
- Native C++ exceptions can now be imported with `importcpp` pragma.
Imported exceptions can be raised and caught just like Nim exceptions.
More details in language manual.
- ``nil`` for strings/seqs is finally gone. Instead the default value for
these is ``"" / @[]``. Use ``--nilseqs:on`` for a transition period.
- Accessing the binary zero terminator in Nim's native strings
is now invalid. Internally a Nim string still has the trailing zero for
zero-copy interoperability with ``cstring``. Compile your code with the
new switch ``--laxStrings:on`` if you need a transition period.
- The command syntax now supports keyword arguments after the first comma.
- Thread-local variables can now be declared inside procs. This implies all
the effects of the ``global`` pragma.
- Nim now supports the ``except`` clause in the export statement.
- Range float types, example ``range[0.0 .. Inf]``. More details in language manual.
- The ``{.this.}`` pragma has been deprecated. It never worked within generics and
we found the resulting code harder to read than the more explicit ``obj.field``
syntax.
- "Memory regions" for pointer types have been deprecated, they were hardly used
anywhere. Note that this has **nothing** to do with the ``--gc:regions`` switch
of managing memory.
- The exception hierarchy was slightly reworked, ``SystemError`` was renamed to
``CatchableError`` and is the new base class for any exception that is guaranteed to
be catchable. This change should have minimal impact on most existing Nim code.
### Tool changes
- ``jsondoc2`` has been renamed ``jsondoc``, similar to how ``doc2`` was renamed
``doc``. The old ``jsondoc`` can still be invoked with ``jsondoc0``.
### Compiler changes
- The VM's instruction count limit was raised to 3 million instructions in
order to support more complex computations at compile-time.
- Support for hot code reloading has been implemented for the JavaScript
target. To use it, compile your code with `--hotCodeReloading:on` and use a
helper library such as LiveReload or BrowserSync.
- A new compiler option `--cppCompileToNamespace` puts the generated C++ code
into the namespace "Nim" in order to avoid naming conflicts with existing
C++ code. This is done for all Nim code - internal and exported.
- Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
machine.
- The ``deadCodeElim`` option is now always turned on and the switch has no
effect anymore, but is recognized for backwards compatibility.
- ``experimental`` is now a pragma / command line switch that can enable specific
language extensions, it is not an all-or-nothing switch anymore.
- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html)
for more info.
- macros.bindSym now capable to accepts not only literal string or string constant expression.
bindSym enhancement make it also can accepts computed string or ident node inside macros /
compile time functions / static blocks. Only in templates / regular code it retains it's old behavior.
This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch.
- On Posix systems the global system wide configuration is now put under ``/etc/nim/nim.cfg``,
it used to be ``/etc/nim.cfg``. Usually it does not exist, however.
- On Posix systems the user configuration is now looked under ``$XDG_CONFIG_HOME/nim/nim.cfg``
(if ``XDG_CONFIG_HOME`` is not defined, then under ``~/.config/nim/nim.cfg``). It used to be
``$XDG_CONFIG_DIR/nim.cfg`` (and ``~/.config/nim.cfg``).
Similarly, on Windows, the user configuration is now looked under ``%APPDATA%/nim/nim.cfg``.
This used to be ``%APPDATA%/nim.cfg``.
### Bugfixes

View File

@@ -0,0 +1,663 @@
## v0.18.0 - 01/03/2018
### Changes affecting backwards compatibility
#### Breaking changes in the standard library
- The ``[]`` proc for strings now raises an ``IndexError`` exception when
the specified slice is out of bounds. See issue
[#6223](https://github.com/nim-lang/Nim/issues/6223) for more details.
You can use ``substr(str, start, finish)`` to get the old behaviour back,
see [this commit](https://github.com/nim-lang/nimbot/commit/98cc031a27ea89947daa7f0bb536bcf86462941f) for an example.
- ``strutils.split`` and ``strutils.rsplit`` with an empty string and a
separator now returns that empty string.
See issue [#4377](https://github.com/nim-lang/Nim/issues/4377).
- Arrays of char cannot be converted to ``cstring`` anymore, pointers to
arrays of char can! This means ``$`` for arrays can finally exist
in ``system.nim`` and do the right thing. This means ``$myArrayOfChar`` changed
its behaviour! Compile with ``-d:nimNoArrayToString`` to see where to fix your
code.
- `reExtended` is no longer default for the `re` constructor in the `re`
module.
- The behavior of ``$`` has been changed for all standard library collections. The
collection-to-string implementations now perform proper quoting and escaping of
strings and chars.
- `newAsyncSocket` taking an `AsyncFD` now runs `setBlocking(false)` on the
fd.
- ``mod`` and bitwise ``and`` do not produce ``range`` subtypes anymore. This
turned out to be more harmful than helpful and the language is simpler
without this special typing rule.
- ``formatFloat``/``formatBiggestFloat`` now support formatting floats with zero
precision digits. The previous ``precision = 0`` behavior (default formatting)
is now available via ``precision = -1``.
- Moved from stdlib into Nimble packages:
- [``basic2d``](https://github.com/nim-lang/basic2d)
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
- [``basic3d``](https://github.com/nim-lang/basic3d)
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
- [``gentabs``](https://github.com/lcrees/gentabs)
- [``libuv``](https://github.com/lcrees/libuv)
- [``numeric``](https://github.com/lcrees/polynumeric)
- [``poly``](https://github.com/lcrees/polynumeric)
- [``pdcurses``](https://github.com/lcrees/pdcurses)
- [``romans``](https://github.com/lcrees/romans)
- [``libsvm``](https://github.com/nim-lang/libsvm_legacy)
- [``joyent_http_parser``](https://github.com/nim-lang/joyent_http_parser)
- Proc [toCountTable](https://nim-lang.org/docs/tables.html#toCountTable,openArray[A])
now produces a `CountTable` with values correspoding to the number of occurrences
of the key in the input. It used to produce a table with all values set to `1`.
Counting occurrences in a sequence used to be:
```nim
let mySeq = @[1, 2, 1, 3, 1, 4]
var myCounter = initCountTable[int]()
for item in mySeq:
myCounter.inc item
```
Now, you can simply do:
```nim
let
mySeq = @[1, 2, 1, 3, 1, 4]
myCounter = mySeq.toCountTable()
```
- If you use ``--dynlibOverride:ssl`` with OpenSSL 1.0.x, you now have to
define ``openssl10`` symbol (``-d:openssl10``). By default OpenSSL 1.1.x is
assumed.
- ``newNativeSocket`` is now named ``createNativeSocket``.
- ``newAsyncNativeSocket`` is now named ``createAsyncNativeSocket``
and it no longer raises an OS error but returns an ``osInvalidSocket`` when
creation fails.
- The ``securehash`` module is now deprecated. Instead import ``std / sha1``.
- The ``readPasswordFromStdin`` proc has been moved from the ``rdstdin``
to the ``terminal`` module, thus it does not depend on linenoise anymore.
#### Breaking changes in the compiler
- ``\n`` is now only the single line feed character like in most
other programming languages. The new platform specific newline escape sequence is
written as ``\p``. This change only affects the Windows platform.
- The overloading rules changed slightly so that constrained generics are
preferred over unconstrained generics. (Bug #6526)
- We changed how array accesses "from backwards" like ``a[^1]`` or ``a[0..^1]`` are
implemented. These are now implemented purely in ``system.nim`` without compiler
support. There is a new "heterogenous" slice type ``system.HSlice`` that takes 2
generic parameters which can be ``BackwardsIndex`` indices. ``BackwardsIndex`` is
produced by ``system.^``.
This means if you overload ``[]`` or ``[]=`` you need to ensure they also work
with ``system.BackwardsIndex`` (if applicable for the accessors).
- The parsing rules of ``if`` expressions were changed so that multiple
statements are allowed in the branches. We found few code examples that
now fail because of this change, but here is one:
```nim
t[ti] = if exp_negative: '-' else: '+'; inc(ti)
```
This now needs to be written as:
```nim
t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
```
- The experimental overloading of the dot ``.`` operators now take
an ``untyped``` parameter as the field name, it used to be
a ``static[string]``. You can use ``when defined(nimNewDot)`` to make
your code work with both old and new Nim versions.
See [special-operators](https://nim-lang.org/docs/manual.html#special-operators)
for more information.
- ``yield`` (or ``await`` which is mapped to ``yield``) never worked reliably
in an array, seq or object constructor and is now prevented at compile-time.
### Library additions
- **Added ``sequtils.mapLiterals`` for easier construction of array and tuple literals.**
- Added ``system.runnableExamples`` to make examples in Nim's documentation easier
to write and test. The examples are tested as the last step of
``nim doc``.
- Implemented ``getIoHandler`` proc in the ``asyncdispatch`` module that allows
you to retrieve the underlying IO Completion Port or ``Selector[AsyncData]``
object in the specified dispatcher.
- For string formatting / interpolation a new module
called [strformat](https://nim-lang.org/docs/strformat.html) has been added
to the stdlib.
- The `ReadyKey` type in the selectors module now contains an ``errorCode``
field to help distinguish between ``Event.Error`` events.
- Implemented an `accept` proc that works on a `SocketHandle` in
``nativesockets``.
- Added ``algorithm.rotateLeft``.
- Added ``typetraits.$`` as an alias for ``typetraits.name``.
- Added ``system.getStackTraceEntries`` that allows you to access the stack
trace in a structured manner without string parsing.
- Added ``parseutils.parseSaturatedNatural``.
- Added ``macros.unpackVarargs``.
- Added support for asynchronous programming for the JavaScript backend using
the `asyncjs` module.
- Added true color support for some terminals. Example:
```nim
import colors, terminal
const Nim = "Efficient and expressive programming."
var
fg = colYellow
bg = colBlue
int = 1.0
enableTrueColors()
for i in 1..15:
styledEcho bgColor, bg, fgColor, fg, Nim, resetStyle
int -= 0.01
fg = intensity(fg, int)
setForegroundColor colRed
setBackgroundColor colGreen
styledEcho "Red on Green.", resetStyle
```
### Library changes
- ``echo`` now works with strings that contain ``\0`` (the binary zero is not
shown) and ``nil`` strings are equal to empty strings.
- JSON: Deprecated `getBVal`, `getFNum`, and `getNum` in favour of
`getBool`, `getFloat`, `getBiggestInt`. A new `getInt` procedure was also
added.
- ``rationals.toRational`` now uses an algorithm based on continued fractions.
This means its results are more precise and it can't run into an infinite loop
anymore.
- ``os.getEnv`` now takes an optional ``default`` parameter that tells ``getEnv``
what to return if the environment variable does not exist.
- The ``random`` procs in ``random.nim`` have all been deprecated. Instead use
the new ``rand`` procs. The module now exports the state of the random
number generator as type ``Rand`` so multiple threads can easily use their
own random number generators that do not require locking. For more information
about this rename see issue [#6934](https://github.com/nim-lang/Nim/issues/6934)
- ``writeStackTrace`` is now proclaimed to have no IO effect (even though it does)
so that it is more useful for debugging purposes.
- ``db_mysql`` module: ``DbConn`` is now a ``distinct`` type that doesn't expose the
details of the underlying ``PMySQL`` type.
- ``parseopt2`` is now deprecated, use ``parseopt`` instead.
### Language additions
- It is now possible to forward declare object types so that mutually
recursive types can be created across module boundaries. See
[package level objects](https://nim-lang.org/docs/manual.html#package-level-objects)
for more information.
- Added support for casting between integers of same bitsize in VM (compile time and nimscript).
This allows to, among other things, reinterpret signed integers as unsigned.
- Custom pragmas are now supported using pragma ``pragma``, please see language
manual for details.
- Standard library modules can now also be imported via the ``std`` pseudo-directory.
This is useful in order to distinguish between standard library and nimble package
imports:
```nim
import std / [strutils, os, osproc]
import someNimblePackage / [strutils, os]
```
### Language changes
- The **unary** ``<`` is now deprecated, for ``.. <`` use ``..<`` for other usages
use the ``pred`` proc.
- Bodies of ``for`` loops now get their own scope:
```nim
# now compiles:
for i in 0..4:
let i = i + 1
echo i
```
- To make Nim even more robust the system iterators ``..`` and ``countup``
now only accept a single generic type ``T``. This means the following code
doesn't die with an "out of range" error anymore:
```nim
var b = 5.Natural
var a = -5
for i in a..b:
echo i
```
- ``atomic`` and ``generic`` are no longer keywords in Nim. ``generic`` used to be
an alias for ``concept``, ``atomic`` was not used for anything.
- The memory manager now uses a variant of the TLSF algorithm that has much
better memory fragmentation behaviour. According
to [http://www.gii.upv.es/tlsf/](http://www.gii.upv.es/tlsf/) the maximum
fragmentation measured is lower than 25%. As a nice bonus ``alloc`` and
``dealloc`` became O(1) operations.
- The compiler is now more consistent in its treatment of ambiguous symbols:
Types that shadow procs and vice versa are marked as ambiguous (bug #6693).
- codegenDecl pragma now works for the JavaScript backend. It returns an empty
string for function return type placeholders.
- Extra semantic checks for procs with noreturn pragma: return type is not allowed,
statements after call to noreturn procs are no longer allowed.
- Noreturn proc calls and raising exceptions branches are now skipped during common type
deduction in ``if`` and ``case`` expressions. The following code snippets now compile:
```nim
import strutils
let str = "Y"
let a = case str:
of "Y": true
of "N": false
else: raise newException(ValueError, "Invalid boolean")
let b = case str:
of nil, "": raise newException(ValueError, "Invalid boolean")
elif str.startsWith("Y"): true
elif str.startsWith("N"): false
else: false
let c = if str == "Y": true
elif str == "N": false
else:
echo "invalid bool"
quit("this is the end")
```
- Pragmas now support call syntax, for example: ``{.exportc"myname".}`` and
``{.exportc("myname").}``
- The ``deprecated`` pragma now supports a user-definable warning message for procs.
```nim
proc bar {.deprecated: "use foo instead".} =
return
bar()
```
### Tool changes
- The ``nim doc`` command is now an alias for ``nim doc2``, the second version of
the documentation generator. The old version 1 can still be accessed
via the new ``nim doc0`` command.
- Nim's ``rst2html`` command now supports the testing of code snippets via an RST
extension that we called ``:test:``::
```rst
.. code-block:: nim
:test:
# shows how the 'if' statement works
if true: echo "yes"
```
### Compiler changes
### Bugfixes
- Fixed "ReraiseError when using try/except within finally block"
([#5871](https://github.com/nim-lang/Nim/issues/5871))
- Fixed "Range type inference leads to counter-intuitive behvaiour"
([#5854](https://github.com/nim-lang/Nim/issues/5854))
- Fixed "JSON % operator can fail in extern procs with dynamic types"
([#6385](https://github.com/nim-lang/Nim/issues/6385))
- Fixed ""intVal is not accessible" in VM"
([#6083](https://github.com/nim-lang/Nim/issues/6083))
- Fixed "Add excl for OrderedSet"
([#2467](https://github.com/nim-lang/Nim/issues/2467))
- Fixed "newSeqOfCap actually doesn't reserve memory"
([#6403](https://github.com/nim-lang/Nim/issues/6403))
- Fixed "[Regression] Nim segfaults"
([#6435](https://github.com/nim-lang/Nim/issues/6435))
- Fixed "Seq assignment is slower than expected"
([#6433](https://github.com/nim-lang/Nim/issues/6433))
- Fixed "json module issues with empty dicts and lists"
([#6438](https://github.com/nim-lang/Nim/issues/6438))
- Fixed "mingw installed via finish.exe fails to link if Nim located in path with whitespace"
([#6452](https://github.com/nim-lang/Nim/issues/6452))
- Fixed "unittest.check does not perform short-circuit evaluation"
([#5784](https://github.com/nim-lang/Nim/issues/5784))
- Fixed "Error while concatenating an array of chars."
([#5861](https://github.com/nim-lang/Nim/issues/5861))
- Fixed "range initialization: [ProveInit] hint: Cannot prove that"
([#6474](https://github.com/nim-lang/Nim/issues/6474))
- Fixed "scanf can call procs with side-effects multiple times"
([#6487](https://github.com/nim-lang/Nim/issues/6487))
- Fixed "gcsafe detection problem"
([#5620](https://github.com/nim-lang/Nim/issues/5620))
- Fixed "C++ codegen: `mitems` generates invalid code."
([#4910](https://github.com/nim-lang/Nim/issues/4910))
- Fixed "strange runtime behavior on macOS"
([#6496](https://github.com/nim-lang/Nim/issues/6496))
- Fixed "stdtmpl: invalid indentation after a line ending in question mark"
([#5070](https://github.com/nim-lang/Nim/issues/5070))
- Fixed "Windows: NAN troubles on c backend"
([#6511](https://github.com/nim-lang/Nim/issues/6511))
- Fixed "lib/nim/system/cellsets.nim(33, 31) Error: type mismatch while attempting to compile for 16bit CPUs"
([#3558](https://github.com/nim-lang/Nim/issues/3558))
- Fixed "Can't compile dynlib with ``-d:useNimRtl`` and ``--threads:on``"
([#5143](https://github.com/nim-lang/Nim/issues/5143))
- Fixed "var s = @[0,1,2,...] can generate thousand of single assignments in C code"
([#5007](https://github.com/nim-lang/Nim/issues/5007))
- Fixed "`echo` discards everything after a null character"
([#1137](https://github.com/nim-lang/Nim/issues/1137))
- Fixed "Turn off reExtended by default"
([#5627](https://github.com/nim-lang/Nim/issues/5627))
- Fixed "Bad Links in docs/backends.html"
([#5914](https://github.com/nim-lang/Nim/issues/5914))
- Fixed "Index out of bounds error in db_postgres when executing non parameter-substituted queries containing "?""
([#6571](https://github.com/nim-lang/Nim/issues/6571))
- Fixed "Please add pipe2 support to posix stdlib"
([#6553](https://github.com/nim-lang/Nim/issues/6553))
- Fixed "Return semantics vary depending on return style"
([#6422](https://github.com/nim-lang/Nim/issues/6422))
- Fixed "parsecsv.open reports SIGSEGV when calling 'open' on missing file"
([#6148](https://github.com/nim-lang/Nim/issues/6148))
- Fixed "VCC: Nim generates non-compilable code for system.nim"
([#6606](https://github.com/nim-lang/Nim/issues/6606))
- Fixed "Generic subtype matches worse than a generic"
([#6526](https://github.com/nim-lang/Nim/issues/6526))
- Fixed "formatFloat inconsistent scientific notation"
([#6589](https://github.com/nim-lang/Nim/issues/6589))
- Fixed "Generated c code calls function twice"
([#6292](https://github.com/nim-lang/Nim/issues/6292))
- Fixed "Range type inference leads to counter-intuitive behvaiour"
([#5854](https://github.com/nim-lang/Nim/issues/5854))
- Fixed "New backward indexing is too limited"
([#6631](https://github.com/nim-lang/Nim/issues/6631))
- Fixed "Table usage in a macro (SIGSEGV: Illegal storage access.)"
([#1860](https://github.com/nim-lang/Nim/issues/1860))
- Fixed "Incorrect deprecation error"
([#6634](https://github.com/nim-lang/Nim/issues/6634))
- Fixed "Wrong indices in arrays not starting with 0"
([#6675](https://github.com/nim-lang/Nim/issues/6675))
- Fixed "if expressions"
([#6609](https://github.com/nim-lang/Nim/issues/6609))
- Fixed "BackwardsIndex: converter + `[]` + unrelated type[^1]: lib/system.nim(3536, 3) Error"
([#6692](https://github.com/nim-lang/Nim/issues/6692))
- Fixed "BackwardsIndex: converter + `[]` + unrelated type[^1]: lib/system.nim(3536, 3) Error"
([#6692](https://github.com/nim-lang/Nim/issues/6692))
- Fixed "js backend 0.17.3: array bounds check for non zero based arrays is buggy"
([#6532](https://github.com/nim-lang/Nim/issues/6532))
- Fixed "HttpClient's new API doesn't work through a proxy for https URLs"
([#6685](https://github.com/nim-lang/Nim/issues/6685))
- Fixed "isServing isn't declared and isn't compiling"
([#6707](https://github.com/nim-lang/Nim/issues/6707))
- Fixed "[Regression] value out of range"
([#6710](https://github.com/nim-lang/Nim/issues/6710))
- Fixed "Error when using `multisync` macro"
([#6708](https://github.com/nim-lang/Nim/issues/6708))
- Fixed "formatFloat inconsistent scientific notation"
([#6589](https://github.com/nim-lang/Nim/issues/6589))
- Fixed "Using : (constructor arguments) for passing values to functions with default arguments causes a compiler crash."
([#6765](https://github.com/nim-lang/Nim/issues/6765))
- Fixed "In-place object initialization leads to vcc incompatible code"
([#6757](https://github.com/nim-lang/Nim/issues/6757))
- Fixed "Improve parseCookies doc"
([#5721](https://github.com/nim-lang/Nim/issues/5721))
- Fixed "Parser regression with nested do notation inside conditional"
([#6166](https://github.com/nim-lang/Nim/issues/6166))
- Fixed "Request for better error message"
([#6776](https://github.com/nim-lang/Nim/issues/6776))
- Fixed "Testament tester does not execute test with `exitcode` only"
([#6775](https://github.com/nim-lang/Nim/issues/6775))
- Fixed "JS integer division off by one"
([#6753](https://github.com/nim-lang/Nim/issues/6753))
- Fixed "Regression: cannot prove not nil"
([#5781](https://github.com/nim-lang/Nim/issues/5781))
- Fixed "SIGSEGV: Illegal storage access. (Attempt to read from nil?) in generic proc"
([#6073](https://github.com/nim-lang/Nim/issues/6073))
- Fixed "Request for better error message"
([#6776](https://github.com/nim-lang/Nim/issues/6776))
- Fixed "Nim #head: sorting via reference hangs compiler"
([#6724](https://github.com/nim-lang/Nim/issues/6724))
- Fixed "Cannot cast pointer to char in cpp"
([#5979](https://github.com/nim-lang/Nim/issues/5979))
- Fixed "asynchttpserver replies with several errors on single request"
([#6386](https://github.com/nim-lang/Nim/issues/6386))
- Fixed "object variants superclass trigger bad codegen"
([#5521](https://github.com/nim-lang/Nim/issues/5521))
- Fixed "JS integer division off by one"
([#6753](https://github.com/nim-lang/Nim/issues/6753))
- Fixed "js backend compiler crash with tables indexed by certain types"
([#6568](https://github.com/nim-lang/Nim/issues/6568))
- Fixed "Jsgen bug with is"
([#6445](https://github.com/nim-lang/Nim/issues/6445))
- Fixed "Subrange definition with ..<"
([#6788](https://github.com/nim-lang/Nim/issues/6788))
- Fixed "fields not initialized: array with enum index type as object field."
([#6682](https://github.com/nim-lang/Nim/issues/6682))
- Fixed "Can not delete data in table when table's data type is kind of "not nil""
([#6555](https://github.com/nim-lang/Nim/issues/6555))
- Fixed "tables.nim: Cannot prove that 'n' is initialized"
([#6121](https://github.com/nim-lang/Nim/issues/6121))
- Fixed "issues with 'not nil' applied to a closure proc"
([#6489](https://github.com/nim-lang/Nim/issues/6489))
- Fixed "`not nil` not working in some cases"
([#4686](https://github.com/nim-lang/Nim/issues/4686))
- Fixed "Cannot prove '@[v]' is not nil"
([#3993](https://github.com/nim-lang/Nim/issues/3993))
- Fixed "Feature: support TCP_NODELAY in net.sockets"
([#6795](https://github.com/nim-lang/Nim/issues/6795))
- Fixed "Code that makes the compiler throw an error message and then hangs"
([#6820](https://github.com/nim-lang/Nim/issues/6820))
- Fixed "Code that makes the compiler throw an error message and then hangs"
([#6820](https://github.com/nim-lang/Nim/issues/6820))
- Fixed "Inconsistent behavior with sequence and string slicing"
([#6223](https://github.com/nim-lang/Nim/issues/6223))
- Fixed "Wrong behavior of "split" (proc and iterator)"
([#4377](https://github.com/nim-lang/Nim/issues/4377))
- Fixed "[Documentation] Invalid module name: [foo, bar]"
([#6831](https://github.com/nim-lang/Nim/issues/6831))
- Fixed "The destructor is not called for temporary objects"
([#4214](https://github.com/nim-lang/Nim/issues/4214))
- Fixed "Destructors does not work with implicit items iterator in for loop"
([#985](https://github.com/nim-lang/Nim/issues/985))
- Fixed "Error in template when using the type of the parameter inside it"
([#6756](https://github.com/nim-lang/Nim/issues/6756))
- Fixed "should json.to() respect parent attributes?"
([#5856](https://github.com/nim-lang/Nim/issues/5856))
- Fixed "json 'to' macro can not marshalize into tuples"
([#6095](https://github.com/nim-lang/Nim/issues/6095))
- Fixed "json.to fails with seq[T]"
([#6604](https://github.com/nim-lang/Nim/issues/6604))
- Fixed "json.to() is not worth using compared to marshal.to[T]"
([#5848](https://github.com/nim-lang/Nim/issues/5848))
- Fixed "Memory not being released in time, running out of memory"
([#6031](https://github.com/nim-lang/Nim/issues/6031))
- Fixed "[Regression] Bad C codegen for generic code"
([#6889](https://github.com/nim-lang/Nim/issues/6889))
- Fixed "rollingFileLogger deletes file on every start."
([#6264](https://github.com/nim-lang/Nim/issues/6264))
- Fixed "Remove/deprecate securehash module."
([#6033](https://github.com/nim-lang/Nim/issues/6033))
- Fixed "[bug or not] object construction for seq[T] failed without space after colon"
([#5999](https://github.com/nim-lang/Nim/issues/5999))
- Fixed "issues with the random module"
([#4726](https://github.com/nim-lang/Nim/issues/4726))
- Fixed "Reassigning local var to seq of objects results in nil element in Object's seq field"
([#668](https://github.com/nim-lang/Nim/issues/668))
- Fixed "Compilation error with "newseq[string]""
([#6726](https://github.com/nim-lang/Nim/issues/6726))
- Fixed "await inside array/dict literal produces invalid code - Part 2"
([#6626](https://github.com/nim-lang/Nim/issues/6626))
- Fixed "terminal.eraseline() gives OverflowError on Windows"
([#6931](https://github.com/nim-lang/Nim/issues/6931))
- Fixed "[Regression] `sequtils.any` conflicts with `system.any`"
([#6932](https://github.com/nim-lang/Nim/issues/6932))
- Fixed "C++ codegen: `mitems` generates invalid code."
([#4910](https://github.com/nim-lang/Nim/issues/4910))
- Fixed "seq.mitems produces invalid cpp codegen"
([#6892](https://github.com/nim-lang/Nim/issues/6892))
- Fixed "Concepts regression"
([#6108](https://github.com/nim-lang/Nim/issues/6108))
- Fixed "Generic iterable concept with array crashes compiler"
([#6277](https://github.com/nim-lang/Nim/issues/6277))
- Fixed "C code generation "a is a pointer; did you mean to use ->?""
([#6462](https://github.com/nim-lang/Nim/issues/6462))
- Fixed "`--NimblePath` fails if a `-` in path which is not followed by a number"
([#6949](https://github.com/nim-lang/Nim/issues/6949))
- Fixed ""not registered in the selector" in asyncfile.close() for something that clearly was registered"
([#6906](https://github.com/nim-lang/Nim/issues/6906))
- Fixed "strange frexp behavior"
([#6353](https://github.com/nim-lang/Nim/issues/6353))
- Fixed "noreturn branches of case statements shouldn't contribute to type"
([#6885](https://github.com/nim-lang/Nim/issues/6885))
- Fixed "Type inference for 'if' statements changed"
([#6980](https://github.com/nim-lang/Nim/issues/6980))
- Fixed "newest asyncdispatch recursion"
([#6100](https://github.com/nim-lang/Nim/issues/6100))
- Fixed "Ambiguous identifier between set type and proc"
([#6965](https://github.com/nim-lang/Nim/issues/6965))
- Fixed "Inconsistent behavior with sequence and string slicing"
([#6223](https://github.com/nim-lang/Nim/issues/6223))
- Fixed "Unsupported OpenSSL library imported dynamically"
([#5000](https://github.com/nim-lang/Nim/issues/5000))
- Fixed "`nim check` segfaults"
([#6972](https://github.com/nim-lang/Nim/issues/6972))
- Fixed "GC deadlock"
([#6988](https://github.com/nim-lang/Nim/issues/6988))
- Fixed "Create a seq without memory initialization"
([#6401](https://github.com/nim-lang/Nim/issues/6401))
- Fixed "Fix bug for getch on Windows while using the arrow keys"
([#6966](https://github.com/nim-lang/Nim/issues/6966))
- Fixed "runnableExamples doesn't work in templates"
([#7018](https://github.com/nim-lang/Nim/issues/7018))
- Fixed "runnableExamples doesn't work with untyped statement blocks"
([#7019](https://github.com/nim-lang/Nim/issues/7019))
- Fixed "Critical bug in parseBiggestFloat"
([#7060](https://github.com/nim-lang/Nim/issues/7060))
- Fixed "[RFC] strformat.% should be gone"
([#7078](https://github.com/nim-lang/Nim/issues/7078))
- Fixed "compiler crash on simple macro"
([#7093](https://github.com/nim-lang/Nim/issues/7093))
- Fixed "Make newlines sane again"
([#7089](https://github.com/nim-lang/Nim/issues/7089))
- Fixed "JS - Unicode enum string representation issue"
([#6741](https://github.com/nim-lang/Nim/issues/6741))
- Fixed "Strange behaviour of 0.17.3 (working ok in 0.17.2)"
([#6989](https://github.com/nim-lang/Nim/issues/6989))
- Fixed "Strange behaviour of 0.17.3 (working ok in 0.17.2)"
([#6989](https://github.com/nim-lang/Nim/issues/6989))
- Fixed "Compiler crash: try expression with infix as"
([#7116](https://github.com/nim-lang/Nim/issues/7116))
- Fixed "nimsuggest crash"
([#7140](https://github.com/nim-lang/Nim/issues/7140))
- Fixed "[RFC] Reintroduce readChar"
([#7072](https://github.com/nim-lang/Nim/issues/7072))
- Fixed "Copyright line needs updating"
([#7129](https://github.com/nim-lang/Nim/issues/7129))
- Fixed "-0.0 doesn't result in negative zero in VM"
([#7079](https://github.com/nim-lang/Nim/issues/7079))
- Fixed "Windows large filesize"
([#7121](https://github.com/nim-lang/Nim/issues/7121))
- Fixed "Securehash is not parsimonious with MD5 and other hash modules"
([#6961](https://github.com/nim-lang/Nim/issues/6961))
- Fixed "os.findExe() shouldn't look in current directory on posix, unless exe has a /"
([#6939](https://github.com/nim-lang/Nim/issues/6939))
- Fixed "`compiles(...)` with `fatal` pragma causes compiler to exit early"
([#7080](https://github.com/nim-lang/Nim/issues/7080))
- Fixed "NPE when compile macro that returns concrete value"
([#5450](https://github.com/nim-lang/Nim/issues/5450))
- Fixed "Using a variable of type `int | float` causes internal compiler error"
([#6946](https://github.com/nim-lang/Nim/issues/6946))
- Fixed "Unsigned integers could not be used as array indexes."
([#7153](https://github.com/nim-lang/Nim/issues/7153))
- Fixed "countdown with uint causes underflow"
([#4220](https://github.com/nim-lang/Nim/issues/4220))
- Fixed "Inconsistent method call syntax"
([#7200](https://github.com/nim-lang/Nim/issues/7200))
- Fixed "Impossible to create an empty const array"
([#6853](https://github.com/nim-lang/Nim/issues/6853))
- Fixed "Strange UINT handling"
([#3985](https://github.com/nim-lang/Nim/issues/3985))
- Fixed "Bad codegen when passing arg that is part of return value destination"
([#6960](https://github.com/nim-lang/Nim/issues/6960))
- Fixed "No info about gcsafety in error message when global var is accessed in async proc"
([#6186](https://github.com/nim-lang/Nim/issues/6186))
- Fixed "Resolving package vs. local import ambiguities"
([#2819](https://github.com/nim-lang/Nim/issues/2819))
- Fixed "Internal error with type() operator"
([#3711](https://github.com/nim-lang/Nim/issues/3711))
- Fixed "newAsyncSocket should raise an OS error plus other inconsistencies"
([#4995](https://github.com/nim-lang/Nim/issues/4995))
- Fixed "mapLiterals fails with negative values"
([#7215](https://github.com/nim-lang/Nim/issues/7215))
- Fixed "fmWrite doesn't truncate file with openAsync, unlike open()"
([#5531](https://github.com/nim-lang/Nim/issues/5531))
- Fixed "Move libsvm to an external nimble module"
([#5786](https://github.com/nim-lang/Nim/issues/5786))
- Fixed "Prevent acceptAddr gotcha with newSocket"
([#7227](https://github.com/nim-lang/Nim/issues/7227))
- Fixed "strtabs.getOrDefault is inconsistent with tables.getOrDefault"
([#4265](https://github.com/nim-lang/Nim/issues/4265))
- Fixed "Code falling through into exception handler when no exception thrown."
([#7232](https://github.com/nim-lang/Nim/issues/7232))
- Fixed "the new generic inference rules are broken"
([#7247](https://github.com/nim-lang/Nim/issues/7247))
- Fixed "Odd `..<` regression"
([#6992](https://github.com/nim-lang/Nim/issues/6992))
- Fixed "Different proc type inferred from default parameter"
([#4659](https://github.com/nim-lang/Nim/issues/4659))
- Fixed "Different proc type inferred from default parameter"
([#4659](https://github.com/nim-lang/Nim/issues/4659))
- Fixed "Testament sometimes ignores test failures"
([#7236](https://github.com/nim-lang/Nim/issues/7236))
- Fixed "New Allocator Fails On >=4GB Requests"
([#7120](https://github.com/nim-lang/Nim/issues/7120))
- Fixed "User pragmas hide effect specifications from sempass2"
([#7216](https://github.com/nim-lang/Nim/issues/7216))
- Fixed "C++: SIGABRT instead of IndexError for out-of-bounds"
([#6512](https://github.com/nim-lang/Nim/issues/6512))
- Fixed "An uncaught exception in cpp mode doesn't show the exception name/msg"
([#6431](https://github.com/nim-lang/Nim/issues/6431))

View File

@@ -0,0 +1,253 @@
## v0.19.X - XX/XX/2018
### Changes affecting backwards compatibility
- The stdlib module ``future`` has been renamed to ``sugar``.
- ``macros.callsite`` is now deprecated. Since the introduction of ``varargs``
parameters this became unnecessary.
- Anonymous tuples with a single element can now be written as ``(1,)`` with a
trailing comma. The underlying AST is ``nnkTupleConstr(newLit 1)`` for this
example. ``nnkTupleConstr`` is a new node kind your macros need to be able
to deal with!
- Indexing into a ``cstring`` for the JS target is now mapped
to ``charCodeAt``.
- Assignments that would "slice" an object into its supertype are now prevented
at runtime. Use ``ref object`` with inheritance rather than ``object`` with
inheritance to prevent this issue.
- The ``not nil`` type annotation now has to be enabled explicitly
via ``{.experimental: "notnil"}`` as we are still not pleased with how this
feature works with Nim's containers.
- The parser now warns about inconsistent spacing around binary operators as
these can easily be confused with unary operators. This warning will likely
become an error in the future.
- The ``'c`` and ``'C'`` suffix for octal literals is now deprecated to
bring the language in line with the standard library (e.g. ``parseOct``).
- The dot style for import paths (e.g ``import path.to.module`` instead of
``import path/to/module``) has been deprecated.
#### Breaking changes in the standard library
- ``re.split`` for empty regular expressions now yields every character in
the string which is what other programming languages chose to do.
- The returned tuple of ``system.instantiationInfo`` now has a third field
containing the column of the instantiation.
- ``cookies.setCookie`` no longer assumes UTC for the expiration date.
- ``strutils.formatEng`` does not distinguish between ``nil`` and ``""``
strings anymore for its ``unit`` parameter. Instead the space is controlled
by a new parameter ``useUnitSpace``.
- The ``times.parse`` and ``times.format`` procs have been rewritten.
The proc signatures are the same so it should generally not break anything.
However, the new implementation is a bit stricter, which is a breaking change.
For example ``parse("2017-01-01 foo", "yyyy-MM-dd")`` will now raise an error.
- ``proc `-`*(a, b: Time): int64`` in the ``times`` module has changed return type
to ``times.Duration`` in order to support higher time resolutions.
The proc is no longer deprecated.
- The ``times.Timezone`` is now an immutable ref-type that must be initialized
with an explicit constructor (``newTimezone``).
- ``posix.Timeval.tv_sec`` has changed type to ``posix.Time``.
- ``math.`mod` `` for floats now behaves the same as ``mod`` for integers
(previously it used floor division like Python). Use ``math.floorMod`` for the old behavior.
- For string inputs, ``unicode.isUpper`` and ``unicode.isLower`` now require a
second mandatory parameter ``skipNonAlpha``.
- For string inputs, ``strutils.isUpperAscii`` and ``strutils.isLowerAscii`` now
require a second mandatory parameter ``skipNonAlpha``.
- ``osLastError`` is now marked with ``sideEffect``
- The procs ``parseHexInt`` and ``parseOctInt`` now fail on empty strings
and strings containing only valid prefixes, e.g. "0x" for hex integers.
- ``terminal.setCursorPos`` and ``terminal.setCursorXPos`` now work correctly
with 0-based coordinates on POSIX (previously, you needed to use
1-based coordinates on POSIX for correct behaviour; the Windows behaviour
was always correct).
- ``lineInfoObj`` now returns absolute path instead of project path.
It's used by ``lineInfo``, ``check``, ``expect``, ``require``, etc.
- ``net.sendTo`` no longer returns an int and now raises an ``OSError``.
- `threadpool`'s `await` and derivatives have been renamed to `blockUntil`
to avoid confusions with `await` from the `async` macro.
#### Breaking changes in the compiler
- The undocumented ``#? braces`` parsing mode was removed.
- The undocumented PHP backend was removed.
- The default location of ``nimcache`` for the native code targets was
changed. Read [the compiler user guide](https://nim-lang.org/docs/nimc.html#generated-c-code-directory)
for more information.
### Library additions
- ``re.split`` now also supports the ``maxsplit`` parameter for consistency
with ``strutils.split``.
- Added ``system.toOpenArray`` in order to support zero-copy slicing
operations. This is currently not yet available for the JavaScript target.
- Added ``getCurrentDir``, ``findExe``, ``cpDir`` and ``mvDir`` procs to
``nimscript``.
- The ``times`` module now supports up to nanosecond time resolution when available.
- Added the type ``times.Duration`` for representing fixed durations of time.
- Added the proc ``times.convert`` for converting between different time units,
e.g days to seconds.
- Added the proc ``algorithm.binarySearch[T, K]`` with the ```cmp``` parameter.
- Added the proc ``algorithm.upperBound``.
- Added inverse hyperbolic functions, ``math.arcsinh``, ``math.arccosh`` and ``math.arctanh`` procs.
- Added cotangent, secant and cosecant procs ``math.cot``, ``math.sec`` and ``math.csc``; and their hyperbolic, inverse and inverse hyperbolic functions, ``math.coth``, ``math.sech``, ``math.csch``, ``math.arccot``, ``math.arcsec``, ``math.arccsc``, ``math.arccoth``, ``math.arcsech`` and ``math.arccsch`` procs.
- Added the procs ``math.floorMod`` and ``math.floorDiv`` for floor based integer division.
- Added the procs ``rationals.`div```, ``rationals.`mod```, ``rationals.floorDiv`` and ``rationals.floorMod`` for rationals.
- Added the proc ``math.prod`` for product of elements in openArray.
- Added the proc ``parseBinInt`` to parse a binary integer from a string, which returns the value.
- ``parseOct`` and ``parseBin`` in parseutils now also support the ``maxLen`` argument similar to ``parseHexInt``.
- Added the proc ``flush`` for memory mapped files.
- Added the ``MemMapFileStream``.
- Added a simple interpreting event parser template ``eventParser`` to the ``pegs`` module.
- Added ``macros.copyLineInfo`` to copy lineInfo from other node.
- Added ``system.ashr`` an arithmetic right shift for integers.
### Library changes
- ``macros.astGenRepr``, ``macros.lispRepr`` and ``macros.treeRepr``
now escapes the content of string literals consistently.
- ``macros.NimSym`` and ``macros.NimIdent`` is now deprecated in favor
of the more general ``NimNode``.
- ``macros.getImpl`` now includes the pragmas of types, instead of omitting them.
- ``macros.hasCustomPragma`` and ``macros.getCustomPragmaVal`` now
also support ``ref`` and ``ptr`` types, pragmas on types and variant
fields.
- ``system.SomeReal`` is now called ``SomeFloat`` for consistency and
correctness.
- ``algorithm.smartBinarySearch`` and ``algorithm.binarySearch`` is
now joined in ``binarySearch``. ``smartbinarySearch`` is now
deprecated.
- The `terminal` module now exports additional procs for generating ANSI color
codes as strings.
- Added the parameter ``val`` for the ``CritBitTree[int].inc`` proc.
- An exception raised from a ``test`` block of ``unittest`` now shows its type in
error message.
- The ``compiler/nimeval`` API was rewritten to simplify the "compiler as an
API". Using the Nim compiler and its VM as a scripting engine has never been
easier. See ``tests/compilerapi/tcompilerapi.nim`` for an example of how to
use the Nim VM in a native Nim application.
- Added the parameter ``val`` for the ``CritBitTree[T].incl`` proc.
- The proc ``tgamma`` was renamed to ``gamma``. ``tgamma`` is deprecated.
- The ``pegs`` module now exports getters for the fields of its ``Peg`` and ``NonTerminal``
object types. ``Peg``s with child nodes now have the standard ``items`` and ``pairs``
iterators.
- The ``accept`` socket procedure defined in the ``net`` module can now accept
a nil socket.
### Language additions
- Dot calls combined with explicit generic instantiations can now be written
as ``x.y[:z]`` which is transformed into ``y[z](x)`` by the parser.
- ``func`` is now an alias for ``proc {.noSideEffect.}``.
- In order to make ``for`` loops and iterators more flexible to use Nim now
supports so called "for-loop macros". See
the [manual](manual.html#macros-for-loop-macros) for more details.
This feature enables a Python-like generic ``enumerate`` implementation.
- Case statements can now be rewritten via macros. See the [manual](manual.html#macros-case-statement-macros) for more information.
This feature enables custom pattern matchers.
- the `typedesc` special type has been renamed to just `type`.
- `static` and `type` are now also modifiers similar to `ref` and `ptr`.
They denote the special types `static[T]` and `type[T]`.
- Forcing compile-time evaluation with `static` now supports specifying
the desired target type (as a concrete type or as a type class)
- The `type` operator now supports checking that the supplied expression
matches an expected type constraint.
### Language changes
- The `importcpp` pragma now allows importing the listed fields of generic
C++ types. Support for numeric parameters have also been added through
the use of `static[T]` types.
(#6415)
- Native C++ exceptions can now be imported with `importcpp` pragma.
Imported exceptions can be raised and caught just like Nim exceptions.
More details in language manual.
- ``nil`` for strings/seqs is finally gone. Instead the default value for
these is ``"" / @[]``. Use ``--nilseqs:on`` for a transition period.
- Accessing the binary zero terminator in Nim's native strings
is now invalid. Internally a Nim string still has the trailing zero for
zero-copy interoperability with ``cstring``. Compile your code with the
new switch ``--laxStrings:on`` if you need a transition period.
- The command syntax now supports keyword arguments after the first comma.
- Thread-local variables can now be declared inside procs. This implies all
the effects of the ``global`` pragma.
- Nim now supports the ``except`` clause in the export statement.
- Range float types, example ``range[0.0 .. Inf]``. More details in language manual.
- The ``{.this.}`` pragma has been deprecated. It never worked within generics and
we found the resulting code harder to read than the more explicit ``obj.field``
syntax.
- "Memory regions" for pointer types have been deprecated, they were hardly used
anywhere. Note that this has **nothing** to do with the ``--gc:regions`` switch
of managing memory.
- The exception hierarchy was slightly reworked, ``SystemError`` was renamed to
``CatchableError`` and is the new base class for any exception that is guaranteed to
be catchable. This change should have minimal impact on most existing Nim code.
### Tool changes
- ``jsondoc2`` has been renamed ``jsondoc``, similar to how ``doc2`` was renamed
``doc``. The old ``jsondoc`` can still be invoked with ``jsondoc0``.
### Compiler changes
- The VM's instruction count limit was raised to 3 million instructions in
order to support more complex computations at compile-time.
- Support for hot code reloading has been implemented for the JavaScript
target. To use it, compile your code with `--hotCodeReloading:on` and use a
helper library such as LiveReload or BrowserSync.
- A new compiler option `--cppCompileToNamespace` puts the generated C++ code
into the namespace "Nim" in order to avoid naming conflicts with existing
C++ code. This is done for all Nim code - internal and exported.
- Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
machine.
- The ``deadCodeElim`` option is now always turned on and the switch has no
effect anymore, but is recognized for backwards compatibility.
- ``experimental`` is now a pragma / command line switch that can enable specific
language extensions, it is not an all-or-nothing switch anymore.
- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html)
for more info.
- macros.bindSym now capable to accepts not only literal string or string constant expression.
bindSym enhancement make it also can accepts computed string or ident node inside macros /
compile time functions / static blocks. Only in templates / regular code it retains it's old behavior.
This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch.
- On Posix systems the global system wide configuration is now put under ``/etc/nim/nim.cfg``,
it used to be ``/etc/nim.cfg``. Usually it does not exist, however.
- On Posix systems the user configuration is now looked under ``$XDG_CONFIG_HOME/nim/nim.cfg``
(if ``XDG_CONFIG_HOME`` is not defined, then under ``~/.config/nim/nim.cfg``). It used to be
``$XDG_CONFIG_DIR/nim.cfg`` (and ``~/.config/nim.cfg``).
Similarly, on Windows, the user configuration is now looked under ``%APPDATA%/nim/nim.cfg``.
This used to be ``%APPDATA%/nim.cfg``.
### Bugfixes

View File

@@ -0,0 +1,27 @@
## v0.XX.0 - XX/XX/2018
### Changes affecting backwards compatibility
- Example item: ``Foo`` changed to ``Bar``.
#### Breaking changes in the standard library
#### Breaking changes in the compiler
### Library additions
### Library changes
### Language additions
### Language changes
### Tool changes
### Compiler changes
### Bugfixes

61
changelogs/readme.md Normal file
View File

@@ -0,0 +1,61 @@
# Update changelog
After each release, call:
```
git mv changelog.md changelogs/changelog_0_19_0.md # use correct version
cp changelogs/changelog_X_XX_X.md changelog.md
git add changelog.md
```
## Recent changelogs are saved here (with their git history)
## Older changelogs are stored in https://github.com/nim-lang/website
## source files:
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2009-12-21-version-086-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2010-03-14-version-088-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2010-10-20-version-0810-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2011-07-10-version-0812-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2012-02-09-version-0814-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2012-09-23-version-090-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2013-05-20-version-092-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2014-04-21-version-094-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2014-10-19-version-096-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2014-12-29-version-0102-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2015-04-30-version-0110-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2015-05-04-version-0112-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2015-10-27-version-0120-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2016-01-18-version-0130-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2016-06-07-version-0140-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2016-06-09-version-0142-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2016-09-30-version-0150-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2016-10-23-version-0152-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2017-01-08-version-0160-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2017-05-17-version-0170-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2017-09-07-version-0172-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2018-03-01-version-0180-released.md
* https://github.com/nim-lang/website/blob/master/jekyll/_posts/2018-09-26-version-0190-released.md
## urls:
* https://nim-lang.org/blog/2009/12/21/version-086-released.html
* https://nim-lang.org/blog/2010/03/14/version-088-released.html
* https://nim-lang.org/blog/2010/10/20/version-0810-released.html
* https://nim-lang.org/blog/2011/07/10/version-0812-released.html
* https://nim-lang.org/blog/2012/02/09/version-0814-released.html
* https://nim-lang.org/blog/2012/09/23/version-090-released.html
* https://nim-lang.org/blog/2013/05/20/version-092-released.html
* https://nim-lang.org/blog/2014/04/21/version-094-released.html
* https://nim-lang.org/blog/2014/10/19/version-096-released.html
* https://nim-lang.org/blog/2014/12/29/version-0102-released.html
* https://nim-lang.org/blog/2015/04/30/version-0110-released.html
* https://nim-lang.org/blog/2015/05/04/version-0112-released.html
* https://nim-lang.org/blog/2015/10/27/version-0120-released.html
* https://nim-lang.org/blog/2016/01/18/version-0130-released.html
* https://nim-lang.org/blog/2016/06/07/version-0140-released.html
* https://nim-lang.org/blog/2016/06/09/version-0142-released.html
* https://nim-lang.org/blog/2016/09/30/version-0150-released.html
* https://nim-lang.org/blog/2016/10/23/version-0152-released.html
* https://nim-lang.org/blog/2017/01/08/version-0160-released.html
* https://nim-lang.org/blog/2017/05/17/version-0170-released.html
* https://nim-lang.org/blog/2017/09/07/version-0172-released.html
* https://nim-lang.org/blog/2018/03/01/version-0180-released.html
* https://nim-lang.org/blog/2018/09/26/version-0190-released.html

View File

@@ -1,4 +1,4 @@
REM - Run the full testsuite; tests\testament\tester all
REM - Run the full testsuite; testament\tester all
REM - Uncomment the list of changes in news.txt
REM - write a news ticker entry

View File

@@ -31,10 +31,18 @@ proc intLiteral(i: BiggestInt): Rope =
result = ~"(IL64(-9223372036854775807) - IL64(1))"
proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
if ty == nil: internalError(p.config, n.info, "genLiteral: ty is nil")
case n.kind
of nkCharLit..nkUInt64Lit:
case skipTypes(ty, abstractVarRange).kind
var k: TTypeKind
if ty != nil:
k = skipTypes(ty, abstractVarRange).kind
else:
case n.kind
of nkCharLit: k = tyChar
of nkUInt64Lit: k = tyUInt64
of nkInt64Lit: k = tyInt64
else: k = tyNil # don't go into the case variant that uses 'ty'
case k
of tyChar, tyNil:
result = intLiteral(n.intVal)
of tyBool:
@@ -46,8 +54,8 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
result = "(($1) $2)" % [getTypeDesc(p.module,
ty), intLiteral(n.intVal)]
of nkNilLit:
let t = skipTypes(ty, abstractVarRange)
if t.kind == tyProc and t.callConv == ccClosure:
let k = if ty == nil: tyPointer else: skipTypes(ty, abstractVarRange).kind
if k == tyProc and skipTypes(ty, abstractVarRange).callConv == ccClosure:
let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels)
result = p.module.tmpBase & rope(id)
if id == p.module.labels:
@@ -59,7 +67,9 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
else:
result = rope("NIM_NIL")
of nkStrLit..nkTripleStrLit:
case skipTypes(ty, abstractVarRange + {tyStatic, tyUserTypeClass, tyUserTypeClassInst}).kind
let k = if ty == nil: tyString
else: skipTypes(ty, abstractVarRange + {tyStatic, tyUserTypeClass, tyUserTypeClassInst}).kind
case k
of tyNil:
result = genNilStringLiteral(p.module, n.info)
of tyString:
@@ -1976,8 +1986,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
frmt = "$1 = $2->len;$n"
lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
putIntoDest(p, d, e, tmp.r)
of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
of mGCref: unaryStmt(p, e, d, "if ($1) { #nimGCref($1); }$n")
of mGCunref: unaryStmt(p, e, d, "if ($1) { #nimGCunref($1); }$n")
of mSetLengthStr: genSetLengthStr(p, e, d)
of mSetLengthSeq: genSetLengthSeq(p, e, d)
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
@@ -2394,15 +2404,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
if ex.kind != nkEmpty:
genLineDir(p, n)
var a: TLoc
if ex.kind in nkCallKinds and (ex[0].kind != nkSym or
ex[0].sym.magic == mNone):
# bug #6037: do not assign to a temp in C++ mode:
incl a.flags, lfSingleUse
genCall(p, ex, a)
if lfSingleUse notin a.flags:
line(p, cpsStmts, a.r & ";\L")
else:
initLocExpr(p, ex, a)
initLocExprSingleUse(p, ex, a)
line(p, cpsStmts, "(void)(" & a.r & ");\L")
of nkAsmStmt: genAsmStmt(p, n)
of nkTryStmt:
if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions:

View File

@@ -307,11 +307,13 @@ proc genSingleVar(p: BProc, a: PNode) =
proc genClosureVar(p: BProc, a: PNode) =
var immediateAsgn = a.sons[2].kind != nkEmpty
var v: TLoc
initLocExpr(p, a.sons[0], v)
genLineDir(p, a)
if immediateAsgn:
var v: TLoc
initLocExpr(p, a.sons[0], v)
genLineDir(p, a)
loadInto(p, a.sons[0], a.sons[2], v)
else:
constructLoc(p, v)
proc genVarStmt(p: BProc, n: PNode) =
for it in n.sons:

View File

@@ -968,9 +968,9 @@ proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
# bugfix: we need to search the type that contains the discriminator:
var objtype = objtype
var objtype = objtype.skipTypes(abstractPtrs)
while lookupInRecord(objtype.n, d.name) == nil:
objtype = objtype.sons[0]
objtype = objtype.sons[0].skipTypes(abstractPtrs)
if objtype.sym == nil:
internalError(m.config, d.info, "anonymous obj with discriminator")
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]

View File

@@ -18,7 +18,7 @@ import
import strutils except `%` # collides with ropes.`%`
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
from lineinfos import
warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile
import dynlib
@@ -567,7 +567,12 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
var p = newProc(nil, m)
p.options = p.options - {optStackTrace, optEndb}
var dest: TLoc
initLocExpr(p, lib.path, dest)
initLoc(dest, locTemp, lib.path, OnStack)
dest.r = getTempName(m)
appcg(m, m.s[cfsDynLibInit],"$1 $2;$n",
[getTypeDesc(m, lib.path.typ), rdLoc(dest)])
expr(p, lib.path, dest)
add(m.s[cfsVars], p.s(cpsLocals))
add(m.s[cfsDynLibInit], p.s(cpsInit))
add(m.s[cfsDynLibInit], p.s(cpsStmts))
@@ -1630,6 +1635,9 @@ proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
# deps are allowed (and the system module is processed in the wrong
# order anyway)
g.config = config
let (outDir, _, _) = splitFile(config.outfile)
if not outDir.isEmpty:
createDir(outDir)
if g.generatedHeader != nil: finishModule(g.generatedHeader)
while g.forwardedProcsCounter > 0:
for m in cgenModules(g):

View File

@@ -13,7 +13,7 @@ import
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
tables, ndi, lineinfos, pathutils
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
type
TLabel* = Rope # for the C generator a label is just a rope
@@ -132,7 +132,7 @@ type
# nimtvDeps is VERY hard to cache because it's
# not a list of IDs nor can it be made to be one.
TCGen = object of TPassContext # represents a C source file
TCGen = object of PPassContext # represents a C source file
s*: TCFileSections # sections of the C file
flags*: set[Codegenflag]
module*: PSym

View File

@@ -462,10 +462,17 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.typ = n.typ
for i in 0 ..< n.len:
if n[i].kind == nkStmtListExpr:
case n[i].kind
of nkExprColonExpr:
if n[i][1].kind == nkStmtListExpr:
let (st, ex) = exprToStmtList(n[i][1])
result.add(st)
n[i][1] = ex
of nkStmtListExpr:
let (st, ex) = exprToStmtList(n[i])
result.add(st)
n[i] = ex
else: discard
result.add(n)
of nkIfStmt, nkIfExpr:
@@ -852,15 +859,8 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
discard
of nkStmtList, nkStmtListExpr:
assert(isEmptyType(n.typ), "nkStmtListExpr not lowered")
result = addGotoOut(result, gotoOut)
for i in 0 ..< n.len:
if n[i].hasYieldsInExpressions:
# Lower nkStmtListExpr nodes inside `n[i]` first
var ns = false
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if n[i].hasYields:
# Create a new split
let go = newNodeI(nkGotoState, n[i].info)
@@ -1009,7 +1009,7 @@ proc stateFromGotoState(n: PNode): int =
assert(n.kind == nkGotoState)
result = n[0].intVal.int
proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
# This transforms 3 patterns:
########################## 1
# yield e
@@ -1051,7 +1051,7 @@ proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(retStmt)
else:
for i in 0 ..< n.len:
n[i] = ctx.tranformStateAssignments(n[i])
n[i] = ctx.transformStateAssignments(n[i])
of nkSkip:
discard
@@ -1071,7 +1071,7 @@ proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
else:
for i in 0 ..< n.len:
n[i] = ctx.tranformStateAssignments(n[i])
n[i] = ctx.transformStateAssignments(n[i])
proc skipStmtList(ctx: Ctx; n: PNode): PNode =
result = n
@@ -1220,18 +1220,20 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
# while true:
# block :stateLoop:
# gotoState :state
# local vars decl (if needed)
# body # Might get wrapped in try-except
let loopBody = newNodeI(nkStmtList, n.info)
result = newTree(nkWhileStmt, newSymNode(ctx.g.getSysSym(n.info, "true")), loopBody)
result.info = n.info
let localVars = newNodeI(nkStmtList, n.info)
if not ctx.stateVarSym.isNil:
let varSect = newNodeI(nkVarSection, n.info)
addVar(varSect, newSymNode(ctx.stateVarSym))
loopBody.add(varSect)
localVars.add(varSect)
if not ctx.tempVars.isNil:
loopBody.add(ctx.tempVars)
localVars.add(ctx.tempVars)
let blockStmt = newNodeI(nkBlockStmt, n.info)
blockStmt.add(newSymNode(ctx.stateLoopLabel))
@@ -1240,7 +1242,7 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
gs.add(ctx.newStateAccess())
gs.add(ctx.g.newIntLit(n.info, ctx.states.len - 1))
var blockBody = newTree(nkStmtList, gs, n)
var blockBody = newTree(nkStmtList, gs, localVars, n)
if ctx.hasExceptions:
blockBody = ctx.wrapIntoTryExcept(blockBody)
@@ -1292,13 +1294,18 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# should folllow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
let n = n.toStmtList
var n = n.toStmtList
discard ctx.newState(n, nil)
let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1))
var ns = false
n = ctx.lowerStmtListExprs(n, ns)
if n.hasYieldsInExpressions():
internalError(ctx.g.config, "yield in expr not lowered")
# Splitting transformation
discard ctx.transformClosureIteratorBody(n, gotoOut)
@@ -1314,7 +1321,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
result.add(s)
result.add(body)
result = ctx.tranformStateAssignments(result)
result = ctx.transformStateAssignments(result)
result = ctx.wrapIntoStateLoop(result)
# echo "TRANSFORM TO STATES: "

View File

@@ -769,6 +769,7 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
# nim filename.nims is the same as "nim e filename.nims":
if p.key.endswith(".nims"):
config.command = "e"
incl(config.globalOptions, optWasNimscript)
config.projectName = unixToNativePath(p.key)
config.arguments = cmdLineRest(p)
result = true

View File

@@ -13,10 +13,10 @@ import
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
pathutils
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
type
TGen = object of TPassContext
TGen = object of PPassContext
module: PSym
config: ConfigRef
graph: ModuleGraph

View File

@@ -40,6 +40,7 @@ type
# already. See bug #3655
destFile*: AbsoluteFile
thisDir*: AbsoluteDir
examples: string
PDoc* = ref TDocumentor ## Alias to type less.
@@ -226,18 +227,30 @@ proc genComment(d: PDoc, n: PNode): string =
toLinenumber(n.info), toColumn(n.info),
dummyHasToc, d.options, d.conf), result)
proc genRecComment(d: PDoc, n: PNode): Rope =
proc genRecCommentAux(d: PDoc, n: PNode): Rope =
if n == nil: return nil
result = genComment(d, n).rope
if result == nil:
if n.kind notin {nkEmpty..nkNilLit, nkEnumTy, nkTupleTy}:
if n.kind in {nkStmtList, nkStmtListExpr, nkTypeDef, nkConstDef,
nkObjectTy, nkRefTy, nkPtrTy, nkAsgn, nkFastAsgn}:
# notin {nkEmpty..nkNilLit, nkEnumTy, nkTupleTy}:
for i in countup(0, len(n)-1):
result = genRecComment(d, n.sons[i])
result = genRecCommentAux(d, n.sons[i])
if result != nil: return
else:
when defined(nimNoNilSeqs): n.comment = ""
else: n.comment = nil
proc genRecComment(d: PDoc, n: PNode): Rope =
if n == nil: return nil
result = genComment(d, n).rope
if result == nil:
if n.kind in {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef,
nkMacroDef, nkTemplateDef, nkConverterDef}:
result = genRecCommentAux(d, n[bodyPos])
else:
result = genRecCommentAux(d, n)
proc getPlainDocstring(n: PNode): string =
## Gets the plain text docstring of a node non destructively.
##
@@ -345,6 +358,14 @@ proc testExample(d: PDoc; ex: PNode) =
"_examples" & $d.exampleCounter & ".nim"))
#let nimcache = outp.changeFileExt"" & "_nimcache"
renderModule(ex, d.filename, outp.string, conf = d.conf)
d.examples.add "import r\"" & outp.string & "\"\n"
proc runAllExamples(d: PDoc) =
if d.examples.len == 0: return
let outputDir = d.conf.getNimcacheDir / RelativeDir"runnableExamples"
let outp = outputDir / RelativeFile(extractFilename(d.filename.changeFileExt"" &
"_examples.nim"))
writeFile(outp, d.examples)
let backend = if isDefined(d.conf, "js"): "js"
elif isDefined(d.conf, "cpp"): "cpp"
elif isDefined(d.conf, "objc"): "objc"
@@ -367,6 +388,9 @@ proc extractImports(n: PNode; result: PNode) =
for i in 0..<n.safeLen: extractImports(n[i], result)
proc prepareExamples(d: PDoc; n: PNode) =
var docComment = newTree(nkCommentStmt)
let loc = d.conf.toFileLineCol(n.info)
docComment.comment = "autogenerated by docgen from " & loc
var runnableExamples = newTree(nkStmtList,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
@@ -413,27 +437,6 @@ proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
getAllRunnableExamplesRec(d, n, n, dest)
when false:
proc findDocComment(n: PNode): PNode =
if n == nil: return nil
if not isNil(n.comment) and startsWith(n.comment, "##"): return n
for i in countup(0, safeLen(n)-1):
result = findDocComment(n.sons[i])
if result != nil: return
proc extractDocComment*(s: PSym, d: PDoc): string =
let n = findDocComment(s.ast)
result = ""
if not n.isNil:
if not d.isNil:
var dummyHasToc: bool
renderRstToOut(d[], parseRst(n.comment, toFilename(d.conf, n.info),
toLinenumber(n.info), toColumn(n.info),
dummyHasToc, d.options + {roSkipPounds}),
result)
else:
result = n.comment.substr(2).replace("\n##", "\n").strip
proc isVisible(d: PDoc; n: PNode): bool =
result = false
if n.kind == nkPostfix:
@@ -723,7 +726,6 @@ proc exportSym(d: PDoc; s: PSym) =
rope changeFileExt(external, "html")])
proc generateDoc*(d: PDoc, n, orig: PNode) =
if orig.info.fileIndex != n.info.fileIndex: return
case n.kind
of nkCommentStmt: add(d.modDesc, genComment(d, n))
of nkProcDef:
@@ -771,13 +773,13 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
proc add(d: PDoc; j: JsonNode) =
if j != nil: d.jArray.add j
proc generateJson*(d: PDoc, n: PNode) =
proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
case n.kind
of nkCommentStmt:
if startsWith(n.comment, "##"):
let stripped = n.comment.substr(2).strip
d.add %{ "comment": %stripped, "line": %n.info.line.int,
"col": %n.info.col }
if includeComments:
d.add %*{"comment": genComment(d, n)}
else:
add(d.modDesc, genComment(d, n))
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skProc)
@@ -805,11 +807,11 @@ proc generateJson*(d: PDoc, n: PNode) =
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in countup(0, sonsLen(n) - 1):
generateJson(d, n.sons[i])
generateJson(d, n.sons[i], includeComments)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateJson(d, lastSon(n.sons[0]))
generateJson(d, lastSon(n.sons[0]), includeComments)
else: discard
proc genTagsItem(d: PDoc, n, nameNode: PNode, k: TSymKind): string =
@@ -891,7 +893,7 @@ proc genOutFile(d: PDoc): Rope =
setIndexTerm(d[], external, "", title)
else:
# Modules get an automatic title for the HTML, but no entry in the index.
title = "Module " & extractFilename(changeFileExt(d.filename, ""))
title = extractFilename(changeFileExt(d.filename, ""))
let bodyname = if d.hasToc and not d.isPureRst: "doc.body_toc_group"
elif d.hasToc: "doc.body_toc"
@@ -923,6 +925,7 @@ proc generateIndex*(d: PDoc) =
writeIndexFile(d[], dest.string)
proc writeOutput*(d: PDoc, useWarning = false) =
runAllExamples(d)
var content = genOutFile(d)
if optStdout in d.conf.globalOptions:
writeRope(stdout, content)
@@ -935,8 +938,13 @@ proc writeOutput*(d: PDoc, useWarning = false) =
outfile.string)
proc writeOutputJson*(d: PDoc, useWarning = false) =
runAllExamples(d)
var modDesc: string
for desc in d.modDesc:
modDesc &= desc
let content = %*{"orig": d.filename,
"nimble": getPackageName(d.conf, d.filename),
"moduleDescription": modDesc,
"entries": d.jArray}
if optStdout in d.conf.globalOptions:
write(stdout, $content)
@@ -946,7 +954,9 @@ proc writeOutputJson*(d: PDoc, useWarning = false) =
write(f, $content)
close(f)
else:
discard "fixme: error report"
localError(d.conf, newLineInfo(d.conf, AbsoluteFile d.filename, -1, -1),
warnUser, "unable to open file \"" & d.destFile.string &
"\" for writing")
proc commandDoc*(cache: IdentCache, conf: ConfigRef) =
var ast = parseFile(conf.projectMainIdx, cache, conf)

View File

@@ -14,10 +14,10 @@ import
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
pathutils
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
type
TGen = object of TPassContext
TGen = object of PPassContext
doc: PDoc
module: PSym
PGen = ref TGen
@@ -55,20 +55,26 @@ proc processNodeJson(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
if shouldProcess(g):
generateJson(g.doc, n)
generateJson(g.doc, n, false)
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
template myOpenImpl(ext: untyped) {.dirty.} =
var g: PGen
new(g)
g.module = module
var d = newDocumentor(AbsoluteFile toFullPath(graph.config, FileIndex module.position),
graph.cache, graph.config)
graph.cache, graph.config, ext)
d.hasToc = true
g.doc = d
result = g
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
myOpenImpl(HtmlExt)
proc myOpenJson(graph: ModuleGraph; module: PSym): PPassContext =
myOpenImpl(JsonExt)
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
const docgen2JsonPass* = makePass(open = myOpen, process = processNodeJson,
const docgen2JsonPass* = makePass(open = myOpenJson, process = processNodeJson,
close = closeJson)
proc finishDoc2Pass*(project: string) =

View File

@@ -17,6 +17,7 @@ type
TemplCtx = object
owner, genSymOwner: PSym
instLines: bool # use the instantiation lines numbers
isDeclarative: bool
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
# new symbol
config: ConfigRef
@@ -54,11 +55,30 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
result.add copyNode(c, templ, actual)
of nkNone..nkIdent, nkType..nkNilLit: # atom
result.add copyNode(c, templ, actual)
of nkCommentStmt:
# for the documentation generator we don't keep documentation comments
# in the AST that would confuse it (bug #9432), but only if we are not in a
# "declarative" context (bug #9235).
if c.isDeclarative:
var res = copyNode(c, templ, actual)
for i in countup(0, sonsLen(templ) - 1):
evalTemplateAux(templ.sons[i], actual, c, res)
result.add res
else:
result.add newNodeI(nkEmpty, templ.info)
else:
var isDeclarative = false
if templ.kind in {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef,
nkMacroDef, nkTemplateDef, nkConverterDef, nkTypeSection,
nkVarSection, nkLetSection, nkConstSection} and
not c.isDeclarative:
c.isDeclarative = true
isDeclarative = true
var res = copyNode(c, templ, actual)
for i in countup(0, sonsLen(templ) - 1):
evalTemplateAux(templ.sons[i], actual, c, res)
result.add res
if isDeclarative: c.isDeclarative = false
const
errWrongNumberOfArguments = "wrong number of arguments"

View File

@@ -24,11 +24,11 @@ proc readOutput(p: Process): (string, int) =
proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (string, int) =
let workingDir = parentDir(toFullPath(conf, info))
if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
if cache.len > 0:
let h = secureHash(cmd & "\t" & input & "\t" & cache)
let filename = toGeneratedFile(conf, AbsoluteFile("gorge_" & $h), "txt").string
var f: File
if open(f, filename):
if optForceFullMake notin conf.globalOptions and open(f, filename):
result = (f.readAll, 0)
f.close
return

View File

@@ -69,6 +69,7 @@ Files: "doc"
Files: "doc/html"
Files: "tools"
Files: "nimpretty"
Files: "testament"
Files: "nimsuggest"
Files: "nimsuggest/tests/*.nim"
Files: "web/website.ini"

View File

@@ -34,10 +34,10 @@ import
times, ropes, math, passes, ccgutils, wordrecg, renderer,
intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
type
TJSGen = object of TPassContext
TJSGen = object of PPassContext
module: PSym
graph: ModuleGraph
config: ConfigRef
@@ -2282,6 +2282,9 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
else: AbsoluteFile(getCurrentDir() / m.config.outFile.string)
else:
changeFileExt(completeCFilePath(m.config, AbsoluteFile f), ext)
let (outDir, _, _) = splitFile(outfile)
if not outDir.isEmpty:
createDir(outDir)
discard writeRopeIfNotEqual(genHeader() & code, outfile)
for obj, content in items(globals.classes):
genClass(m.config, obj, content, ext)

View File

@@ -277,8 +277,9 @@ proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
let s = n.sym
if illegalCapture(s):
localError(g.config, n.info, "illegal capture '$1' of type <$2> which is declared here: $3" %
[s.name.s, typeToString(s.typ), g.config$s.info])
localError(g.config, n.info,
("'$1' is of type <$2> which cannot be captured as it would violate memory" &
" safety, declared here: $3") % [s.name.s, typeToString(s.typ), g.config$s.info])
elif owner.typ.callConv notin {ccClosure, ccDefault}:
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
[s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]])

View File

@@ -28,10 +28,10 @@ type
config: ConfigRef
fid: FileIndex
lastTok: TTokType
inquote: bool
inquote, lastTokWasTerse: bool
semicolons: SemicolonKind
col, lastLineNumber, lineSpan, indentLevel, indWidth: int
nested: int
col, lastLineNumber, lineSpan, indentLevel, indWidth*: int
keepIndents*: int
doIndentMore*: int
content: string
indentStack: seq[int]
@@ -41,9 +41,10 @@ type
proc openEmitter*(em: var Emitter, cache: IdentCache;
config: ConfigRef, fileIdx: FileIndex) =
let fullPath = Absolutefile config.toFullPath(fileIdx)
em.indWidth = getIndentWidth(fileIdx, llStreamOpen(fullPath, fmRead),
cache, config)
if em.indWidth == 0: em.indWidth = 2
if em.indWidth == 0:
em.indWidth = getIndentWidth(fileIdx, llStreamOpen(fullPath, fmRead),
cache, config)
if em.indWidth == 0: em.indWidth = 2
em.config = config
em.fid = fileIdx
em.lastTok = tkInvalid
@@ -52,11 +53,16 @@ proc openEmitter*(em: var Emitter, cache: IdentCache;
em.content = newStringOfCap(16_000)
em.indentStack = newSeqOfCap[int](30)
em.indentStack.add 0
em.lastLineNumber = 1
proc closeEmitter*(em: var Emitter) =
if fileExists(em.config.outFile) and readFile(em.config.outFile.string) == em.content:
discard "do nothing, see #9499"
return
var f = llStreamOpen(em.config.outFile, fmWrite)
if f == nil:
rawMessage(em.config, errGenerated, "cannot open file: " & em.config.outFile.string)
return
f.llStreamWrite em.content
llStreamClose(f)
@@ -106,15 +112,16 @@ proc softLinebreak(em: var Emitter, lit: string) =
for i in 1..em.indentLevel+moreIndent(em): wr(" ")
else:
# search backwards for a good split position:
for a in em.altSplitPos:
for a in mitems(em.altSplitPos):
if a > em.fixedUntil:
var spaces = 0
while a+spaces < em.content.len and em.content[a+spaces] == ' ':
inc spaces
if spaces > 0: delete(em.content, a, a+spaces-1)
let ws = "\L" & repeat(' ',em.indentLevel+moreIndent(em))
em.col = em.content.len - a
let ws = "\L" & repeat(' ', em.indentLevel+moreIndent(em))
em.content.insert(ws, a)
a = -1
break
proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
@@ -134,6 +141,22 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
for i in 1 .. LineCommentColumn - em.col: wr(" ")
wr lit
if tok.tokType == tkComment and tok.literal.startsWith("#!nimpretty"):
case tok.literal
of "#!nimpretty off":
inc em.keepIndents
wr("\L")
em.lastLineNumber = tok.line + 1
of "#!nimpretty on":
dec em.keepIndents
em.lastLineNumber = tok.line
wr("\L")
#for i in 1 .. tok.indent: wr " "
wr tok.literal
em.col = 0
em.lineSpan = 0
return
var preventComment = false
if tok.tokType == tkComment and tok.line == em.lastLineNumber and tok.indent >= 0:
# we have an inline comment so handle it before the indentation token:
@@ -142,7 +165,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
em.fixedUntil = em.content.high
elif tok.indent >= 0:
if em.lastTok in (splitters + oprSet):
if em.lastTok in (splitters + oprSet) or em.keepIndents > 0:
em.indentLevel = tok.indent
else:
if tok.indent > em.indentStack[^1]:
@@ -171,12 +194,13 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wr(" ")
em.fixedUntil = em.content.high
var lastTokWasTerse = false
case tok.tokType
of tokKeywordLow..tokKeywordHigh:
if endsInAlpha(em):
wr(" ")
elif not em.inquote and not endsInWhite(em) and
em.lastTok notin openPars:
em.lastTok notin openPars and not em.lastTokWasTerse:
#and tok.tokType in oprSet
wr(" ")
@@ -212,14 +236,19 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
tkBracketDotRi,
tkCurlyDotRi,
tkParDotRi,
tkColonColon, tkDot:
tkColonColon:
wr(TokTypeToStr[tok.tokType])
of tkDot:
lastTokWasTerse = true
wr(TokTypeToStr[tok.tokType])
of tkEquals:
if not em.inquote and not em.endsInWhite: wr(" ")
wr(TokTypeToStr[tok.tokType])
if not em.inquote: wr(" ")
of tkOpr, tkDotDot:
if tok.strongSpaceA == 0 and tok.strongSpaceB == 0:
if (tok.strongSpaceA == 0 and tok.strongSpaceB == 0) or em.inquote:
# bug #9504: remember to not spacify a keyword:
lastTokWasTerse = true
# if not surrounded by whitespace, don't produce any whitespace either:
wr(tok.ident.s)
else:
@@ -229,8 +258,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
tok.strongSpaceB == 0 and tok.strongSpaceA > 0
if not isUnary(tok):
wr(" ")
rememberSplit(splitBinary)
wr(" ")
of tkAccent:
if not em.inquote and endsInAlpha(em): wr(" ")
wr(TokTypeToStr[tok.tokType])
@@ -253,6 +282,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wr lit
em.lastTok = tok.tokType
em.lastTokWasTerse = lastTokWasTerse
em.lastLineNumber = tok.line + em.lineSpan
em.lineSpan = 0

View File

@@ -224,7 +224,7 @@ proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache; config: ConfigRef) =
openBaseLexer(lex, inputstream)
lex.fileIdx = fileidx
lex.indentAhead = - 1
lex.indentAhead = -1
lex.currLineIndent = 0
inc(lex.lineNumber, inputstream.lineOffset)
lex.cache = cache
@@ -740,11 +740,17 @@ proc handleCRLF(L: var TLexer, pos: int): int =
result = nimlexbase.handleLF(L, pos)
else: result = pos
proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
type
StringMode = enum
normal,
raw,
generalized
proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
var pos = L.bufpos
var buf = L.buf # put `buf` in a register
var line = L.lineNumber # save linenumber for better error message
tokenBegin(tok, pos)
tokenBegin(tok, pos - ord(mode == raw))
inc pos # skip "
if buf[pos] == '\"' and buf[pos+1] == '\"':
tok.tokType = tkTripleStrLit # long string literal:
@@ -784,12 +790,12 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
inc(pos)
else:
# ordinary string literal
if rawMode: tok.tokType = tkRStrLit
if mode != normal: tok.tokType = tkRStrLit
else: tok.tokType = tkStrLit
while true:
var c = buf[pos]
if c == '\"':
if rawMode and buf[pos+1] == '\"':
if mode != normal and buf[pos+1] == '\"':
inc(pos, 2)
add(tok.literal, '"')
else:
@@ -800,7 +806,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) =
tokenEndIgnore(tok, pos)
lexMessage(L, errGenerated, "closing \" expected")
break
elif (c == '\\') and not rawMode:
elif (c == '\\') and mode == normal:
L.bufpos = pos
getEscapedChar(L, tok)
pos = L.bufpos
@@ -1064,8 +1070,10 @@ proc skip(L: var TLexer, tok: var TToken) =
tok.strongSpaceA = 0
when defined(nimpretty):
var hasComment = false
var commentIndent = L.currLineIndent
tok.commentOffsetA = L.offsetBase + pos
tok.commentOffsetB = tok.commentOffsetA
tok.line = -1
while true:
case buf[pos]
of ' ':
@@ -1076,9 +1084,6 @@ proc skip(L: var TLexer, tok: var TToken) =
inc(pos)
of CR, LF:
tokenEndPrevious(tok, pos)
when defined(nimpretty):
# we are not yet in a comment, so update the comment token's line information:
if not hasComment: inc tok.line
pos = handleCRLF(L, pos)
buf = L.buf
var indent = 0
@@ -1087,13 +1092,19 @@ proc skip(L: var TLexer, tok: var TToken) =
inc(pos)
inc(indent)
elif buf[pos] == '#' and buf[pos+1] == '[':
when defined(nimpretty): hasComment = true
when defined(nimpretty):
hasComment = true
if tok.line < 0:
tok.line = L.lineNumber
commentIndent = indent
skipMultiLineComment(L, tok, pos+2, false)
pos = L.bufpos
buf = L.buf
else:
break
tok.strongSpaceA = 0
when defined(nimpretty):
if buf[pos] == '#' and tok.line < 0: commentIndent = indent
if buf[pos] > ' ' and (buf[pos] != '#' or buf[pos+1] == '#'):
tok.indent = indent
L.currLineIndent = indent
@@ -1101,14 +1112,20 @@ proc skip(L: var TLexer, tok: var TToken) =
of '#':
# do not skip documentation comment:
if buf[pos+1] == '#': break
when defined(nimpretty): hasComment = true
when defined(nimpretty):
hasComment = true
if tok.line < 0:
tok.line = L.lineNumber
if buf[pos+1] == '[':
skipMultiLineComment(L, tok, pos+2, false)
pos = L.bufpos
buf = L.buf
else:
tokenBegin(tok, pos)
while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}: inc(pos)
while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
when defined(nimpretty): tok.literal.add buf[pos]
inc(pos)
tokenEndIgnore(tok, pos+1)
when defined(nimpretty):
tok.commentOffsetB = L.offsetBase + pos + 1
@@ -1120,6 +1137,7 @@ proc skip(L: var TLexer, tok: var TToken) =
if hasComment:
tok.commentOffsetB = L.offsetBase + pos - 1
tok.tokType = tkComment
tok.indent = commentIndent
if gIndentationWidth <= 0:
gIndentationWidth = tok.indent
@@ -1168,7 +1186,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
of 'r', 'R':
if L.buf[L.bufpos + 1] == '\"':
inc(L.bufpos)
getString(L, tok, true)
getString(L, tok, raw)
else:
getSymbol(L, tok)
of '(':
@@ -1246,9 +1264,9 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
lexMessage(L, errGenerated, "invalid token: " & c & " (\\" & $(ord(c)) & ')')
of '\"':
# check for generalized raw string literal:
var rawMode = L.bufpos > 0 and L.buf[L.bufpos-1] in SymChars
getString(L, tok, rawMode)
if rawMode:
let mode = if L.bufpos > 0 and L.buf[L.bufpos-1] in SymChars: generalized else: normal
getString(L, tok, mode)
if mode == generalized:
# tkRStrLit -> tkGStrLit
# tkTripleStrLit -> tkGTripleStrLit
inc(tok.tokType, 2)

View File

@@ -41,7 +41,7 @@ type
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintName, hintPattern,
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
hintExecuting, hintLinking, hintDependency,
hintSource, hintPerformance, hintStackTrace, hintGCStats,
hintGlobalVar,
@@ -107,6 +107,7 @@ const
hintConf: "used config file '$1'",
hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'",
hintConditionAlwaysFalse: "condition is always false: '$1'",
hintName: "name should be: '$1'",
hintPattern: "$1",
hintExecuting: "$1",
@@ -140,7 +141,7 @@ const
"Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar",
"User", "UserRaw", "ExtendedContext",
]

View File

@@ -265,6 +265,7 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdInteractive
commandInteractive(graph)
of "e":
incl conf.globalOptions, optWasNimscript
commandEval(graph, mainCommandArg(conf))
of "nop", "help":
# prevent the "success" message:

View File

@@ -62,6 +62,19 @@ type
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
cacheCounters*: Table[string, BiggestInt]
cacheTables*: Table[string, BTree[string, PNode]]
passes*: seq[TPass]
TPassContext* = object of RootObj # the pass's context
PPassContext* = ref TPassContext
TPassOpen* = proc (graph: ModuleGraph; module: PSym): PPassContext {.nimcall.}
TPassClose* = proc (graph: ModuleGraph; p: PPassContext, n: PNode): PNode {.nimcall.}
TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}
TPass* = tuple[open: TPassOpen,
process: TPassProcess,
close: TPassClose,
isFrontend: bool]
proc hash*(x: FileIndex): Hash {.borrow.}

View File

@@ -190,10 +190,13 @@ template toFullPath*(conf: ConfigRef; info: TLineInfo): string =
proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
if info.fileIndex.int32 < 0:
result = "???"
elif optListFullPaths in conf.globalOptions:
result = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
return
let absPath = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
if optListFullPaths in conf.globalOptions:
result = absPath
else:
result = conf.m.fileInfos[info.fileIndex.int32].projPath.string
let relPath = conf.m.fileInfos[info.fileIndex.int32].projPath.string
result = if relPath.count("..") > 2: absPath else: relPath
proc toLinenumber*(info: TLineInfo): int {.inline.} =
result = int info.line
@@ -414,7 +417,7 @@ proc addSourceLine(conf: ConfigRef; fileIdx: FileIndex, line: string) =
proc sourceLine*(conf: ConfigRef; i: TLineInfo): string =
if i.fileIndex.int32 < 0: return ""
if not optPreserveOrigSource(conf) and conf.m.fileInfos[i.fileIndex.int32].lines.len == 0:
if conf.m.fileInfos[i.fileIndex.int32].lines.len == 0:
try:
for line in lines(toFullPath(conf, i)):
addSourceLine conf, i.fileIndex, line.string

View File

@@ -54,7 +54,8 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
of cmdArgument:
if processArgument(pass, p, argsCount, config): break
if pass == passCmd2:
if optRun notin config.globalOptions and config.arguments.len > 0 and config.command.normalize != "run":
if {optRun, optWasNimscript} * config.globalOptions == {} and
config.arguments.len > 0 and config.command.normalize notin ["run", "e"]:
rawMessage(config, errGenerated, errArgsNeedRunOption)
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =

View File

@@ -45,7 +45,7 @@ type # please make sure we have under 32 options
TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible**
gloptNone, optForceFullMake,
optDeadCodeElimUnused, # deprecated, always on
optWasNimscript,
optListCmd, optCompileOnly, optNoLinking,
optCDebug, # turn on debugging information
optGenDynLib, # generate a dynamic library

View File

@@ -46,7 +46,7 @@ type
inSemiStmtList*: int
emptyNode: PNode
when defined(nimpretty2):
em: Emitter
em*: Emitter
SymbolMode = enum
smNormal, smAllowNil, smAfterDot
@@ -286,7 +286,7 @@ proc checkBinary(p: TParser) {.inline.} =
#|
#| prefixOperator = operator
#|
#| optInd = COMMENT?
#| optInd = COMMENT? IND?
#| optPar = (IND{>} | IND{=})?
#|
#| simpleExpr = arrowExpr (OP0 optInd arrowExpr)* pragma?
@@ -1037,6 +1037,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
addSon(result, p.emptyNode) # return type
when defined(nimpretty2):
inc p.em.doIndentMore
inc p.em.keepIndents
let hasParLe = p.tok.tokType == tkParLe and p.tok.indent < 0
if hasParLe:
getTok(p)
@@ -1073,6 +1074,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
result = p.emptyNode
when defined(nimpretty2):
dec p.em.doIndentMore
dec p.em.keepIndents
proc optPragmas(p: var TParser): PNode =
if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)):
@@ -1578,7 +1580,6 @@ proc parseTry(p: var TParser; isExpr: bool): PNode =
colcom(p, b)
addSon(b, parseStmt(p))
addSon(result, b)
if b.kind == nkFinally: break
if b == nil: parMessage(p, "expected 'except'")
proc parseExceptBlock(p: var TParser, kind: TNodeKind): PNode =

View File

@@ -12,10 +12,10 @@
import
strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
type
VerboseRef = ref object of TPassContext
VerboseRef = ref object of PPassContext
config: ConfigRef
proc verboseOpen(graph: ModuleGraph; s: PSym): PPassContext =

View File

@@ -16,21 +16,8 @@ import
nimsets, syntaxes, times, idgen, modulegraphs, reorder, rod,
lineinfos, pathutils
type
TPassContext* = object of RootObj # the pass's context
PPassContext* = ref TPassContext
TPassOpen* = proc (graph: ModuleGraph; module: PSym): PPassContext {.nimcall.}
TPassClose* = proc (graph: ModuleGraph; p: PPassContext, n: PNode): PNode {.nimcall.}
TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}
TPass* = tuple[open: TPassOpen, process: TPassProcess, close: TPassClose,
isFrontend: bool]
TPassData* = tuple[input: PNode, closeOutput: PNode]
TPasses* = openArray[TPass]
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
# nodes. These are passed to the other close procedures.
@@ -57,16 +44,12 @@ const
type
TPassContextArray = array[0..maxPasses - 1, PPassContext]
var
gPasses: array[0..maxPasses - 1, TPass]
gPassesLen*: int
proc clearPasses*(g: ModuleGraph) =
gPassesLen = 0
g.passes.setLen(0)
proc registerPass*(g: ModuleGraph; p: TPass) =
gPasses[gPassesLen] = p
inc(gPassesLen)
internalAssert g.config, g.passes.len < maxPasses
g.passes.add(p)
proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
m: TPassData): TPassData =
@@ -76,7 +59,7 @@ proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
else: m.closeOutput
proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
passes: TPasses) =
passes: openArray[TPass]) =
var passdata: TPassData
passdata.input = nodes
for pass in passes:
@@ -84,23 +67,23 @@ proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
proc openPasses(g: ModuleGraph; a: var TPassContextArray;
module: PSym) =
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].open):
a[i] = gPasses[i].open(g, module)
for i in countup(0, g.passes.len - 1):
if not isNil(g.passes[i].open):
a[i] = g.passes[i].open(g, module)
else: a[i] = nil
proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
var m: PNode = nil
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].close): m = gPasses[i].close(graph, a[i], m)
for i in countup(0, graph.passes.len - 1):
if not isNil(graph.passes[i].close): m = graph.passes[i].close(graph, a[i], m)
a[i] = nil # free the memory here
proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool =
proc processTopLevelStmt(graph: ModuleGraph, n: PNode, a: var TPassContextArray): bool =
# this implements the code transformation pipeline
var m = n
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].process):
m = gPasses[i].process(a[i], m)
for i in countup(0, graph.passes.len - 1):
if not isNil(graph.passes[i].process):
m = graph.passes[i].process(a[i], m)
if isNil(m): return false
result = true
@@ -111,19 +94,19 @@ proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
else:
result = fileInfoIdx(conf, fullPath)
proc processImplicits(conf: ConfigRef; implicits: seq[string], nodeKind: TNodeKind,
proc processImplicits(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
a: var TPassContextArray; m: PSym) =
# XXX fixme this should actually be relative to the config file!
let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
let relativeTo = toFullPath(conf, m.info)
let relativeTo = toFullPath(graph.config, m.info)
for module in items(implicits):
# implicit imports should not lead to a module importing itself
if m.position != resolveMod(conf, module, relativeTo).int32:
if m.position != resolveMod(graph.config, module, relativeTo).int32:
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
var str = newStrNode(nkStrLit, module)
str.info = gCmdLineInfo
importStmt.addSon str
if not processTopLevelStmt(importStmt, a): break
if not processTopLevelStmt(graph, importStmt, a): break
const
imperativeCode = {low(TNodeKind)..high(TNodeKind)} - {nkTemplateDef, nkProcDef, nkMethodDef,
@@ -139,25 +122,25 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
fileIdx = module.fileIdx
if module.id < 0:
# new module caching mechanism:
for i in 0..<gPassesLen:
if not isNil(gPasses[i].open) and not gPasses[i].isFrontend:
a[i] = gPasses[i].open(graph, module)
for i in 0 ..< graph.passes.len:
if not isNil(graph.passes[i].open) and not graph.passes[i].isFrontend:
a[i] = graph.passes[i].open(graph, module)
else:
a[i] = nil
if not graph.stopCompile():
let n = loadNode(graph, module)
var m = n
for i in 0..<gPassesLen:
if not isNil(gPasses[i].process) and not gPasses[i].isFrontend:
m = gPasses[i].process(a[i], m)
for i in 0 ..< graph.passes.len:
if not isNil(graph.passes[i].process) and not graph.passes[i].isFrontend:
m = graph.passes[i].process(a[i], m)
if isNil(m):
break
var m: PNode = nil
for i in 0..<gPassesLen:
if not isNil(gPasses[i].close) and not gPasses[i].isFrontend:
m = gPasses[i].close(graph, a[i], m)
for i in 0 ..< graph.passes.len:
if not isNil(graph.passes[i].close) and not graph.passes[i].isFrontend:
m = graph.passes[i].close(graph, a[i], m)
a[i] = nil
else:
openPasses(graph, a, module)
@@ -177,8 +160,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
# modules to include between compilation runs? we'd need to track that
# in ROD files. I think we should enable this feature only
# for the interactive mode.
processImplicits graph.config, graph.config.implicitImports, nkImportStmt, a, module
processImplicits graph.config, graph.config.implicitIncludes, nkIncludeStmt, a, module
processImplicits graph, graph.config.implicitImports, nkImportStmt, a, module
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module
while true:
if graph.stopCompile(): break
@@ -194,7 +177,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
sl.add n
if sfReorder in module.flags:
sl = reorder(graph, sl, module)
discard processTopLevelStmt(sl, a)
discard processTopLevelStmt(graph, sl, a)
break
elif n.kind in imperativeCode:
# read everything until the next proc declaration etc.
@@ -208,13 +191,13 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
break
sl.add n
#echo "-----\n", sl
if not processTopLevelStmt(sl, a): break
if not processTopLevelStmt(graph, sl, a): break
if rest != nil:
#echo "-----\n", rest
if not processTopLevelStmt(rest, a): break
if not processTopLevelStmt(graph, rest, a): break
else:
#echo "----- single\n", n
if not processTopLevelStmt(n, a): break
if not processTopLevelStmt(graph, n, a): break
closeParsers(p)
if s.kind != llsStdIn: break
closePasses(graph, a)

View File

@@ -99,24 +99,26 @@ proc isDotDot(x: string; bounds: (int, int)): bool =
proc isSlash(x: string; bounds: (int, int)): bool =
bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep}
const canonDirSep = when isMainModule: '/' else: DirSep
proc canon(x: string; result: var string; state: var int) =
# state: 0th bit set if isAbsolute path. Other bits count
# the number of path components.
for b in dirs(x):
if (state shr 1 == 0) and isSlash(x, b):
result.add DirSep
result.add canonDirSep
state = state or 1
elif result.len > (state and 1) and isDotDot(x, b):
var d = result.len
# f/..
while d > (state and 1) and result[d-1] != DirSep:
while (d-1) > (state and 1) and result[d-1] notin {DirSep, AltSep}:
dec d
if d > 0: setLen(result, d-1)
elif isDot(x, b):
discard "discard the dot"
elif b[1] >= b[0]:
if result.len > 0 and result[^1] != DirSep:
result.add DirSep
if result.len > 0 and result[^1] notin {DirSep, AltSep}:
result.add canonDirSep
result.add substr(x, b[0], b[1])
inc state, 2
@@ -133,7 +135,7 @@ when FileSystemCaseSensitive:
else:
template `!=?`(a, b: char): bool = a != b
proc relativeTo(full, base: string; sep = DirSep): string =
proc relativeTo(full, base: string; sep = canonDirSep): string =
if full.len == 0: return ""
var f, b: PathIter
var ff = (0, -1)
@@ -207,7 +209,7 @@ when true:
canon(f.string, result.string, state)
proc relativeTo*(fullPath: AbsoluteFile, baseFilename: AbsoluteDir;
sep = DirSep): RelativeFile =
sep = canonDirSep): RelativeFile =
RelativeFile(relativeTo(fullPath.string, baseFilename.string, sep))
proc toAbsolute*(file: string; base: AbsoluteDir): AbsoluteFile =
@@ -222,7 +224,7 @@ when true:
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
when isMainModule and defined(posix):
when isMainModule:
doAssert canon"/foo/../bar" == "/bar"
doAssert canon"foo/../bar" == "bar"
@@ -257,4 +259,4 @@ when isMainModule and defined(posix):
when isMainModule and defined(windows):
let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim")
doAssert nasty == r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\simplePkgs\pkgB-#head\pkgA\module.nim"
doAssert nasty.replace('/', '\\') == r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\simplePkgs\pkgB-#head\pkgA\module.nim"

View File

@@ -1104,10 +1104,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else: sym.flags.incl sfUsed
of wLiftLocals: discard
else: invalidPragma(c, it)
elif sym.kind in {skVar,skLet,skParam,skField,skProc,skFunc,skConverter,skMethod,skType}:
elif sym != nil and sym.kind in {skVar, skLet, skParam, skField, skProc,
skFunc, skConverter, skMethod, skType}:
n.sons[i] = semCustomPragma(c, it)
else:
elif sym != nil:
illegalCustomPragma(c, it, sym)
else:
invalidPragma(c, it)
proc mergePragmas(n, pragmas: PNode) =
if n[pragmasPos].kind == nkEmpty:
n[pragmasPos] = pragmas
else:
for p in pragmas: n.sons[pragmasPos].add p
proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
validPragmas: TSpecialWords) =
@@ -1117,11 +1126,12 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
if not o.isNil:
pushInfoContext(c.config, n.info)
var i = 0
while i < o.len():
while i < o.len:
if singlePragma(c, sym, o, i, validPragmas):
internalError(c.config, n.info, "implicitPragmas")
inc i
popInfoContext(c.config)
if sym.kind in routineKinds and sym.ast != nil: mergePragmas(sym.ast, o)
if lfExportLib in sym.loc.flags and sfExportc notin sym.flags:
localError(c.config, n.info, ".dynlib requires .exportc")

View File

@@ -853,12 +853,10 @@ proc loadNode*(g: ModuleGraph; module: PSym): PNode =
result = newNodeI(nkStmtList, module.info)
for row in db.rows(sql"select data from toplevelstmts where module = ? order by position asc",
abs module.id):
var b = BlobReader(pos: 0)
# ensure we can read without index checks:
b.s = row[0] & '\0'
result.add decodeNode(g, b, module.info)
db.exec(sql"insert into controlblock(idgen) values (?)", gFrontEndId)
replay(g, module, result)

View File

@@ -117,6 +117,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
cbconf setCommand:
conf.command = a.getString 0
let arg = a.getString 1
incl(conf.globalOptions, optWasNimscript)
if arg.len > 0:
conf.projectName = arg
let path =
@@ -159,11 +160,8 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
defineSymbol(conf.symbols, "nimscript")
defineSymbol(conf.symbols, "nimconfig")
var registeredPasses {.global.} = false
if not registeredPasses:
registerPass(graph, semPass)
registerPass(graph, evalPass)
registeredPasses = true
registerPass(graph, semPass)
registerPass(graph, evalPass)
conf.searchPaths.add(conf.libpath)

View File

@@ -18,7 +18,7 @@ import
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
semparallel, lowerings, pluginsupport, plugins/active, rod, lineinfos
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
when defined(nimfix):
import nimfix/prettybase

View File

@@ -379,7 +379,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
result = newStrNodeT(s, n, g)
else:
result = newStrNodeT(getStrOrChar(a), n, g)
of mStrToStr: result = a
of mStrToStr: result = newStrNodeT(getStrOrChar(a), n, g)
of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
of mArrToSeq:
result = copyTree(a)

View File

@@ -299,7 +299,13 @@ proc semOf(c: PContext, n: PNode): PNode =
result.typ = getSysType(c.graph, n.info, tyBool)
return result
elif diff == high(int):
localError(c.config, n.info, "'$1' cannot be of this subtype" % typeToString(a))
if commonSuperclass(a, b) == nil:
localError(c.config, n.info, "'$1' cannot be of this subtype" % typeToString(a))
else:
message(c.config, n.info, hintConditionAlwaysFalse, renderTree(n))
result = newIntNode(nkIntLit, 0)
result.info = n.info
result.typ = getSysType(c.graph, n.info, tyBool)
else:
localError(c.config, n.info, "'of' takes 2 arguments")
n.typ = getSysType(c.graph, n.info, tyBool)

View File

@@ -207,6 +207,8 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
typ = commonType(typ, n[0].typ)
var last = sonsLen(n) - 1
var catchAllExcepts = 0
for i in countup(1, last):
let a = n.sons[i]
checkMinSonsLen(a, 1, c.config)
@@ -227,8 +229,16 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
# Overwrite symbol in AST with the symbol in the symbol table.
a[0][2] = newSymNode(symbol, a[0][2].info)
elif a.len == 1:
# count number of ``except: body`` blocks
inc catchAllExcepts
else:
# support ``except KeyError, ValueError, ... : body``
if catchAllExcepts > 0:
# if ``except: body`` already encountered,
# cannot be followed by a ``except KeyError, ... : body`` block
inc catchAllExcepts
var is_native, is_imported: bool
for j in 0..a.len-2:
let tmp = semExceptBranchType(a[j])
@@ -238,9 +248,18 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
if is_native and is_imported:
localError(c.config, a[0].info, "Mix of imported and native exception types is not allowed in one except branch")
elif a.kind != nkFinally:
elif a.kind == nkFinally:
if i != n.len-1:
localError(c.config, a.info, "Only one finally is allowed after all other branches")
else:
illFormedAst(n, c.config)
if catchAllExcepts > 1:
# if number of ``except: body`` blocks is greater than 1
# or more specific exception follows a general except block, it is invalid
localError(c.config, a.info, "Only one general except clause is allowed after more specific exceptions")
# last child of an nkExcept/nkFinally branch is a statement:
a[^1] = semExprBranchScope(c, a[^1])
if a.kind != nkFinally: typ = commonType(typ, a[^1])
@@ -1917,7 +1936,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
case n.sons[j].kind
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr,
nkBlockStmt, nkState: discard
else: localError(c.config, n.sons[j].info, "unreachable statement after 'return'")
else: localError(c.config, n.sons[j].info,
"unreachable statement after 'return' statement or '{.noReturn.}' proc")
else: discard
if result.len == 1 and

View File

@@ -1292,7 +1292,7 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
of tyDistinct:
if a.kind == tyDistinct:
if sameDistinctTypes(f, a): result = isEqual
elif f.base.kind == tyAnything: result = isGeneric
#elif f.base.kind == tyAnything: result = isGeneric # issue 4435
elif c.coerceDistincts: result = typeRel(c, f.base, a)
elif a.kind == tyNil and f.base.kind in NilableTypes:
result = f.allowsNil
@@ -1911,10 +1911,13 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
else:
var evaluated = c.semTryConstExpr(c, arg)
if evaluated != nil:
arg.typ = newTypeS(tyStatic, c)
arg.typ.sons = @[evaluated.typ]
arg.typ.n = evaluated
a = arg.typ
# Don't build the type in-place because `evaluated` and `arg` may point
# to the same object and we'd end up creating recursive types (#9255)
let typ = newTypeS(tyStatic, c)
typ.sons = @[evaluated.typ]
typ.n = evaluated
arg.typ = typ
a = typ
else:
if m.callee.kind == tyGenericBody:
if f.kind == tyStatic and typeRel(m, f.base, a) != isNone:
@@ -2236,8 +2239,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
if n.sons[a].kind == nkHiddenStdConv:
doAssert n.sons[a].sons[0].kind == nkEmpty and
n.sons[a].sons[1].kind == nkArgList and
n.sons[a].sons[1].len == 0
n.sons[a].sons[1].kind in {nkBracket, nkArgList}
# Steal the container and pass it along
setSon(m.call, formal.position + 1, n.sons[a].sons[1])
else:

View File

@@ -72,12 +72,16 @@ proc parsePipe(filename: AbsoluteFile, inputStream: PLLStream; cache: IdentCache
i = 0
inc linenumber
if i+1 < line.len and line[i] == '#' and line[i+1] == '?':
inc(i, 2)
while i < line.len and line[i] in Whitespace: inc(i)
var q: TParser
parser.openParser(q, filename, llStreamOpen(substr(line, i)), cache, config)
result = parser.parseAll(q)
parser.closeParser(q)
when defined(nimpretty2):
# XXX this is a bit hacky, but oh well...
quit "can't nimpretty a source code filter"
else:
inc(i, 2)
while i < line.len and line[i] in Whitespace: inc(i)
var q: TParser
parser.openParser(q, filename, llStreamOpen(substr(line, i)), cache, config)
result = parser.parseAll(q)
parser.closeParser(q)
llStreamClose(s)
proc getFilter(ident: PIdent): TFilterKind =
@@ -156,14 +160,18 @@ proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream;
proc closeParsers*(p: var TParsers) =
parser.closeParser(p.parser)
proc parseFile*(fileIdx: FileIndex; cache: IdentCache; config: ConfigRef): PNode {.procvar.} =
var
p: TParsers
f: File
proc setupParsers*(p: var TParsers; fileIdx: FileIndex; cache: IdentCache;
config: ConfigRef): bool =
var f: File
let filename = toFullPathConsiderDirty(config, fileIdx)
if not open(f, filename.string):
rawMessage(config, errGenerated, "cannot open file: " & filename.string)
return
return false
openParsers(p, fileIdx, llStreamOpen(f), cache, config)
result = parseAll(p)
closeParsers(p)
result = true
proc parseFile*(fileIdx: FileIndex; cache: IdentCache; config: ConfigRef): PNode {.procvar.} =
var p: TParsers
if setupParsers(p, fileIdx, cache, config):
result = parseAll(p)
closeParsers(p)

View File

@@ -38,7 +38,7 @@ type
# if we encounter the 2nd yield statement
next: PTransCon # for stacking
TTransfContext = object of passes.TPassContext
TTransfContext = object of TPassContext
module: PSym
transCon: PTransCon # top of a TransCon stack
inlining: int # > 0 if we are in inlining context (copy vars)
@@ -110,8 +110,8 @@ proc transformSons(c: PTransf, n: PNode): PTransNode =
for i in countup(0, sonsLen(n)-1):
result[i] = transform(c, n.sons[i])
proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
result = newTransNode(nkFastAsgn, PNode(ri).info, 2)
proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PTransNode): PTransNode =
result = newTransNode(kind, PNode(ri).info, 2)
result[0] = PTransNode(le)
result[1] = ri
@@ -299,12 +299,6 @@ proc transformBreak(c: PTransf, n: PNode): PTransNode =
else:
result = n.PTransNode
proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) =
# XXX: BUG: what if `n` is an expression with side-effects?
for i in countup(0, sonsLen(c.transCon.forStmt) - 3):
add(father, newAsgnStmt(c, c.transCon.forStmt.sons[i],
transform(c, newTupleAccess(c.graph, n, i))))
proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
case n.kind
of nkSym:
@@ -328,6 +322,18 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
result[i] = introduceNewLocalVars(c, n.sons[i])
proc transformYield(c: PTransf, n: PNode): PTransNode =
proc asgnTo(lhs: PNode, rhs: PTransNode): PTransNode =
# Choose the right assignment instruction according to the given ``lhs``
# node since it may not be a nkSym (a stack-allocated skForVar) but a
# nkDotExpr (a heap-allocated slot into the envP block)
case lhs.kind:
of nkSym:
internalAssert c.graph.config, lhs.sym.kind == skForVar
result = newAsgnStmt(c, nkFastAsgn, lhs, rhs)
of nkDotExpr:
result = newAsgnStmt(c, nkAsgn, lhs, rhs)
else:
internalAssert c.graph.config, false
result = newTransNode(nkStmtList, n.info, 0)
var e = n.sons[0]
# c.transCon.forStmt.len == 3 means that there is one for loop variable
@@ -340,13 +346,20 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
for i in countup(0, sonsLen(e) - 1):
var v = e.sons[i]
if v.kind == nkExprColonExpr: v = v.sons[1]
add(result, newAsgnStmt(c, c.transCon.forStmt.sons[i],
transform(c, v)))
let lhs = c.transCon.forStmt.sons[i]
let rhs = transform(c, v)
add(result, asgnTo(lhs, rhs))
else:
unpackTuple(c, e, result)
# Unpack the tuple into the loop variables
# XXX: BUG: what if `n` is an expression with side-effects?
for i in countup(0, sonsLen(c.transCon.forStmt) - 3):
let lhs = c.transCon.forStmt.sons[i]
let rhs = transform(c, newTupleAccess(c.graph, e, i))
add(result, asgnTo(lhs, rhs))
else:
var x = transform(c, e)
add(result, newAsgnStmt(c, c.transCon.forStmt.sons[0], x))
let lhs = c.transCon.forStmt.sons[0]
let rhs = transform(c, e)
add(result, asgnTo(lhs, rhs))
inc(c.transCon.yieldStmts)
if c.transCon.yieldStmts <= 1:
@@ -584,7 +597,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
# generate a temporary and produce an assignment statement:
var temp = newTemp(c, formal.typ, formal.info)
addVar(v, temp)
add(stmtList, newAsgnStmt(c, temp, arg.PTransNode))
add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode))
idNodeTablePut(newC.mapping, formal, temp)
of paVarAsgn:
assert(skipTypes(formal.typ, abstractInst).kind == tyVar)
@@ -595,7 +608,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
addSonSkipIntLit(typ, formal.typ.sons[0])
var temp = newTemp(c, typ, formal.info)
addVar(v, temp)
add(stmtList, newAsgnStmt(c, temp, arg.PTransNode))
add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode))
idNodeTablePut(newC.mapping, formal, temp)
var body = iter.getBody.copyTree

View File

@@ -92,8 +92,7 @@ proc isCaseObj*(n: PNode): bool =
proc isDeepConstExpr*(n: PNode): bool =
case n.kind
of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit,
nkFloatLit..nkFloat64Lit, nkNilLit:
of nkCharLit..nkNilLit:
result = true
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
result = isDeepConstExpr(n.sons[1])

View File

@@ -1079,8 +1079,8 @@ proc inheritanceDiff*(a, b: PType): int =
# | returns: +x iff `a` is the x'th direct subclass of `b`
# | returns: `maxint` iff `a` and `b` are not compatible at all
if a == b or a.kind == tyError or b.kind == tyError: return 0
assert a.kind == tyObject
assert b.kind == tyObject
assert a.kind in {tyObject} + skipPtrs
assert b.kind in {tyObject} + skipPtrs
var x = a
result = 0
while x != nil:

View File

@@ -24,7 +24,7 @@ import
from semfold import leValueConv, ordinalValToString
from evaltempl import evalTemplate
from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
when hasFFI:
import evalffi
@@ -413,26 +413,12 @@ proc recSetFlagIsRef(arg: PNode) =
arg.sons[i].recSetFlagIsRef
proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
# FIXME: this doesn't attempt to solve incomplete
# support of tyPtr, tyRef in VM.
let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
let typeKind = case typeEntry.kind
of tyUInt..tyUInt64: nkUIntLit
of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
of tyFloat..tyFloat128: nkFloatLit
of tyString: nkStrLit
of tyObject: nkObjConstr
of tySequence: nkNilLit
of tyProc, tyTuple: nkTupleConstr
else: nkEmpty
let oldLen = node.len
setLen(node.sons, newLen)
if oldLen < newLen:
# TODO: This is still not correct for tyPtr, tyRef default value
for i in oldLen ..< newLen:
node.sons[i] = newNodeI(typeKind, info)
node.sons[i] = getNullValue(typ.sons[0], info, c.config)
const
errIndexOutOfBounds = "index out of bounds"
@@ -458,7 +444,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
#if c.traceActive:
when traceCode:
echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
# message(c.config, c.debug[pc], warnUser, "Trace")
# message(c.config, c.debug[pc], warnUser, "Trace")
case instr.opcode
of opcEof: return regs[ra]
@@ -917,7 +903,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
stackTrace(c, tos, pc, errNilAccess)
of opcGetImpl:
decodeB(rkNode)
let a = regs[rb].node
var a = regs[rb].node
if a.kind == nkVarTy: a = a[0]
if a.kind == nkSym:
regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit)
else: copyTree(a.sym.ast)
@@ -1201,7 +1188,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcOf:
decodeBC(rkInt)
let typ = c.types[regs[rc].intVal.int]
regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) >= 0)
regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) <= 0)
of opcIs:
decodeBC(rkInt)
let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc})
@@ -1215,8 +1202,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let newLen = regs[rb].intVal.int
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
of opcReset:
internalError(c.config, c.debug[pc], "too implement")
of opcNarrowS:
decodeB(rkInt)
let min = -(1.BiggestInt shl (rb-1))

View File

@@ -69,7 +69,7 @@ type
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
opcIsNil, opcOf, opcIs,
opcSubStr, opcParseFloat, opcConv, opcCast,
opcQuit, opcReset,
opcQuit,
opcNarrowS, opcNarrowU,
opcAddStrCh,
@@ -191,7 +191,7 @@ type
VmCallback* = proc (args: VmArgs) {.closure.}
PCtx* = ref TCtx
TCtx* = object of passes.TPassContext # code gen context
TCtx* = object of TPassContext # code gen context
code*: seq[TInstr]
debug*: seq[TLineInfo] # line info for every instruction; kept separate
# to not slow down interpretation

View File

@@ -237,8 +237,15 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
of tyRange:
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
result.add atomicType("range", mRange)
result.add t.n.sons[0].copyTree
result.add t.n.sons[1].copyTree
if inst:
let rng = newNodeX(nkInfix)
rng.add newIdentNode(getIdent(cache, ".."), info)
rng.add t.n.sons[0].copyTree
rng.add t.n.sons[1].copyTree
result.add rng
else:
result.add t.n.sons[0].copyTree
result.add t.n.sons[1].copyTree
of tyPointer: result = atomicType("pointer", mPointer)
of tyString: result = atomicType("string", mString)
of tyCString: result = atomicType("cstring", mCString)

View File

@@ -1063,13 +1063,15 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mReset:
unused(c, n, dest)
var d = c.genx(n.sons[1])
c.gABC(n, opcReset, d)
c.gABx(n, opcLdNull, d, c.genType(n.sons[1].typ))
c.gABx(n, opcNodeToReg, d, d)
c.genAsgnPatch(n.sons[1], d)
of mOf, mIs:
if dest < 0: dest = c.getTemp(n.typ)
var tmp = c.genx(n.sons[1])
var idx = c.getTemp(getSysType(c.graph, n.info, tyInt))
var typ = n.sons[2].typ
if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
if m == mOf: typ = typ.skipTypes(abstractPtrs)
c.gABx(n, opcLdImmInt, idx, c.genType(typ))
c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
c.freeTemp(tmp)
@@ -1088,13 +1090,14 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mEcho:
unused(c, n, dest)
let n = n[1].skipConv
let x = c.getTempRange(n.len, slotTempUnknown)
internalAssert c.config, n.kind == nkBracket
for i in 0..<n.len:
var r: TRegister = x+i
c.gen(n.sons[i], r)
c.gABC(n, opcEcho, x, n.len)
c.freeTempRange(x, n.len)
if n.kind == nkBracket:
# can happen for nim check, see bug #9609
let x = c.getTempRange(n.len, slotTempUnknown)
for i in 0..<n.len:
var r: TRegister = x+i
c.gen(n.sons[i], r)
c.gABC(n, opcEcho, x, n.len)
c.freeTempRange(x, n.len)
of mAppendStrCh:
unused(c, n, dest)
genBinaryStmtVar(c, n, opcAddStrCh)
@@ -1648,8 +1651,9 @@ proc genVarSection(c: PCtx; n: PNode) =
#assert(a.sons[0].kind == nkSym) can happen for transformed vars
if a.kind == nkVarTuple:
for i in 0 .. a.len-3:
if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
checkCanEval(c, a[i])
if a[i].kind == nkSym:
if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
checkCanEval(c, a[i])
c.gen(lowerTupleUnpacking(c.graph, a, c.getOwner))
elif a.sons[0].kind == nkSym:
let s = a.sons[0].sym

View File

@@ -73,6 +73,19 @@ path="$lib/pure"
opt:speed
@end
@if unix and mingw:
# Cross compile for Windows from Linux/OSX using MinGW
os = windows
i386.windows.gcc.path = "/usr/bin"
i386.windows.gcc.exe = "i686-w64-mingw32-gcc"
i386.windows.gcc.linkerexe = "i686-w64-mingw32-gcc"
amd64.windows.gcc.path = "/usr/bin"
amd64.windows.gcc.exe = "x86_64-w64-mingw32-gcc"
amd64.windows.gcc.linkerexe = "x86_64-w64-mingw32-gcc"
@end
@if unix:
@if not bsd or haiku:
# -fopenmp
@@ -89,9 +102,6 @@ path="$lib/pure"
tlsEmulation:on
@end
@if haiku:
# Haiku currently have problems with TLS
# https://dev.haiku-os.org/ticket/14342
tlsEmulation:on
gcc.options.linker = "-Wl,--as-needed -lnetwork"
gcc.cpp.options.linker = "-Wl,--as-needed -lnetwork"
clang.options.linker = "-Wl,--as-needed -lnetwork"

View File

@@ -38,7 +38,7 @@ doc.section.toc = """
# * $seeSrc: generated HTML from doc.item.seesrc (if some switches are used).
doc.item = """
<a id="$itemSymOrIdEnc"></a>
<a id="$itemSymOrID"></a>
<dt><pre>$header</pre></dt>
<dd>
$desc

View File

@@ -268,7 +268,7 @@ form the Nim code, then link them into a static binary along your main C
program::
$ nim c --noMain --noLinking --header:fib.h fib.nim
$ gcc -o m -Inimcache -Ipath/to/nim/lib nimcache/*.c maths.c
$ gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
The first command runs the Nim compiler with three special options to avoid
generating a ``main()`` function in the generated files, avoid linking the

View File

@@ -1,3 +1,20 @@
============
Contributing
============
.. contents::
Contributing happens via "Pull requests" (PR) on github. Every PR needs to be
reviewed before it can be merged and the Continuous Integration should be green.
The PR has to be approved (and is often merged too) by one "code owner", either
by the code owner who is responsible for the subsystem the PR belongs to or by
two core developers or by Araq.
See `codeowners <codeowners.html>`_ for more details.
Writing tests
=============
@@ -78,12 +95,27 @@ only want to see the output of failing tests, go for
You can also run only a single category of tests. A category is a subdirectory
in the ``tests`` directory. There are a couple of special categories; for a
list of these, see ``tests/testament/categories.nim``, at the bottom.
list of these, see ``testament/categories.nim``, at the bottom.
::
./koch tests c lib
To run a single test:
::
./koch tests c <category>/<name>
E.g. ``./koch test run stdlib/thttpclient_ssl``
For reproducible tests (to reproduce an environment more similar to the one
run by Continuous Integration on travis/appveyor), you may want to disable your
local configuration (eg in ``~/.config/nim/nim.cfg``) which may affect some
tests; this can also be achieved by using
``export XDG_CONFIG_HOME=pathtoAlternateConfig`` before running ``./koch``
commands.
Comparing tests
===============
@@ -195,13 +227,100 @@ or
the first is preferred.
Best practices
=============
Note: these are general guidelines, not hard rules; there are always exceptions.
Code reviews can just point to a specific section here to save time and
propagate best practices.
.. _noimplicitbool:
Take advantage of no implicit bool conversion
.. code-block:: nim
doAssert isValid() == true
doAssert isValid() # preferred
.. _immediately_invoked_lambdas:
Immediately invoked lambdas (https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
.. code-block:: nim
let a = (proc (): auto = getFoo())()
let a = block: # preferred
getFoo()
.. _design_for_mcs:
Design with method call syntax (UFCS in other languages) chaining in mind
.. code-block:: nim
proc foo(cond: bool, lines: seq[string]) # bad
proc foo(lines: seq[string], cond: bool) # preferred
# can be called as: `getLines().foo(false)`
.. _avoid_quit:
Use exceptions (including assert / doAssert) instead of ``quit``
rationale: https://forum.nim-lang.org/t/4089
.. code-block:: nim
quit() # bad in almost all cases
doAssert() # preferred
.. _tests_use_doAssert:
Use ``doAssert`` (or ``require``, etc), not ``assert`` in all tests.
.. code-block:: nim
runnableExamples: assert foo() # bad
runnableExamples: doAssert foo() # preferred
.. _delegate_printing:
Delegate printing to caller: return ``string`` instead of calling ``echo``
rationale: it's more flexible (eg allows caller to call custom printing,
including prepending location info, writing to log files, etc).
.. code-block:: nim
proc foo() = echo "bar" # bad
proc foo(): string = "bar" # preferred (usually)
.. _use_Option:
[Ongoing debate] Consider using Option instead of return bool + var argument,
unless stack allocation is needed (eg for efficiency).
.. code-block:: nim
proc foo(a: var Bar): bool
proc foo(): Option[Bar]
.. _use_doAssert_not_echo:
Tests (including in testament) should always prefer assertions over ``echo``,
except when that's not possible. It's more precise, easier for readers and
maintaners to where expected values refer to. See for example
https://github.com/nim-lang/Nim/pull/9335 and https://forum.nim-lang.org/t/4089
.. code-block:: nim
echo foo() # adds a line in testament `discard` block.
doAssert foo() == [1, 2] # preferred, except when not possible to do so.
The Git stuff
=============
General commit rules
--------------------
1. All changes introduced by the commit (diff lines) must be related to the
1. Bugfixes that should be backported to the latest stable release should
contain the string ``[backport]`` in the commit message! There will be an
outmated process relying on these. However, bugfixes also have the inherent
risk of causing regressions which are worse for a "stable, bugfixes-only"
branch, so in doubt, leave out the ``[backport]``. Standard library bugfixes
are less critical than compiler bugfixes.
2. All changes introduced by the commit (diff lines) must be related to the
subject of the commit.
If you change some other unrelated to the subject parts of the file, because
@@ -211,7 +330,7 @@ General commit rules
*Tip:* Never commit everything as is using ``git commit -a``, but review
carefully your changes with ``git add -p``.
2. Changes should not introduce any trailing whitespace.
3. Changes should not introduce any trailing whitespace.
Always check your changes for whitespace errors using ``git diff --check``
or add following ``pre-commit`` hook:
@@ -221,6 +340,52 @@ General commit rules
#!/bin/sh
git diff --check --cached || exit $?
3. Describe your commit and use your common sense.
4. Describe your commit and use your common sense.
Example Commit messages: ``Fixes #123; refs #124``
indicates that issue ``#123`` is completely fixed (github may automatically
close it when the PR is committed), wheres issue ``#124`` is referenced
(eg: partially fixed) and won't close the issue when committed.
5. Commits should be always be rebased against devel (so a fast forward
merge can happen)
eg: use ``git pull --rebase origin devel``. This is to avoid messing up
git history, see `#8664 <https://github.com/nim-lang/Nim/issues/8664>`_ .
Exceptions should be very rare: when rebase gives too many conflicts, simply
squash all commits using the script shown in
https://github.com/nim-lang/Nim/pull/9356
6. Do not mix pure formatting changes (eg whitespace changes, nimpretty) or
automated changes (eg nimfix) with other code changes: these should be in
separate commits (and the merge on github should not squash these into 1).
Continuous Integration (CI)
---------------------------
1. Continuous Integration is by default run on every push in a PR; this clogs
the CI pipeline and affects other PR's; if you don't need it (eg for WIP or
documentation only changes), add ``[ci skip]`` to your commit message title.
This convention is supported by `Appveyor <https://www.appveyor.com/docs/how-to/filtering-commits/#skip-directive-in-commit-message>`_
and `Travis <https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build>`_
2. Consider enabling CI (travis and appveyor) in your own Nim fork, and
waiting for CI to be green in that fork (fixing bugs as needed) before
opening your PR in original Nim repo, so as to reduce CI congestion. Same
applies for updates on a PR: you can test commits on a separate private
branch before updating the main PR.
Code reviews
------------
1. Whenever possible, use github's new 'Suggested change' in code reviews, which
saves time explaining the change or applying it; see also
https://forum.nim-lang.org/t/4317
.. include:: docstyle.rst

View File

@@ -117,6 +117,7 @@ Output::
{
"orig": "docgen_sample.nim",
"nimble": "",
"moduleDescription": "This module is a sample",
"entries": [
{
"name": "helloWorld",

View File

@@ -6,6 +6,9 @@ The documentation consists of several documents:
- | `Tutorial (part II) <tut2.html>`_
| The Nim tutorial part two deals with the advanced language constructs.
- | `Tutorial (part III) <tut3.html>`_
| The Nim tutorial part three about Nim's macro system.
- | `Language Manual <manual.html>`_
| The Nim manual is a draft that will evolve into a proper specification.

View File

@@ -4,7 +4,7 @@ Source Code Filters
.. contents::
A `Source Code Filter` transforms the input character stream to an in-memory
A `Source Code Filter (SCF)` transforms the input character stream to an in-memory
output stream before parsing. A filter can be used to provide templating
systems or preprocessors.
@@ -23,10 +23,23 @@ just like an ordinary procedure call with named or positional arguments. The
available parameters depend on the invoked filter. Before version 0.12.0 of
the language ``#!`` was used instead of ``#?``.
**Hint:** With ``--hint[codeBegin]:on```or ``--verbosity:2``
(or higher) Nim lists the processed code after each filter
application.
**Hint:** With ``--hint[codeBegin]:on`` or ``--verbosity:2``
(or higher) while compiling or `nim check`, Nim lists the processed code after
each filter application.
Usage
=====
First, put your SCF code in a separate file with filters specified in the first line.
**Note:** You can name your SCF file with any file extension you want, but the conventional extension is ``.tmpl``.
If we use `generateXML` code shown above and call the SCF file `xmlGen.tmpl`
In your `main.nim`:
.. code-block:: nim
include "xmlGen.tmpl"
echo generateXML("John Smith","42")
Pipe operator
=============

View File

@@ -9,7 +9,7 @@ operator = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9
| 'is' | 'isnot' | 'in' | 'notin' | 'of'
| 'div' | 'mod' | 'shl' | 'shr' | 'not' | 'static' | '..'
prefixOperator = operator
optInd = COMMENT?
optInd = COMMENT? IND?
optPar = (IND{>} | IND{=})?
simpleExpr = arrowExpr (OP0 optInd arrowExpr)* pragma?
arrowExpr = assignExpr (OP1 optInd assignExpr)*
@@ -85,17 +85,19 @@ paramListColon = paramList? (':' optInd typeDesc)?
doBlock = 'do' paramListArrow pragmas? colcom stmt
procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
distinct = 'distinct' optInd typeDesc
forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
forExpr = forStmt
expr = (blockExpr
| ifExpr
| whenExpr
| caseExpr
| forExpr
| tryExpr)
/ simpleExpr
typeKeyw = 'var' | 'out' | 'ref' | 'ptr' | 'shared' | 'tuple'
| 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
primary = typeKeyw typeDescK
/ prefixOperator* identOrLiteral primarySuffix*
/ 'static' primary
/ 'bind' primary
typeDesc = simpleExpr
typeDefAux = simpleExpr
@@ -142,12 +144,11 @@ tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
(optInd 'except' exprList colcom stmt)*
(optInd 'finally' colcom stmt)?
exceptBlock = 'except' colcom stmt
forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
blockStmt = 'block' symbol? colcom stmt
blockExpr = 'block' symbol? colcom stmt
staticStmt = 'static' colcom stmt
deferStmt = 'defer' colcom stmt
asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLE_STR_LIT)
asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
genericParam = symbol (comma symbol)* (colon expr)? ('=' optInd expr)?
genericParamList = '[' optInd
genericParam ^* (comma/semicolon) optPar ']'

View File

@@ -16,9 +16,9 @@ Directory structure
The Nim project's directory structure is:
============ ==============================================
============ ===================================================
Path Purpose
============ ==============================================
============ ===================================================
``bin`` generated binary files
``build`` generated C code for the installation
``compiler`` the Nim compiler itself; note that this
@@ -32,7 +32,7 @@ Path Purpose
``lib`` the Nim library
``web`` website of Nim; generated by ``nimweb``
from the ``*.txt`` and ``*.tmpl`` files
============ ==============================================
============ ===================================================
Bootstrapping the compiler
@@ -386,8 +386,9 @@ So now ``G.c`` MUST contain both ``P1`` and ``P2``, but we haven't even
loaded ``P1`` from the symbol file, nor do we want to because we then quickly
would restore large parts of the whole program.
Solution
~~~~~~~~ 
~~~~~~~~
The backend must have some logic so that if the currently processed module
is from the compilation cache, the ``ast`` field is not accessed. Instead
@@ -517,6 +518,7 @@ Code generation for closures
Code generation for closures is implemented by `lambda lifting`:idx:.
Design
------
@@ -665,5 +667,3 @@ important the hidden formal param is ``void*`` and not something more
specialized. However the more specialized env type needs to passed to the
backend somehow. We deal with this by modifying ``s.ast[paramPos]`` to contain
the formal hidden parameter, but not ``s.typ``!

View File

@@ -61,7 +61,7 @@ test command
------------
The `test`:idx: command can also be invoked with the alias ``tests``. This
command will compile and run ``tests/testament/tester.nim``, which is the main
command will compile and run ``testament/tester.nim``, which is the main
driver of Nim's test suite. You can pass options to the ``test`` command,
they will be forwarded to the tester. See its source code for available
options.

View File

@@ -18,9 +18,9 @@ low-level interface to a C library.
Read this `document <apis.html>`_ for a quick overview of the API design.
The `bottom <#nimble>`_ of this page includes a list of 3rd party packages
created by the Nim community. These packages are a useful addition to the
modules in the standard library.
In addition to the modules in the standard library, third-party packages
created by the Nim community can be used via `Nimble <#nimble>`_, Nim's
package manager.
Pure libraries
@@ -59,7 +59,7 @@ Core
This module defines compile-time reflection procs for working with types.
* `threadpool <threadpool.html>`_
Implements Nim's `spawn <manual.html#spawn>`_.
Implements Nim's `spawn <manual.html#parallel-amp-spawn>`_.
* `cpuinfo <cpuinfo.html>`_
This module implements procs to determine the number of CPUs / cores.
@@ -67,6 +67,8 @@ Core
* `lenientops <lenientops.html>`_
Provides binary operators for mixed integer/float expressions for convenience.
* `bitops <bitops.html>`_
Provides a series of low level methods for bit manipulation.
Collections and algorithms
@@ -74,26 +76,38 @@ Collections and algorithms
* `algorithm <algorithm.html>`_
Implements some common generic algorithms like sort or binary search.
* `tables <tables.html>`_
Nim hash table support. Contains tables, ordered tables and count tables.
* `sets <sets.html>`_
Nim hash and bit set support.
* `lists <lists.html>`_
Nim linked list support. Contains singly and doubly linked lists and
circular lists ("rings").
* `deques <deques.html>`_
Implementation of a double-ended queue.
The underlying implementation uses a ``seq``.
* `heapqueue <heapqueue.html>`_
This module implements Heap queue (a.k.a. priority queue) algorithm.
* `intsets <intsets.html>`_
Efficient implementation of a set of ints as a sparse bit set.
* `critbits <critbits.html>`_
This module implements a *crit bit tree* which is an efficient
container for a sorted set of strings, or for a sorted mapping of strings.
* `sequtils <sequtils.html>`_
This module implements operations for the built-in seq type
which were inspired by functional programming languages.
* `sharedtables <sharedtables.html>`_
Nim shared hash table support. Contains shared tables.
* `sharedlist <sharedlist.html>`_
Nim shared linked list support. Contains shared singly linked list.
@@ -107,8 +121,8 @@ String handling
substrings, replacing substrings.
* `strformat <strformat.html>`_
Macro based standard string interpolation / formatting. Inpired by
Python's ```f``-strings.
Macro based standard string interpolation / formatting. Inspired by
Python's ``f``-strings.
* `strmisc <strmisc.html>`_
This module contains uncommon string handling operations that do not
@@ -129,6 +143,13 @@ String handling
* `unicode <unicode.html>`_
This module provides support to handle the Unicode UTF-8 encoding.
* `unidecode <unidecode.html>`_
It provides a single proc that does Unicode to ASCII transliterations.
Based on Python's Unidecode module.
* `punycode <punycode.html>`_
Implements a representation of Unicode with the limited ASCII character subset.
* `encodings <encodings.html>`_
Converts between different character encodings. On UNIX, this uses
the ``iconv`` library, on Windows the Windows API.
@@ -189,10 +210,16 @@ Generic Operating System Services
``asyncdispatch``.
* `distros <distros.html>`_
This module implements the basics for OS distribution ("distro") detection and the OS's native package manager.
Its primary purpose is to produce output for Nimble packages, but it also contains the widely used **Distribution** enum
This module implements the basics for OS distribution ("distro") detection
and the OS's native package manager.
Its primary purpose is to produce output for Nimble packages,
but it also contains the widely used **Distribution** enum
that is useful for writing platform specific code.
* `volatile <volatile.html>`_
This module contains code for generating volatile loads and stores,
which are useful in embedded and systems programming.
Math libraries
--------------
@@ -274,6 +301,7 @@ Internet Protocols and Support
This module implements a selector API with backends specific to each OS.
Currently epoll on Linux and select on other operating systems.
Parsers
-------
@@ -406,6 +434,7 @@ Miscellaneous
* `segfaults <segfaults.html>`_
Turns access violations or segfaults into a ``NilAccessError`` exception.
Modules for JS backend
----------------------
@@ -434,7 +463,6 @@ Regular expressions
expressions. The current implementation uses PCRE.
Database support
----------------
@@ -465,6 +493,7 @@ Wrappers
The generated HTML for some of these wrappers is so huge that it is
not contained in the distribution. You can then find them on the website.
Windows specific
----------------
@@ -520,4 +549,5 @@ Nimble is a package manager for the Nim programming language.
For instructions on how to install Nimble packages see
`its README <https://github.com/nim-lang/nimble#readme>`_.
To see a list of Nimble's packages, check out `https://nimble.directory/ <https://nimble.directory/>`_ or the `packages repos <https://github.com/nim-lang/packages>`_ on GitHub.
To see a list of Nimble's packages, check out `<https://nimble.directory/>`_
or the `packages repo <https://github.com/nim-lang/packages>`_ on GitHub.

View File

@@ -475,7 +475,6 @@ The type suffixes are:
``'d`` float64
``'f32`` float32
``'f64`` float64
``'f128`` float128
================= =========================
Floating point literals may also be in binary, octal or hexadecimal
@@ -3037,7 +3036,7 @@ The `case expression` is again very similar to the case statement:
As seen in the above example, the case expression can also introduce side
effects. When multiple statements are given for a branch, Nim will use
the last expression as the result value, much like in an `expr` template.
the last expression as the result value.
Table constructor
-----------------
@@ -4611,8 +4610,8 @@ The concept types can be parametric just like the regular generic types:
M.data[m * M.N + n] = v
# Adapt the Matrix type to the concept's requirements
template Rows*(M: type Matrix): expr = M.M
template Cols*(M: type Matrix): expr = M.N
template Rows*(M: type Matrix): int = M.M
template Cols*(M: type Matrix): int = M.N
template ValueType*(M: type Matrix): type = M.T
-------------
@@ -5036,9 +5035,8 @@ an ``immediate`` pragma and then these templates do not take part in
overloading resolution and the parameters' types are *ignored* by the
compiler. Explicit immediate templates are now deprecated.
**Note**: For historical reasons ``stmt`` is an alias for ``typed`` and
``expr`` an alias for ``untyped``, but new code should use the newer,
clearer names.
**Note**: For historical reasons ``stmt`` was an alias for ``typed`` and
``expr`` was an alias for ``untyped``, but they are removed.
Passing a code block to a template
@@ -5129,9 +5127,6 @@ also ``varargs[untyped]`` so that not even the number of parameters is fixed:
However, since a template cannot iterate over varargs, this feature is
generally much more useful for macros.
**Note**: For historical reasons ``varargs[expr]`` is not equivalent
to ``varargs[untyped]``.
Symbol binding in templates
---------------------------
@@ -5965,6 +5960,12 @@ curlies is the pattern to match against. The operators ``*``, ``**``,
notation, so to match verbatim against ``*`` the ordinary function call syntax
needs to be used.
Term rewriting macro are applied recursively, up to a limit. This means that
if the result of a term rewriting macro is eligible for another rewriting,
the compiler will try to perform it, and so on, until no more optimizations
are applicable. To avoid putting the compiler into an infinite loop, there is
a hard limit on how many times a single term rewriting macro can be applied.
Once this limit has been passed, the term rewriting macro will be ignored.
Unfortunately optimizations are hard to get right and even the tiny example
is **wrong**:
@@ -8003,7 +8004,7 @@ To enable thread support the ``--threads:on`` command line switch needs to
be used. The ``system`` module then contains several threading primitives.
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
for the low level thread API. There are also high level parallelism constructs
available. See `spawn <#parallel-spawn>`_ for further details.
available. See `spawn <#parallel-amp-spawn>`_ for further details.
Nim's memory model for threads is quite different than that of other common
programming languages (C, Pascal, Java): Each thread has its own (garbage

View File

@@ -157,7 +157,7 @@ passed as a command line argument to the compiler.
The ``nim`` executable processes configuration files in the following
directories (in this order; later files overwrite previous settings):
1) ``$nim/config/nim.cfg``, ``/etc/nim/nim.cfg`` (UNIX) or ``%NIM%/config/nim.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option.
1) ``$nim/config/nim.cfg``, ``/etc/nim/nim.cfg`` (UNIX) or ``<Nim's installation director>\config\nim.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option.
2) If environment variable ``XDG_CONFIG_HOME`` is defined, ``$XDG_CONFIG_HOME/nim/nim.cfg`` or ``~/.config/nim/nim.cfg`` (POSIX) or ``%APPDATA%/nim/nim.cfg`` (Windows). This file can be skipped with the ``--skipUserCfg`` command line option.
3) ``$parentDir/nim.cfg`` where ``$parentDir`` stands for any parent directory of the project file's path. These files can be skipped with the ``--skipParentCfg`` command line option.
4) ``$projectDir/nim.cfg`` where ``$projectDir`` stands for the project file's path. This file can be skipped with the ``--skipProjCfg`` command line option.
@@ -261,6 +261,21 @@ configuration file should contain something like::
arm.linux.gcc.exe = "arm-linux-gcc"
arm.linux.gcc.linkerexe = "arm-linux-gcc"
Cross compilation for Windows
=============================
To cross compile for Windows from Linux or OSX using the MinGW-w64 toolchain::
nim c -d:mingw myproject.nim
Use ``--cpu:i386`` or ``--cpu:amd64`` to switch the cpu arch.
The MinGW-w64 toolchain can be installed as follows::
Ubuntu: apt install mingw-w64
CentOS: yum install mingw32-gcc | mingw64-gcc - requires EPEL
OSX: brew install mingw-w64
Cross compilation for Nintendo Switch
=====================================

View File

@@ -6,9 +6,25 @@ Strictly speaking, ``NimScript`` is the subset of Nim that can be evaluated
by Nim's builtin virtual machine (VM). This VM is used for Nim's compiletime
function evaluation features.
You can use a ``<myproject>.nims`` file that simply contains Nim code
controlling the compilation process. For a directory wide
configuration, use ``config.nims`` instead of ``<myproject>.nims``.
The ``nim`` executable processes the ``.nims`` configuration files in
the following directories (in this order; later files overwrite
previous settings):
1) If environment variable ``XDG_CONFIG_HOME`` is defined,
``$XDG_CONFIG_HOME/nim/config.nims`` or
``~/.config/nim/config.nims`` (POSIX) or
``%APPDATA%/nim/config.nims`` (Windows). This file can be skipped
with the ``--skipUserCfg`` command line option.
2) ``$parentDir/config.nims`` where ``$parentDir`` stands for any
parent directory of the project file's path. These files can be
skipped with the ``--skipParentCfg`` command line option.
3) ``$projectDir/config.nims`` where ``$projectDir`` stands for the
project's path. This file can be skipped with the ``--skipProjCfg``
command line option.
4) A project can also have a project specific configuration file named
``$project.nims`` that resides in the same directory as
``$project.nim``. This file can be skipped with the same
``--skipProjCfg`` command line option.
The VM cannot deal with ``importc`` because the FFI is not
available. So the stdlib modules using ``importc`` cannot be used with
@@ -74,6 +90,7 @@ In fact, as a convention the following tasks should be available:
========= ===================================================
Task Description
========= ===================================================
``help`` List all the available NimScript tasks along with their docstrings.
``build`` Build the project with the required
backend (``c``, ``cpp`` or ``js``).
``tests`` Runs the tests belonging to the project.

View File

@@ -48,7 +48,7 @@ by default.
Specifying the location of the query
------------------------------------
Nimsuggest than waits for queries to process. A query consists of a
Nimsuggest then waits for queries to process. A query consists of a
cryptic 3 letter "command" ``def`` or ``con`` or ``sug`` or ``use`` followed by
a location. A query location consists of:
@@ -59,7 +59,7 @@ a location. A query location consists of:
``dirtyfile.nim``
This is optional.
The ``file`` paramater is enough for static analysis, but IDEs
The ``file`` parameter is enough for static analysis, but IDEs
tend to have *unsaved buffers* where the user may still be in
the middle of typing a line. In such situations the IDE can
save the current contents to a temporary file and then use the
@@ -143,7 +143,7 @@ tab characters (``\t``). The values of each column are:
``def`` for definition, ``sug`` for suggestion, etc).
2. Type of the symbol. This can be ``skProc``, ``skLet``, and just
about any of the enums defined in the module ``compiler/ast.nim``.
3. Full qualitifed path of the symbol. If you are querying a symbol
3. Fully qualified path of the symbol. If you are querying a symbol
defined in the ``proj.nim`` file, this would have the form
``proj.symbolName``.
4. Type/signature. For variables and enums this will contain the

69
doc/packaging.rst Normal file
View File

@@ -0,0 +1,69 @@
=============
Packaging Nim
=============
Supported architectures
-----------------------
Nim runs on a wide variety of platforms. Support on amd64 and i386 is tested regularly, while less popular platforms are tested by the community.
- amd64
- arm64 (aka aarch64)
- armel
- armhf
- i386
- m68k
- mips64el
- mipsel
- powerpc
- ppc64
- ppc64el (aka ppc64le)
- riscv64
The following platforms are seldomly tested:
- alpha
- hppa
- ia64
- mips
- s390x
- sparc64
Packaging for Linux
-------------------
See https://github.com/nim-lang/Nim/labels/Installation for installation-related bugs.
Build Nim from the released tarball at https://nim-lang.org/install_unix.html
It is different from the GitHub sources as it contains Nimble, C sources & other tools.
The Debian package ships bash and ksh completion and manpages that can be reused.
Hints on the build process:
::
# build from C sources and then using koch
./build.sh --os $os_type --cpu $cpu_arch
./bin/nim c koch
./koch boot -d:release
# optionally generate docs into doc/html
./koch docs
./koch tools -d:release
# extract files to be really installed
./install.sh <tempdir>
# also include the tools
for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn <tempdir>/nim/bin/; done
What to install:
- The expected stdlib location is /usr/lib/nim
- Global configuration files under /etc/nim
- Optionally: manpages, documentation, shell completion
- When installing documentation, .idx files are not required
- The "compiler" directory contains compiler sources and should not be part of the compiler binary package

View File

@@ -13,7 +13,6 @@ Introduction
"Repetition renders the ridiculous reasonable." -- Norman Wildberger
This document is a tutorial for the advanced constructs of the *Nim*
programming language. **Note that this document is somewhat obsolete as the**
`manual <manual.html>`_ **contains many more examples of the advanced language
@@ -652,369 +651,8 @@ avoid a common bug: to forget to close the file. Note how the
``let fn = filename`` statement ensures that ``filename`` is evaluated only
once.
Macros
======
Macros enable advanced compile-time code transformations, but they cannot
change Nim's syntax. However, this is no real restriction because Nim's
syntax is flexible enough anyway. Macros have to be implemented in pure Nim
code if the `foreign function interface (FFI)
<manual.html#foreign-function-interface>`_ is not enabled in the compiler, but
other than that restriction (which at some point in the future will go away)
you can write any kind of Nim code and the compiler will run it at compile
time.
There are two ways to write a macro, either *generating* Nim source code and
letting the compiler parse it, or creating manually an abstract syntax tree
(AST) which you feed to the compiler. In order to build the AST one needs to
know how the Nim concrete syntax is converted to an abstract syntax tree
(AST). The AST is documented in the `macros <macros.html>`_ module.
Once your macro is finished, there are two ways to invoke it:
(1) invoking a macro like a procedure call (expression macros)
(2) invoking a macro with the special ``macrostmt``
syntax (statement macros)
Expression Macros
-----------------
The following example implements a powerful ``debug`` command that accepts a
variable number of arguments:
.. code-block:: nim
:test: "nim c $1"
# to work with Nim syntax trees, we need an API that is defined in the
# ``macros`` module:
import macros
macro debug(n: varargs[untyped]): typed =
# `n` is a Nim AST that contains a list of expressions;
# this macro returns a list of statements (n is passed for proper line
# information):
result = newNimNode(nnkStmtList, n)
# iterate over any argument that is passed to this macro:
for x in n:
# add a call to the statement list that writes the expression;
# `toStrLit` converts an AST to its string representation:
result.add(newCall("write", newIdentNode("stdout"), toStrLit(x)))
# add a call to the statement list that writes ": "
result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
# add a call to the statement list that writes the expressions value:
result.add(newCall("writeLine", newIdentNode("stdout"), x))
var
a: array[0..10, int]
x = "some string"
a[0] = 42
a[1] = 45
debug(a[0], a[1], x)
The macro call expands to:
.. code-block:: nim
write(stdout, "a[0]")
write(stdout, ": ")
writeLine(stdout, a[0])
write(stdout, "a[1]")
write(stdout, ": ")
writeLine(stdout, a[1])
write(stdout, "x")
write(stdout, ": ")
writeLine(stdout, x)
Statement Macros
----------------
Statement macros are defined just as expression macros. However, they are
invoked by an expression following a colon.
The following example outlines a macro that generates a lexical analyzer from
regular expressions:
.. code-block:: nim
macro case_token(n: varargs[untyped]): typed =
# creates a lexical analyzer from regular expressions
# ... (implementation is an exercise for the reader :-)
discard
case_token: # this colon tells the parser it is a macro statement
of r"[A-Za-z_]+[A-Za-z_0-9]*":
return tkIdentifier
of r"0-9+":
return tkInteger
of r"[\+\-\*\?]+":
return tkOperator
else:
return tkUnknown
Building your first macro
-------------------------
To give a footstart to writing macros we will show now how to turn your typical
dynamic code into something that compiles statically. For the exercise we will
use the following snippet of code as the starting point:
.. code-block:: nim
:test: "nim c $1"
import strutils, tables
proc readCfgAtRuntime(cfgFilename: string): Table[string, string] =
let
inputString = readFile(cfgFilename)
var
source = ""
result = initTable[string, string]()
for line in inputString.splitLines:
# Ignore empty lines
if line.len < 1: continue
var chunks = split(line, ',')
if chunks.len != 2:
quit("Input needs comma split values, got: " & line)
result[chunks[0]] = chunks[1]
if result.len < 1: quit("Input file empty!")
let info = readCfgAtRuntime("data.cfg")
when isMainModule:
echo info["licenseOwner"]
echo info["licenseKey"]
echo info["version"]
Presumably this snippet of code could be used in a commercial software, reading
a configuration file to display information about the person who bought the
software. This external file would be generated by an online web shopping cart
to be included along the program containing the license information::
version,1.1
licenseOwner,Hyori Lee
licenseKey,M1Tl3PjBWO2CC48m
The ``readCfgAtRuntime`` proc will open the given filename and return a
``Table`` from the `tables module <tables.html>`_. The parsing of the file is
done (without much care for handling invalid data or corner cases) using the
`splitLines proc from the strutils module <strutils.html#splitLines>`_. There
are many things which can fail; mind the purpose is explaining how to make
this run at compile time, not how to properly implement a DRM scheme.
The reimplementation of this code as a compile time proc will allow us to get
rid of the ``data.cfg`` file we would need to distribute along the binary, plus
if the information is really constant, it doesn't make from a logical point of
view to have it *mutable* in a global variable, it would be better if it was a
constant. Finally, and likely the most valuable feature, we can implement some
verification at compile time. You could think of this as a *better unit
testing*, since it is impossible to obtain a binary unless everything is
correct, preventing you to ship to users a broken program which won't start
because a small critical file is missing or its contents changed by mistake to
something invalid.
Generating source code
++++++++++++++++++++++
Our first attempt will start by modifying the program to generate a compile
time string with the *generated source code*, which we then pass to the
``parseStmt`` proc from the `macros module <macros.html>`_. Here is the
modified source code implementing the macro:
.. code-block:: nim
:number-lines:
import macros, strutils
macro readCfgAndBuildSource(cfgFilename: string): typed =
let
inputString = slurp(cfgFilename.strVal)
var
source = ""
for line in inputString.splitLines:
# Ignore empty lines
if line.len < 1: continue
var chunks = split(line, ',')
if chunks.len != 2:
error("Input needs comma split values, got: " & line)
source &= "const cfg" & chunks[0] & "= \"" & chunks[1] & "\"\n"
if source.len < 1: error("Input file empty!")
result = parseStmt(source)
readCfgAndBuildSource("data.cfg")
when isMainModule:
echo cfglicenseOwner
echo cfglicenseKey
echo cfgversion
The good news is not much has changed! First, we need to change the handling
of the input parameter (line 3). In the dynamic version the
``readCfgAtRuntime`` proc receives a string parameter. However, in the macro
version it is also declared as string, but this is the *outside* interface of
the macro. When the macro is run, it actually gets a ``PNimNode`` object
instead of a string, and we have to call the `strVal proc
<macros.html#strVal>`_ (line 5) from the `macros module <macros.html>`_ to
obtain the string being passed in to the macro.
Second, we cannot use the `readFile proc <system.html#readFile>`_ from the
`system module <system.html>`_ due to FFI restriction at compile time. If we
try to use this proc, or any other which depends on FFI, the compiler will
error with the message ``cannot evaluate`` and a dump of the macro's source
code, along with a stack trace where the compiler reached before bailing out.
We can get around this limitation by using the `slurp proc
<system.html#slurp>`_ from the `system module <system.html>`_, which was
precisely made for compilation time (just like `gorge <system.html#gorge>`_
which executes an external program and captures its output).
The interesting thing is that our macro does not return a runtime `Table
<tables.html#Table>`_ object. Instead, it builds up Nim source code into
the ``source`` variable. For each line of the configuration file a ``const``
variable will be generated (line 15). To avoid conflicts we prefix these
variables with ``cfg``. In essence, what the compiler is doing is replacing
the line calling the macro with the following snippet of code:
.. code-block:: nim
const cfgversion = "1.1"
const cfglicenseOwner = "Hyori Lee"
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
You can verify this yourself adding the line ``echo source`` somewhere at the
end of the macro and compiling the program. Another difference is that instead
of calling the usual `quit proc <system.html#quit>`_ to abort (which we could
still call) this version calls the `error proc <macros.html#error>`_ (line
14). The ``error`` proc has the same behavior as ``quit`` but will dump also
the source and file line information where the error happened, making it
easier for the programmer to find where compilation failed. In this situation
it would point to the line invoking the macro, but **not** the line of
``data.cfg`` we are processing, that's something the macro itself would need
to control.
Generating AST by hand
++++++++++++++++++++++
To generate an AST we would need to intimately know the structures used by the
Nim compiler exposed in the `macros module <macros.html>`_, which at first
look seems a daunting task. But we can use as helper shortcut the `dumpTree
macro <macros.html#dumpTree>`_, which is used as a statement macro instead of
an expression macro. Since we know that we want to generate a bunch of
``const`` symbols we can create the following source file and compile it to
see what the compiler *expects* from us:
.. code-block:: nim
:test: "nim c $1"
import macros
dumpTree:
const cfgversion: string = "1.1"
const cfglicenseOwner = "Hyori Lee"
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
During compilation of the source code we should see the following lines in the
output (again, since this is a macro, compilation is enough, you don't have to
run any binary)::
StmtList
ConstSection
ConstDef
Ident !"cfgversion"
Ident !"string"
StrLit 1.1
ConstSection
ConstDef
Ident !"cfglicenseOwner"
Empty
StrLit Hyori Lee
ConstSection
ConstDef
Ident !"cfglicenseKey"
Empty
StrLit M1Tl3PjBWO2CC48m
With this output we have a better idea of what kind of input the compiler
expects. We need to generate a list of statements. For each constant the source
code generates a ``ConstSection`` and a ``ConstDef``. If we were to move all
the constants to a single ``const`` block we would see only a single
``ConstSection`` with three children.
Maybe you didn't notice, but in the ``dumpTree`` example the first constant
explicitly specifies the type of the constant. That's why in the tree output
the two last constants have their second child ``Empty`` but the first has a
string identifier. So basically a ``const`` definition is made up from an
identifier, optionally a type (can be an *empty* node) and the value. Armed
with this knowledge, let's look at the finished version of the AST building
macro:
.. code-block:: nim
:number-lines:
import macros, strutils
macro readCfgAndBuildAST(cfgFilename: string): typed =
let
inputString = slurp(cfgFilename.strVal)
result = newNimNode(nnkStmtList)
for line in inputString.splitLines:
# Ignore empty lines
if line.len < 1: continue
var chunks = split(line, ',')
if chunks.len != 2:
error("Input needs comma split values, got: " & line)
var
section = newNimNode(nnkConstSection)
constDef = newNimNode(nnkConstDef)
constDef.add(newIdentNode("cfg" & chunks[0]))
constDef.add(newEmptyNode())
constDef.add(newStrLitNode(chunks[1]))
section.add(constDef)
result.add(section)
if result.len < 1: error("Input file empty!")
readCfgAndBuildAST("data.cfg")
when isMainModule:
echo cfglicenseOwner
echo cfglicenseKey
echo cfgversion
Since we are building on the previous example generating source code, we will
only mention the differences to it. Instead of creating a temporary ``string``
variable and writing into it source code as if it were written *by hand*, we
use the ``result`` variable directly and create a statement list node
(``nnkStmtList``) which will hold our children (line 7).
For each input line we have to create a constant definition (``nnkConstDef``)
and wrap it inside a constant section (``nnkConstSection``). Once these
variables are created, we fill them hierarchichally (line 17) like the
previous AST dump tree showed: the constant definition is a child of the
section definition, and the constant definition has an identifier node, an
empty node (we let the compiler figure out the type), and a string literal
with the value.
A last tip when writing a macro: if you are not sure the AST you are building
looks ok, you may be tempted to use the ``dumpTree`` macro. But you can't use
it *inside* the macro you are writting/debugging. Instead ``echo`` the string
generated by `treeRepr <macros.html#treeRepr>`_. If at the end of the this
example you add ``echo treeRepr(result)`` you should get the same output as
using the ``dumpTree`` macro, but of course you can call that at any point of
the macro where you might be having troubles.
Example Templates and Macros
============================
Lifting Procs
+++++++++++++
Example: Lifting Procs
----------------------
.. code-block:: nim
:test: "nim c $1"
@@ -1039,36 +677,6 @@ Lifting Procs
liftScalarProc(sqrt) # make sqrt() work for sequences
echo sqrt(@[4.0, 16.0, 25.0, 36.0]) # => @[2.0, 4.0, 5.0, 6.0]
Identifier Mangling
+++++++++++++++++++
.. code-block:: nim
proc echoHW() =
echo "Hello world"
proc echoHW0() =
echo "Hello world 0"
proc echoHW1() =
echo "Hello world 1"
template joinSymbols(a, b: untyped): untyped =
`a b`()
joinSymbols(echo, HW)
macro str2Call(s1, s2): typed =
result = newNimNode(nnkStmtList)
for i in 0..1:
# combines s1, s2 and an integer into an proc identifier
# that is called in a statement list
result.add(newCall(!($s1 & $s2 & $i)))
str2Call("echo", "HW")
# Output:
# Hello world
# Hello world 0
# Hello world 1
Compilation to JavaScript
=========================
@@ -1083,3 +691,9 @@ JavaScript-compatible code you should remember the following:
- ``cstring`` in JavaScript means JavaScript string. It is a good practice to
use ``cstring`` only when it is semantically appropriate. E.g. don't use
``cstring`` as a binary data buffer.
Part 3
======
Next part will be entirely about metaprogramming via macros: `Part III <tut3.html>`_

354
doc/tut3.rst Normal file
View File

@@ -0,0 +1,354 @@
=======================
Nim Tutorial (Part III)
=======================
:Author: Arne Döring
:Version: |nimversion|
.. contents::
Introduction
============
"With Great Power Comes Great Responsibility." -- Spider Man's Uncle
This document is a tutorial about Nim's macro system.
A macro is a function that is executed at compile time and transforms
a Nim syntax tree into a different tree.
Examples of things that can be implemented in macros:
* An assert macro that prints both sides of a comparison operator, if
the assertion fails. ``myAssert(a == b)`` is converted to
``if a != b: quit($a " != " $b)``
* A debug macro that prints the value and the name of the symbol.
``myDebugEcho(a)`` is converted to ``echo "a: ", a``
* Symbolic differentiation of an expression.
``diff(a*pow(x,3) + b*pow(x,2) + c*x + d, x)`` is converted to
``3*a*pow(x,2) + 2*a*x + c``
Macro Arguments
---------------
The types of macro arguments have two faces. One face is used for
the overload resolution, and the other face is used within the macro
body. For example, if ``macro foo(arg: int)`` is called in an
expression ``foo(x)``, ``x`` has to be of a type compatible to int, but
*within* the macro's body ``arg`` has the type ``NimNode``, not ``int``!
Why it is done this way will become obvious later, when we have seen
concrete examples.
There are two ways to pass arguments to a macro, an argument can be
either ``typed`` or ``untyped``.
Untyped Arguments
-----------------
Untyped macro arguments are passed to the macro before they are
semantically checked. This means the syntax tree that is passed down
to the macro does not need to make sense for Nim yet, the only
limitation is that it needs to be parseable. Usually the macro does
not check the argument either but uses it in the transformation's
result somehow. The result of a macro expansion is always checked
by the compiler, so apart from weird error messages nothing bad
can happen.
The downside for an ``untyped`` argument is that these do not play
well with Nim's overloading resolution.
The upside for untyped arguments is that the syntax tree is
quite predictable and less complex compared to its ``typed``
counterpart.
Typed Arguments
---------------
For typed arguments, the semantic checker runs on the argument and
does transformations on it, before it is passed to the macro. Here
identifier nodes are resolved as symbols, implicit type
conversions are visible in the tree as calls, templates are
expanded and probably most importantly, nodes have type information.
Typed arguments can have the type ``typed`` in the arguments list.
But all other types, such as ``int``, ``float`` or ``MyObjectType``
are typed arguments as well, and they are passed to the macro as a
syntax tree.
Static Arguments
----------------
Static arguments are a way to pass values as values and not as syntax
tree nodes to a macro. For example for ``macro foo(arg: static[int])``
in the expression ``foo(x)``, ``x`` needs to be an integer constant,
but in the macro body ``arg`` is just like a normal parameter of type
``int``.
.. code-block:: nim
import macros
macro myMacro(arg: static[int]): untyped =
echo arg # just an int (7), not ``NimNode``
myMacro(1 + 2 * 3)
Code blocks as arguments
------------------------
It is possible to pass the last argument of a call expression in a
separate code block with indentation. For example the following code
example is a valid (but not a recommended) way to call ``echo``:
.. code-block:: nim
echo "Hello ":
let a = "Wor"
let b = "ld!"
a & b
For macros this way of calling is very useful; syntax trees of arbitrary
complexity can be passed to macros with this notation.
The Syntax Tree
---------------
In order to build a Nim syntax tree one needs to know how Nim source
code is represented as a syntax tree, and how such a tree needs to
look like so that the Nim compiler will understand it. The nodes of the
Nim syntax tree are documented in the `macros <macros.html>`_ module.
But a more interactive way to explore the Nim
syntax tree is with ``macros.treeRepr``, it converts a syntax tree
into a multi line string for printing on the console. It can be used
to explore how the argument expressions are represented in tree form
and for debug printing of generated syntax tree. ``dumpTree`` is a
predefined macro that just prints its argument in tree representation,
but does nothing else. Here is an example of such a tree representation:
.. code-block:: nim
dumpTree:
var mt: MyType = MyType(a:123.456, b:"abcdef")
# output:
# StmtList
# VarSection
# IdentDefs
# Ident "mt"
# Ident "MyType"
# ObjConstr
# Ident "MyType"
# ExprColonExpr
# Ident "a"
# FloatLit 123.456
# ExprColonExpr
# Ident "b"
# StrLit "abcdef"
Custom sematic checking
-----------------------
The first thing that a macro should do with its arguments is to check
if the argument is in the correct form. Not every type of wrong input
needs to be caught here, but anything that could cause a crash during
macro evaluation should be caught and create a nice error message.
``macros.expectKind`` and ``macros.expectLen`` are a good start. If
the checks need to be more complex, arbitrary error messages can
be created with the ``macros.error`` proc.
.. code-block:: nim
macro myAssert(arg: untyped): untyped =
arg.expectKind nnkInfix
Generating Code
---------------
There are two ways to generate the code. Either by creating the syntax
tree with expressions that contain a lot of calls to ``newTree`` and
``newLit``, or with ``quote do:`` expressions. The first option offers
the best low level control for the syntax tree generation, but the
second option is much less verbose. If you choose to create the syntax
tree with calls to ``newTree`` and ``newLit`` the macro
``marcos.dumpAstGen`` can help you with the verbosity. ``quote do:``
allows you to write the code that you want to generate literally,
backticks are used to insert code from ``NimNode`` symbols into the
generated expression. This means that you can't use backticks within
``quote do:`` for anything else than injecting symbols. Make sure to
inject only symbols of type ``NimNode`` into the generated syntax
tree. You can use ``newLit`` to convert arbitrary values into
expressions trees of type ``NimNode`` so that it is safe to inject
them into the tree.
.. code-block:: nim
:test: "nim c $1"
import macros
type
MyType = object
a: float
b: string
macro myMacro(arg: untyped): untyped =
var mt: MyType = MyType(a:123.456, b:"abcdef")
# ...
let mtLit = newLit(mt)
result = quote do:
echo `arg`
echo `mtLit`
myMacro("Hallo")
The call to ``myMacro`` will generate the following code:
.. code-block:: nim
echo "Hallo"
echo MyType(a: 123.456'f64, b: "abcdef")
Building your first macro
-------------------------
To give a footstart to writing macros we will show now how to
implement the ``myDebug`` macro mentioned earlier. The first thing to
do is to build a simple example of the macro usage, and then just
print the argument. This way it is possible to get an idea of a
correct argument should be look like.
.. code-block:: nim
:test: "nim c $1"
import macros
macro myAssert(arg: untyped): untyped =
echo arg.treeRepr
let a = 1
let b = 2
myAssert(a != b)
.. code-block::
Infix
Ident "!="
Ident "a"
Ident "b"
From the output it is possible to see that the information that the
argument is an infix operator (node kind is "Infix"), as well as that the two
operands are at index 1 and 2. With this information the actual
macro can be written.
.. code-block:: nim
:test: "nim c $1"
import macros
macro myAssert(arg: untyped): untyped =
# all node kind identifiers are prefixed with "nnk"
arg.expectKind nnkInfix
arg.expectLen 3
# operator as string literal
let op = newLit(" " & arg[0].repr & " ")
let lhs = arg[1]
let rhs = arg[2]
result = quote do:
if not `arg`:
raise newException(AssertionError,$`lhs` & `op` & $`rhs`)
let a = 1
let b = 2
myAssert(a != b)
myAssert(a == b)
This is the code that will be generated. To debug what the macro
actually generated, the statement ``echo result.repr`` can be used, in
the last line of the macro. It is also the statement that has been
used to get this output.
.. code-block:: nim
if not (a != b):
raise newException(AssertionError, $a & " != " & $b)
With Power Comes Responsibility
-------------------------------
Macros are very powerful. A good advice is to use them as little as
possible, but as much as necessary. Macros can change the semantics of
expressions, making the code incomprehensible for anybody who does not
know exactly what the macro does with it. So whenever a macro is not
necessary and the same logic can be implemented using templates or
generics, it is probably better not to use a macro. And when a macro
is used for something, the macro should better have a well written
documentation. For all the people who claim to write only perfectly
self-explanatory code: when it comes to macros, the implementation is
not enough for documentation.
Limitations
-----------
Since macros are evaluated in the compiler in the NimVM, macros share
all the limitations of the NimVM. They have to be implemented in pure Nim
code. Macros can start external processes on the shell, but they
cannot call C functions except from those that are built in the
compiler.
More Examples
=============
This tutorial can only cover the basics of the macro system. There are
macros out there that could be an inspiration for you of what is
possible with it.
Strformat
---------
In the Nim standard library, the ``strformat`` library provides a
macro that parses a string literal at compile time. Parsing a string
in a macro like here is generally not recommended. The parsed AST
cannot have type information, and parsing implemented on the VM is
generally not very fast. Working on AST nodes is almost always the
recommended way. But still ``strformat`` is a good example for a
practical use case for a macro that is slightly more complex that the
``assert`` macro.
`Strformat <https://github.com/nim-lang/Nim/blob/5845716df8c96157a047c2bd6bcdd795a7a2b9b1/lib/pure/strformat.nim#L280>`_
Ast Pattern Matching
--------------------
Ast Pattern Matching is a macro library to aid in writing complex
macros. This can be seen as a good example of how to repurpose the
Nim syntax tree with new semantics.
`Ast Pattern Matching <https://github.com/krux02/ast-pattern-matching>`_
OpenGL Sandbox
--------------
This project has a working Nim to GLSL compiler written entirely in
macros. It scans recursively though all used function symbols to
compile them so that cross library functions can be executed on the GPU.
`OpenGL Sandbox <https://github.com/krux02/opengl-sandbox>`_

View File

@@ -380,11 +380,11 @@ template `|`(a, b): string = (if a.len > 0: a else: b)
proc tests(args: string) =
# we compile the tester with taintMode:on to have a basic
# taint mode test :-)
nimexec "cc --taintMode:on --opt:speed tests/testament/tester"
nimexec "cc --taintMode:on --opt:speed testament/tester"
# Since tests take a long time (on my machine), and we want to defy Murhpys
# law - lets make sure the compiler really is freshly compiled!
nimexec "c --lib:lib -d:release --opt:speed compiler/nim.nim"
let tester = quoteShell(getCurrentDir() / "tests/testament/tester".exe)
let tester = quoteShell(getCurrentDir() / "testament/tester".exe)
let success = tryExec tester & " " & (args|"all")
if not existsEnv("TRAVIS") and not existsEnv("APPVEYOR"):
exec tester & " html"
@@ -474,8 +474,7 @@ proc testUnixInstall(cmdLineRest: string) =
execCleanPath("./koch --latest tools")
# check the tests work:
putEnv("NIM_EXE_NOT_IN_PATH", "NOT_IN_PATH")
execCleanPath("./koch tests", destDir / "bin")
#execCleanPath("./koch tests cat newconfig", destDir / "bin")
execCleanPath("./koch tests cat megatest", destDir / "bin")
else:
echo "Version check: failure"
finally:

View File

@@ -1034,10 +1034,18 @@ proc name*(someProc: NimNode): NimNode {.compileTime.} =
someProc.expectRoutine
result = someProc[0]
if result.kind == nnkPostfix:
result = result[1]
if result[1].kind == nnkAccQuoted:
result = result[1][0]
else:
result = result[1]
elif result.kind == nnkAccQuoted:
result = result[0]
proc `name=`*(someProc: NimNode; val: NimNode) {.compileTime.} =
someProc.expectRoutine
someProc[0] = val
if someProc[0].kind == nnkPostfix:
someProc[0][1] = val
else: someProc[0] = val
proc params*(someProc: NimNode): NimNode {.compileTime.} =
someProc.expectRoutine

View File

@@ -108,6 +108,7 @@ proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
of 1: d = ze(cast[ptr int8](a +% n.offset)[])
of 2: d = ze(cast[ptr int16](a +% n.offset)[])
of 4: d = int(cast[ptr int32](a +% n.offset)[])
of 8: d = int(cast[ptr int64](a +% n.offset)[])
else: assert(false)
return d

View File

@@ -180,7 +180,7 @@ proc asyncSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP,
buffered = true): AsyncSocket =
## Initialises an AsyncSocket object. If a socket cannot be initialised
## EOS is raised.
## OSError is raised.
result = newAsyncSocket()
result.socket = socket(domain, typ, protocol, buffered)
result.proto = protocol
@@ -476,7 +476,7 @@ proc recvLine*(s: AsyncSocket, line: var TaintedString): bool {.deprecated.} =
## if this function can only retrieve some data; it will save this data and
## add it to the result when a full line is retrieved.
##
## Unlike ``sockets.recvLine`` this function will raise an EOS or ESSL
## Unlike ``sockets.recvLine`` this function will raise an OSError or SslError
## exception if an error occurs.
##
## **Deprecated since version 0.9.2**: This function has been deprecated in
@@ -512,7 +512,7 @@ proc readLine*(s: AsyncSocket, line: var TaintedString): bool =
## retrieved or the socket has been disconnected in which case ``line`` will
## be set to "".
##
## This function will raise an EOS exception when a socket error occurs.
## This function will raise an OSError exception when a socket error occurs.
setLen(line.string, 0)
var dataReceived = "".TaintedString
var ret = s.socket.readLineAsync(dataReceived)

View File

@@ -23,7 +23,7 @@
##
## SSL is supported through the OpenSSL library. This support can be activated
## by compiling with the ``-d:ssl`` switch. When an SSL socket is used it will
## raise ESSL exceptions when SSL errors occur.
## raise SslError exceptions when SSL errors occur.
##
## Asynchronous sockets are supported, however a better alternative is to use
## the `asyncio <asyncio.html>`_ module.
@@ -262,7 +262,7 @@ proc socket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP, buffered = true): Socket =
## Creates a new socket; returns `InvalidSocket` if an error occurs.
# TODO: Perhaps this should just raise EOS when an error occurs.
# TODO: Perhaps this should just raise OSError when an error occurs.
when defined(Windows):
result = newTSocket(winlean.socket(cint(domain), cint(typ), cint(protocol)), buffered)
else:
@@ -422,7 +422,7 @@ proc parseIp4*(s: string): BiggestInt =
##
## This is equivalent to `inet_ntoa`:idx:.
##
## Raises EInvalidValue in case of an error.
## Raises ValueError in case of an error.
var a, b, c, d: int
var i = 0
var j = parseInt(s, a, i)
@@ -543,7 +543,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string) {.
## If ``server`` is non-blocking then this function returns immediately, and
## if there are no connections queued the returned socket will be
## ``InvalidSocket``.
## This function will raise EOS if an error occurs.
## This function will raise OSError if an error occurs.
##
## The resulting client will inherit any properties of the server socket. For
## example: whether the socket is buffered or not.
@@ -664,7 +664,7 @@ proc close*(socket: Socket) =
discard winlean.closesocket(socket.fd)
else:
discard posix.close(socket.fd)
# TODO: These values should not be discarded. An EOS should be raised.
# TODO: These values should not be discarded. An OSError should be raised.
# http://stackoverflow.com/questions/12463473/what-happens-if-you-call-close-on-a-bsd-socket-multiple-times
when defined(ssl):
if socket.isSSL:
@@ -920,7 +920,7 @@ when defined(ssl):
## Returns ``False`` whenever the socket is not yet ready for a handshake,
## ``True`` whenever handshake completed successfully.
##
## A ESSL error is raised on any other errors.
## A SslError error is raised on any other errors.
result = true
if socket.isSSL:
var ret = SSLConnect(socket.sslHandle)
@@ -946,7 +946,7 @@ when defined(ssl):
## Determines whether a handshake has occurred between a client (``socket``)
## and the server that ``socket`` is connected to.
##
## Throws ESSL if ``socket`` is not an SSL socket.
## Throws SslError if ``socket`` is not an SSL socket.
if socket.isSSL:
return not socket.sslNoHandshake
else:
@@ -1215,7 +1215,7 @@ proc recv*(socket: Socket, data: var string, size: int, timeout = -1): int =
##
## When 0 is returned the socket's connection has been closed.
##
## This function will throw an EOS exception when an error occurs. A value
## This function will throw an OSError exception when an error occurs. A value
## lower than 0 is never returned.
##
## A timeout may be specified in milliseconds, if enough data is not received
@@ -1273,7 +1273,7 @@ proc recvLine*(socket: Socket, line: var TaintedString, timeout = -1): bool {.
## will be set to it.
##
## ``True`` is returned if data is available. ``False`` suggests an
## error, EOS exceptions are not raised and ``False`` is simply returned
## error, OSError exceptions are not raised and ``False`` is simply returned
## instead.
##
## If the socket is disconnected, ``line`` will be set to ``""`` and ``True``
@@ -1321,7 +1321,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1) {.
##
## If the socket is disconnected, ``line`` will be set to ``""``.
##
## An EOS exception will be raised in the case of a socket error.
## An OSError exception will be raised in the case of a socket error.
##
## A timeout can be specified in milliseconds, if data is not received within
## the specified time an ETimeout exception will be raised.
@@ -1394,7 +1394,7 @@ proc readLineAsync*(socket: Socket,
## * If some data has been retrieved; ``ReadPartialLine`` is returned.
## * If the socket has been disconnected; ``ReadDisconnected`` is returned.
## * If no data could be retrieved; ``ReadNone`` is returned.
## * If call to ``recv`` failed; **an EOS exception is raised.**
## * If call to ``recv`` failed; **an OSError exception is raised.**
setLen(line.string, 0)
template errorOrNone =
@@ -1421,7 +1421,7 @@ proc readLineAsync*(socket: Socket,
proc recv*(socket: Socket): TaintedString {.tags: [ReadIOEffect], deprecated.} =
## receives all the available data from the socket.
## Socket errors will result in an ``EOS`` error.
## Socket errors will result in an ``OSError`` error.
## If socket is not a connectionless socket and socket is not connected
## ``""`` will be returned.
##
@@ -1470,7 +1470,7 @@ proc recvAsync*(socket: Socket, s: var TaintedString): bool {.
tags: [ReadIOEffect], deprecated.} =
## receives all the data from a non-blocking socket. If socket is non-blocking
## and there are no messages available, `False` will be returned.
## Other socket errors will result in an ``EOS`` error.
## Other socket errors will result in an ``OSError`` error.
## If socket is not a connectionless socket and socket is not connected
## ``s`` will be set to ``""``.
##
@@ -1547,7 +1547,7 @@ proc recvFromAsync*(socket: Socket, data: var string, length: int,
address: var string, port: var Port,
flags = 0'i32): bool {.tags: [ReadIOEffect].} =
## Variant of ``recvFrom`` for non-blocking sockets. Unlike ``recvFrom``,
## this function will raise an EOS error whenever a socket error occurs.
## this function will raise an OSError error whenever a socket error occurs.
##
## If there is no data to be read from the socket ``False`` will be returned.
result = true
@@ -1622,7 +1622,7 @@ proc sendAsync*(socket: Socket, data: string): int {.tags: [WriteIOEffect].} =
## returns the amount of bytes of ``data`` that was successfully sent. This
## number may not always be the length of ``data`` but typically is.
##
## An EOS (or ESSL if socket is an SSL socket) exception is raised if an error
## An OSError (or SslError if socket is an SSL socket) exception is raised if an error
## occurs.
result = send(socket, cstring(data), data.len)
when defined(ssl):
@@ -1656,7 +1656,7 @@ proc sendAsync*(socket: Socket, data: string): int {.tags: [WriteIOEffect].} =
proc trySend*(socket: Socket, data: string): bool {.tags: [WriteIOEffect].} =
## safe alternative to ``send``. Does not raise an EOS when an error occurs,
## safe alternative to ``send``. Does not raise an OSError when an error occurs,
## and instead returns ``false`` on failure.
result = send(socket, cstring(data), data.len) == data.len

View File

@@ -133,7 +133,7 @@ proc getErrInfo(db: var DbConn): tuple[res: int, ss, ne, msg: string] {.
511.TSqlSmallInt, retSz.addr.PSQLSMALLINT)
except:
discard
return (res.int, $sqlState, $nativeErr, $errMsg)
return (res.int, $(addr sqlState), $(addr nativeErr), $(addr errMsg))
proc dbError*(db: var DbConn) {.
tags: [ReadDbEffect, WriteDbEffect], raises: [DbError] .} =

View File

@@ -31,7 +31,7 @@
##
## .. code-block:: Nim
## import db_sqlite
## let db = open("mytest.db", nil, nil, nil) # user, password, database name can be nil
## let db = open("mytest.db", "", "", "") # user, password, database name can be empty
## db.close()
##
## Creating a table

View File

@@ -8,7 +8,7 @@
from pcre import nil
import nre.private.util
import nre/private/util
import tables
from strutils import `%`
from math import ceil
@@ -469,7 +469,8 @@ proc matchImpl(str: string, pattern: Regex, start, endpos: int, flags: int): Opt
# 1x capture count as slack space for PCRE
let vecsize = (pattern.captureCount() + 1) * 3
# div 2 because each element is 2 cints long
myResult.pcreMatchBounds = newSeq[HSlice[cint, cint]](ceil(vecsize / 2).int)
# plus 1 because we need the ceiling, not the floor
myResult.pcreMatchBounds = newSeq[HSlice[cint, cint]]((vecsize + 1) div 2)
myResult.pcreMatchBounds.setLen(vecsize div 3)
let strlen = if endpos == int.high: str.len else: endpos+1

View File

@@ -408,7 +408,7 @@ proc startsWith*(s: string, prefix: Regex): bool {.inline.} =
result = matchLen(s, prefix) >= 0
proc endsWith*(s: string, suffix: Regex): bool {.inline.} =
## returns true if `s` ends with the pattern `prefix`
## returns true if `s` ends with the pattern `suffix`
for i in 0 .. s.len-1:
if matchLen(s, suffix, i) == s.len - i: return true
@@ -428,7 +428,7 @@ proc replace*(s: string, sub: Regex, by = ""): string =
## "; "
result = ""
var prev = 0
while true:
while prev < s.len:
var match = findBounds(s, sub, prev)
if match.first < 0: break
add(result, substr(s, prev, match.first-1))
@@ -453,7 +453,7 @@ proc replacef*(s: string, sub: Regex, by: string): string =
result = ""
var caps: array[MaxSubpatterns, string]
var prev = 0
while true:
while prev < s.len:
var match = findBounds(s, sub, caps, prev)
if match.first < 0: break
add(result, substr(s, prev, match.first-1))

View File

@@ -105,7 +105,7 @@ proc add*(monitor: FSMonitor, target: string,
proc del*(monitor: FSMonitor, wd: cint) =
## Removes watched directory or file as specified by ``wd`` from ``monitor``.
##
## If ``wd`` is not a part of ``monitor`` an EOS error is raised.
## If ``wd`` is not a part of ``monitor`` an OSError error is raised.
if inotifyRmWatch(monitor.fd, wd) < 0:
raiseOSError(osLastError())

View File

@@ -145,7 +145,9 @@ export asyncfutures, asyncstreams
##
## Futures should **never** be discarded. This is because they may contain
## errors. If you do not care for the result of a Future then you should
## use the ``asyncCheck`` procedure instead of the ``discard`` keyword.
## use the ``asyncCheck`` procedure instead of the ``discard`` keyword. Note
## however that this does not wait for completion, and you should use
## ``waitFor`` for that purpose.
##
## Examples
## --------

View File

@@ -339,7 +339,8 @@ proc asyncCheck*[T](future: Future[T]) =
## Sets a callback on ``future`` which raises an exception if the future
## finished with an error.
##
## This should be used instead of ``discard`` to discard void futures.
## This should be used instead of ``discard`` to discard void futures,
## or use ``waitFor`` if you need to wait for the future's completion.
assert(not future.isNil, "Future is nil")
future.callback =
proc () =

View File

@@ -245,6 +245,12 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
var outerProcBody = newNimNode(nnkStmtList, prc.body)
# Extract the documentation comment from the original procedure declaration.
# Note that we're not removing it from the body in order not to make this
# transformation even more complex.
if prc.body.len > 1 and prc.body[0].kind == nnkCommentStmt:
outerProcBody.add(prc.body[0])
# -> var retFuture = newFuture[T]()
var retFutureSym = genSym(nskVar, "retFuture")
var subRetType =

View File

@@ -218,7 +218,7 @@ when defineSsl:
var data = await recv(socket.fd.AsyncFD, BufferSize, flags)
let length = len(data)
if length > 0:
let ret = bioWrite(socket.bioIn, addr data[0], data.len.cint)
let ret = bioWrite(socket.bioIn, addr data[0], length.cint)
if ret < 0:
raiseSSLError()
elif length == 0:
@@ -599,7 +599,7 @@ proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].}
## ``Backlog`` specifies the maximum length of the
## queue of pending connections.
##
## Raises an EOS error upon failure.
## Raises an OSError error upon failure.
if listen(socket.fd, backlog) < 0'i32: raiseOSError(osLastError())
proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.

View File

@@ -81,6 +81,9 @@ proc read*[T](future: FutureStream[T]): Future[(bool, T)] =
let savedCb = future.cb
future.callback =
proc (fs: FutureStream[T]) =
# Exit early if `resFut` is already complete. (See #8994).
if resFut.finished: return
# We don't want this callback called again.
future.cb = nil
@@ -93,8 +96,7 @@ proc read*[T](future: FutureStream[T]): Future[(bool, T)] =
res[0] = true
res[1] = fs.queue.popFirst()
if not resFut.finished:
resFut.complete(res)
resFut.complete(res)
# If the saved callback isn't nil then let's call it.
if not savedCb.isNil: savedCb()

View File

@@ -158,10 +158,14 @@ template rawGetKnownHCImpl() {.dirty.} =
h = nextTry(h, high(s.data))
result = -1 - h # < 0 => MISSING; insert idx = -1 - result
template rawGetImpl() {.dirty.} =
hc = hash(key)
template genHash(key: typed): Hash =
var hc = hash(key)
if hc == 0: # This almost never taken branch should be very predictable.
hc = 314159265 # Value doesn't matter; Any non-zero favorite is fine.
hc
template rawGetImpl() {.dirty.} =
hc = genHash(key)
rawGetKnownHCImpl()
template rawInsertImpl() {.dirty.} =
@@ -794,39 +798,24 @@ proc incl*[A](s: var HashSet[A], other: OrderedSet[A]) =
proc exclImpl[A](s: var OrderedSet[A], key: A) : bool {. inline .} =
assert s.isValid, "The set needs to be initialized."
var hc: Hash
var i = rawGet(s, key, hc)
var msk = high(s.data)
var n: OrderedKeyValuePairSeq[A]
newSeq(n, len(s.data))
var h = s.first
s.first = -1
s.last = -1
swap(s.data, n)
let hc = genHash(key)
result = true
if i >= 0:
result = false
# Fix ordering
if s.first == i:
s.first = s.data[i].next
else:
var itr = s.first
while true:
if (s.data[itr].next == i):
s.data[itr].next = s.data[i].next
if s.last == i:
s.last = itr
break
itr = s.data[itr].next
dec(s.counter)
while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1
var j = i # The correctness of this depends on (h+1) in nextTry,
var r = j # though may be adaptable to other simple sequences.
s.data[i].hcode = 0 # mark current EMPTY
s.data[i].key = default(type(s.data[i].key))
s.data[i].next = 0
doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
i = (i + 1) and msk # increment mod table size
if isEmpty(s.data[i].hcode): # end of collision cluster; So all done
return
r = s.data[i].hcode and msk # "home" location of key@i
shallowCopy(s.data[j], s.data[i]) # data[i] will be marked EMPTY next loop
while h >= 0:
var nxt = n[h].next
if isFilled(n[h].hcode):
if n[h].hcode == hc and n[h].key == key:
dec s.counter
result = false
else:
var j = -1 - rawGetKnownHC(s, n[h].key, n[h].hcode)
rawInsert(s, s.data, n[h].key, n[h].hcode, j)
h = nxt
proc missingOrExcl*[A](s: var OrderedSet[A], key: A): bool =
## Excludes `key` in the set `s` and tells if `key` was removed from `s`. Efficiency: O(n).
@@ -1097,6 +1086,12 @@ when isMainModule and not defined(release):
for item in s: items.add item
assert items == @[2, 6, 7]
block: #9005
var s = initOrderedSet[(int, int)]()
for i in 0 .. 30: incl(s, (i, 0))
for i in 0 .. 30: excl(s, (i, 0))
doAssert s.len == 0
#block orderedSetIterator:
# var a = initOrderedSet[int]()
# for value in [9, 2, 1, 5, 1, 8, 4, 2]:

File diff suppressed because it is too large Load Diff

View File

@@ -377,7 +377,7 @@ proc colorNameCmp(x: tuple[name: string, col: Color], y: string): int =
proc parseColor*(name: string): Color =
## parses `name` to a color value. If no valid color could be
## parsed ``EInvalidValue`` is raised. Case insensitive.
## parsed ``ValueError`` is raised. Case insensitive.
if name[0] == '#':
result = Color(parseHexInt(name))
else:

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
## Implements Nim's 'spawn'.
## Implements Nim's `spawn <manual.html#parallel-amp-spawn>`_.
when not compileOption("threads"):
{.error: "Threadpool requires --threads:on option.".}

295
lib/pure/editdistance.nim Normal file
View File

@@ -0,0 +1,295 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2018 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module implements an algorithm to compute the
## `edit distance`:idx: between two Unicode strings.
import unicode
proc editDistance*(a, b: string): int {.noSideEffect.} =
## Returns the unicode-rune edit distance between ``a`` and ``b``.
##
## This uses the `Levenshtein`:idx: distance algorithm with only a linear
## memory overhead.
if len(a) > len(b):
# make ``b`` the longer string
return editDistance(b, a)
# strip common prefix
var
i_start = 0 ## The character starting index of the first rune in both strings ``a`` and ``b``
i_next_a = 0
i_next_b = 0
rune_a, rune_b: Rune
len_runes_a = 0 ## The number of relevant runes in string ``a``.
len_runes_b = 0 ## The number of relevant runes in string ``b``.
block commonPrefix:
# ``a`` is the shorter string
while i_start < len(a):
i_next_a = i_start
a.fastRuneAt(i_next_a, rune_a, doInc = true)
i_next_b = i_start
b.fastRuneAt(i_next_b, rune_b, doInc = true)
if rune_a != rune_b:
inc(len_runes_a)
inc(len_runes_b)
break
i_start = i_next_a
var
# we know that we are either at the start of the strings
# or that the current value of rune_a is not equal to rune_b
# => start search for common suffix after the current rune (``i_next_*``)
i_end_a = i_next_a ## The exclusive upper index bound of string ``a``.
i_end_b = i_next_b ## The exclusive upper index bound of string ``b``.
i_current_a = i_next_a
i_current_b = i_next_b
block commonSuffix:
var
add_runes_a = 0
add_runes_b = 0
while i_current_a < len(a) and i_current_b < len(b):
i_next_a = i_current_a
a.fastRuneAt(i_next_a, rune_a)
i_next_b = i_current_b
b.fastRuneAt(i_next_b, rune_b)
inc(add_runes_a)
inc(add_runes_b)
if rune_a != rune_b:
i_end_a = i_next_a
i_end_b = i_next_b
inc(len_runes_a, add_runes_a)
inc(len_runes_b, add_runes_b)
add_runes_a = 0
add_runes_b = 0
i_current_a = i_next_a
i_current_b = i_next_b
if i_current_a >= len(a): # ``a`` exhausted
if i_current_b < len(b): # ``b`` not exhausted
i_end_a = i_current_a
i_end_b = i_current_b
inc(len_runes_a, add_runes_a)
inc(len_runes_b, add_runes_b)
while true:
b.fastRuneAt(i_end_b, rune_b)
inc(len_runes_b)
if i_end_b >= len(b): break
elif i_current_b >= len(b): # ``b`` exhausted and ``a`` not exhausted
i_end_a = i_current_a
i_end_b = i_current_b
inc(len_runes_a, add_runes_a)
inc(len_runes_b, add_runes_b)
while true:
a.fastRuneAt(i_end_a, rune_a)
inc(len_runes_a)
if i_end_a >= len(a): break
block specialCases:
# trivial cases:
if len_runes_a == 0: return len_runes_b
if len_runes_b == 0: return len_runes_a
# another special case:
if len_runes_a == 1:
a.fastRuneAt(i_start, rune_a, doInc = false)
var i_current_b = i_start
while i_current_b < i_end_b:
b.fastRuneAt(i_current_b, rune_b, doInc = true)
if rune_a == rune_b: return len_runes_b - 1
return len_runes_b
# common case:
var
len1 = len_runes_a + 1
len2 = len_runes_b + 1
row: seq[int]
let half = len_runes_a div 2
newSeq(row, len2)
var e = i_start + len2 - 1 # end marker
# initialize first row:
for i in 1 .. (len2 - half - 1): row[i] = i
row[0] = len1 - half - 1
i_current_a = i_start
var
char2p_i = -1
char2p_prev: int
for i in 1 .. (len1 - 1):
i_next_a = i_current_a
a.fastRuneAt(i_next_a, rune_a)
var
char2p: int
D, x: int
p: int
if i >= (len1 - half):
# skip the upper triangle:
let offset = i + half - len1
if char2p_i == i:
b.fastRuneAt(char2p_prev, rune_b)
char2p = char2p_prev
char2p_i = i + 1
else:
char2p = i_start
for j in 0 ..< offset:
rune_b = b.runeAt(char2p)
inc(char2p, rune_b.size)
char2p_i = i + 1
char2p_prev = char2p
p = offset
rune_b = b.runeAt(char2p)
var c3 = row[p] + (if rune_a != rune_b: 1 else: 0)
inc(char2p, rune_b.size)
inc(p)
x = row[p] + 1
D = x
if x > c3: x = c3
row[p] = x
inc(p)
else:
p = 1
char2p = i_start
D = i
x = i
if i <= (half + 1):
# skip the lower triangle:
e = len2 + i - half - 2
# main:
while p <= e:
dec(D)
rune_b = b.runeAt(char2p)
var c3 = D + (if rune_a != rune_b: 1 else: 0)
inc(char2p, rune_b.size)
inc(x)
if x > c3: x = c3
D = row[p] + 1
if x > D: x = D
row[p] = x
inc(p)
# lower triangle sentinel:
if i <= half:
dec(D)
rune_b = b.runeAt(char2p)
var c3 = D + (if rune_a != rune_b: 1 else: 0)
inc(x)
if x > c3: x = c3
row[p] = x
i_current_a = i_next_a
result = row[e]
proc editDistanceAscii*(a, b: string): int {.noSideEffect.} =
## Returns the edit distance between `a` and `b`.
##
## This uses the `Levenshtein`:idx: distance algorithm with only a linear
## memory overhead.
var len1 = a.len
var len2 = b.len
if len1 > len2:
# make `b` the longer string
return editDistanceAscii(b, a)
# strip common prefix:
var s = 0
while s < len1 and a[s] == b[s]:
inc(s)
dec(len1)
dec(len2)
# strip common suffix:
while len1 > 0 and len2 > 0 and a[s+len1-1] == b[s+len2-1]:
dec(len1)
dec(len2)
# trivial cases:
if len1 == 0: return len2
if len2 == 0: return len1
# another special case:
if len1 == 1:
for j in s..s+len2-1:
if a[s] == b[j]: return len2 - 1
return len2
inc(len1)
inc(len2)
var half = len1 shr 1
# initalize first row:
#var row = cast[ptr array[0..high(int) div 8, int]](alloc(len2*sizeof(int)))
var row: seq[int]
newSeq(row, len2)
var e = s + len2 - 1 # end marker
for i in 1..len2 - half - 1: row[i] = i
row[0] = len1 - half - 1
for i in 1 .. len1 - 1:
var char1 = a[i + s - 1]
var char2p: int
var D, x: int
var p: int
if i >= len1 - half:
# skip the upper triangle:
var offset = i - len1 + half
char2p = offset
p = offset
var c3 = row[p] + ord(char1 != b[s + char2p])
inc(p)
inc(char2p)
x = row[p] + 1
D = x
if x > c3: x = c3
row[p] = x
inc(p)
else:
p = 1
char2p = 0
D = i
x = i
if i <= half + 1:
# skip the lower triangle:
e = len2 + i - half - 2
# main:
while p <= e:
dec(D)
var c3 = D + ord(char1 != b[char2p + s])
inc(char2p)
inc(x)
if x > c3: x = c3
D = row[p] + 1
if x > D: x = D
row[p] = x
inc(p)
# lower triangle sentinel:
if i <= half:
dec(D)
var c3 = D + ord(char1 != b[char2p + s])
inc(x)
if x > c3: x = c3
row[p] = x
result = row[e]
when isMainModule:
doAssert editDistance("", "") == 0
doAssert editDistance("kitten", "sitting") == 3 # from Wikipedia
doAssert editDistance("flaw", "lawn") == 2 # from Wikipedia
doAssert editDistance("привет", "превет") == 1
doAssert editDistance("Åge", "Age") == 1
# editDistance, one string is longer in bytes, but shorter in rune length
# first string: 4 bytes, second: 6 bytes, but only 3 runes
doAssert editDistance("aaaa", "×××") == 4
block veryLongStringEditDistanceTest:
const cap = 256
var
s1 = newStringOfCap(cap)
s2 = newStringOfCap(cap)
while len(s1) < cap:
s1.add 'a'
while len(s2) < cap:
s2.add 'b'
doAssert editDistance(s1, s2) == cap
block combiningCodePointsEditDistanceTest:
const s = "A\xCC\x8Age"
doAssert editDistance(s, "Age") == 1
doAssert editDistanceAscii("", "") == 0
doAssert editDistanceAscii("kitten", "sitting") == 3 # from Wikipedia
doAssert editDistanceAscii("flaw", "lawn") == 2 # from Wikipedia

View File

@@ -302,7 +302,7 @@ proc getCurrentEncoding*(): string =
proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter =
## opens a converter that can convert from `srcEncoding` to `destEncoding`.
## Raises `EIO` if it cannot fulfill the request.
## Raises `IOError` if it cannot fulfill the request.
when not defined(windows):
result = iconvOpen(destEncoding, srcEncoding)
if result == nil:

View File

@@ -44,20 +44,23 @@ else:
const useBuiltinSwap = false
when useBuiltinSwap:
template swapOpImpl(T: typedesc, op: untyped) =
## We have to use `copyMem` here instead of a simple deference because they
## may point to a unaligned address. A sufficiently smart compiler _should_
## be able to elide them when they're not necessary.
var tmp: T
copyMem(addr tmp, inp, sizeOf(T))
tmp = op(tmp)
copyMem(outp, addr tmp, sizeOf(T))
proc swapEndian64*(outp, inp: pointer) {.inline, nosideeffect.}=
var i = cast[ptr uint64](inp)
var o = cast[ptr uint64](outp)
o[] = builtin_bswap64(i[])
swapOpImpl(uint64, builtin_bswap64)
proc swapEndian32*(outp, inp: pointer) {.inline, nosideeffect.}=
var i = cast[ptr uint32](inp)
var o = cast[ptr uint32](outp)
o[] = builtin_bswap32(i[])
swapOpImpl(uint32, builtin_bswap32)
proc swapEndian16*(outp, inp: pointer) {.inline, nosideeffect.}=
var i = cast[ptr uint16](inp)
var o = cast[ptr uint16](outp)
o[] = builtin_bswap16(i[])
swapOpImpl(uint16, builtin_bswap16)
else:
proc swapEndian64*(outp, inp: pointer) =

View File

@@ -32,7 +32,7 @@ import
const
coreAttr* = " accesskey class contenteditable dir hidden id lang " &
"spellcheck style tabindex title translate "
"spellcheck style tabindex title translate " ## HTML DOM Core Attributes
eventAttr* = "onabort onblur oncancel oncanplay oncanplaythrough onchange " &
"onclick oncuechange ondblclick ondurationchange onemptied onended " &
"onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload " &
@@ -40,9 +40,9 @@ const
"onmouseleave onmousemove onmouseout onmouseover onmouseup onmousewheel " &
"onpause onplay onplaying onprogress onratechange onreset onresize " &
"onscroll onseeked onseeking onselect onshow onstalled onsubmit " &
"onsuspend ontimeupdate ontoggle onvolumechange onwaiting "
ariaAttr* = " role "
commonAttr* = coreAttr & eventAttr & ariaAttr
"onsuspend ontimeupdate ontoggle onvolumechange onwaiting " ## HTML DOM Event Attributes
ariaAttr* = " role " ## HTML DOM Aria Attributes
commonAttr* = coreAttr & eventAttr & ariaAttr ## HTML DOM Common Attributes
proc getIdent(e: NimNode): string {.compileTime.} =
case e.kind
@@ -203,6 +203,11 @@ macro caption*(e: varargs[untyped]): untyped =
let e = callsite()
result = xmlCheckedTag(e, "caption", commonAttr)
macro center*(e: varargs[untyped]): untyped =
## Generates the HTML ``center`` element.
let e = callsite()
result = xmlCheckedTag(e, "center", commonAttr)
macro cite*(e: varargs[untyped]): untyped =
## generates the HTML ``cite`` element.
let e = callsite()
@@ -243,11 +248,21 @@ macro del*(e: varargs[untyped]): untyped =
let e = callsite()
result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr)
macro details*(e: varargs[untyped]): untyped =
## Generates the HTML ``details`` element.
let e = callsite()
result = xmlCheckedTag(e, "details", commonAttr & "open")
macro dfn*(e: varargs[untyped]): untyped =
## generates the HTML ``dfn`` element.
let e = callsite()
result = xmlCheckedTag(e, "dfn", commonAttr)
macro dialog*(e: varargs[untyped]): untyped =
## Generates the HTML ``dialog`` element.
let e = callsite()
result = xmlCheckedTag(e, "dialog", commonAttr & "open")
macro `div`*(e: varargs[untyped]): untyped =
## generates the HTML ``div`` element.
let e = callsite()
@@ -428,6 +443,13 @@ macro mark*(e: varargs[untyped]): untyped =
let e = callsite()
result = xmlCheckedTag(e, "mark", commonAttr)
macro marquee*(e: varargs[untyped]): untyped =
## Generates the HTML ``marquee`` element.
let e = callsite()
result = xmlCheckedTag(e, "marquee", coreAttr &
"behavior bgcolor direction height hspace loop scrollamount " &
"scrolldelay truespeed vspace width onbounce onfinish onstart")
macro meta*(e: varargs[untyped]): untyped =
## generates the HTML ``meta`` element.
let e = callsite()
@@ -487,6 +509,11 @@ macro param*(e: varargs[untyped]): untyped =
let e = callsite()
result = xmlCheckedTag(e, "param", commonAttr, "name value", true)
macro picture*(e: varargs[untyped]): untyped =
## Generates the HTML ``picture`` element.
let e = callsite()
result = xmlCheckedTag(e, "picture", commonAttr)
macro pre*(e: varargs[untyped]): untyped =
## generates the HTML ``pre`` element.
let e = callsite()
@@ -554,6 +581,11 @@ macro select*(e: varargs[untyped]): untyped =
result = xmlCheckedTag(e, "select", "autofocus disabled form multiple " &
"name required size" & commonAttr)
macro slot*(e: varargs[untyped]): untyped =
## Generates the HTML ``slot`` element.
let e = callsite()
result = xmlCheckedTag(e, "slot", commonAttr)
macro small*(e: varargs[untyped]): untyped =
## generates the HTML ``small`` element.
let e = callsite()
@@ -584,6 +616,11 @@ macro sub*(e: varargs[untyped]): untyped =
let e = callsite()
result = xmlCheckedTag(e, "sub", commonAttr)
macro summary*(e: varargs[untyped]): untyped =
## Generates the HTML ``summary`` element.
let e = callsite()
result = xmlCheckedTag(e, "summary", commonAttr)
macro sup*(e: varargs[untyped]): untyped =
## generates the HTML ``sup`` element.
let e = callsite()
@@ -684,7 +721,7 @@ macro wbr*(e: varargs[untyped]): untyped =
let e = callsite()
result = xmlCheckedTag(e, "wbr", commonAttr, "", true)
when isMainModule:
runnableExamples:
let nim = "Nim"
assert h1(a(href="http://nim-lang.org", nim)) ==
"""<h1><a href="http://nim-lang.org">Nim</a></h1>"""

View File

@@ -1,4 +1,4 @@
## Include file that implements 'getEnv' and friends. Do not import it!
# Include file that implements 'getEnv' and friends. Do not import it!
when not declared(ospaths):
{.error: "This is an include file for ospaths.nim!".}

View File

@@ -1,4 +1,4 @@
## Include file that implements 'osErrorMsg' and friends. Do not import it!
# Include file that implements 'osErrorMsg' and friends. Do not import it!
when not declared(ospaths):
{.error: "This is an include file for ospaths.nim!".}

View File

@@ -383,14 +383,14 @@ proc selectInto*[T](s: Selector[T], timeout: int,
if (pevents and EPOLLERR) != 0 or (pevents and EPOLLHUP) != 0:
if (pevents and EPOLLHUP) != 0:
rkey.errorCode = ECONNRESET.OSErrorCode
rkey.errorCode = OSErrorCode ECONNRESET
else:
# Try reading SO_ERROR from fd.
var error: cint
var size = sizeof(error).SockLen
if getsockopt(fdi.SocketHandle, SOL_SOCKET, SO_ERROR, addr(error),
var size = SockLen sizeof(error)
if getsockopt(SocketHandle fdi, SOL_SOCKET, SO_ERROR, addr(error),
addr(size)) == 0'i32:
rkey.errorCode = error.OSErrorCode
rkey.errorCode = OSErrorCode error
rkey.events.incl(Event.Error)
if (pevents and EPOLLOUT) != 0:

View File

@@ -603,7 +603,7 @@ proc escapeJsonUnquoted*(s: string; result: var string) =
of '\r': result.add("\\r")
of '"': result.add("\\\"")
of '\0'..'\7': result.add("\\u000" & $ord(c))
of '\14'..'\31': result.add("\\u00" & $ord(c))
of '\14'..'\31': result.add("\\u00" & toHex(ord(c), 2))
of '\\': result.add("\\\\")
else: result.add(c)
@@ -1664,9 +1664,9 @@ when isMainModule:
doAssert(parsed2{"repository", "description"}.str=="IRC Library for Haskell", "Couldn't fetch via multiply nested key using {}")
doAssert escapeJsonUnquoted("\10Foo🎃barÄ") == "\\nFoo🎃barÄ"
doAssert escapeJsonUnquoted("\0\7\20") == "\\u0000\\u0007\\u0020" # for #7887
doAssert escapeJsonUnquoted("\0\7\20") == "\\u0000\\u0007\\u0014" # for #7887
doAssert escapeJson("\10Foo🎃barÄ") == "\"\\nFoo🎃barÄ\""
doAssert escapeJson("\0\7\20") == "\"\\u0000\\u0007\\u0020\"" # for #7887
doAssert escapeJson("\0\7\20") == "\"\\u0000\\u0007\\u0014\"" # for #7887
# Test with extra data
when not defined(js):

View File

@@ -256,12 +256,12 @@ proc loadAny(s: Stream, a: Any, t: var Table[BiggestInt, pointer]) =
close(p)
proc load*[T](s: Stream, data: var T) =
## loads `data` from the stream `s`. Raises `EIO` in case of an error.
## loads `data` from the stream `s`. Raises `IOError` in case of an error.
var tab = initTable[BiggestInt, pointer]()
loadAny(s, toAny(data), tab)
proc store*[T](s: Stream, data: T) =
## stores `data` into the stream `s`. Raises `EIO` in case of an error.
## stores `data` into the stream `s`. Raises `IOError` in case of an error.
var stored = initIntSet()
var d: T
shallowCopy(d, data)

Some files were not shown because too many files have changed in this diff Show More