Compare commits

...

191 Commits

Author SHA1 Message Date
narimiran
89b39ee8fe create changelog for v1.0.6 2020-01-23 15:05:26 +01:00
narimiran
d038e1b750 bump version to 1.0.6 2020-01-23 14:50:44 +01:00
chr v1.x
a6846b81eb [backport] documentation: Add channels examples (#13202) [ci skip]
(cherry picked from commit aebcbfe5ea)
2020-01-23 14:47:59 +01:00
Ștefan Talpalaru
de43bdfa70 generic stack trace overriding mechanism (#12922)
* libbacktrace support

* switch to a generic stack trace overriding mechanism

When "nimStackTraceOverride" is defined, once of the imported modules
can register its own procedure to replace the default stack trace
generation by calling `registerStackTraceOverride(myOwnProc)`.

Tested with `./koch boot -d:release --debugger:native -d:nimStackTraceOverride --import:libbacktrace`
for the compiler itself and `./bin/nim c -r -f --stacktrace:off --debugger:native -d:nimStackTraceOverride --import:libbacktrace foo.nim`
for an external program.

* make the StackTraceOverrideProc {.noinline.}

(cherry picked from commit ee9ee297d8)
2020-01-23 10:45:10 +01:00
Ștefan Talpalaru
25a4026cda c_fflush() the rawWrite() buffer (#12987)
Stack traces on an unbuffered stderr get out of sync with line-buffered
stdout - usually on Windows terminals or CI logs. This fixes it by
calling C's fflush() on the output buffer in the procedure used for
printing stack traces.

(cherry picked from commit defaf3b5a5)
2020-01-23 10:44:54 +01:00
D-Nice
2e9d595f92 [backport] fix #11440, add docs to isNil for seq types needing nilseq (#13234) [ci skip]
(cherry picked from commit f12bea16ad)
2020-01-23 07:55:00 +01:00
Mera
13ad15dffe [backport] Fix typo and improve in code-block of 'lib/pure/parseutils.nim' (#13231) [ci skip]
(cherry picked from commit 4a754ff392)
2020-01-23 07:54:35 +01:00
Milan
0ff510ca07 [backport] times/getClockStr(): fix mistake in doc (#13229) [ci skip]
(cherry picked from commit 3e843ab335)
2020-01-23 07:54:25 +01:00
Juan Carlos
16eaebbf51 [backport] Documentation Fix #12251 (#13226) [ci skip]
(cherry picked from commit fbd7fe118c)
2020-01-23 07:54:14 +01:00
Andreas Rumpf
61c8a2b1e7 fixes a critical times.nim bug reported on IRC [backport] (#13216)
(cherry picked from commit bdb7c82c6a)
2020-01-23 07:53:56 +01:00
Araq
b64d59635c fixes the distros.nim regression
(cherry picked from commit fbb8052e3a)
2020-01-17 09:26:08 +01:00
Emery Hemingway
cd28e01a1a Implement NixOS distro check (#12914)
(cherry picked from commit 148f6d9820)
2020-01-17 09:25:58 +01:00
Andreas Rumpf
2f557f74e5 fixes #9674 [backport] (#13143)
(cherry picked from commit 675ca997fb)
2020-01-16 07:38:25 +01:00
Andreas Rumpf
f1ec998e71 fixes #13104 [backport] (#13142)
(cherry picked from commit 8b00586488)
2020-01-16 07:38:18 +01:00
Andreas Rumpf
a3d5a3ca9b fixes #10665 (#13141) [backport]
(cherry picked from commit fadbd8f70d)
2020-01-16 07:38:12 +01:00
Timothee Cour
74350447ed fixes #13100 nim doc now treats export localSymbol correctly (#13123) [backport]
* fix #13100 nim doc now treats `export localSymbol` correctly
* use owner instead

(cherry picked from commit 49d1822c8f)
2020-01-16 07:37:52 +01:00
narimiran
83c1ec46ce fix hts test command
(cherry picked from commit b26f564d19ede8b5353fe7ac9a90b5034b3ea55b)
2020-01-14 07:46:33 +01:00
narimiran
29b6dd6196 Correctly remove a key from CountTable when it is set to zero.
(fixes #12813 and #13079)

(cherry picked from commit e40dee6162a1ca364da1da2ecab546e0a28778f0)
2020-01-14 07:46:24 +01:00
Jasper Jenkins
8994e8f2e2 fix rtti sizeof for varargs in global scope (#13125) [backport]
(cherry picked from commit bf2e052e6d)
2020-01-14 06:31:57 +01:00
perter lee
3e76777de8 fix the ftp store function read the local file bug (#13108) [backport]
* Update asyncftpclient.nim

When use newStringOfCap function not have assign memory for the string data,so if use this address the fault is rasise.

* complelete the bugfix

(cherry picked from commit 1f27a2f8ab)
2020-01-14 06:27:34 +01:00
Andreas Rumpf
d237b73e6e fixes an asyncftpclient bug; refs #13096 [backport]
(cherry picked from commit 3a39ab83ac)
2020-01-14 06:27:24 +01:00
narimiran
7134d57cd4 [backport] system/io.nim fix wrong documentation comment [ci skip]
(cherry picked from commit e9e114058c)
2020-01-14 06:26:56 +01:00
Tomohiro
17ddc7e894 Fix error check code in osproc (#13090) [backport]
(cherry picked from commit a33b72af49)
2020-01-14 06:26:30 +01:00
Teashrock
26331a9005 Deleted misplaced separator (#13085) [backport]
Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.

(cherry picked from commit 27fee4d8b4)
2020-01-14 06:26:22 +01:00
BinHong Lee
6d2884be9c Allow -o option for buildIndex (#13037) [backport]
Addressing #12771

This is also included in the docgen documentation [here](https://nim-lang.org/docs/docgen.html) but its not respected as reported in the issue.

(cherry picked from commit 2cfa8d8385)
2020-01-14 06:26:14 +01:00
Andy Davidoff
e636b47429 fix crash due to errant symbols in nim.cfg (#13073) [backport]
(cherry picked from commit 56fb909676)
2020-01-14 06:25:45 +01:00
cooldome
4028514eeb fixes #13013, reverts previous changes to readLines() (#13036) [backport]
* Revert "remove default argument for readLines (#12807) [backport]"

This reverts commit c949b81efd.

(cherry picked from commit a3df1b55f3)
2020-01-05 10:40:13 +01:00
Siegfried Ehret
8b956dba09 Fix typo (#13015) [backport]
(cherry picked from commit a577a88c36)
2020-01-05 10:40:02 +01:00
cooldome
78f9933b8f remove default argument for readLines (#12807) [backport]
(cherry picked from commit c949b81efd)
2020-01-05 10:39:55 +01:00
Andy Davidoff
46be787fb2 fixes disruptek/nimph#102 multi-level nim.cfg use (#13001) [backport]
(cherry picked from commit 8a63caca07)
2020-01-05 10:39:48 +01:00
Timothee Cour
7afe6b1f4b [ci skip] docfix .. < => ..< (#12981) [backport]
(cherry picked from commit 8c19372690)
2019-12-30 12:25:39 +01:00
King Eca
f9d30dc1e5 Fixes stackoverflow links in readme (#12963) [backport]
(cherry picked from commit b67dea7a33)
2019-12-30 12:25:21 +01:00
genotrance
89b244a2f5 Path substitution for --out and --outdir (#12796)
* Enable pathSubs for --out and --outDir
* Cleanup

(cherry picked from commit eed328856f)
2019-12-30 12:24:39 +01:00
Araq
4c120c1978 fixes a bug that kept sugar.collect from working with for loop macros [backport]
(cherry picked from commit a7b4b2ed54)
2019-12-26 15:42:31 +01:00
Timothee Cour
bc601a62a2 fix cmdline bugs affecting nimBetterRun correctness (#12933) [backport]
(cherry picked from commit 206a4cee77)
2019-12-26 15:42:07 +01:00
flywind
9167eb6c89 fix error in assertions document (#12925) [backport]
(cherry picked from commit cb0a20b9b4)
2019-12-26 15:41:48 +01:00
Andreas Rumpf
7c4bc63b00 fixes #12885 [backport] (#12895)
(cherry picked from commit 347a04606b)
2019-12-16 09:28:31 +01:00
cooldome
261592de18 Better clang_cl support (#12896)
(cherry picked from commit 777c9ad0ef)
2019-12-16 09:28:26 +01:00
Andreas Rumpf
f52395f2d8 fixes #12148 [backport] (#12888)
(cherry picked from commit 22b2684608)
2019-12-16 09:28:07 +01:00
cooldome
d807c4b7c0 fixes #12827 (#12829) [backport]
(cherry picked from commit 13d232ec56)
2019-12-10 16:14:38 +01:00
Kevin
65aa564c54 added cstrutils (#12858) [backport]
fixed for 'csuCmpIgnoreStyle' error on hotcodereloading

(cherry picked from commit a02d043b58)
2019-12-10 16:14:32 +01:00
Neelesh Chandola
0f05a0dd5b Fixes #12832 (#12842) [backport]
(cherry picked from commit ff5ef95414)
2019-12-10 16:14:22 +01:00
Mark
512727d75e Manual update: custom exceptions (#12847) [backport]
Said that you can have custom exceptions and showed how to create and raise them.

(cherry picked from commit 73dd348ddd)
2019-12-10 16:10:51 +01:00
Elliot Waite
00408a4554 Removing the mention of using discard for block comments (#12837) [backport]
* Remove mention of using `discard` for block comments

* Add a 32x32 alternate favicon

(cherry picked from commit 5da27a891c)
2019-12-10 16:10:40 +01:00
Mark
09be379b91 deviated -> derived (#12846) [backport]
(cherry picked from commit 0ebc709037)
2019-12-10 16:10:33 +01:00
Mark
6f520fb6d9 deviated -> derived (#12845) [backport]
(cherry picked from commit 46144a31ab)
2019-12-10 16:09:51 +01:00
Neelesh Chandola
789a984c1e Fixed objects being erroneously zeroed out before object construction (#12814) [backport]
(cherry picked from commit 1db21721ec)
2019-12-10 16:09:43 +01:00
cooldome
1edb81b66c fixes #12783 [backport] (#12810)
* fixes #12783

* Trigger build

(cherry picked from commit 9b0e874687)
2019-12-10 16:09:30 +01:00
itsumura-h
340c9248f1 fix db_mysql getRow() when column is null error raised (#12806) [backport]
* fix db_mysql getRow()
* added if y == nil [backport]

(cherry picked from commit 208b018f6b)
2019-12-10 16:09:19 +01:00
Araq
9ec09bfa55 fixes #12798 [backport]
(cherry picked from commit de1a283383)
2019-12-10 16:09:08 +01:00
Jasper Jenkins
a13f623f16 [backport] always set fileInfoIdx.isKnownFile (#12773)
(cherry picked from commit b6b8d540e3)
2019-12-10 16:08:54 +01:00
Jasper Jenkins
5129a1e88d make addQuoted work on nimscript (#12717) [backport]
(cherry picked from commit 9ea55eccbb)
2019-12-10 16:08:42 +01:00
Araq
3f6a08d5b0 fixes #11727 [backport]
(cherry picked from commit 0996eb174f)
2019-12-10 16:00:29 +01:00
Araq
299f1e99cd fixes #12488 [backport]
(cherry picked from commit 87f0d534d6)
2019-12-10 16:00:20 +01:00
3n-k1
a02a4d8fc5 [backport] Fix style issues in lib/, tools/, and testament/. Fixes #12687. (#12754)
(cherry picked from commit 0944b0f441)
2019-12-10 16:00:07 +01:00
Brian Wignall
10935a71ed [backport] Fix spelling typos (#12755)
(cherry picked from commit a7aeabb9d2)
2019-12-10 15:55:19 +01:00
Andreas Rumpf
d0e8ad17b5 more fixes for --cpu:avr [backport] (#12748)
(cherry picked from commit fd85a5ae05)
2019-12-10 15:49:11 +01:00
narimiran
60100a9a64 bump version to 1.0.5 2019-12-10 15:44:36 +01:00
narimiran
c8998c498f clean up the changelog 2019-11-27 09:33:51 +01:00
narimiran
97e0ce3c75 bump version to 1.0.4 2019-11-25 17:46:16 +01:00
narimiran
aa7b0c8581 create a changelog for v1.0.4 2019-11-25 17:45:58 +01:00
Andreas Rumpf
d6f52f3cef added 'since' template for further stdlib additions
(cherry picked from commit 372b01711e)
2019-11-25 17:25:41 +01:00
Timothee Cour
fa15083cc9 fixes #12663 staticRead now creates a dependency for rebuilds (#12731) [backport]
* fix #12663 staticRead
* address comments

(cherry picked from commit dfe5d115fb)
2019-11-25 17:05:26 +01:00
tauplus
c868f1ef67 Fix wrong section hierarchy in the manual (#12724) [backport]
(cherry picked from commit bfad0056ab)
2019-11-25 17:05:26 +01:00
Andy Davidoff
8f0b891e68 export nim.cfg parser (#12602)
(cherry picked from commit 61889c604a)
2019-11-25 09:46:51 +01:00
Andreas Rumpf
4084ef19a3 conversions to unsigned numbers are not checked anymore (#12688) [backport]
* conversions to unsigned numbers are not checked anymore; implements / fixes https://github.com/nim-lang/RFCs/issues/175

* change the spec yet again to be less consistent but to make more sense; updated the changelog

(cherry picked from commit c98e0e22ad)
2019-11-21 17:31:35 +01:00
Andreas Rumpf
7d444ff04c fixes #12670 [backport] (#12693)
(cherry picked from commit 78e02d174d)
2019-11-21 17:27:50 +01:00
Andy Davidoff
aaf06dba1b restore --define🔑val in nim.cfg and fix #12367 (#12611)
(cherry picked from commit 5544a13236)
2019-11-20 10:23:02 +01:00
Andy Davidoff
0e1dd54fee add --clearNimblePath; fixes #12601 (#12609)
(cherry picked from commit 738c957e94)
2019-11-20 10:22:45 +01:00
Andreas Rumpf
c78cee697d fixes #12612 [backport] (#12681)
(cherry picked from commit 56a00da34a)
2019-11-20 10:22:12 +01:00
narimiran
4c4116d63a a better way to test Arraymancer + test more packages
(cherry picked from commit a1e7bf81b3)
2019-11-18 12:33:24 +01:00
Andreas Rumpf
9d17d02734 attempt to add valgrind support to the CIs and testament (#12646)
* attempt to add valgrind support to the CIs and testament

* valgrind (currently) works only on 64-bit Linux

(cherry picked from commit 223e65e529)
2019-11-18 12:28:33 +01:00
Juan Carlos
e8578c926e Fix htmlgen html lang (#12668) [backport]
(cherry picked from commit 9c46526cfa)
2019-11-18 12:28:18 +01:00
Dominik Picheta
5937c40928 Fixes ambiguity errors when evaluating Nimble files. (#12674) [backport]
When trying to evaluate a Nimble file which imports a Nim module
I was getting the following errors for some reason:

```
/Users/dom/projects/nim/lib/pure/parseopt.nim(229, 46) Error: ambiguous call; both system.paramCount() [declared in /Users/dom/projects/nim/lib/system/nimscript.nim(65, 6)] and os.paramCount() [declared in /Users/dom/projects/nim/lib/pure/os.nim(2613, 8)] match for: ()
```

(cherry picked from commit bab5351d43)
2019-11-18 12:24:33 +01:00
Miran
f3e088f11a remove two asserts in int128.nim (#12648) [backport]
Before this PR, `tests/misc/tconv.nim` fails when the compiler
is compiled without `-d:danger` flag.
Bear in mind that even without the asserts, the values outside of
a given range are still checked and a meaningful error message
(from `compiler/semexprs.nim`) is printed.

(cherry picked from commit 107b40f097)
2019-11-18 12:24:32 +01:00
David Krause
39122ecd93 fix documentation of $*(dt: DateTime) (#12660) 2019-11-14 20:41:04 +01:00
Volodymyr Lashko
7ea60f78b5 Fix crash in terminate handler (#12572) [backport]
* fix undefined behavior in terminate handler

* fix failing unit test

* Revert "fix failing unit test"

This reverts commit 0e5e385fbf.

* Revert "fix undefined behavior in terminate handler"

This reverts commit 2b582871f1.

* do not throw inside terminate handler with msvc < 1923

(cherry picked from commit 4e841ab156)
2019-11-08 15:08:08 +01:00
cooldome
ee260dd838 fixes #5050; fixes #11826 (#12606) [backport]
(cherry picked from commit e1b1759439)
2019-11-08 15:08:08 +01:00
Andreas Rumpf
23881b188e bugfix that enables the 'since' template [backport]
(cherry picked from commit f69ee294c8)
2019-11-08 15:08:08 +01:00
narimiran
e5f968da0c revert the most of #12532
The reason for this revert is that 'runnableExamples' keep
mysteriously failing on 32-bit OS-es on version 1.0.x
(devel version is fine, as are 64-bit OS-es).
2019-11-08 15:07:49 +01:00
narimiran
cb2f8d4d39 [backport] print more information for the previous commit
(cherry picked from commit 717da9f158)
2019-11-06 16:14:53 +01:00
narimiran
e2aa1d6d84 [backport] rewrite flaky runnable example
(cherry picked from commit 5381c810a8)
2019-11-06 15:54:39 +01:00
Tor Arvid Lund
beaead0fd1 [backport] doc/tut3.rst: Fix typo in Introduction (#12607) [ci skip]
Derivative of `b*pow(x, 2)` is `2*b*x`, while old version had `2*a*x`

(cherry picked from commit 5ccbf7e3cf)
2019-11-06 15:54:39 +01:00
Federico Ceratto
763486a3aa [backport] Add links to packaging and distro pages (#12603) [ci skip]
(cherry picked from commit 59c212607e)
2019-11-06 15:54:39 +01:00
narimiran
d61dd518d9 clean up a previous merge conflict 2019-11-06 14:38:37 +01:00
Clyybber
2a292c0e71 Refactor injectdestructors (#12295)
One improvement over #devel is visible in the transformation of getEnv. With this approach we move to result whenever possible.

(cherry picked from commit 5f5879dc4c)
2019-11-06 13:49:24 +01:00
Araq
814e237ab6 refactoring: --newruntime consists of 3 different switches
(cherry picked from commit 61ea85687c)
2019-11-06 12:34:23 +01:00
narimiran
8324b7a86d port the whole 'lambdalifting.nim' from devel 2019-11-06 09:44:26 +01:00
Clyybber
7ccefbc422 Fixes #12379 (#12591) [backport]
(cherry picked from commit cf5c3f2400)
2019-11-05 16:20:43 +01:00
Miran
8fddc8e8a1 [backport] fix #12395 (#12590)
'countBits32' is now fixed in the same way that
'countBits64' was already patched earlier (by adding 'u32
where needed).

(cherry picked from commit ae32d637f7)
2019-11-05 16:20:25 +01:00
Andreas Rumpf
f47d977f6d --os:ios needs to imply defined(macosx) [backport] (#12585)
(cherry picked from commit 62fc3db9d7)
2019-11-05 16:18:50 +01:00
Andreas Rumpf
a5c98bf3af fixes #12577 [backport] (#12584)
(cherry picked from commit ceda586d88)
2019-11-05 16:18:06 +01:00
Tomohiro
93b868bff9 Fixes #12536 (#12568) [backport]
(cherry picked from commit 4e0f12092e)
2019-11-05 16:15:54 +01:00
Kaushal Modi
274f94c84a [backport] Add docs to better distinguish among getProjectPath, getCurrentDir and currentSourcePath (#12565)
Fixes https://github.com/nim-lang/Nim/issues/10477.

(cherry picked from commit d914e9a65f)
2019-11-05 16:15:44 +01:00
jiro
1ff3494dab Add or detectOs(Manjaro) (#12587) [backport]
Using `pacman` command in Manjaro Linux
2019-11-04 12:20:23 +01:00
Nindaleth
1d43c8620e fix several typos in documentation and comments (#12553)
(cherry picked from commit 34dbc5699e)
2019-10-30 10:38:25 +01:00
Araq
f5e096b13f fixes #12547 [backport]
(cherry picked from commit 1214960a1b)
2019-10-30 10:38:25 +01:00
zah
29c099ccd1 Fix newLit for objects having string fields (#12542) [backport]
(cherry picked from commit de5f6a07c2)
2019-10-30 10:38:25 +01:00
Andreas Rumpf
6887d6de80 [backport] fix #12528, fix #12525: incorrect generic type resolution for default values (#12538)
(cherry picked from commit e58c2d261c)
2019-10-30 10:38:25 +01:00
Solitude
7c2d64c18d Fix code style errors (#12545)
(cherry picked from commit 160c07be00)
2019-10-30 10:38:25 +01:00
Anthon van der Neut
f991d2c1fd [backport] fix broken link to non-existing c2nim manual html, fixes #12537 [ci skip] (#12544)
(cherry picked from commit c58aa7705d)
2019-10-30 10:38:25 +01:00
Jjp137
d6ae4e00f4 colors: fix 'mix' template and make most examples runnable (#12532) [backport]
* colors: fix the 'mix' template
* colors: make most examples runnable

(cherry picked from commit ee119f7984)
2019-10-30 10:38:25 +01:00
Arne Döring
2a2a9110b2 integer literal documentation [ci skip] (#12513)
* integer literal documentation [ci skip]

* apply feedback [ci skip]

(cherry picked from commit 91af075244)
2019-10-30 10:38:25 +01:00
Arne Döring
4a7ccfa333 fixes #12514 (#12520) [backport]
(cherry picked from commit 3c567bcf20)
2019-10-30 10:38:25 +01:00
Jjp137
476d677c6f Remove sentences referring to the graphics module (#12522)
(cherry picked from commit 3a62cf29d8)
2019-10-30 10:38:25 +01:00
Jjp137
ee0c1482d7 sequtils: replace deprecated 'random' call within example (#12515) [backport]
(cherry picked from commit 1d42108fda)
2019-10-30 10:30:47 +01:00
Andreas Rumpf
731d1dff84 VM: fixes register leaks [backport] (#12510)
(cherry picked from commit e0d13abaff)
2019-10-30 10:30:47 +01:00
Tomohiro
e02dc971f5 Fix Nim specify wrong option to vccexe when vcc.options.always is set (#12490) [backport]
(cherry picked from commit 8040c84615)
2019-10-30 10:30:47 +01:00
Andreas Rumpf
5f77d5ad85 fixes #12491 [backport]
(cherry picked from commit 8a599fb571)
2019-10-30 10:30:47 +01:00
Andreas Rumpf
f69dac8038 VM: fixes most ran-out-registers problems [backport] (#12485)
(cherry picked from commit 801a794039)
2019-10-24 19:00:47 +02:00
narimiran
338f43f305 disable flaky test on OSX
(cherry picked from commit d5cd5b00b9)
2019-10-24 18:59:16 +02:00
Jjp137
d1d8cd1000 Fix word wrapping
(cherry picked from commit 3ad48069d3)
2019-10-24 14:12:23 +02:00
Jjp137
f042acc535 asyncstreams: replace unintended link with emphasis
(cherry picked from commit e6d5379b3b)
2019-10-24 14:12:23 +02:00
Jjp137
eac5452082 manual.rst: remove unintended link
cast[T](0) is interpreted as a link to id 0 with text T, so escape
the opening parentheses to display the intended output.

(cherry picked from commit 59c1f7c87f)
2019-10-24 14:12:23 +02:00
Jjp137
80861998c7 koch.rst: remove link to nonexistent section
(cherry picked from commit 79aa58979c)
2019-10-24 14:12:23 +02:00
Jjp137
c1fd463834 Prefer relative links for Nim documentation
This is more friendly to those browsing the documentation without
a network connection. The nim-doc package in Debian allows this,
for example.

Also, the domain name being used was not consistent. It could have
been either nim-lang.org or nim-lang.github.io, and those reading
the stable docs could have found themselves suddenly reading the
devel docs instead.

(cherry picked from commit 72147c9ba4)
2019-10-24 14:12:12 +02:00
Jjp137
dedff71ca0 Fix many broken links
Note that contrary to what docgen.rst currently says, the ids have
to match exactly or else most web browsers will not jump to the
intended symbol.

(cherry picked from commit 93461aee34)
2019-10-24 14:10:46 +02:00
Federico Ceratto
cd60067638 [backport] Add link to posix_utils.html - related to #10723 (#12509)
(cherry picked from commit 9ac062b746)
2019-10-24 14:08:46 +02:00
UNIcodeX
bf047d6ef1 [backport] Clarifies experimental / parallel example on manual.rst (#12472)
* Clarifies experimental / parallel on manual.rst

Details:
Calling `useParallel()` in example fails with compiler error
  Error: 'parallel' section without 'spawn'

Adding `spawn` causes error:
  Error: internal error: (filename: "ccgexprs.nim", line: 1032, column: 17)
  No stack traceback available
  To create a stacktrace, rerun compilation with ./koch temp c <file>

Therefore a separate proc, `threadedEcho`, is added for the echo'ing
of the string, which allows the example to build, however, `sync()`
must be added so that the "echo in parallel" strings will actually
be shown on the terminal. Otherwise, the program will spawn of the
threads and exit before they can return to the main thread.

* Fixes and clarifies example for threading in manual.rst

Issue:
Calling useParallel() in example failed with compiler error
`Error: 'parallel' section without 'spawn'`

Adding spawn yielded compiler error:
```bash
Error: internal error: (filename: "ccgexprs.nim", line: 1032, column: 17)
No stack traceback available
To create a stacktrace, rerun compilation with ./koch temp c
```

Proposed Solution:
- Separate proc, threadedEcho, is added for the echo'ing
  of the string, which allows the example to build
- Added the thread number so that it can demonstrate that sometimes
  threads which were started sooner, come back after threads which
  were started later.

(cherry picked from commit d731646106)
2019-10-24 14:08:46 +02:00
Juan Carlos
313b2f0d71 [backport] Documentation Math module (#12460)
(cherry picked from commit 8f8916413f)
2019-10-24 14:08:46 +02:00
narimiran
f5269876ea disable package 'chronos' for now
(cherry picked from commit 2baa21d461)
2019-10-24 13:54:57 +02:00
Oscar Nihlgård
89738fd95d Fix JS bug in std/monotimes (#12499) [backport]
(cherry picked from commit 3d0c756a3c)
2019-10-24 13:45:43 +02:00
Oscar Nihlgård
ab51a8e08b Fix jsgen bug with uninitialized seq (#12500) [backport]
(cherry picked from commit 4ac100c912)
2019-10-24 13:45:43 +02:00
narimiran
6ffe5ee7e8 [backport] package chronos now has dependencies
(cherry picked from commit 2120fb2777)
2019-10-24 13:45:42 +02:00
Artem V L
ab2a8344b3 Docstring refined for the getSectionValue() (#12478) [backport]
(cherry picked from commit 049032432c)
2019-10-24 13:45:42 +02:00
Paul Tan
fc9cccccd3 guards.nim:sameTree(): handle uint literals correctly (#12483) [backport]
(cherry picked from commit ad3c10022a)
2019-10-24 13:45:42 +02:00
Ico Doornekamp
faf5ffd970 Fixed #12337, leaking pipe after gorge (#12339)
(cherry picked from commit 982086dbe9)
2019-10-24 13:45:31 +02:00
narimiran
6fc9327ebf nightly version is 1.0.3 2019-10-24 13:44:46 +02:00
Anthony Sottile
93aeb9c825 [ci skip] Fix link in changelog (#12498) 2019-10-23 17:36:47 +02:00
narimiran
59e8ca721e add changelog for v1.0.2
(cherry picked from commit 822078ed12)
2019-10-23 14:36:06 +02:00
Arne Döring
193b3c66bb fix #12426 (#12462)
(cherry picked from commit ec20fd3544)
2019-10-22 07:21:24 +02:00
Andreas Rumpf
0b134412f8 fixes #12310 [backport] (#12470)
(cherry picked from commit 38b3590e40)
2019-10-21 07:32:38 +02:00
ducdetronquito
1526ae8791 Namespace unittest enums to avoid name conflicts (#12468) [backport]
* [backport] Fixes: #12465 - Unittest - Namespace the usage of TestStatus enum to avoid name conflicts.

(cherry picked from commit df4c339cfc)
2019-10-21 07:32:38 +02:00
Andreas Rumpf
b914573d18 fixes #12420 [backport] (#12456)
(cherry picked from commit 832b0a0232)
2019-10-21 07:32:38 +02:00
Juan Carlos
f579d29b68 Fixes #8802 (#12439)
* Fix #8802

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12439#discussion_r335905397

(cherry picked from commit f5b4d9a2e5)
2019-10-21 07:32:38 +02:00
Juan Carlos
f79f7fed98 Fixes #10824 (#12437)
(cherry picked from commit 4d1f69c7d2)
2019-10-17 22:27:54 +02:00
Juan Carlos
e0c4015bbe Fix #10804 (#12438)
(cherry picked from commit 2cfd58de48)
2019-10-17 22:27:38 +02:00
Miran
7b500cbfad [backport] fix type's case in random.nim (#12445)
(cherry picked from commit a5ab502f08)
2019-10-17 22:25:51 +02:00
Andreas Rumpf
53e4692665 [backport] add back a check that got accidentically removed; fixes #12379 (#12444)
(cherry picked from commit 81125e2029)
2019-10-17 22:25:51 +02:00
Miran
b0e595b3cf [backport] fix #12418, fix random.randomize on JS backend (#12432)
(cherry picked from commit 5f5ac8ce16)
2019-10-17 22:25:51 +02:00
Yuriy Glukhov
4e3c997d40 Fixed yield in nkCheckedFieldExpr (#12429) [backport]
(cherry picked from commit 1aed455e7c)
2019-10-17 22:25:51 +02:00
Alexander Ivanov
f16bb4d85b Fixes semCustomPragma when nkSym (#12414) [backport]
(cherry picked from commit 990aadc43c)
2019-10-12 08:00:44 +02:00
genotrance
8f1dea614e Fixes #12286 - require explicit disabling of boehm interior pointer checking (#12406) [backport]
(cherry picked from commit 9e62876647)
2019-10-12 08:00:44 +02:00
Arne Döring
63d710f5a1 fix #12332 (#12402) [backport]
(cherry picked from commit 0a29c05a1b)
2019-10-12 08:00:44 +02:00
Andreas Rumpf
2ebd47089a fixes a koch regression that made 'koch boot --listcmd' not work anymore [backport] (#12400)
(cherry picked from commit d783c0f7ff)
2019-10-12 08:00:43 +02:00
Araq
535f0b9c9d fixes #12244 [backport]
(cherry picked from commit 7f904e2c66)
2019-10-12 08:00:43 +02:00
awr1
813b371758 [backport] Mention "lambdas" and => in the manual (#12397) [ci skip]
(so that "lambda" can be CTRL+F'd)

(cherry picked from commit 3b1760df72)
2019-10-12 08:00:43 +02:00
Andreas Rumpf
a09379f5fd fixes #12366 [backport] (#12393)
(cherry picked from commit f728614ef8)
2019-10-12 08:00:43 +02:00
narimiran
e9f7455bd6 bump version to 1.0.2 2019-10-09 06:42:54 +02:00
Andrew Smith
e03b1b79ae Updated the code example in the os module to use better grammar. (#12328)
(cherry picked from commit 0d94ee15c0)
2019-10-09 06:39:41 +02:00
Jasper Jenkins
0ea770c8f0 Macro docs additions (#12270)
* small macros doc additions

* more changes

* fixes [ci skip]

* capitalization, couple additions

* nkNodeKind to nnkNodeKind

(cherry picked from commit c20778d2d3)
2019-10-09 06:39:16 +02:00
Nindaleth
8a0012de42 fix a few dead links and a missing sentence in documentation (#12387)
(cherry picked from commit 84c956d9da)
2019-10-09 06:36:39 +02:00
treeform
1d4916b481 Easier build instructions for windows - just run build_all.bat. (#12276)
* Easier build instructions for windows.

* title letter

* Update build_all.bat to be like build_all.sh

(cherry picked from commit dbcffcfccb)
2019-10-09 06:36:19 +02:00
Ray Imber
2de758e68a Documentation improvements around the db interface (#12362)
Added more details about the limits and reasoning behind the API.
Came about from this discussion on IRC: https://irclogs.nim-lang.org/04-10-2019.html#16:58:04

(cherry picked from commit 7c23522b29)
2019-10-09 06:35:37 +02:00
pietroppeter
c8c9699850 [doc/tut1] removed discard discussion in comments (#12352)
(cherry picked from commit 89c37fada7)
2019-10-09 06:34:06 +02:00
kraptor
5df7f3fd5c Fix reference to parseSpec proc in readme (#12359)
(cherry picked from commit 412011eb96)
2019-10-09 06:33:45 +02:00
Andreas Rumpf
44d45b763c fixes #12315 [backport]; refs #12314 (#12385)
(cherry picked from commit f30da2f266)
2019-10-09 06:28:27 +02:00
alaviss
f7c150766a nimsuggest: fix tcp socket leak for epc backend (#12384) [backport]
Same as e9fa4c9b9c, but for the epc
backend which is used by emacs and vscode plugin.

Since the EPC backend only deal with one connection per nimsuggest
instance, only one socket is leaked, thus not as servere as with the tcp
backend.

(cherry picked from commit edb24b7ce0)
2019-10-09 06:28:27 +02:00
alaviss
4ae143ca60 nimsuggest: fix tcp socket leak (#12377) [backport]
A new socket is created for each iteration and leak immediately thanks
to the accept() call replacing the created socket with the client socket.

This commit fixes that.

(cherry picked from commit e9fa4c9b9c)
2019-10-09 06:28:27 +02:00
Leorize
0a8dcd5e11 azure: disable failing tests
(cherry picked from commit 73c8391fd3)
2019-10-08 11:43:16 +02:00
Leorize
929aa99665 testament: add azure integration
(cherry picked from commit acebcd7899)
2019-10-08 11:41:44 +02:00
Leorize
bae10d44fa azure-pipelines: add pipelines for linux, mac and win
This is the equivalent to the current AppVeyor + Travis setup.

(cherry picked from commit 880df4de62)
2019-10-08 11:41:38 +02:00
Andreas Rumpf
4632e8b26e fixes #12323 [backport]
(cherry picked from commit a60f18d025)
2019-10-07 18:40:07 +02:00
Andreas Rumpf
97e2e06b00 VM: no special casing for big endian machines; refs #9690 [backport] (#12364)
(cherry picked from commit 5be8e0b088)
2019-10-07 18:40:07 +02:00
Miran
b827431499 [backport] bundle nimpretty on Windows (#12358)
(cherry picked from commit 2909e41370)
2019-10-04 17:53:27 +02:00
Andrew Owen
99d448deeb [backport] Fix typo in docs (#12356) [ci skip]
(cherry picked from commit 64acc9dbfb)
2019-10-04 17:53:27 +02:00
Andreas Rumpf
9afd19b236 fixes #12291 [backport] (#12338)
(cherry picked from commit c51857f434)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
0d0cf86401 fixes #12336 [backport]
(cherry picked from commit 98e76a1058)
2019-10-03 09:32:46 +02:00
Tomohiro
5785444520 Fix how relativePath handle case sensitiviy (#12312) [backport]
(cherry picked from commit 64d5e25821)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
1b3f5eed70 fixes #12240 [backport] (#12308)
(cherry picked from commit 6dd4cbc3af)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
517538dcf8 fixes #12264 [backport] (#12302)
(cherry picked from commit dd082b6ec8)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
59916007cc fixes #12281 [backport]
(cherry picked from commit 72acf5de94)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
a5bcbe6dff fixes #12294 [backport]
(cherry picked from commit 1964589a29)
2019-10-03 09:32:46 +02:00
narimiran
cd3d4b5e05 [backport] run nimpretty on the remaining files
(cherry picked from commit 5732bb41ef)
2019-09-30 18:43:36 +02:00
narimiran
ac2181c5b9 [backport] run nimpretty on os-related stuff
(cherry picked from commit 34d0be2ec1)
2019-09-30 18:43:36 +02:00
narimiran
4675aae90b [backport] run nimpretty on string stuff
(cherry picked from commit dcf3181bd1)
2019-09-30 18:43:36 +02:00
narimiran
a0402b2012 [backport] run nimpretty on web stuff
(cherry picked from commit 0ca9cc7419)
2019-09-30 18:43:36 +02:00
narimiran
cbdc48ec66 [backport] run nimpretty on hashes
(cherry picked from commit 15895ebc3f)
2019-09-30 18:43:36 +02:00
narimiran
f19edae1b8 [backport] run nimpretty on parsers
(cherry picked from commit b17ed2ca9c)
2019-09-30 18:43:36 +02:00
narimiran
c5b9a44894 [backport] run nimpretty on numbers stuff
(cherry picked from commit 6c994b2498)
2019-09-30 18:43:36 +02:00
narimiran
3009eafc89 [backport] run nimpretty on async
(cherry picked from commit aa513d78e7)
2019-09-30 18:43:35 +02:00
Araq
1e97abec96 JS: gensym is stricter for 'this'; refs #12246 [backport]
(cherry picked from commit 63bcbea700)
2019-09-30 18:43:35 +02:00
Araq
95a655a975 different fix for #12279 [backport]
(cherry picked from commit c5a1149e00)
2019-09-30 18:43:35 +02:00
Araq
39f5a2b218 fixes #12279 [backport]
(cherry picked from commit 86de2cddf6)
2019-09-30 18:43:35 +02:00
narimiran
6c1f389d72 [backport] fix nimpretty removing space before pragma
(cherry picked from commit f804245087)
2019-09-30 18:43:35 +02:00
narimiran
1ae9cac3a4 [backport] fix #12278, don't expose internal PCRE documentation
(cherry picked from commit e0cd52365c)
2019-09-30 18:43:35 +02:00
Federico Ceratto
fa7f5742d3 Fix spellings (#12277) [backport]
(cherry picked from commit 39290cf88c)
2019-09-30 18:43:35 +02:00
Endeg
c8314b7c9c Fix #12242, replacing ":" with "@c" in packages [backport] (#12265)
(cherry picked from commit 657e09e79d)
2019-09-30 18:40:12 +02:00
Jjp137
52ea15cc24 threadpool: fix link in docs [ci skip] (#12258) [backport]
[backport]

(cherry picked from commit e065e51245)
2019-09-30 18:40:00 +02:00
Andreas Rumpf
7926440ae3 fixes the --verbosity:2 regression [backport]
(cherry picked from commit 13960066cb)
2019-09-30 18:39:48 +02:00
narimiran
bda6e071cd nightly version is 1.0.1 2019-09-30 18:38:14 +02:00
321 changed files with 4672 additions and 3299 deletions

View File

@@ -51,6 +51,8 @@ addons:
- libsdl1.2-dev
- libgc-dev
- libsfml-dev
- libc6-dbg
- valgrind
homebrew:
packages:
- boehmgc

148
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,148 @@
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-16.04'
CPU: amd64
Linux_i386:
vmImage: 'ubuntu-16.04'
CPU: i386
OSX_amd64:
vmImage: 'macOS-10.14'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-10.14'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64:
vmImage: 'windows-2019'
CPU: amd64
Windows_amd64_pkg:
vmImage: 'windows-2019'
CPU: amd64
NIM_TEST_PACKAGES: true
pool:
vmImage: $(vmImage)
workspace:
clean: all
steps:
- bash: git config --global core.autocrlf false
displayName: 'Disable auto conversion to CRLF by git (Windows-only)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- checkout: self
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
displayName: 'Checkout csources'
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install node.js 8.x'
- bash: |
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
displayName: 'Install dependencies (amd64 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
- bash: |
sudo dpkg --add-architecture i386
# Downgrade llvm, libgcc and libstdc++:
# - llvm has to be downgraded to have 32bit version installed for sfml.
# - libgcc and libstdc++ have to be downgraded as an optimization to
# prevent the use of the toolchain ppa, which has a terrible download
# speed.
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
Package: libllvm6.0 libgcc1 libstdc++6
Pin: origin "azure.archive.ubuntu.com"
Pin-Priority: 1001
Package: *
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
Pin-Priority: 100
EOF
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386
cat << EOF > bin/gcc
#!/bin/bash
exec $(which gcc) -m32 "\$@"
EOF
cat << EOF > bin/g++
#!/bin/bash
exec $(which g++) -m32 "\$@"
EOF
chmod 755 bin/gcc
chmod 755 bin/g++
displayName: 'Install dependencies (i386 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'i386'))
- bash: brew install boehmgc make sfml
displayName: 'Install dependencies (OSX)'
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64-6.3.0.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/dist/mingw64/bin'
displayName: 'Install dependencies (Windows)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/bin'
displayName: 'Add build binaries to PATH'
- bash: |
echo 'PATH:' "$PATH"
echo '##[section]gcc version'
gcc -v
echo '##[section]nodejs version'
node -v
echo '##[section]make version'
make -v
displayName: 'System information'
- bash: |
ncpu=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
;;
'Darwin')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
displayName: 'Build csources'
- bash: nim c koch
displayName: 'Build koch'
# set result to omit the "bash exited with error code '1'" message
- bash: |
./koch runCI || echo '##vso[task.complete result=Failed]'
displayName: 'Run CI'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

16
build_all.bat Normal file
View File

@@ -0,0 +1,16 @@
@echo off
rem build development version of the compiler; can be rerun safely
if not exist csources (
git clone --depth 1 https://github.com/nim-lang/csources.git
)
if not exist bin\nim.exe (
cd csources
if PROCESSOR_ARCHITECTURE == AMD64 (
SET ARCH=64
)
CALL build.bat
cd ..
)
bin\nim.exe c --skipUserCfg --skipParentCfg koch
koch.exe boot -d:release
koch.exe tools

View File

@@ -100,7 +100,7 @@
- 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
support. There is a new "heterogeneous" 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
@@ -660,4 +660,4 @@ for i in a..b:
- 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))
([#6431](https://github.com/nim-lang/Nim/issues/6431))

View File

@@ -0,0 +1,56 @@
# v1.0.2 - 2019-10-23
## Bugfixes
* fixes the --verbosity:2 regression
* Fixed "Fail to compile a file twice under Windows (v1.0 bug)." [#12242](https://github.com/nim-lang/Nim/issues/12242)
* fix nimpretty removing space before pragma
* JS: gensym is stricter for 'this'
* Fixed "VM Assertion Error with newruntime" [#12294](https://github.com/nim-lang/Nim/issues/12294)
* Fixed "Assertion error when running `nim check` on compiler/nim.nim" [#12281](https://github.com/nim-lang/Nim/issues/12281)
* Fixed "Compiler crash with empty array and generic instantiation with int as parameter" [#12264](https://github.com/nim-lang/Nim/issues/12264)
* Fixed "Regression in JS backend codegen "Error: request to generate code for .compileTime proc"" [#12240](https://github.com/nim-lang/Nim/issues/12240)
* Fix how `relativePath` handle case sensitiviy
* Fixed "SIGSEGV in compiler when using generic types and seqs" [#12336](https://github.com/nim-lang/Nim/issues/12336)
* Fixed "[1.0.0] weird interaction between `import os` and casting integer to char on macosx trigger bad codegen" [#12291](https://github.com/nim-lang/Nim/issues/12291)
* VM: no special casing for big endian machines
* Fixed "`internal error: environment misses` with a simple template inside one of Jester macros" [#12323](https://github.com/nim-lang/Nim/issues/12323)
* nimsuggest: fix tcp socket leak
* nimsuggest: fix tcp socket leak for epc backend
* Fixed "`writeFile` and `write(f, str)` skip null bytes on Windows" [#12315](https://github.com/nim-lang/Nim/issues/12315)
* Fixed "Crash in intsets symmetric_difference" [#12366](https://github.com/nim-lang/Nim/issues/12366)
* Fixed "[regression] VM crash when dealing with var param of a proc result" [#12244](https://github.com/nim-lang/Nim/issues/12244)
* fixes a koch regression that made 'koch boot --listcmd' not work anymore
* Fixed "[regression] inconsistent signed int `mod` operator between runtime, compiletime, and semfold" [#12332](https://github.com/nim-lang/Nim/issues/12332)
* Fixed "Boehm disables interior pointer checking" [#12286](https://github.com/nim-lang/Nim/issues/12286)
* Fixes semCustomPragma when nkSym
* Fixed yield in nkCheckedFieldExpr
* Fixed "`randomize()` from `random` not working on JS" [#12418](https://github.com/nim-lang/Nim/issues/12418)
* Fixed "Compiler crash with invalid object variant" [#12379](https://github.com/nim-lang/Nim/issues/12379)
* fix type's case in random.nim
* Fixed "Update docs with a better way to signal unimplemented methods" [#10804](https://github.com/nim-lang/Nim/issues/10804)
* Fixed "Nim language manual, push pragma is not explained well" [#10824](https://github.com/nim-lang/Nim/issues/10824)
* Fixed "[regression] Importing more than one module with same name from different packages produce bad codegen" [#12420](https://github.com/nim-lang/Nim/issues/12420)
* Namespace unittest enums to avoid name conflicts
* Fixed "VM checks unsigned integers for overflow." [#12310](https://github.com/nim-lang/Nim/issues/12310)
* Fixed "line directive is not generated for first line of function definition" [#12426](https://github.com/nim-lang/Nim/issues/12426)
## Documentation improvements
* threadpool: fix link in docs (#12258)
* Fix spellings (#12277)
* fix #12278, don't expose internal PCRE documentation
* Fixed "Documentation of quitprocs is wrong" [#12279](https://github.com/nim-lang/Nim/issues/12279)
* Fix typo in docs
* Fix reference to parseSpec proc in readme
* [doc/tut1] removed discard discussion in comments
* Documentation improvements around the db interface
* Easier build instructions for windows - just run `build_all.bat`.
* fix a few dead links and a missing sentence in documentation
* Macro docs additions
* Updated the code example in the os module to use better grammar.
* Mention "lambdas" and `=>` in the manual
* Better documentation on Garbage Collector

View File

@@ -0,0 +1,75 @@
# v1.0.4 - 2019-11-26
## Language changes
- Conversions to unsigned integers are unchecked at runtime, imitating earlier Nim
versions. The documentation was improved to acknowledge this special case.
See https://github.com/nim-lang/RFCs/issues/175 for more details. (#12688)
- Add `or detectOs(Manjaro)` (#12587)
- --os:ios needs to imply defined(macosx) (#12585)
- export nim.cfg parser (#12602)
## Bugfixes
- Fixed "gorge(Ex) fails after a few calls on OSX"
([#12337](https://github.com/nim-lang/Nim/issues/12337))
- Fixed "Improve posix module"
([#10723](https://github.com/nim-lang/Nim/issues/10723))
- Fixed "nim check allows gorgeEx but doesn't allow writeFile"
([#12491](https://github.com/nim-lang/Nim/issues/12491))
- Fixed "Low level arithmetics bug: -3 mod 7 == 3"
([#12514](https://github.com/nim-lang/Nim/issues/12514))
- Fixed "Broken link to c2nim in backends.rst/.html"
([#12537](https://github.com/nim-lang/Nim/issues/12537))
- Fixed "generic argument with default value causes incorrect generic type resolution"
([#12528](https://github.com/nim-lang/Nim/issues/12528))
- Fixed "regression: compiler/vmgen.nim(354, 20) `false` leaking temporary 10 slotTempInt [AssertionError]
([#12547](https://github.com/nim-lang/Nim/issues/12547))
- Fixed "Compile/link broken for nim (64-bit only) on Windows"
([#12536](https://github.com/nim-lang/Nim/issues/12536))
- Fixed "No `=destroy` for elements of closure environments other than for latest devel --gc:destructors"
([#12577](https://github.com/nim-lang/Nim/issues/12577))
- Fixed "[1.0.0] Cannot compile anything with --cpu:avr"
([#12395](https://github.com/nim-lang/Nim/issues/12395))
- Fixed "Compiler crash with invalid object variant"
([#12379](https://github.com/nim-lang/Nim/issues/12379))
- Fixed "push pragma is silently ignored if position is in front of import statement"
([#5050](https://github.com/nim-lang/Nim/issues/5050))
- Fixed "Error with strformat + asyncdispatch + const"
([#12612](https://github.com/nim-lang/Nim/issues/12612))
- Fixed "The --nimblePath is additive; need a pain-free workaround"
([#12601](https://github.com/nim-lang/Nim/issues/12601))
- Fixed "nim.cfg syntax for --define:FOO:VAL undocumented or absent"
([#12367](https://github.com/nim-lang/Nim/issues/12367))
- Fixed "vm string literals do not work when generated by a macro"
([#12670](https://github.com/nim-lang/Nim/issues/12670))
- Fixed "StaticRead does force a recompile if static file changes."
([#12663](https://github.com/nim-lang/Nim/issues/12663))
- Fixed crash in terminate handler
([#12572](https://github.com/nim-lang/Nim/pull/12572))
- Fixed newLit for objects having string fields
([#12542](https://github.com/nim-lang/Nim/pull/12542))
## Documentation improvements
- Documentation Math module (#12460)
- Fix many broken links and prefer relative links within docs (#12463)
- sequtils: replace deprecated 'random' call within example (#12515)
- integer literal documentation (#12513)
- Fix code style errors (#12545)
- fix several typos in documentation and comments (#12553)
- Add docs to better distinguish among getProjectPath, getCurrentDir and currentSourcePath (#12565)
- doc/tut3.rst: Fix typo in Introduction (#12607)
- Add links to packaging and distro pages (#12603)
- fix documentation of `$`\*(dt: DateTime) (#12660)
- Clarifies experimental / parallel example on manual.rst (#12472)
- Fix wrong section hierarchy in the manual (#12724)

View File

@@ -0,0 +1,68 @@
# v1.0.6 - 2020-01-24
## Bugfixes
### Fixed issues
- Fixed "Nim stdlib style issues with --styleCheck:error"
([#12687](https://github.com/nim-lang/Nim/issues/12687))
- Fixed "new(ref MyObject) doesn't work at compile time"
([#12488](https://github.com/nim-lang/Nim/issues/12488))
- Fixed "Accessing the wrong variant field in the VM does not trigger the appropriate error message"
([#11727](https://github.com/nim-lang/Nim/issues/11727))
- Fixed "orderedTable.del() crashes with unitialized table"
([#12798](https://github.com/nim-lang/Nim/issues/12798))
- Fixed "semfold bug with negative value * 0"
([#12783](https://github.com/nim-lang/Nim/issues/12783))
- Fixed "nimsuggest `use` command does not return all instances of symbol"
([#12832](https://github.com/nim-lang/Nim/issues/12832))
- Fixed "Codegen ICE in allPathsAsgnResult"
([#12827](https://github.com/nim-lang/Nim/issues/12827))
- Fixed "Static[T] + syntactic error in the for loop = compiler crash"
([#12148](https://github.com/nim-lang/Nim/issues/12148))
- Fixed "Incorrect unused import warning involving templates and tables"
([#12885](https://github.com/nim-lang/Nim/issues/12885))
- Fixed "regression(1.0.4): undeclared identifier: 'readLines'; plus another regression and bug"
([#13013](https://github.com/nim-lang/Nim/issues/13013))
- Fixed "`nim doc` treats `export localSymbol` incorrectly"
([#13100](https://github.com/nim-lang/Nim/issues/13100))
- Fixed "symbols not defined in the grammar"
([#10665](https://github.com/nim-lang/Nim/issues/10665))
- Fixed "nim-gdb is missing from all released packages"
([#13104](https://github.com/nim-lang/Nim/issues/13104))
- Fixed "[JS] Move is not defined"
([#9674](https://github.com/nim-lang/Nim/issues/9674))
- Fixed "Error: usage of 'isNil' is a user-defined error"
([#11440](https://github.com/nim-lang/Nim/issues/11440))
### Other bugfixes
- make addQuoted work on nimscript (#12717)
- fix db_mysql getRow() when column is null error raised (#12806)
- Fixed objects being erroneously zeroed out before object construction (#12814)
- added cstrutils (#12858): fixed for 'csuCmpIgnoreStyle' error on hotcodereloading
- Better clang_cl support (#12896)
- fix cmdline bugs affecting nimBetterRun correctness (#12933)
- fixes a bug that kept sugar.collect from working with for loop macros
- Path substitution for --out and --outdir (#12796)
- fix crash due to errant symbols in nim.cfg (#13073)
- Allow `-o` option for `buildIndex` (#13037)
- Deleted misplaced separator (#13085): Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.
- fixes an asyncftpclient bug; refs #13096
- fix the ftp store function read the local file bug (#13108)
- fix rtti sizeof for varargs in global scope (#13125)
- Correctly remove a key from CountTable when it is set to zero.
- fixes the distros.nim regression
- fixes a critical times.nim bug reported on IRC
- c_fflush() the rawWrite() buffer
## Documentation improvements
- Fixed "Documentation, Testament missing from "Tools available with Nim""
([#12251](https://github.com/nim-lang/Nim/issues/12251))
- Manual update: custom exceptions (#12847)
- times/getClockStr(): fix mistake in doc
- Fix typo and improve in code-block of 'lib/pure/parseutils.nim'

View File

@@ -193,4 +193,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
if res != arNo:
result = res
if res == arYes: break
of nkBracket:
if b.len > 0:
result = isPartOf(a, b[0])
else: discard

View File

@@ -71,7 +71,7 @@ iterator parseTableCells*(s: string, delim = '\t'): Cell =
proc alignTable*(s: string, delim = '\t', fill = ' ', sep = " "): string =
## formats a `delim`-delimited `s` representing a table; each cell is aligned
## to a width that's computed for each column; consecutive columns are
## delimted by `sep`, and alignment space is filled using `fill`.
## delimited by `sep`, and alignment space is filled using `fill`.
## More customized formatting can be done by calling `parseTableCells` directly.
for cell in parseTableCells(s, delim):
result.add cell.text

View File

@@ -185,7 +185,7 @@ type
nkStmtListExpr, # a statement list followed by an expr; this is used
# to allow powerful multi-line templates
nkBlockExpr, # a statement block ending in an expr; this is used
# to allowe powerful multi-line templates that open a
# to allow powerful multi-line templates that open a
# temporary scope
nkStmtListType, # a statement list ending in a type; for macros
nkBlockType, # a statement block ending in a type; for macros
@@ -272,7 +272,7 @@ type
sfNamedParamCall, # symbol needs named parameter call syntax in target
# language; for interfacing with Objective C
sfDiscardable, # returned value may be discarded implicitly
sfOverriden, # proc is overriden
sfOverriden, # proc is overridden
sfCallsite # A flag for template symbols to tell the
# compiler it should use line information from
# the calling side of the macro, not from the
@@ -291,10 +291,6 @@ type
const
sfNoInit* = sfMainModule # don't generate code to init the variable
sfCursor* = sfDispatcher
# local variable has been computed to be a "cursor".
# see cursors.nim for details about what that means.
sfAllUntyped* = sfVolatile # macro or template is immediately expanded \
# in a generic context
@@ -535,11 +531,12 @@ type
tfTriggersCompileTime # uses the NimNode type which make the proc
# implicitly '.compiletime'
tfRefsAnonObj # used for 'ref object' and 'ptr object'
tfCovariant # covariant generic param mimicing a ptr type
tfWeakCovariant # covariant generic param mimicing a seq/array type
tfCovariant # covariant generic param mimicking a ptr type
tfWeakCovariant # covariant generic param mimicking a seq/array type
tfContravariant # contravariant generic param
tfCheckedForDestructor # type was checked for having a destructor.
# If it has one, t.destructor is not nil.
tfIncompleteStruct # treat this type as if it had sizeof(pointer)
TTypeFlags* = set[TTypeFlag]
@@ -581,7 +578,6 @@ type
const
routineKinds* = {skProc, skFunc, skMethod, skIterator,
skConverter, skMacro, skTemplate}
tfIncompleteStruct* = tfVarargs
tfUnion* = tfNoSideEffect
tfGcSafe* = tfThread
tfObjHasKids* = tfEnumHasHoles
@@ -1250,7 +1246,7 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
# this is dirty. abstractVarRange isn't defined yet and therefor it
# this is dirty. abstractVarRange isn't defined yet and therefore it
# is duplicated here.
const abstractVarRange = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
tyTypeDesc, tyAlias, tyInferred, tySink, tyOwned}

View File

@@ -1027,7 +1027,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
dec p.splitDecls
proc genEcho(p: BProc, n: PNode) =
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
# this unusual way of implementing it ensures that e.g. ``echo("hallo", 45)``
# is threadsafe.
internalAssert p.config, n.kind == nkBracket
if p.config.target.targetOS == osGenode:
@@ -1206,7 +1206,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
if sizeExpr.isNil:
sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)]
if optNimV2 in p.config.globalOptions:
if optOwnedRefs in p.config.globalOptions:
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
[getTypeDesc(p.module, typ), sizeExpr])
genAssignment(p, a, b, {})
@@ -1484,7 +1484,7 @@ proc genNewFinalize(p: BProc, e: PNode) =
gcUsage(p.config, e)
proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
if optNimV2 in p.config.globalOptions:
if optTinyRtti in p.config.globalOptions:
result = ropecg(p.module, "#isObj($1.m_type, $2)",
[a, genTypeInfo2Name(p.module, dest)])
else:
@@ -1535,7 +1535,7 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) =
genOf(p, n.sons[1], n.sons[2].typ, d)
proc genRepr(p: BProc, e: PNode, d: var TLoc) =
if optNimV2 in p.config.globalOptions:
if optTinyRtti in p.config.globalOptions:
localError(p.config, e.info, "'repr' is not available for --newruntime")
var a: TLoc
initLocExpr(p, e.sons[1], a)
@@ -1931,7 +1931,8 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
var a: TLoc
var dest = skipTypes(n.typ, abstractVar)
if optRangeCheck notin p.options:
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
checkUnsignedConversions notin p.config.legacyFeatures):
initLocExpr(p, n.sons[0], a)
putIntoDest(p, d, n, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
@@ -2148,7 +2149,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr, mUnown: expr(p, e.sons[1], d)
of mEnumToStr:
if optNimV2 in p.config.globalOptions:
if optTinyRtti in p.config.globalOptions:
genEnumToStr(p, e, d)
else:
genRepr(p, e, d)
@@ -2423,7 +2424,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
while t.kind == tyObject and t.sons[0] != nil:
add(r, ".Sup")
t = skipTypes(t.sons[0], skipPtrs)
let checkFor = if optNimV2 in p.config.globalOptions:
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, dest)
else:
genTypeInfo(p.module, dest, n.info)

View File

@@ -17,7 +17,7 @@ const
proc getTraverseProc(p: BProc, v: PSym): Rope =
if p.config.selectedGC in {gcMarkAndSweep, gcDestructors, gcV2, gcRefc} and
optNimV2 notin p.config.globalOptions and
optOwnedRefs notin p.config.globalOptions and
containsGarbageCollectedRef(v.loc.t):
# we register a specialized marked proc here; this has the advantage
# that it works out of the box for thread local storage then :-)
@@ -692,7 +692,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
[e, makeCString(typ.sym.name.s),
makeCString(if p.prc != nil: p.prc.name.s else: p.module.module.name.s),
quotedFilename(p.config, t.info), toLinenumber(t.info)])
if optNimV2 in p.config.globalOptions:
if optOwnedRefs in p.config.globalOptions:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [e])
else:
genLineDir(p, t)
@@ -784,7 +784,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
var branches: seq[Rope]
newSeq(branches, bitMask + 1)
var a: TLoc
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
initLocExpr(p, t.sons[0], a) # fist pass: generate ifs+goto:
var labId = p.labels
for i in 1 ..< len(t):
inc(p.labels)
@@ -1057,7 +1057,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
for j in 0 .. blen - 2:
assert(t.sons[i].sons[j].kind == nkType)
if orExpr != nil: add(orExpr, "||")
let checkFor = if optNimV2 in p.config.globalOptions:
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, t[i][j].typ)
else:
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
@@ -1220,7 +1220,7 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
getTemp(p, a.t, tmp)
expr(p, e.sons[1], tmp)
let field = dotExpr.sons[1].sym
if optNimV2 in p.config.globalOptions:
if optTinyRtti in p.config.globalOptions:
let t = dotExpr[0].typ.skipTypes(abstractInst)
var oldVal, newVal: TLoc
genCaseObjDiscMapping(p, e[0], t, field, oldVal)

View File

@@ -17,7 +17,7 @@ type
visitorFrmt: string
const
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType)
proc genCaseRange(p: BProc, branch: PNode)
@@ -104,7 +104,8 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
elif containsGarbageCollectedRef(typ.lastSon):
# destructor based seqs are themselves not traced but their data is, if
# they contain a GC'ed type:
genTraverseProcSeq(c, accessor, typ)
lineCg(p, cpsStmts, "#nimGCvisitSeq((void*)$1, $2);$n", [accessor, c.visitorFrmt])
#genTraverseProcSeq(c, accessor, typ)
of tyString:
if tfHasAsgn notin typ.flags:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])

View File

@@ -61,7 +61,7 @@ proc mangleParamName(m: BModule; s: PSym): Rope =
var res = s.name.s.mangle
# Take into account if HCR is on because of the following scenario:
# if a module gets imported and it has some more importc symbols in it,
# some param names might recieve the "_0" suffix to distinguish from what
# some param names might receive the "_0" suffix to distinguish from what
# is newly available. That might lead to changes in the C code in nimcache
# that contain only a parameter name change, but that is enough to mandate
# recompilation of that source file and thus a new shared object will be
@@ -287,6 +287,7 @@ proc fillResult(conf: ConfigRef; param: PNode) =
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
useHeader(m, t.sym)
result = t.sym.loc.r
else:
result = rope(literal)
@@ -1364,7 +1365,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
of tySet: genSetInfo(m, t, result, info)
of tyEnum: genEnumInfo(m, t, result, info)
of tyObject:
if optNimV2 in m.config.globalOptions:
if optTinyRtti in m.config.globalOptions:
genObjectInfoV2(m, t, origType, result, info)
else:
genObjectInfo(m, t, origType, result, info)

View File

@@ -347,7 +347,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
s = skipTypes(s.sons[0], skipPtrs)
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t, a.lode.info)])
of frEmbedded:
if optNimV2 in p.config.globalOptions:
if optTinyRtti in p.config.globalOptions:
localError(p.config, p.prc.info,
"complex object initialization is not supported with --newruntime")
# worst case for performance:
@@ -931,11 +931,12 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
# assignment this is not good enough! The only pattern we allow for
# is 'finally: result = x'
result = InitSkippable
for it in n:
if it.kind == nkFinally:
result = allPathsAsgnResult(it.lastSon)
allPathsInBranch(n[0])
for i in 1..<n.len:
if n[i].kind == nkFinally:
result = allPathsAsgnResult(n[i].lastSon)
else:
allPathsInBranch(it.lastSon)
allPathsInBranch(n[i].lastSon)
else:
for i in 0..<safeLen(n):
allPathsInBranch(n[i])
@@ -997,13 +998,14 @@ proc genProcAux(m: BModule, prc: PSym) =
closureSetup(p, prc)
genStmts(p, procBody) # modifies p.locals, p.init, etc.
var generatedProc: Rope
generatedProc.genCLineDir prc.info, m.config
if sfNoReturn in prc.flags:
if hasDeclspec in extccomp.CC[p.config.cCompiler].props:
header = "__declspec(noreturn) " & header
if sfPure in prc.flags:
if hasDeclspec in extccomp.CC[p.config.cCompiler].props:
header = "__declspec(naked) " & header
generatedProc = ropecg(p.module, "$N$1 {$n$2$3$4}$N$N",
generatedProc.add ropecg(p.module, "$1 {$n$2$3$4}$N$N",
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
else:
if m.hcrOn and isReloadable(m, prc):
@@ -1011,7 +1013,7 @@ proc genProcAux(m: BModule, prc: PSym) =
# This fixes the use of methods and also the case when 2 functions within the same module
# call each other using directly the "_actual" versions (an optimization) - see issue #11608
addf(m.s[cfsProcHeaders], "$1;\n", [header])
generatedProc = ropecg(p.module, "$N$1 {$N", [header])
generatedProc.add ropecg(p.module, "$1 {", [header])
add(generatedProc, initGCFrame(p))
if optStackTrace in prc.options:
add(generatedProc, p.s(cpsLocals))
@@ -1255,7 +1257,7 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
proc genMainProc(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
## it means raising dependency on the symbols is too late as it will not propogate
## it means raising dependency on the symbols is too late as it will not propagate
## into other modules, only simple rope manipulations are allowed
var preMainCode: Rope
@@ -1514,7 +1516,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
proc genDatInitCode(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
## it means raising dependency on the symbols is too late as it will not propogate
## it means raising dependency on the symbols is too late as it will not propagate
## into other modules, only simple rope manipulations are allowed
var moduleDatInitRequired = m.hcrOn
@@ -1558,7 +1560,7 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
proc genInitCode(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
## it means raising dependency on the symbols is too late as it will not propogate
## it means raising dependency on the symbols is too late as it will not propagate
## into other modules, only simple rope manipulations are allowed
var moduleInitRequired = m.hcrOn
let initname = getInitName(m)
@@ -1746,7 +1748,7 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
result.typeNodesName = getTempName(result)
result.nimTypesName = getTempName(result)
# no line tracing for the init sections of the system module so that we
# don't generate a TFrame which can confuse the stack botton initialization:
# don't generate a TFrame which can confuse the stack bottom initialization:
if sfSystemModule in module.flags:
incl result.flags, preventStackTrace
excl(result.preInitProc.options, optStackTrace)

View File

@@ -58,7 +58,7 @@ type
id*: int # the ID of the label; positive means that it
label*: Rope # generated text for the label
# nil if label is not used
sections*: TCProcSections # the code beloging
sections*: TCProcSections # the code belonging
isLoop*: bool # whether block is a loop
nestedTryStmts*: int16 # how many try statements is it nested into
nestedExceptStmts*: int16 # how many except statements is it nested into
@@ -150,7 +150,7 @@ type
initProc*: BProc # code for init procedure
preInitProc*: BProc # code executed before the init proc
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
inHcrInitGuard*: bool # We are currently withing a HCR reloading guard.
inHcrInitGuard*: bool # We are currently within a HCR reloading guard.
typeStack*: TTypeSeq # used for type generation
dataCache*: TNodeTable
typeNodes*, nimTypes*: int # used for type info generation

View File

@@ -683,7 +683,8 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = ex
result.add(n)
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv:
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv,
nkDerefExpr, nkHiddenDeref:
var ns = false
for i in 0 ..< n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
@@ -757,7 +758,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = newSymNode(ctx.g.getSysSym(n[0].info, "true"))
n[1] = newBody
of nkDotExpr:
of nkDotExpr, nkCheckedFieldExpr:
var ns = false
n[0] = ctx.lowerStmtListExprs(n[0], ns)
if ns:
@@ -1288,7 +1289,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
if getEnvParam(fn).isNil:
# Lambda lifting was not done yet. Use temporary :state sym, which will
# be handled specially by lambda lifting. Local temp vars (if needed)
# should folllow the same logic.
# should follow 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)
@@ -1309,7 +1310,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# Optimize empty states away
ctx.deleteEmptyStates()
# Make new body by concating the list of states
# Make new body by concatenating the list of states
result = newNodeI(nkStmtList, n.info)
for s in ctx.states:
assert(s.len == 2)

View File

@@ -87,7 +87,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
discard
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars(conf)
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":

View File

@@ -380,6 +380,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "nonimblepath", "nobabelpath":
expectNoArg(conf, switch, arg, pass, info)
disableNimblePath(conf)
of "clearnimblepath":
expectNoArg(conf, switch, arg, pass, info)
clearNimblePath(conf)
of "excludepath":
expectArg(conf, switch, arg, pass, info)
let path = processPath(conf, arg, info)
@@ -387,15 +390,15 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf.lazyPaths.keepItIf(it != path)
of "nimcache":
expectArg(conf, switch, arg, pass, info)
conf.nimcacheDir = processPath(conf, arg, info, true)
conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
of "out", "o":
expectArg(conf, switch, arg, pass, info)
let f = splitFile(arg.expandTilde)
let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
conf.outFile = RelativeFile f.name & f.ext
conf.outDir = toAbsoluteDir f.dir
of "outdir":
expectArg(conf, switch, arg, pass, info)
conf.outDir = toAbsoluteDir arg.expandTilde
conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
of "docseesrcurl":
expectArg(conf, switch, arg, pass, info)
conf.docSeeSrcUrl = arg
@@ -614,22 +617,20 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optGenMapping}, arg, pass, info)
of "os":
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd1, passPP}:
let theOS = platform.nameToOS(arg)
if theOS == osNone:
let osList = platform.listOSnames().join(", ")
localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
elif theOS != conf.target.hostOS:
setTarget(conf.target, theOS, conf.target.targetCPU)
let theOS = platform.nameToOS(arg)
if theOS == osNone:
let osList = platform.listOSnames().join(", ")
localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
else:
setTarget(conf.target, theOS, conf.target.targetCPU)
of "cpu":
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd1, passPP}:
let cpu = platform.nameToCPU(arg)
if cpu == cpuNone:
let cpuList = platform.listCPUnames().join(", ")
localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
elif cpu != conf.target.hostCPU:
setTarget(conf.target, conf.target.targetOS, cpu)
let cpu = platform.nameToCPU(arg)
if cpu == cpuNone:
let cpuList = platform.listCPUnames().join(", ")
localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
else:
setTarget(conf.target, conf.target.targetOS, cpu)
of "run", "r":
processOnOffSwitchG(conf, {optRun}, arg, pass, info)
of "errormax":
@@ -758,7 +759,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if pass in {passCmd2, passPP}:
doAssert(conf != nil)
incl(conf.features, destructor)
incl(conf.globalOptions, optNimV2)
incl(conf.globalOptions, optTinyRtti)
incl(conf.globalOptions, optOwnedRefs)
incl(conf.globalOptions, optSeqDestructors)
defineSymbol(conf.symbols, "nimV2")
conf.selectedGC = gcDestructors
defineSymbol(conf.symbols, "gcdestructors")

View File

@@ -1,72 +0,0 @@
#
#
# The Nim Compiler
# (c) Copyright 2019 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
lineinfos, parampatterns
##[
This module implements "cursor" detection. A cursor is a local variable
that is used for navigation in a datastructure, it does not "own" the
data it aliases but it might update the underlying datastructure.
Two primary examples for cursors that I have in mind and that are critical
for optimization:
1. Local string variable introduced by ``for x in a``::
var i = 0
while i < a.len:
let cursor = a[i]
use cursor
inc i
2. Local ``ref`` variable for navigation::
var cursor = listHead
while cursor != nil:
use cursor
cursor = cursor.next
Cursors are very interesting for the optimizer because they can be copyMem'ed
and don't need a destructor.
More formally, a cursor is a variable that is set on all paths to
a *location* or a proc call that produced a ``lent/var`` type. All statements
that come after these assignments MUST not mutate what the cursor aliases.
Mutations *through* the cursor are allowed if the cursor has ref semantics.
Look at this complex real world example taken from the compiler itself:
.. code-block:: Nim
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
var t = typ
while true:
if t.sym != nil and {sfImportc, sfExportc} * t.sym.flags != {}:
return t.sym.loc.r
if t.kind in irrelevantForBackend:
t = t.lastSon
else:
break
let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.lastSon else: typ
if typ.loc.r == nil:
typ.loc.r = typ.typeName & $sig
result = typ.loc.r
if result == nil: internalError(m.config, "getTypeName: " & $typ.kind)
Here `t` is a cursor but without a control flow based analysis we are unlikely
to detect it.
]##
# Araq: I owe you an implementation. For now use the .cursor pragma. :-/

View File

@@ -513,7 +513,7 @@ proc genTry(c: var Con; n: PNode) =
let f = c.tryStmtFixups[i]
c.patch(f)
# we also need to produce join instructions
# for the 'fork' that might preceed the goto instruction
# for the 'fork' that might precede the goto instruction
if f.int-1 >= 0 and c.code[f.int-1].kind == fork:
c.joinI(TPosition(f.int-1), n)

View File

@@ -26,6 +26,7 @@ type
TSections = array[TSymKind, Rope]
TDocumentor = object of rstgen.RstGenerator
modDesc: Rope # module description
module: PSym
modDeprecationMsg: Rope
toc, section: TSections
indexValFilename: string
@@ -115,9 +116,10 @@ proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
else:
result = getOutFile(conf, filename, ext)
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, outExt: string = HtmlExt): PDoc =
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, outExt: string = HtmlExt, module: PSym = nil): PDoc =
declareClosures()
new(result)
result.module = module
result.conf = conf
result.cache = cache
initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
@@ -592,7 +594,7 @@ proc docstringSummary(rstText: string): string =
##
## Most docstrings will contain a one liner summary, so stripping at the
## first newline is usually fine. If after that the content is still too big,
## it is stripped at the first comma, colon or dot, usual english sentence
## it is stripped at the first comma, colon or dot, usual English sentence
## separators.
##
## No guarantees are made on the size of the output, but it should be small.
@@ -631,8 +633,12 @@ proc genDeprecationMsg(d: PDoc, n: PNode): Rope =
else:
doAssert false
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
if not isVisible(d, nameNode): return
type DocFlags = enum
kDefault
kForceExport
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
if (docFlags != kForceExport) and not isVisible(d, nameNode): return
let
name = getName(d, nameNode)
nameRope = name.rope
@@ -848,7 +854,9 @@ proc documentRaises*(cache: IdentCache; n: PNode) =
if p4 != nil: n.sons[pragmasPos].add p4
if p5 != nil: n.sons[pragmasPos].add p5
proc generateDoc*(d: PDoc, n, orig: PNode) =
proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
template genItemAux(skind) =
genItem(d, n, n[namePos], skind, docFlags)
case n.kind
of nkPragma:
let pragmaNode = findPragma(n, wDeprecated)
@@ -856,27 +864,27 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
of nkCommentStmt: add(d.modDesc, genComment(d, n))
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skProc)
genItemAux(skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skFunc)
genItemAux(skFunc)
of nkMethodDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skMethod)
genItemAux(skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skIterator)
of nkMacroDef: genItem(d, n, n.sons[namePos], skMacro)
of nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate)
genItemAux(skIterator)
of nkMacroDef: genItemAux(skMacro)
of nkTemplateDef: genItemAux(skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skConverter)
genItemAux(skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< len(n):
if n.sons[i].kind != nkCommentStmt:
# order is always 'type var let const':
genItem(d, n.sons[i], n.sons[i].sons[0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
genItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)), docFlags)
of nkStmtList:
for i in 0 ..< len(n): generateDoc(d, n.sons[i], orig)
of nkWhenStmt:
@@ -887,7 +895,11 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
for it in n: traceDeps(d, it)
of nkExportStmt:
for it in n:
if it.kind == nkSym: exportSym(d, it.sym)
if it.kind == nkSym:
if d.module != nil and d.module == it.sym.owner:
generateDoc(d, it.sym.ast, orig, kForceExport)
else:
exportSym(d, it.sym)
of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
of nkCallKinds:
@@ -1169,6 +1181,9 @@ proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
["Index".rope, nil, nil, rope(getDateStr()),
rope(getClockStr()), content, nil, nil, nil])
# no analytics because context is not available
let filename = getOutFile(conf, RelativeFile"theindex", HtmlExt)
var outFile = RelativeFile"theindex"
if conf.outFile != RelativeFile"":
outFile = conf.outFile
let filename = getOutFile(conf, outFile, HtmlExt)
if not writeRope(code, filename):
rawMessage(conf, errCannotOpenFile, filename.string)

View File

@@ -62,7 +62,7 @@ template myOpenImpl(ext: untyped) {.dirty.} =
g.module = module
g.config = graph.config
var d = newDocumentor(AbsoluteFile toFullPath(graph.config, FileIndex module.position),
graph.cache, graph.config, ext)
graph.cache, graph.config, ext, module)
d.hasToc = true
g.doc = d
result = g

View File

@@ -63,9 +63,9 @@ proc importcSymbol*(conf: ConfigRef, sym: PSym): PNode =
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
globalError(conf, sym.info, "dynlib needs to be a string lit")
var theAddr: pointer
if (lib.isNil or lib.kind == libHeader) and not gExehandle.isNil:
if (lib.isNil or lib.kind == libHeader) and not gExeHandle.isNil:
# first try this exe itself:
theAddr = gExehandle.symAddr(name)
theAddr = gExeHandle.symAddr(name)
# then try libc:
if theAddr.isNil:
let dllhandle = getDll(conf, gDllCache, libcDll, sym.info)

View File

@@ -135,7 +135,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
else:
addSon(result, default.copyTree)
# add any generic paramaters
# add any generic parameters
for i in 1 .. genericParams:
result.addSon n.sons[givenRegularParams + i]

View File

@@ -138,7 +138,7 @@ compiler vcc:
optSize: " /O1 /G7 ",
compilerExe: "cl",
cppCompiler: "cl",
compileTmpl: "/c$vccplatform$options $include /Fo$objfile $file",
compileTmpl: "/c$vccplatform $options $include /Fo$objfile $file",
buildGui: " /link /SUBSYSTEM:WINDOWS ",
buildDll: " /LD",
buildLib: "lib /OUT:$libfile $objfiles",
@@ -404,7 +404,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
CC[c].name & fullSuffix
result = getConfigVar(conf, fullCCname)
if result.len == 0:
# not overriden for this cross compilation setting?
# not overridden for this cross compilation setting?
result = getConfigVar(conf, CC[c].name & fullSuffix)
else:
result = getConfigVar(conf, CC[c].name & fullSuffix)
@@ -757,7 +757,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
# way of being able to debug and rebuild the program at the same time. This
# is accomplished using the /PDB:<filename> flag (there also exists the
# /PDBALTPATH:<filename> flag). The only downside is that the .pdb files are
# atleast 300kb big (when linking statically to the runtime - or else 5mb+)
# at least 300kb big (when linking statically to the runtime - or else 5mb+)
# and will quickly accumulate. There is a hacky solution: we could try to
# delete all .pdb files with a pattern and swallow exceptions.
#
@@ -996,15 +996,16 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
pastStart = true
lit "\L"
proc nimfiles(conf: ConfigRef; f: File) =
proc depfiles(conf: ConfigRef; f: File) =
var i = 0
for it in conf.m.fileInfos:
if isAbsolute(it.fullPath.string):
let path = it.fullPath.string
if isAbsolute(path): # TODO: else?
if i > 0: lit "],\L"
lit "["
str it.fullPath.string
str path
lit ", "
str $secureHashFile(it.fullPath.string)
str $secureHashFile(path)
inc i
lit "]\L"
@@ -1028,8 +1029,8 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"):
lit ",\L\"cmdline\": "
str conf.commandLine
lit ",\L\"nimfiles\":[\L"
nimfiles(conf, f)
lit ",\L\"depfiles\":[\L"
depfiles(conf, f)
lit "],\L\"nimexe\": \L"
str hashNimExe()
lit "\L"
@@ -1044,22 +1045,22 @@ proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; projectfile: Absol
result = false
try:
let data = json.parseFile(jsonFile.string)
if not data.hasKey("nimfiles") or not data.hasKey("cmdline"):
if not data.hasKey("depfiles") or not data.hasKey("cmdline"):
return true
let oldCmdLine = data["cmdline"].getStr
if conf.commandLine != oldCmdLine:
return true
if hashNimExe() != data["nimexe"].getStr:
return true
let nimfilesPairs = data["nimfiles"]
doAssert nimfilesPairs.kind == JArray
for p in nimfilesPairs:
let depfilesPairs = data["depfiles"]
doAssert depfilesPairs.kind == JArray
for p in depfilesPairs:
doAssert p.kind == JArray
# >= 2 for forwards compatibility with potential later .json files:
doAssert p.len >= 2
let nimFilename = p[0].getStr
let depFilename = p[0].getStr
let oldHashValue = p[1].getStr
let newHashValue = $secureHashFile(nimFilename)
let newHashValue = $secureHashFile(depFilename)
if oldHashValue != newHashValue:
return true
except IOError, OSError, ValueError:

View File

@@ -22,7 +22,7 @@ type
info: TLineInfo
indent, emitPar: int
x: string # the current input line
outp: PLLStream # the ouput will be parsed by pnimsyn
outp: PLLStream # the output will be parsed by pnimsyn
subsChar, nimDirective: char
emit, conc, toStr: string
curly, bracket, par: int

View File

@@ -40,6 +40,7 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
p.inputStream.write(input)
p.inputStream.close()
result = p.readOutput
p.close()
readSuccessful = true
# only cache successful runs:
if result[1] == 0:
@@ -54,5 +55,6 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
p.inputStream.write(input)
p.inputStream.close()
result = p.readOutput
p.close()
except IOError, OSError:
result = ("", -1)

View File

@@ -436,7 +436,7 @@ proc sameTree*(a, b: PNode): bool =
if not result and a.sym.magic != mNone:
result = a.sym.magic == b.sym.magic or sameOpr(a.sym, b.sym)
of nkIdent: result = a.ident.id == b.ident.id
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkType: result = a.typ == b.typ

View File

@@ -14,7 +14,7 @@ proc hlo(c: PContext, n: PNode): PNode
proc evalPattern(c: PContext, n, orig: PNode): PNode =
internalAssert c.config, n.kind == nkCall and n.sons[0].kind == nkSym
# we need to ensure that the resulting AST is semchecked. However, it's
# aweful to semcheck before macro invocation, so we don't and treat
# awful to semcheck before macro invocation, so we don't and treat
# templates and macros as immediate in this context.
var rule: string
if optHints in c.config.options and hintPattern in c.config.notes:

View File

@@ -27,7 +27,7 @@ proc importPureEnumField*(c: PContext; s: PSym) =
if checkB == nil:
strTableAdd(c.pureEnumFields, s)
else:
# mark as ambigous:
# mark as ambiguous:
incl(c.ambiguousSymbols, checkB.id)
incl(c.ambiguousSymbols, s.id)
@@ -153,7 +153,11 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
err.add toFullPath(c.config, c.graph.importStack[i]) & " imports " &
toFullPath(c.config, c.graph.importStack[i+1])
c.recursiveDep = err
discard pushOptionEntry(c)
result = importModuleAs(c, n, c.graph.importModuleCallback(c.graph, c.module, f))
popOptionEntry(c)
#echo "set back to ", L
c.graph.importStack.setLen(L)
# we cannot perform this check reliably because of

View File

@@ -11,136 +11,14 @@
## an optimizer that optimizes copies to moves. This is implemented as an
## AST to AST transformation so that every backend benefits from it.
## Rules for destructor injections:
##
## foo(bar(X(), Y()))
## X and Y get destroyed after bar completes:
##
## foo( (tmpX = X(); tmpY = Y(); tmpBar = bar(tmpX, tmpY);
## destroy(tmpX); destroy(tmpY);
## tmpBar))
## destroy(tmpBar)
##
## var x = f()
## body
##
## is the same as:
##
## var x;
## try:
## move(x, f())
## finally:
## destroy(x)
##
## But this really just an optimization that tries to avoid to
## introduce too many temporaries, the 'destroy' is caused by
## the 'f()' call. No! That is not true for 'result = f()'!
##
## x = y where y is read only once
## is the same as: move(x, y)
##
## Actually the more general rule is: The *last* read of ``y``
## can become a move if ``y`` is the result of a construction.
##
## We also need to keep in mind here that the number of reads is
## control flow dependent:
## let x = foo()
## while true:
## y = x # only one read, but the 2nd iteration will fail!
## This also affects recursions! Only usages that do not cross
## a loop boundary (scope) and are not used in function calls
## are safe.
##
##
## x = f() is the same as: move(x, f())
##
## x = y
## is the same as: copy(x, y)
##
## Reassignment works under this scheme:
## var x = f()
## x = y
##
## is the same as:
##
## var x;
## try:
## move(x, f())
## copy(x, y)
## finally:
## destroy(x)
##
## result = f() must not destroy 'result'!
##
## The produced temporaries clutter up the code and might lead to
## inefficiencies. A better strategy is to collect all the temporaries
## in a single object that we put into a single try-finally that
## surrounds the proc body. This means the code stays quite efficient
## when compiled to C. In fact, we do the same for variables, so
## destructors are called when the proc returns, not at scope exit!
## This makes certains idioms easier to support. (Taking the slice
## of a temporary object.)
##
## foo(bar(X(), Y()))
## X and Y get destroyed after bar completes:
##
## var tmp: object
## foo( (move tmp.x, X(); move tmp.y, Y(); tmp.bar = bar(tmpX, tmpY);
## tmp.bar))
## destroy(tmp.bar)
## destroy(tmp.x); destroy(tmp.y)
##
## See doc/destructors.rst for a spec of the implemented rewrite rules
#[
From https://github.com/nim-lang/Nim/wiki/Destructors
Rule Pattern Transformed into
---- ------- ----------------
1.1 var x: T; stmts var x: T; try stmts
finally: `=destroy`(x)
2 x = f() `=sink`(x, f())
3 x = lastReadOf z `=sink`(x, z); wasMoved(z)
3.2 x = path z; body ``x = bitwiseCopy(path z);``
do not emit `=destroy(x)`. Note: body
must not mutate ``z`` nor ``x``. All
assignments to ``x`` must be of the form
``path z`` but the ``z`` can differ.
Neither ``z`` nor ``x`` can have the
flag ``sfAddrTaken`` to ensure no other
aliasing is going on.
4.1 y = sinkParam `=sink`(y, sinkParam)
4.2 x = y `=`(x, y) # a copy
5.1 f_sink(g()) f_sink(g())
5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read
5.3 f_sink(move y) f_sink(y); wasMoved(y) # explicit moves empties 'y'
5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp)
Rule 3.2 describes a "cursor" variable, a variable that is only used as a
view into some data structure. See ``compiler/cursors.nim`` for details.
Note: In order to avoid the very common combination ``reset(x); =sink(x, y)`` for
variable definitions we must turn "the first sink/assignment" operation into a
copyMem. This is harder than it looks:
while true:
try:
if cond: break # problem if we run destroy(x) here :-/
var x = f()
finally:
destroy(x)
And the C++ optimizers don't sweat to optimize it for us, so we don't have
to do it.
]#
import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents,
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
lineinfos, parampatterns, sighashes
const
InterestingSyms = {skVar, skResult, skLet, skForVar, skTemp}
type
Con = object
owner: PSym
@@ -217,46 +95,9 @@ proc isLastRead(n: PNode; c: var Con): bool =
dbg:
echo "ugh ", c.otherRead.isNil, " ", result
when false:
let s = n.sym
var pcs: seq[int] = @[instr+1]
var takenGotos: IntSet
var takenForks = initIntSet()
while pcs.len > 0:
var pc = pcs.pop
takenGotos = initIntSet()
while pc < c.g.len:
case c.g[pc].kind
of def:
if c.g[pc].sym == s:
# the path lead to a redefinition of 's' --> abandon it.
break
inc pc
of use:
if c.g[pc].sym == s:
c.otherRead = c.g[pc].n
return false
inc pc
of goto:
# we must leave endless loops eventually:
if not takenGotos.containsOrIncl(pc):
pc = pc + c.g[pc].dest
else:
inc pc
of fork:
# we follow the next instruction but push the dest onto our "work" stack:
if not takenForks.containsOrIncl(pc):
pcs.add pc + c.g[pc].dest
inc pc
of InstrKind.join:
inc pc
#echo c.graph.config $ n.info, " last read here!"
return true
proc initialized(code: ControlFlowGraph; pc: int,
init, uninit: var IntSet; comesFrom: int): int =
## Computes the set of definitely initialized variables accross all code paths
## Computes the set of definitely initialized variables across all code paths
## as an IntSet of IDs.
var pc = pc
while pc < code.len:
@@ -290,9 +131,6 @@ proc initialized(code: ControlFlowGraph; pc: int,
inc pc
return pc
template interestingSym(s: PSym): bool =
s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ)
template isUnpackedTuple(s: PSym): bool =
## we move out all elements of unpacked tuples,
## hence unpacked tuples themselves don't need to be destroyed
@@ -353,8 +191,8 @@ proc canBeMoved(t: PType): bool {.inline.} =
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
result = t.kind != tyRef and t.attachedOps[attachedSink] != nil
proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
proc genSink(c: Con; dest, ri: PNode): PNode =
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
let k = if t.attachedOps[attachedSink] != nil: attachedSink
else: attachedAsgn
if t.attachedOps[k] != nil:
@@ -365,20 +203,20 @@ proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
# we generate a fast assignment in this case:
result = newTree(nkFastAsgn, dest)
proc genCopy(c: var Con; t: PType; dest, ri: PNode): PNode =
proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode =
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = genOp(c, t, attachedAsgn, dest, ri)
proc genCopy(c: var Con; dest, ri: PNode): PNode =
let t = dest.typ
if tfHasOwned in t.flags:
# try to improve the error message here:
if c.otherRead == nil: discard isLastRead(ri, c)
checkForErrorPragma(c, t, ri, "=")
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
result = genOp(c, t, attachedAsgn, dest, ri)
genCopyNoCheck(c, dest, ri)
proc genCopyNoCheck(c: Con; t: PType; dest, ri: PNode): PNode =
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
result = genOp(c, t, attachedAsgn, dest, ri)
proc genDestroy(c: Con; t: PType; dest: PNode): PNode =
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
proc genDestroy(c: Con; dest: PNode): PNode =
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = genOp(c, t, attachedDestructor, dest, nil)
proc addTopVar(c: var Con; v: PNode) =
@@ -390,20 +228,10 @@ proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
result = newSymNode(sym)
c.addTopVar(result)
proc p(n: PNode; c: var Con): PNode
template recurse(n, dest) =
for i in 0..<n.len:
dest.add p(n[i], c)
proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode =
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, magicname, m)))
result.add n
proc genWasMoved(n: PNode; c: var Con): PNode =
# The mWasMoved builtin does not take the address.
result = genMagicCall(n, c, "wasMoved", mWasMoved)
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, "wasMoved", mWasMoved)))
result.add n #mWasMoved does not take the address
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
result = newNodeI(nkCall, info)
@@ -422,9 +250,9 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode =
let tempAsNode = newSymNode(temp)
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
vpart.sons[0] = tempAsNode
vpart.sons[1] = c.emptyNode
vpart.sons[2] = n
vpart[0] = tempAsNode
vpart[1] = c.emptyNode
vpart[2] = n
add(v, vpart)
result.add v
@@ -437,6 +265,10 @@ proc sinkParamIsLastReadCheck(c: var Con, s: PNode) =
localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s &
"` is already consumed at " & toFileLineCol(c. graph.config, s.info))
proc p(n: PNode; c: var Con): PNode
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode
proc passCopyToSink(n: PNode; c: var Con): PNode =
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
let tmp = getTemp(c, n.typ, n.info)
@@ -444,7 +276,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
# out of loops we need to mark it as 'wasMoved'.
result.add genWasMoved(tmp, c)
if hasDestructor(n.typ):
var m = genCopy(c, n.typ, tmp, n)
var m = genCopy(c, tmp, n)
m.add p(n, c)
result.add m
if isLValue(n):
@@ -457,7 +289,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
proc isDangerousSeq(t: PType): bool {.inline.} =
let t = t.skipTypes(abstractInst)
result = t.kind == tySequence and tfHasOwned notin t.sons[0].flags
result = t.kind == tySequence and tfHasOwned notin t[0].flags
proc containsConstSeq(n: PNode): bool =
if n.kind == nkBracket and n.len > 0 and n.typ != nil and isDangerousSeq(n.typ):
@@ -467,19 +299,66 @@ proc containsConstSeq(n: PNode): bool =
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
result = containsConstSeq(n[1])
of nkObjConstr, nkClosure:
for i in 1 ..< n.len:
for i in 1..<n.len:
if containsConstSeq(n[i]): return true
of nkCurly, nkBracket, nkPar, nkTupleConstr:
for i in 0 ..< n.len:
if containsConstSeq(n[i]): return true
for son in n:
if containsConstSeq(son): return true
else: discard
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
template pArgIfTyped(argPart: PNode): PNode =
# typ is nil if we are in if/case expr branch with noreturn
if argPart.typ == nil: p(argPart, c)
else: pArg(argPart, c, isSink)
template handleNested(n: untyped, processCall: untyped) =
case n.kind
of nkStmtList, nkStmtListExpr:
if n.len == 0: return n
result = copyNode(n)
for i in 0..<n.len-1:
result.add p(n[i], c)
template node: untyped = n[^1]
result.add processCall
of nkBlockStmt, nkBlockExpr:
result = copyNode(n)
result.add n[0]
template node: untyped = n[1]
result.add processCall
of nkIfStmt, nkIfExpr:
result = copyNode(n)
for son in n:
var branch = copyNode(son)
if son.kind in {nkElifBranch, nkElifExpr}:
template node: untyped = son[1]
branch.add p(son[0], c) #The condition
branch.add if node.typ == nil: p(node, c) #noreturn
else: processCall
else:
template node: untyped = son[0]
branch.add if node.typ == nil: p(node, c) #noreturn
else: processCall
result.add branch
of nkCaseStmt:
result = copyNode(n)
result.add p(n[0], c)
for i in 1..<n.len:
var branch: PNode
if n[i].kind == nkOfBranch:
branch = n[i] # of branch conditions are constants
template node: untyped = n[i][^1]
branch[^1] = if node.typ == nil: p(node, c) #noreturn
else: processCall
elif n[i].kind in {nkElifBranch, nkElifExpr}:
branch = copyNode(n[i])
branch.add p(n[i][0], c) #The condition
template node: untyped = n[i][1]
branch.add if node.typ == nil: p(node, c) #noreturn
else: processCall
else:
branch = copyNode(n[i])
template node: untyped = n[i][0]
branch.add if node.typ == nil: p(node, c) #noreturn
else: processCall
result.add branch
else: assert(false)
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
if isSink:
if arg.kind in nkCallKinds:
# recurse but skip the call expression in order to prevent
@@ -492,11 +371,11 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
result.add pArg(arg[i], c, i < L and isSinkTypeForParam(parameters[i]))
elif arg.containsConstSeq:
# const sequences are not mutable and so we need to pass a copy to the
# sink parameter (bug #11524). Note that the string implemenation is
# sink parameter (bug #11524). Note that the string implementation is
# different and can deal with 'const string sunk into var'.
result = passCopyToSink(arg, c)
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkCharLit..nkTripleStrLit}:
discard "object construction to sink parameter: nothing to do"
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr} + nkLiterals:
# object construction to sink parameter: nothing to do
result = arg
elif arg.kind == nkSym and isSinkParam(arg.sym):
# Sinked params can be consumed only once. We need to reset the memory
@@ -507,202 +386,216 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
# it is the last read, can be sinked. We need to reset the memory
# to disable the destructor which we have not elided
result = destructiveMoveVar(arg, c)
elif arg.kind in {nkBlockExpr, nkBlockStmt}:
result = copyNode(arg)
result.add arg[0]
result.add pArg(arg[1], c, isSink)
elif arg.kind == nkStmtListExpr:
result = copyNode(arg)
for i in 0..arg.len-2:
result.add p(arg[i], c)
result.add pArg(arg[^1], c, isSink)
elif arg.kind in {nkIfExpr, nkIfStmt}:
result = copyNode(arg)
for i in 0..<arg.len:
var branch = copyNode(arg[i])
if arg[i].kind in {nkElifBranch, nkElifExpr}:
branch.add p(arg[i][0], c)
branch.add pArgIfTyped(arg[i][1])
else:
branch.add pArgIfTyped(arg[i][0])
result.add branch
elif arg.kind == nkCaseStmt:
result = copyNode(arg)
result.add p(arg[0], c)
for i in 1..<arg.len:
var branch: PNode
if arg[i].kind == nkOfBranch:
branch = arg[i] # of branch conditions are constants
branch[^1] = pArgIfTyped(arg[i][^1])
elif arg[i].kind in {nkElifBranch, nkElifExpr}:
branch = copyNode(arg[i])
branch.add p(arg[i][0], c)
branch.add pArgIfTyped(arg[i][1])
else:
branch = copyNode(arg[i])
branch.add pArgIfTyped(arg[i][0])
result.add branch
elif arg.kind in {nkStmtListExpr, nkBlockExpr, nkBlockStmt, nkIfExpr, nkIfStmt, nkCaseStmt}:
handleNested(arg): pArg(node, c, isSink)
else:
# an object that is not temporary but passed to a 'sink' parameter
# results in a copy.
result = passCopyToSink(arg, c)
elif arg.kind == nkBracket:
# Treat `f([...])` like `f(...)`
result = copyNode(arg)
for son in arg:
result.add pArg(son, c, isSinkTypeForParam(son.typ))
elif arg.kind in nkCallKinds and arg.typ != nil and hasDestructor(arg.typ):
# produce temp creation
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
let tmp = getTemp(c, arg.typ, arg.info)
let res = p(arg, c)
var sinkExpr = genSink(c, tmp, res)
sinkExpr.add res
result.add sinkExpr
result.add tmp
c.destroys.add genDestroy(c, tmp)
else:
result = p(arg, c)
proc p(n: PNode; c: var Con): PNode =
case n.kind
of nkCallKinds:
let parameters = n[0].typ
let L = if parameters != nil: parameters.len else: 0
for i in 1..<n.len:
n[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
result = n
of nkDiscardStmt: #Small optimization
if n[0].kind != nkEmpty:
n[0] = pArg(n[0], c, false)
result = n
of nkBracket:
result = copyTree(n)
for i in 0..<n.len:
# everything that is passed to an array constructor is consumed,
# so these all act like 'sink' parameters:
result[i] = pArg(n[i], c, isSink = true)
of nkObjConstr:
result = copyTree(n)
for i in 1..<n.len:
# everything that is passed to an object constructor is consumed,
# so these all act like 'sink' parameters:
result[i][1] = pArg(n[i][1], c, isSink = true)
of nkTupleConstr, nkClosure:
result = copyTree(n)
for i in ord(n.kind == nkClosure)..<n.len:
# everything that is passed to an tuple constructor is consumed,
# so these all act like 'sink' parameters:
if n[i].kind == nkExprColonExpr:
result[i][1] = pArg(n[i][1], c, isSink = true)
else:
result[i] = pArg(n[i], c, isSink = true)
of nkVarSection, nkLetSection:
# transform; var x = y to var x; x op y where op is a move or copy
result = newNodeI(nkStmtList, n.info)
for it in n:
var ri = it[^1]
if it.kind == nkVarTuple and hasDestructor(ri.typ):
let x = lowerTupleUnpacking(c.graph, it, c.owner)
result.add p(x, c)
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
for j in 0..<it.len-2:
let v = it[j]
if v.kind == nkSym:
if sfCompileTime in v.sym.flags: continue
# move the variable declaration to the top of the frame:
c.addTopVar v
# make sure it's destroyed at the end of the proc:
if not isUnpackedTuple(it[0].sym):
c.destroys.add genDestroy(c, v)
if ri.kind == nkEmpty and c.inLoop > 0:
ri = genDefaultCall(v.typ, c, v.info)
if ri.kind != nkEmpty:
let r = moveOrCopy(v, ri, c)
result.add r
else: # keep the var but transform 'ri':
var v = copyNode(n)
var itCopy = copyNode(it)
for j in 0..<it.len-1:
itCopy.add it[j]
itCopy.add p(it[^1], c)
v.add itCopy
result.add v
of nkAsgn, nkFastAsgn:
if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda}:
# rule (self-assignment-removal):
if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
result = newNodeI(nkEmpty, n.info)
else:
result = moveOrCopy(n[0], n[1], c)
else:
result = copyNode(n)
result.add n[0]
result.add p(n[1], c)
of nkRaiseStmt:
if optOwnedRefs in c.graph.config.globalOptions and n[0].kind != nkEmpty:
if n[0].kind in nkCallKinds:
let call = p(n[0], c)
result = copyNode(n)
result.add call
else:
let tmp = getTemp(c, n[0].typ, n.info)
var m = genCopyNoCheck(c, tmp, n[0])
m.add p(n[0], c)
result = newTree(nkStmtList, genWasMoved(tmp, c), m)
var toDisarm = n[0]
if toDisarm.kind == nkStmtListExpr: toDisarm = toDisarm.lastSon
if toDisarm.kind == nkSym and toDisarm.sym.owner == c.owner:
result.add genWasMoved(toDisarm, c)
result.add newTree(nkRaiseStmt, tmp)
else:
result = copyNode(n)
result.add p(n[0], c)
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef,
nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt, nkExportStmt,
nkPragma, nkCommentStmt, nkBreakStmt:
result = n
of nkWhileStmt:
result = copyNode(n)
inc c.inLoop
result.add p(n[0], c)
result.add p(n[1], c)
dec c.inLoop
of nkWhen: # This should be a "when nimvm" node.
result = copyTree(n)
result[1][0] = p(result[1][0], c)
of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt, nkIfExpr, nkCaseStmt:
handleNested(n): p(node, c)
else:
result = shallowCopy(n)
for i in 0..<n.len:
result[i] = p(n[i], c)
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
# unfortunately, this needs to be kept consistent with the cases
# we handle in the 'case of' statement below:
const movableNodeKinds = (nkCallKinds + {nkSym, nkTupleConstr, nkObjConstr,
nkBracket, nkBracketExpr, nkNilLit})
template moveOrCopyIfTyped(riPart: PNode): PNode =
# typ is nil if we are in if/case expr branch with noreturn
if riPart.typ == nil: p(riPart, c)
else: moveOrCopy(dest, riPart, c)
case ri.kind
of nkCallKinds:
result = genSink(c, dest.typ, dest, ri)
# watch out and no not transform 'ri' twice if it's a call:
let ri2 = copyNode(ri)
let parameters = ri[0].typ
let L = if parameters != nil: parameters.len else: 0
ri2.add ri[0]
for i in 1..<ri.len:
ri2.add pArg(ri[i], c, i < L and isSinkTypeForParam(parameters[i]))
#recurse(ri, ri2)
result.add ri2
result = genSink(c, dest, ri)
result.add p(ri, c)
of nkBracketExpr:
if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym):
# unpacking of tuple: move out the elements
result = genSink(c, dest.typ, dest, ri)
result = genSink(c, dest, ri)
result.add p(ri, c)
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, dest.typ, dest, ri)
var snk = genSink(c, dest, ri)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
else:
result = genCopy(c, dest.typ, dest, ri)
result = genCopy(c, dest, ri)
result.add p(ri, c)
of nkStmtListExpr:
result = newNodeI(nkStmtList, ri.info)
for i in 0..ri.len-2:
result.add p(ri[i], c)
result.add moveOrCopy(dest, ri[^1], c)
of nkBlockExpr, nkBlockStmt:
result = newNodeI(nkBlockStmt, ri.info)
result.add ri[0] ## add label
result.add moveOrCopy(dest, ri[1], c)
of nkIfExpr, nkIfStmt:
result = newNodeI(nkIfStmt, ri.info)
for i in 0..<ri.len:
var branch = copyNode(ri[i])
if ri[i].kind in {nkElifBranch, nkElifExpr}:
branch.add p(ri[i][0], c)
branch.add moveOrCopyIfTyped(ri[i][1])
else:
branch.add moveOrCopyIfTyped(ri[i][0])
result.add branch
of nkCaseStmt:
result = newNodeI(nkCaseStmt, ri.info)
result.add p(ri[0], c)
for i in 1..<ri.len:
var branch: PNode
if ri[i].kind == nkOfBranch:
branch = ri[i] # of branch conditions are constants
branch[^1] = moveOrCopyIfTyped(ri[i][^1])
elif ri[i].kind in {nkElifBranch, nkElifExpr}:
branch = copyNode(ri[i])
branch.add p(ri[i][0], c)
branch.add moveOrCopyIfTyped(ri[i][1])
else:
branch = copyNode(ri[i])
branch.add moveOrCopyIfTyped(ri[i][0])
result.add branch
of nkBracket:
# array constructor
if ri.len > 0 and isDangerousSeq(ri.typ):
result = genCopy(c, dest.typ, dest, ri)
result = genCopy(c, dest, ri)
else:
result = genSink(c, dest.typ, dest, ri)
let ri2 = copyTree(ri)
for i in 0..<ri.len:
# everything that is passed to an array constructor is consumed,
# so these all act like 'sink' parameters:
ri2[i] = pArg(ri[i], c, isSink = true)
result.add ri2
of nkObjConstr:
result = genSink(c, dest.typ, dest, ri)
let ri2 = copyTree(ri)
for i in 1..<ri.len:
# everything that is passed to an object constructor is consumed,
# so these all act like 'sink' parameters:
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
result.add ri2
of nkTupleConstr, nkClosure:
result = genSink(c, dest.typ, dest, ri)
let ri2 = copyTree(ri)
for i in ord(ri.kind == nkClosure)..<ri.len:
# everything that is passed to an tuple constructor is consumed,
# so these all act like 'sink' parameters:
if ri[i].kind == nkExprColonExpr:
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
else:
ri2[i] = pArg(ri[i], c, isSink = true)
result.add ri2
of nkNilLit:
result = genSink(c, dest.typ, dest, ri)
result.add ri
result = genSink(c, dest, ri)
result.add p(ri, c)
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
result = genSink(c, dest, ri)
result.add p(ri, c)
of nkSym:
if isSinkParam(ri.sym):
# Rule 3: `=sink`(x, z); wasMoved(z)
sinkParamIsLastReadCheck(c, ri)
var snk = genSink(c, dest.typ, dest, ri)
var snk = genSink(c, dest, ri)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
isLastRead(ri, c) and canBeMoved(dest.typ):
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, dest.typ, dest, ri)
var snk = genSink(c, dest, ri)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
else:
result = genCopy(c, dest.typ, dest, ri)
result.add p(ri, c)
of nkHiddenSubConv, nkHiddenStdConv:
if sameType(ri.typ, ri[1].typ):
result = moveOrCopy(dest, ri[1], c)
elif ri[1].kind in movableNodeKinds:
result = moveOrCopy(dest, ri[1], c)
var b = newNodeIT(ri.kind, ri.info, ri.typ)
b.add ri[0] # add empty node
let L = result.len-1
b.add result[L]
result[L] = b
else:
result = genCopy(c, dest.typ, dest, ri)
result = genCopy(c, dest, ri)
result.add p(ri, c)
of nkHiddenSubConv, nkHiddenStdConv, nkConv:
result = moveOrCopy(dest, ri[1], c)
if not sameType(ri.typ, ri[1].typ):
let copyRi = copyTree(ri)
copyRi[1] = result[^1]
result[^1] = copyRi
of nkObjDownConv, nkObjUpConv:
if ri[0].kind in movableNodeKinds:
result = moveOrCopy(dest, ri[0], c)
var b = newNodeIT(ri.kind, ri.info, ri.typ)
let L = result.len-1
b.add result[L]
result[L] = b
else:
result = genCopy(c, dest.typ, dest, ri)
result.add p(ri, c)
result = moveOrCopy(dest, ri[0], c)
let copyRi = copyTree(ri)
copyRi[0] = result[^1]
result[^1] = copyRi
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
handleNested(ri): moveOrCopy(dest, node, c)
else:
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
canBeMoved(dest.typ):
# Rule 3: `=sink`(x, z); wasMoved(z)
var snk = genSink(c, dest.typ, dest, ri)
var snk = genSink(c, dest, ri)
snk.add ri
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
else:
# XXX At least string literals can be moved?
result = genCopy(c, dest.typ, dest, ri)
result = genCopy(c, dest, ri)
result.add p(ri, c)
proc computeUninit(c: var Con) =
@@ -715,17 +608,14 @@ proc computeUninit(c: var Con) =
proc injectDefaultCalls(n: PNode, c: var Con) =
case n.kind
of nkVarSection, nkLetSection:
for i in 0..<n.len:
let it = n[i]
let L = it.len-1
let ri = it[L]
if it.kind == nkIdentDefs and ri.kind == nkEmpty:
for it in n:
if it.kind == nkIdentDefs and it[^1].kind == nkEmpty:
computeUninit(c)
for j in 0..L-2:
for j in 0..<it.len-2:
let v = it[j]
doAssert v.kind == nkSym
if c.uninit.contains(v.sym.id):
it[L] = genDefaultCall(v.sym.typ, c, v.info)
it[^1] = genDefaultCall(v.sym.typ, c, v.info)
break
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
@@ -734,130 +624,16 @@ proc injectDefaultCalls(n: PNode, c: var Con) =
for i in 0..<safeLen(n):
injectDefaultCalls(n[i], c)
proc isCursor(n: PNode): bool {.inline.} =
result = n.kind == nkSym and sfCursor in n.sym.flags
proc keepVar(n, it: PNode, c: var Con): PNode =
# keep the var but transform 'ri':
result = copyNode(n)
var itCopy = copyNode(it)
for j in 0..it.len-2:
itCopy.add it[j]
itCopy.add p(it[it.len-1], c)
result.add itCopy
proc p(n: PNode; c: var Con): PNode =
case n.kind
of nkVarSection, nkLetSection:
discard "transform; var x = y to var x; x op y where op is a move or copy"
result = newNodeI(nkStmtList, n.info)
for i in 0..<n.len:
let it = n[i]
let L = it.len
var ri = it[L-1]
if it.kind == nkVarTuple and hasDestructor(ri.typ):
let x = lowerTupleUnpacking(c.graph, it, c.owner)
result.add p(x, c)
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isCursor(it[0]):
for j in 0..L-3:
let v = it[j]
if v.kind == nkSym:
if sfCompileTime in v.sym.flags: continue
# move the variable declaration to the top of the frame:
c.addTopVar v
# make sure it's destroyed at the end of the proc:
if not isUnpackedTuple(it[0].sym):
c.destroys.add genDestroy(c, v.typ, v)
if ri.kind == nkEmpty and c.inLoop > 0:
ri = genDefaultCall(v.typ, c, v.info)
if ri.kind != nkEmpty:
let r = moveOrCopy(v, ri, c)
result.add r
else:
result.add keepVar(n, it, c)
of nkCallKinds:
let parameters = n[0].typ
let L = if parameters != nil: parameters.len else: 0
for i in 1 ..< n.len:
n.sons[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
if n.typ != nil and hasDestructor(n.typ):
discard "produce temp creation"
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
let tmp = getTemp(c, n.typ, n.info)
var sinkExpr = genSink(c, n.typ, tmp, n)
sinkExpr.add n
result.add sinkExpr
result.add tmp
c.destroys.add genDestroy(c, n.typ, tmp)
else:
result = n
of nkAsgn, nkFastAsgn:
if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda}:
# rule (self-assignment-removal):
if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
result = newNodeI(nkEmpty, n.info)
else:
result = moveOrCopy(n[0], n[1], c)
else:
result = copyNode(n)
recurse(n, result)
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
result = n
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = copyNode(n)
# Destination type
result.add n[0]
# Analyse the inner expression
result.add p(n[1], c)
of nkWhen:
# This should be a "when nimvm" node.
result = copyTree(n)
result[1][0] = p(result[1][0], c)
of nkRaiseStmt:
if optNimV2 in c.graph.config.globalOptions and n[0].kind != nkEmpty:
if n[0].kind in nkCallKinds:
let call = copyNode(n[0])
recurse(n[0], call)
result = copyNode(n)
result.add call
else:
let t = n[0].typ
let tmp = getTemp(c, t, n.info)
var m = genCopyNoCheck(c, t, tmp, n[0])
m.add p(n[0], c)
result = newTree(nkStmtList, genWasMoved(tmp, c), m)
var toDisarm = n[0]
if toDisarm.kind == nkStmtListExpr: toDisarm = toDisarm.lastSon
if toDisarm.kind == nkSym and toDisarm.sym.owner == c.owner:
result.add genWasMoved(toDisarm, c)
result.add newTree(nkRaiseStmt, tmp)
else:
result = copyNode(n)
recurse(n, result)
of nkForStmt, nkParForStmt, nkWhileStmt:
inc c.inLoop
result = copyNode(n)
recurse(n, result)
dec c.inLoop
else:
result = copyNode(n)
recurse(n, result)
proc extractDestroysForTemporaries(c: Con, destroys: PNode): PNode =
result = newNodeI(nkStmtList, destroys.info)
for i in 0 ..< destroys.len:
for i in 0..<destroys.len:
if destroys[i][1][0].sym.kind == skTemp:
result.add destroys[i]
destroys[i] = c.emptyNode
proc reverseDestroys(destroys: PNode) =
var reversed: seq[PNode]
proc reverseDestroys(destroys: seq[PNode]): seq[PNode] =
for i in countdown(destroys.len - 1, 0):
reversed.add(destroys[i])
destroys.sons = reversed
result.add destroys[i]
proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
if sfGeneratedOp in owner.flags or isInlineIterator(owner): return n
@@ -874,14 +650,15 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
if c.g[i].kind in {goto, fork}:
c.jumpTargets.incl(i+c.g[i].dest)
dbg:
echo "injecting into ", n
echo "\n### ", owner.name.s, ":\nCFG:"
echoCfg(c.g)
echo n
if owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter}:
let params = owner.typ.n
for i in 1 ..< params.len:
let param = params[i].sym
if isSinkTypeForParam(param.typ) and hasDestructor(param.typ.skipTypes({tySink})):
c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i])
for i in 1..<params.len:
let t = params[i].sym.typ
if isSinkTypeForParam(t) and hasDestructor(t.skipTypes({tySink})):
c.destroys.add genDestroy(c, params[i])
#if optNimV2 in c.graph.config.globalOptions:
# injectDefaultCalls(n, c)
@@ -890,7 +667,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
if c.topLevelVars.len > 0:
result.add c.topLevelVars
if c.destroys.len > 0:
reverseDestroys(c.destroys)
c.destroys.sons = reverseDestroys(c.destroys.sons)
if owner.kind == skModule:
result.add newTryFinally(body, extractDestroysForTemporaries(c, c.destroys))
g.globalDestructors.add c.destroys
@@ -898,8 +675,6 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
result.add newTryFinally(body, c.destroys)
else:
result.add body
dbg:
echo "------------------------------------"
echo owner.name.s, " transformed to: "
echo ">---------transformed-to--------->"
echo result

View File

@@ -65,6 +65,7 @@ Files: "compiler"
Files: "doc"
Files: "doc/html"
Files: "tools"
Files: "tools/nim-gdb.py"
Files: "nimpretty"
Files: "testament"
Files: "nimsuggest"

View File

@@ -73,6 +73,15 @@ proc toInt64*(arg: Int128): int64 =
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt64Checked*(arg: Int128; onError: int64): int64 =
if isNegative(arg):
if arg.sdata(3) != -1 or arg.sdata(2) != -1:
return onError
else:
if arg.sdata(3) != 0 or arg.sdata(2) != 0:
return onError
return cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt32*(arg: Int128): int32 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
@@ -326,7 +335,6 @@ proc `*`(a: Int128, b: uint32): Int128 =
result.udata[3] = cast[uint32](tmp3) + cast[uint32](tmp2 shr 32)
proc `*`*(a: Int128, b: int32): Int128 =
let isNegative = isNegative(a) xor isNegative(b)
result = a * cast[uint32](abs(b))
if b < 0:
result = -result
@@ -347,8 +355,6 @@ proc low64(a: Int128): uint64 =
bitconcat(a.udata[1], a.udata[0])
proc `*`*(lhs,rhs: Int128): Int128 =
let isNegative = isNegative(lhs) xor isNegative(rhs)
let
a = cast[uint64](lhs.udata[0])
b = cast[uint64](lhs.udata[1])
@@ -370,9 +376,6 @@ proc `*`*(lhs,rhs: Int128): Int128 =
result = result + toInt128(a32 * b00) shl 32
result = result + toInt128(a00 * b32) shl 32
if isNegative != isNegative(result):
assert(false, "overflow")
proc `*=`*(a: var Int128, b: Int128) =
a = a * b
@@ -398,11 +401,17 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
if divisor > dividend:
result.quotient = Zero
result.remainder = dividend
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
return
if divisor == dividend:
result.quotient = One
if isNegativeA xor isNegativeB:
result.quotient = NegOne
else:
result.quotient = One
result.remainder = Zero
return
@@ -427,7 +436,7 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
result.quotient = -quotient
else:
result.quotient = quotient
if isNegativeB:
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
@@ -534,8 +543,6 @@ template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
proc toInt128*(arg: float64): Int128 =
let isNegative = arg < 0
assert(arg < 0x47E0000000000000'f64, "out of range")
assert(arg >= 0xC7E0000000000000'f64, "out of range")
let v0 = ldexp(abs(arg), -100)
let w0 = uint64(trunc(v0))
let v1 = ldexp(v0 - float64(w0), 50)
@@ -667,3 +674,25 @@ when isMainModule:
doAssert $high(Int128) == "170141183460469231731687303715884105727"
doAssert $low(Int128) == "-170141183460469231731687303715884105728"
var ma = 100'i64
var mb = 13
doAssert toInt128(ma) * toInt128(0) == toInt128(0)
doAssert toInt128(-ma) * toInt128(0) == toInt128(0)
# sign correctness
doAssert divMod(toInt128( ma),toInt128( mb)) == (toInt128( ma div mb), toInt128( ma mod mb))
doAssert divMod(toInt128(-ma),toInt128( mb)) == (toInt128(-ma div mb), toInt128(-ma mod mb))
doAssert divMod(toInt128( ma),toInt128(-mb)) == (toInt128( ma div -mb), toInt128( ma mod -mb))
doAssert divMod(toInt128(-ma),toInt128(-mb)) == (toInt128(-ma div -mb), toInt128(-ma mod -mb))
doAssert divMod(toInt128( mb),toInt128( mb)) == (toInt128( mb div mb), toInt128( mb mod mb))
doAssert divMod(toInt128(-mb),toInt128( mb)) == (toInt128(-mb div mb), toInt128(-mb mod mb))
doAssert divMod(toInt128( mb),toInt128(-mb)) == (toInt128( mb div -mb), toInt128( mb mod -mb))
doAssert divMod(toInt128(-mb),toInt128(-mb)) == (toInt128(-mb div -mb), toInt128(-mb mod -mb))
doAssert divMod(toInt128( mb),toInt128( ma)) == (toInt128( mb div ma), toInt128( mb mod ma))
doAssert divMod(toInt128(-mb),toInt128( ma)) == (toInt128(-mb div ma), toInt128(-mb mod ma))
doAssert divMod(toInt128( mb),toInt128(-ma)) == (toInt128( mb div -ma), toInt128( mb mod -ma))
doAssert divMod(toInt128(-mb),toInt128(-ma)) == (toInt128(-mb div -ma), toInt128(-mb mod -ma))

View File

@@ -1169,7 +1169,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
first = firstOrd(p.config, typ.sons[0])
if optBoundsCheck in p.options:
useMagic(p, "chckIndx")
r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), tmp]
r.res = "chckIndx($1, $2, ($3 != null ? $3.length : 0)+$2-1)-$2" % [b.res, rope(first), tmp]
elif first != 0:
r.res = "($1)-$2" % [b.res, rope(first)]
else:
@@ -1295,12 +1295,16 @@ proc genCopyForParamIfNeeded(p: PProc, n: PNode) =
return
owner = owner.up
proc genVarInit(p: PProc, v: PSym, n: PNode)
proc genSym(p: PProc, n: PNode, r: var TCompRes) =
var s = n.sym
case s.kind
of skVar, skLet, skParam, skTemp, skResult, skForVar:
if s.loc.r == nil:
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
if sfCompileTime in s.flags:
genVarInit(p, s, if s.ast != nil: s.ast else: newNodeI(nkEmpty, s.info))
if s.kind == skParam:
genCopyForParamIfNeeded(p, n)
let k = mapType(p, s.typ)
@@ -1732,7 +1736,11 @@ proc genVarStmt(p: PProc, n: PNode) =
var v = a.sons[0].sym
if lfNoDecl notin v.loc.flags and sfImportc notin v.flags:
genLineDir(p, a)
genVarInit(p, v, a.sons[2])
if sfCompileTime notin v.flags:
genVarInit(p, v, a.sons[2])
else:
# lazy emit, done when it's actually used.
if v.ast == nil: v.ast = a[2]
proc genConstant(p: PProc, c: PSym) =
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
@@ -1886,6 +1894,15 @@ proc genReset(p: PProc, n: PNode) =
lineF(p, "$1 = genericReset($3, $2);$n", [a,
genTypeInfo(p, n.sons[1].typ), tmp])
proc genMove(p: PProc; n: PNode; r: var TCompRes) =
var a: TCompRes
r.kind = resVal
r.res = p.getTemp()
gen(p, n[1], a)
lineF(p, "$1 = $2;$n", [r.rdLoc, a.rdLoc])
genReset(p, n)
#lineF(p, "$1 = $2;$n", [dest.rdLoc, src.rdLoc])
proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
var
a: TCompRes
@@ -2010,7 +2027,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]")
of mOf: genOf(p, n, r)
of mDefault: genDefault(p, n, r)
of mReset: genReset(p, n)
of mReset, mWasMoved: genReset(p, n)
of mEcho: genEcho(p, n, r)
of mNLen..mNError, mSlurp, mStaticExec:
localError(p.config, n.info, errXMustBeCompileTime % n.sons[0].sym.name.s)
@@ -2033,6 +2050,8 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
gen(p, n.sons[3], z)
r.res = "($1.slice($2, $3+1))" % [x.rdLoc, y.rdLoc, z.rdLoc]
r.kind = resExpr
of mMove:
genMove(p, n, r)
else:
genCall(p, n, r)
#else internalError(p.config, e.info, 'genMagic: ' + magicToStr[op]);
@@ -2147,7 +2166,10 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) =
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
var a, b: TCompRes
gen(p, n.sons[0], r)
if optRangeCheck in p.options:
if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and
checkUnsignedConversions notin p.config.legacyFeatures):
discard "XXX maybe emit masking instructions here"
else:
gen(p, n.sons[1], a)
gen(p, n.sons[2], b)
useMagic(p, "chckRange")

View File

@@ -233,6 +233,10 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
result = conf.cmd == cmdCompileToJS and not isCompileTime
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo) =
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
if liftingHarmful(g.config, owner): return n
@@ -245,7 +249,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var env: PNode
if owner.isIterator:
let it = getHiddenParam(g, owner)
addUniqueField(it.typ.sons[0], hp, g.cache)
addUniqueField(it.typ.skipTypes({tyOwned}).sons[0], hp, g.cache)
env = indirectAccess(newSymNode(it), hp, hp.info)
else:
let e = newSym(skLet, iter.name, owner, n.info)
@@ -257,13 +261,13 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result.add(v)
# add 'new' statement:
result.add newCall(getSysSym(g, n.info, "internalNew"), env)
if optNimV2 in g.config.globalOptions:
if optOwnedRefs in g.config.globalOptions:
createTypeBoundOps(g, nil, env.typ, n.info)
result.add makeClosure(g, iter, env, n.info)
proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
let envParam = getHiddenParam(g, owner)
let obj = envParam.typ.skipTypes({tyOwned, tyRef})
let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr})
addField(obj, s, g.cache)
var access = newSymNode(envParam)
@@ -323,7 +327,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
c.ownerToType[owner.id] = result
proc asOwnedRef(c: DetectionPass; t: PType): PType =
if optNimV2 in c.graph.config.globalOptions:
if optOwnedRefs in c.graph.config.globalOptions:
assert t.kind == tyRef
result = newType(tyOwned, t.owner)
result.flags.incl tfHasOwned
@@ -335,16 +339,17 @@ proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
info: TLineInfo): PType =
var r = c.getEnvTypeForOwner(owner, info)
result = newType(tyPtr, owner)
rawAddSon(result, r.skipTypes({tyOwned, tyRef}))
rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr}))
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
let obj = refObj.skipTypes({tyOwned, tyRef})
let obj = refObj.skipTypes({tyOwned, tyRef, tyPtr})
# The assumption here is that gcDestructors means we cannot deal
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
# This seems to be generally correct but since it's a bit risky it's only
# enabled for gcDestructors.
let fieldType = if false: # c.graph.config.selectedGC == gcDestructors:
# This seems to be generally correct but since it's a bit risky it's disabled
# for now.
let fieldType = if isDefined(c.graph.config, "nimCycleBreaker") or
c.graph.config.selectedGC == gcDestructors:
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
else:
c.getEnvTypeForOwner(dep, info)
@@ -354,7 +359,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
let upIdent = getIdent(c.graph.cache, upName)
let upField = lookupInRecord(obj.n, upIdent)
if upField != nil:
if upField.typ.skipTypes({tyOwned, tyRef}) != fieldType.skipTypes({tyOwned, tyRef}):
if upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) != fieldType.skipTypes({tyOwned, tyRef, tyPtr}):
localError(c.graph.config, dep.info, "internal error: up references do not agree")
else:
let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
@@ -425,8 +430,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
addClosureParam(c, owner, n.info)
if interestingIterVar(s):
if not c.capturedVars.containsOrIncl(s.id):
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef})
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef})
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
if s.name.id == getIdent(c.graph.cache, ":state").id:
obj.n[0].sym.id = -s.id
@@ -451,8 +456,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
#echo "capturing ", n.info
# variable 's' is actually captured:
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef})
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
addField(obj, s, c.graph.cache)
# create required upFields:
var w = owner.skipGenericOwner
@@ -477,7 +482,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
w = up
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt:
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
discard
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil:
@@ -542,7 +547,7 @@ proc setupEnvVar(owner: PSym; d: DetectionPass;
localError d.graph.config, owner.info, "internal error: could not determine closure type"
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info)
c.envVars[owner.id] = result
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = envVarType
@@ -552,7 +557,7 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
let p = getHiddenParam(g, owner)
result = p.newSymNode
if owner.isIterator:
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef}).n, getIdent(g.cache, upName))
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(g.cache, upName))
if upField == nil:
localError(g.config, owner.info, "could not find up reference for closure iter")
else:
@@ -572,20 +577,20 @@ proc rawClosureCreation(owner: PSym;
var v = newNodeI(nkVarSection, env.info)
addVar(v, env)
result.add(v)
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
addVar(v, unowned)
# add 'new' statement:
result.add(newCall(getSysSym(d.graph, env.info, "internalNew"), env))
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
let env2 = copyTree(env)
env2.typ = unowned.typ
result.add newAsgnStmt(unowned, env2, env.info)
createTypeBoundOps(d.graph, nil, unowned.typ, env.info)
createTypeBoundOpsLL(d.graph, unowned.typ, env.info)
# add assignment statements for captured parameters:
for i in 1..<owner.typ.n.len:
@@ -595,10 +600,10 @@ proc rawClosureCreation(owner: PSym;
# add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
if upField != nil:
let up = getUpViaParam(d.graph, owner)
if up != nil and upField.typ.skipTypes({tyOwned, tyRef}) == up.typ.skipTypes({tyOwned, tyRef}):
if up != nil and upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) == up.typ.skipTypes({tyOwned, tyRef, tyPtr}):
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
up, env.info))
#elif oldenv != nil and oldenv.typ == upField.typ:
@@ -608,12 +613,12 @@ proc rawClosureCreation(owner: PSym;
localError(d.graph.config, env.info, "internal error: cannot create up reference")
# we are not in the sem'check phase anymore! so pass 'nil' for the PContext
# and hope for the best:
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
createTypeBoundOps(d.graph, nil, env.typ, owner.info)
proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass;
info: TLineInfo; res: PNode) =
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
let nilLit = newNodeIT(nkNilLit, info, unowned.typ)
@@ -629,7 +634,7 @@ proc closureCreationForIter(iter: PNode;
var vnode: PNode
if owner.isIterator:
let it = getHiddenParam(d.graph, owner)
addUniqueField(it.typ.skipTypes({tyOwned, tyRef}), v, d.graph.cache)
addUniqueField(it.typ.skipTypes({tyOwned, tyRef, tyPtr}), v, d.graph.cache)
vnode = indirectAccess(newSymNode(it), v, v.info)
else:
vnode = v.newSymNode
@@ -637,13 +642,13 @@ proc closureCreationForIter(iter: PNode;
addVar(vs, vnode)
result.add(vs)
result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
createTypeBoundOps(d.graph, nil, vnode.typ, iter.info)
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
if upField != nil:
let u = setupEnvVar(owner, d, c, iter.info)
if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}):
if u.typ.skipTypes({tyOwned, tyRef, tyPtr}) == upField.typ.skipTypes({tyOwned, tyRef, tyPtr}):
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
u, iter.info))
else:
@@ -653,9 +658,9 @@ proc closureCreationForIter(iter: PNode;
proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode =
var access = setupEnvVar(owner, d, c, n.info)
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
access = c.unownedEnvVars[owner.id]
let obj = access.typ.skipTypes({tyOwned, tyRef})
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
let field = getFieldFromObj(obj, n.sym)
if field != nil:
result = rawIndirectAccess(access, field, n.info)
@@ -664,7 +669,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
result = n
proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef}).n.sons[0].sym
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n.sons[0].sym
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode
@@ -689,7 +694,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
while true:
if access.typ == wanted:
return makeClosure(d.graph, s, access, n.info)
let obj = access.typ.skipTypes({tyOwned, tyRef})
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName))
if upField == nil:
localError(d.graph.config, n.info, "internal error: no environment found")
@@ -760,6 +765,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
n[0].sons[1] = liftCapturedVars(n[0].sons[1], owner, d, c)
else:
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
of nkTypeOfExpr:
result = n
else:
if owner.isIterator:
if nfLL in n.flags:
@@ -921,7 +928,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
result.add(v)
# add 'new' statement:
result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode))
if optNimV2 in g.config.globalOptions:
if optOwnedRefs in g.config.globalOptions:
createTypeBoundOps(g, nil, env.typ, body.info)
elif op.kind == nkStmtListExpr:

View File

@@ -499,7 +499,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
rememberSplit(splitComma)
wrSpace em
of openPars:
if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker:
if tok.strongSpaceA > 0 and not em.endsInWhite and
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
wrSpace em
wr(em, TokTypeToStr[tok.tokType], ltSomeParLe)
rememberSplit(splitParLe)

View File

@@ -134,7 +134,7 @@ type
TErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
TLexer* = object of TBaseLexer
fileIdx*: FileIndex
indentAhead*: int # if > 0 an indendation has already been read
indentAhead*: int # if > 0 an indentation has already been read
# this is needed because scanning comments
# needs so much look-ahead
currLineIndent*: int

View File

@@ -404,14 +404,14 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind == attachedDeepCopy:
# a big problem is that we don't know the enviroment's type here, so we
# a big problem is that we don't know the environment's type here, so we
# have to go through some indirection; we delegate this to the codegen:
let call = newNodeI(nkCall, c.info, 2)
call.typ = t
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
call.sons[1] = y
body.add newAsgnStmt(x, call)
elif optNimV2 in c.g.config.globalOptions and
elif optOwnedRefs in c.g.config.globalOptions and
optRefCheck in c.g.config.options:
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.g, c.info, tyPointer)
@@ -457,7 +457,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
tyPtr, tyOpt, tyUncheckedArray:
defaultOp(c, t, body, x, y)
of tyRef:
if optNimV2 in c.g.config.globalOptions and
if optOwnedRefs in c.g.config.globalOptions and
optRefCheck in c.g.config.options:
weakrefOp(c, t, body, x, y)
else:
@@ -469,7 +469,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
defaultOp(c, t, body, x, y)
of tyOwned:
let base = t.skipTypes(abstractInstOwned)
if optNimV2 in c.g.config.globalOptions:
if optOwnedRefs in c.g.config.globalOptions:
case base.kind
of tyRef:
ownedRefOp(c, base, body, x, y)

View File

@@ -233,7 +233,7 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addInterfaceDeclAux(c, sym)
when defined(nimfix):
# when we cannot find the identifier, retry with a changed identifer:
# when we cannot find the identifier, retry with a changed identifier:
proc altSpelling(x: PIdent): PIdent =
case x.s[0]
of 'A'..'Z': result = getIdent(toLowerAscii(x.s[0]) & x.s.substr(1))

View File

@@ -64,7 +64,7 @@ type
importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.}
includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.}
recordStmt*: proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.}
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API
cacheCounters*: Table[string, BiggestInt]
cacheTables*: Table[string, BTree[string, PNode]]
passes*: seq[TPass]
@@ -215,7 +215,7 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false)
if g.suggestMode:
g.deps.incl m.position.dependsOn(dep.int)
# we compute the transitive closure later when quering the graph lazily.
# we compute the transitive closure later when querying the graph lazily.
# this improves efficiency quite a lot:
#invalidTransitiveClosure = true

View File

@@ -81,6 +81,7 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
pseudoPath = true
if conf.m.filenameToIndexTbl.hasKey(canon.string):
isKnownFile = true
result = conf.m.filenameToIndexTbl[canon.string]
else:
isKnownFile = false

View File

@@ -40,19 +40,31 @@ proc prependCurDir(f: AbsoluteFile): AbsoluteFile =
else:
result = f
proc addCmdPrefix*(result: var string, kind: CmdLineKind) =
# consider moving this to std/parseopt
case kind
of cmdLongOption: result.add "--"
of cmdShortOption: result.add "-"
of cmdArgument, cmdEnd: discard
proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
config.commandLine.setLen 0
# bugfix: otherwise, config.commandLine ends up duplicated
while true:
parseopt.next(p)
case p.kind
of cmdEnd: break
of cmdLongOption, cmdShortOption:
config.commandLine.add " "
config.commandLine.add p.key
config.commandLine.addCmdPrefix p.kind
config.commandLine.add p.key.quoteShell # quoteShell to be future proof
if p.val.len > 0:
config.commandLine.add ':'
config.commandLine.add p.val
config.commandLine.add p.val.quoteShell
if p.key == " ":
p.key = "-"
@@ -61,7 +73,7 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
processSwitch(pass, p, config)
of cmdArgument:
config.commandLine.add " "
config.commandLine.add p.key
config.commandLine.add p.key.quoteShell
if processArgument(pass, p, argsCount, config): break
if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and

View File

@@ -69,9 +69,10 @@ proc getPathVersion*(p: string): tuple[name, version: string] =
result.version = ""
const specialSeparator = "-#"
var sepIdx = p.find(specialSeparator)
let last = p.rfind(p.lastPathPart) # the index where the last path part begins
var sepIdx = p.find(specialSeparator, start = last)
if sepIdx == -1:
sepIdx = p.rfind('-')
sepIdx = p.rfind('-', start = last)
if sepIdx == -1:
result.name = p

View File

@@ -160,8 +160,9 @@ proc checkSymbol(L: TLexer, tok: TToken) =
proc parseAssignment(L: var TLexer, tok: var TToken;
config: ConfigRef; condStack: var seq[bool]) =
if tok.ident.s == "-" or tok.ident.s == "--":
confTok(L, tok, config, condStack) # skip unnecessary prefix
if tok.ident != nil:
if tok.ident.s == "-" or tok.ident.s == "--":
confTok(L, tok, config, condStack) # skip unnecessary prefix
var info = getLineInfo(L, tok) # save for later in case of an error
checkSymbol(L, tok)
var s = $tok
@@ -190,6 +191,12 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
checkSymbol(L, tok)
add(val, $tok)
confTok(L, tok, config, condStack) # skip symbol
if tok.tokType in {tkColon, tkEquals}:
add(val, $tok) # add the :
confTok(L, tok, config, condStack) # skip symbol
checkSymbol(L, tok)
add(val, $tok) # add the token after it
confTok(L, tok, config, condStack) # skip symbol
while tok.ident != nil and tok.ident.s == "&":
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
@@ -201,7 +208,7 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
else:
processSwitch(s, val, passPP, info, config)
proc readConfigFile(filename: AbsoluteFile; cache: IdentCache;
proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache;
config: ConfigRef): bool =
var
L: TLexer

View File

@@ -46,7 +46,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
s = nextIdentIter(it, i.mainModule.tab)
proc selectRoutine*(i: Interpreter; name: string): PSym =
## Selects a declared rountine (proc/func/etc) from the main module.
## Selects a declared routine (proc/func/etc) from the main module.
## The routine needs to have the export marker ``*``. The only matching
## routine is returned and ``nil`` if it is overloaded.
result = selectUniqueSymbol(i, name, {skTemplate, skMacro, skFunc,

View File

@@ -98,7 +98,7 @@ proc handleCmdLine(config: ConfigRef) =
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig, config) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "", config)
mainCommand()

View File

@@ -15,6 +15,6 @@ const
VersionAsString* = system.NimVersion
RodFileVersion* = "1223" # modify this if the rod-format changes!
NimCompilerApiVersion* = 3 ## Check for the existance of this before accessing it
NimCompilerApiVersion* = 3 ## Check for the existence of this before accessing it
## as older versions of the compiler API do not
## declare this.

View File

@@ -81,7 +81,11 @@ type # please make sure we have under 32 options
optNoNimblePath
optHotCodeReloading
optDynlibOverrideAll
optNimV2
optSeqDestructors # active if the implementation uses the new
# string/seq implementation based on destructors
optTinyRtti # active if we use the new "tiny RTTI"
# implementation
optOwnedRefs # active if the Nim compiler knows about 'owned'.
optMultiMethods
optNimV019
@@ -138,8 +142,12 @@ type
LegacyFeature* = enum
allowSemcheckedAstModification,
## Allows to modify a NimNode where the type has already been
## flaged with nfSem. If you actually do this, it will cause
## flagged with nfSem. If you actually do this, it will cause
## bugs.
checkUnsignedConversions
## Historically and especially in version 1.0.0 of the language
## conversions to unsigned numbers were checked. In 1.0.4 they
## are not anymore.
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf
@@ -409,7 +417,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
of "mswindows", "win32": result = conf.target.targetOS == osWindows
of "macintosh":
result = conf.target.targetOS in {osMacos, osMacosx, osIos}
of "osx":
of "osx", "macosx":
result = conf.target.targetOS in {osMacosx, osIos}
of "sunos": result = conf.target.targetOS == osSolaris
of "nintendoswitch":
@@ -540,6 +548,9 @@ proc disableNimblePath*(conf: ConfigRef) =
incl conf.globalOptions, optNoNimblePath
conf.lazyPaths.setLen(0)
proc clearNimblePath*(conf: ConfigRef) =
conf.lazyPaths.setLen(0)
include packagehandling
proc getOsCacheDir(): string =
@@ -568,9 +579,7 @@ proc pathSubs*(conf: ConfigRef; p, config: string): string =
"projectname", conf.projectName,
"projectpath", conf.projectPath.string,
"projectdir", conf.projectPath.string,
"nimcache", getNimcacheDir(conf).string])
if "~/" in result:
result = result.replace("~/", home & '/')
"nimcache", getNimcacheDir(conf).string]).expandTilde
proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
ext: string): AbsoluteFile =
@@ -727,7 +736,7 @@ proc `$`*(c: IdeCmd): string =
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.
if conf.target.targetCPU == cpuI386:
if conf != nil and conf.target.targetCPU == cpuI386:
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
if conf.target.targetOS != osWindows:
# on i386 for all known POSIX systems, 64bits ints are aligned

View File

@@ -40,19 +40,16 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@"})
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@", ":": "@c"})
proc demanglePackageName*(path: string): string =
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": ""})
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
proc withPackageName*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
let x = getPackageName(conf, path.string)
if x.len == 0:
result = path
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
result = p / RelativeFile(fakePackageName(conf, path))
result = p / RelativeFile(fakePackageName(conf, path))

View File

@@ -26,6 +26,9 @@ when isMainModule:
outp.write matches[0], "\L"
outp.close
import ".." / tools / grammar_nanny
checkGrammarFile()
import
llstream, lexer, idents, strutils, ast, msgs, options, lineinfos,
pathutils
@@ -710,7 +713,7 @@ proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode =
result = parseCast(p)
else:
parMessage(p, errExprExpected, p.tok)
getTok(p) # we must consume a token here to prevend endless loops!
getTok(p) # we must consume a token here to prevent endless loops!
result = p.emptyNode
proc namedParams(p: var TParser, callee: PNode,
@@ -750,11 +753,10 @@ proc commandExpr(p: var TParser; r: PNode; mode: TPrimaryMode): PNode =
proc primarySuffix(p: var TParser, r: PNode,
baseIndent: int, mode: TPrimaryMode): PNode =
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
#| | doBlocks
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')'
#| | '.' optInd symbol generalizedLit?
#| | '[' optInd indexExprList optPar ']'
#| | '{' optInd indexExprList optPar '}'
#| | '[' optInd exprColonEqExprList optPar ']'
#| | '{' optInd exprColonEqExprList optPar '}'
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
result = r
@@ -908,7 +910,7 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
p.currInd = oldInd
proc parsePragma(p: var TParser): PNode =
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
#| pragma = '{.' optInd (exprColonEqExpr comma?)* optPar ('.}' | '}')
result = newNodeP(nkPragma, p)
inc p.inPragma
when defined(nimpretty):
@@ -937,8 +939,8 @@ proc parsePragma(p: var TParser): PNode =
dec p.em.keepIndents
proc identVis(p: var TParser; allowDot=false): PNode =
#| identVis = symbol opr? # postfix position
#| identVisDot = symbol '.' optInd symbol opr?
#| identVis = symbol OPR? # postfix position
#| identVisDot = symbol '.' optInd symbol OPR?
var a = parseSymbol(p)
if p.tok.tokType == tkOpr:
when defined(nimpretty):
@@ -973,7 +975,7 @@ type
proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
#| declColonEquals = identWithPragma (comma identWithPragma)* comma?
#| (':' optInd typeDesc)? ('=' optInd expr)?
#| identColonEquals = ident (comma ident)* comma?
#| identColonEquals = IDENT (comma IDENT)* comma?
#| (':' optInd typeDesc)? ('=' optInd expr)?)
var a: PNode
result = newNodeP(nkIdentDefs, p)
@@ -1006,7 +1008,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
proc parseTuple(p: var TParser, indentAllowed = false): PNode =
#| inlTupleDecl = 'tuple'
#| [' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
#| '[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
#| extTupleDecl = 'tuple'
#| COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
#| tupleClass = 'tuple'
@@ -1104,7 +1106,7 @@ proc optPragmas(p: var TParser): PNode =
result = p.emptyNode
proc parseDoBlock(p: var TParser; info: TLineInfo): PNode =
#| doBlock = 'do' paramListArrow pragmas? colcom stmt
#| doBlock = 'do' paramListArrow pragma? colcom stmt
let params = parseParamList(p, retColon=false)
let pragmas = optPragmas(p)
colcom(p, result)
@@ -1115,7 +1117,7 @@ proc parseDoBlock(p: var TParser; info: TLineInfo): PNode =
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode =
#| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
#| procExpr = 'proc' paramListColon pragma? ('=' COMMENT? stmt)?
# either a proc type or a anonymous proc
let info = parLineInfo(p)
getTok(p)
@@ -1214,11 +1216,11 @@ proc parseExpr(p: var TParser): PNode =
#| expr = (blockExpr
#| | ifExpr
#| | whenExpr
#| | caseExpr
#| | forExpr
#| | caseStmt
#| | forExpr
#| | tryExpr)
#| / simpleExpr
case p.tok.tokType:
case p.tok.tokType
of tkBlock:
nimprettyDontTouch:
result = parseBlock(p)
@@ -1248,7 +1250,7 @@ proc parseTypeClass(p: var TParser): PNode
proc primary(p: var TParser, mode: TPrimaryMode): PNode =
#| typeKeyw = 'var' | 'out' | 'ref' | 'ptr' | 'shared' | 'tuple'
#| | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
#| primary = typeKeyw typeDescK
#| primary = typeKeyw optInd typeDesc
#| / prefixOperator* identOrLiteral primarySuffix*
#| / 'bind' primary
if isOperator(p.tok):
@@ -1420,8 +1422,7 @@ proc parseExprStmt(p: var TParser): PNode =
#| exprStmt = simpleExpr
#| (( '=' optInd expr colonBody? )
#| / ( expr ^+ comma
#| doBlocks
#| / macroColon
#| postExprBlocks
#| ))?
var a = simpleExpr(p)
if p.tok.tokType == tkEquals:
@@ -1468,6 +1469,9 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode =
#| importStmt = 'import' optInd expr
#| ((comma expr)*
#| / 'except' optInd (expr ^+ comma))
#| exportStmt = 'export' optInd expr
#| ((comma expr)*
#| / 'except' optInd (expr ^+ comma))
result = newNodeP(kind, p)
getTok(p) # skip `import` or `export`
optInd(p, result)
@@ -1506,7 +1510,7 @@ proc parseIncludeStmt(p: var TParser): PNode =
#expectNl(p)
proc parseFromStmt(p: var TParser): PNode =
#| fromStmt = 'from' moduleName 'import' optInd expr (comma expr)*
#| fromStmt = 'from' expr 'import' optInd expr (comma expr)*
result = newNodeP(nkFromStmt, p)
getTok(p) # skip `from`
optInd(p, result)
@@ -1791,7 +1795,7 @@ type
proc parseSection(p: var TParser, kind: TNodeKind,
defparser: TDefParser): PNode =
#| section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
#| section(RULE) = COMMENT? RULE / (IND{>} (RULE / COMMENT)^+IND{=} DED)
result = newNodeP(kind, p)
if kind != nkTypeSection: getTok(p)
skipComment(p, result)
@@ -1819,7 +1823,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
parMessage(p, errIdentifierExpected, p.tok)
proc parseEnum(p: var TParser): PNode =
#| enum = 'enum' optInd (symbol optPragmas optInd ('=' optInd expr COMMENT?)? comma?)+
#| enum = 'enum' optInd (symbol pragma? optInd ('=' optInd expr COMMENT?)? comma?)+
result = newNodeP(nkEnumTy, p)
getTok(p)
addSon(result, p.emptyNode)
@@ -2105,7 +2109,7 @@ proc parseVarTuple(p: var TParser): PNode =
eat(p, tkParRi)
proc parseVariable(p: var TParser): PNode =
#| colonBody = colcom stmt doBlocks?
#| colonBody = colcom stmt postExprBlocks?
#| variable = (varTuple / identColonEquals) colonBody? indAndComment
if p.tok.tokType == tkParLe:
result = parseVarTuple(p)
@@ -2117,7 +2121,7 @@ proc parseVariable(p: var TParser): PNode =
indAndComment(p, result)
proc parseConstant(p: var TParser): PNode =
#| constant = (parseVarTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
#| constant = (varTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
if p.tok.tokType == tkParLe: result = parseVarTuple(p)
else:
result = newNodeP(nkConstDef, p)

View File

@@ -66,7 +66,7 @@ const
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor}
wGensym, wInject, wCodegenDecl, wGuard, wGoto}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
@@ -418,14 +418,7 @@ proc processOption(c: PContext, n: PNode, resOptions: var TOptions) =
proc processPush(c: PContext, n: PNode, start: int) =
if n.sons[start-1].kind in nkPragmaCallKinds:
localError(c.config, n.info, "'push' cannot have arguments")
var x = newOptionEntry(c.config)
var y = c.optionStack[^1]
x.options = c.config.options
x.defaultCC = y.defaultCC
x.dynlib = y.dynlib
x.notes = c.config.notes
x.features = c.features
c.optionStack.add(x)
var x = pushOptionEntry(c)
for i in start ..< len(n):
if not tryProcessOption(c, n.sons[i], c.config.options):
# simply store it somewhere:
@@ -444,10 +437,7 @@ proc processPop(c: PContext, n: PNode) =
if c.optionStack.len <= 1:
localError(c.config, n.info, "{.pop.} without a corresponding {.push.}")
else:
c.config.options = c.optionStack[^1].options
c.config.notes = c.optionStack[^1].notes
c.features = c.optionStack[^1].features
c.optionStack.setLen(c.optionStack.len - 1)
popOptionEntry(c)
when defined(debugOptions):
echo c.config $ n.info, " POP config is now ", c.config.options
@@ -720,7 +710,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
proc semCustomPragma(c: PContext, n: PNode): PNode =
var callNode: PNode
if n.kind == nkIdent:
if n.kind in {nkIdent, nkSym}:
# pragma -> pragma()
callNode = newTree(nkCall, n)
elif n.kind == nkExprColonExpr:
@@ -1103,11 +1093,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
invalidPragma(c, it)
else:
sym.flags.incl sfGoto
of wCursor:
if sym == nil or sym.kind notin {skVar, skLet}:
invalidPragma(c, it)
else:
sym.flags.incl sfCursor
of wExportNims:
if sym == nil: invalidPragma(c, it)
else: magicsys.registerNimScriptSymbol(c.graph, sym)

View File

@@ -29,7 +29,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
result = true
proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
# Searchs for a forward declaration or a "twin" symbol of fn
# Searches for a forward declaration or a "twin" symbol of fn
# in the symbol table. If the parameter lists are exactly
# the same the sym in the symbol table is returned, else nil.
var it: TIdentIter
@@ -108,7 +108,7 @@ when false:
result = true
proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
var it: TIdentIter
for scope in walkScopes(startScope):

View File

@@ -217,7 +217,7 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
let oldGlobalOptions = conf.globalOptions
let oldSelectedGC = conf.selectedGC
undefSymbol(conf.symbols, "nimv2")
conf.globalOptions.excl optNimV2
conf.globalOptions.excl {optTinyRtti, optOwnedRefs, optSeqDestructors}
conf.selectedGC = gcUnselected
var m = graph.makeModule(scriptName)
@@ -229,8 +229,8 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
# watch out, "newruntime" can be set within NimScript itself and then we need
# to remember this:
if optNimV2 in oldGlobalOptions:
conf.globalOptions.incl optNimV2
if optOwnedRefs in oldGlobalOptions:
conf.globalOptions.incl {optTinyRtti, optOwnedRefs, optSeqDestructors}
defineSymbol(conf.symbols, "nimv2")
if conf.selectedGC == gcUnselected:
conf.selectedGC = oldSelectedGC

View File

@@ -293,7 +293,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
assert result.startsWith "sk"
result = result[2..^1].toLowerAscii
result &= "\n found '$1' of kind '$2'" % [getSymRepr(c.config, sym), sym.kind.toHumanStr]
sym = nextOverloadIter(o, c, n)
sym = nextOverloadIter(o, c, f)
let ident = considerQuotedIdent(c, f, n).s
if nfDotField in n.flags and nfExplicitCall notin n.flags:
@@ -304,7 +304,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
# in a concept, eg:
# ExplainedConcept {.explain.} = concept x
# x.foo is int
# We coudl use: `(c.config $ n.sons[1].info)` to get more context.
# We could use: `(c.config $ n.sons[1].info)` to get more context.
discard
else:
typeHint = " for type " & getProcHeader(c.config, sym)
@@ -640,7 +640,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
result = explicitGenericInstError(c, n)
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
# New approach: generate fn(x, y, z) where x, y, z have the proper types
# and use the overloading resolution mechanism:

View File

@@ -212,13 +212,28 @@ proc newOptionEntry*(conf: ConfigRef): POptionEntry =
result.dynlib = nil
result.notes = conf.notes
proc pushOptionEntry*(c: PContext): POptionEntry =
new(result)
var prev = c.optionStack[^1]
result.options = c.config.options
result.defaultCC = prev.defaultCC
result.dynlib = prev.dynlib
result.notes = c.config.notes
result.features = c.features
c.optionStack.add(result)
proc popOptionEntry*(c: PContext) =
c.config.options = c.optionStack[^1].options
c.config.notes = c.optionStack[^1].notes
c.features = c.optionStack[^1].features
c.optionStack.setLen(c.optionStack.len - 1)
proc newContext*(graph: ModuleGraph; module: PSym): PContext =
new(result)
result.enforceVoidContext = PType(kind: tyTyped)
result.ambiguousSymbols = initIntSet()
result.optionStack = @[]
result.optionStack = @[newOptionEntry(graph.config)]
result.libs = @[]
result.optionStack.add(newOptionEntry(graph.config))
result.module = module
result.friendModules = @[module]
result.converters = @[]

View File

@@ -2038,7 +2038,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
let oldErrorMax = c.config.errorMax
let oldCompilesId = c.compilesContextId
# if this is a nested 'when compiles', do not increase the ID so that
# generic instantations can still be cached for this level.
# generic instantiations can still be cached for this level.
if c.compilesContextId == 0:
inc c.compilesContextIdGenerator
c.compilesContextId = c.compilesContextIdGenerator
@@ -2563,7 +2563,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# if isGenericRoutine(result.sym):
# localError(c.config, n.info, errInstantiateXExplicitly, s.name.s)
# "procs literals" are 'owned'
if optNimV2 in c.config.globalOptions:
if optOwnedRefs in c.config.globalOptions:
result.typ = makeVarType(c, result.typ, tyOwned)
else:
result = semSym(c, n, s, flags)

View File

@@ -433,15 +433,12 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
# if srcTyp.kind == tyUInt64 and "FFFFFF" in $n:
# echo "n: ", n, " a: ", a
# echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check
# echo getInt(a)
# echo high(int64)
# writeStackTrace()
# XXX range checks?
case dstTyp.kind
of tyInt..tyInt64, tyUInt..tyUInt64:
case srcTyp.kind
@@ -449,9 +446,10 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
result = newIntNodeT(BiggestInt(getFloat(a)), n, g)
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
var val = a.getOrdValue
if check: rangeCheck(n, val, g)
result = newIntNodeT(val, n, g)
if dstTyp.kind in {tyUInt .. tyUInt64}:
if dstTyp.kind in {tyUInt..tyUInt64}:
result.kind = nkUIntLit
else:
result = a

View File

@@ -211,7 +211,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
param.typ = makeTypeDesc(c, header[i+1])
# this scope was not created by the user,
# unused params shoudn't be reported.
# unused params shouldn't be reported.
param.flags.incl sfUsed
addDecl(c, param)

View File

@@ -279,7 +279,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
a.setResult opBindSym(c, scope, a.getNode(0), a.getInt(1).int, a.getNode(2))
let
# altough we use VM callback here, it is not
# although we use VM callback here, it is not
# executed like 'normal' VM callback
idx = vm.registerCallback("bindSymImpl", bindSymWrapper)
# dummy node to carry idx information to VM

View File

@@ -339,7 +339,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
result = initPartial
if discriminatorVal.kind == nkIntLit:
# When the discriminator is a compile-time value, we also know
# which brach will be selected:
# which branch will be selected:
let matchedBranch = recNode.pickCaseBranch discriminatorVal
if matchedBranch != nil: checkMissingFields matchedBranch
else:
@@ -380,7 +380,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned})
if t.kind == tyRef:
t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink, tyOwned})
if optNimV2 in c.config.globalOptions:
if optOwnedRefs in c.config.globalOptions:
result.typ = makeVarType(c, result.typ, tyOwned)
# we have to watch out, there are also 'owned proc' types that can be used
# multiple times as long as they don't have closures.

View File

@@ -575,7 +575,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType; caller: PNode)
notNilCheck(tracked, n, paramType)
proc breaksBlock(n: PNode): bool =
# sematic check doesn't allow statements after raise, break, return or
# semantic check doesn't allow statements after raise, break, return or
# call to noreturn proc, so it is safe to check just the last statements
var it = n
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
@@ -751,7 +751,9 @@ proc track(tracked: PEffects, n: PNode) =
discard
else:
message(tracked.config, arg.info, warnProveInit, $arg)
createTypeBoundOps(tracked.graph, tracked.c, n[1].typ.lastSon, n.info)
# check required for 'nim check':
if n[1].typ.len > 0:
createTypeBoundOps(tracked.graph, tracked.c, n[1].typ.lastSon, n.info)
for i in 0 ..< safeLen(n):
track(tracked, n.sons[i])
of nkDotExpr:

View File

@@ -792,7 +792,8 @@ proc isTrivalStmtExpr(n: PNode): bool =
return false
result = true
proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string): PNode =
proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string;
flags: TExprFlags): PNode =
if selector.kind in nkCallKinds:
# we transform
# n := for a, b, c in m(x, y, z): Y
@@ -821,14 +822,14 @@ proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string): PNode
callExpr.add newSymNode(match)
callExpr.add n
case match.kind
of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, {})
of skTemplate: result = semTemplateExpr(c, callExpr, match, {})
of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, flags)
of skTemplate: result = semTemplateExpr(c, callExpr, match, flags)
else: result = nil
proc handleForLoopMacro(c: PContext; n: PNode): PNode =
result = handleStmtMacro(c, n, n[^2], "ForLoopStmt")
proc handleForLoopMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
result = handleStmtMacro(c, n, n[^2], "ForLoopStmt", flags)
proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
proc handleCaseStmtMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
# n[0] has been sem'checked and has a type. We use this to resolve
# 'match(n[0])' but then we pass 'n' to the 'match' macro. This seems to
# be the best solution.
@@ -848,8 +849,8 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
r.call.sons[1] = n
let toExpand = semResolvedCall(c, r, r.call, {})
case match.kind
of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, {})
of skTemplate: result = semTemplateExpr(c, toExpand, match, {})
of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, flags)
of skTemplate: result = semTemplateExpr(c, toExpand, match, flags)
else: result = nil
# this would be the perfectly consistent solution with 'for loop macros',
# but it kinda sucks for pattern matching as the matcher is not attached to
@@ -861,7 +862,7 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
checkMinSonsLen(n, 3, c.config)
var length = len(n)
if forLoopMacros in c.features:
result = handleForLoopMacro(c, n)
result = handleForLoopMacro(c, n, flags)
if result != nil: return result
openScope(c)
result = n
@@ -924,7 +925,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
popCaseContext(c)
closeScope(c)
if caseStmtMacros in c.features:
result = handleCaseStmtMacro(c, n)
result = handleCaseStmtMacro(c, n, flags)
if result != nil:
return result
localError(c.config, n.sons[0].info, errSelectorMustBeOfCertainTypes)
@@ -1449,8 +1450,13 @@ proc semProcAnnotation(c: PContext, prc: PNode;
continue
doAssert r.sons[0].kind == nkSym
# Expand the macro here
result = semMacroExpr(c, r, r, r.sons[0].sym, {})
let m = r.sons[0].sym
case m.kind
of skMacro: result = semMacroExpr(c, r, r, m, {})
of skTemplate: result = semTemplateExpr(c, r, m, {})
else:
prc.sons[pragmasPos] = n
continue
doAssert result != nil
@@ -1526,7 +1532,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
closeScope(c) # close scope for parameters
popOwner(c)
result.typ = s.typ
if optNimV2 in c.config.globalOptions:
if optOwnedRefs in c.config.globalOptions:
result.typ = makeVarType(c, result.typ, tyOwned)
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
@@ -1563,7 +1569,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
popProcCon(c)
popOwner(c)
closeScope(c)
if optNimV2 in c.config.globalOptions and result.typ != nil:
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
result.typ = makeVarType(c, result.typ, tyOwned)
# alternative variant (not quite working):
# var prc = arg[0].sym
@@ -1955,7 +1961,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if isAnon:
n.kind = nkLambda
result.typ = s.typ
if optNimV2 in c.config.globalOptions:
if optOwnedRefs in c.config.globalOptions:
result.typ = makeVarType(c, result.typ, tyOwned)
if isTopLevel(c) and s.kind != skIterator and
s.typ.callConv == ccClosure:

View File

@@ -242,6 +242,10 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode =
incl(s.flags, sfUsed)
# bug #12885; ideally sem'checking is performed again afterwards marking
# the symbol as used properly, but the nfSem mechanism currently prevents
# that from happening, so we mark the module as used here already:
markOwnerModuleAsUsed(c, s)
# we do not call onUse here, as the identifier is not really
# resolved here. We will fixup the used identifiers later.
case s.kind
@@ -261,6 +265,11 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode =
else:
if isField and sfGenSym in s.flags: result = n
else: result = newSymNode(s, n.info)
# Issue #12832
when defined(nimsuggest):
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
styleCheckUse(c.config, n.info, s)
proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
result = n

View File

@@ -635,6 +635,12 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
errorUndeclaredIdentifier(c, n.sons[0].info, typ.sym.name.s)
elif not isOrdinalType(typ):
localError(c.config, n.sons[0].info, "selector must be of an ordinal type, float or string")
if firstOrd(c.config, typ) != 0:
localError(c.config, n.info, "low(" & $a.sons[0].sym.name.s &
") must be 0 for discriminant")
elif lengthOrd(c.config, typ) > 0x00007FFF:
localError(c.config, n.info, "len($1) must be less than 32768" % a.sons[0].sym.name.s)
for i in 1 ..< len(n):
var b = copyTree(n.sons[i])
addSon(a, b)
@@ -871,7 +877,7 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
if tfPartial in result.flags:
if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial)
#if not isNilable: result.flags.incl tfNotNil
if isOwned and optNimV2 in c.config.globalOptions:
if isOwned and optOwnedRefs in c.config.globalOptions:
let t = newTypeS(tyOwned, c)
t.flags.incl tfHasOwned
t.rawAddSonNoPropagationOfTypeFlags result
@@ -1638,7 +1644,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semTypeof(c, n[1], prev)
elif op.s == "typeof" and n[0].kind == nkSym and n[0].sym.magic == mTypeOf:
result = semTypeof2(c, n, prev)
elif op.s == "owned" and optNimV2 notin c.config.globalOptions and n.len == 2:
elif op.s == "owned" and optOwnedRefs notin c.config.globalOptions and n.len == 2:
result = semTypeExpr(c, n[1], prev)
else:
if c.inGenericContext > 0 and n.kind == nkCall:

View File

@@ -76,13 +76,13 @@ type
c*: PContext
typeMap*: ptr LayeredIdTable # map PType to PType
symMap*: TIdTable # map PSym to PSym
localCache*: TIdTable # local cache for remembering alraedy replaced
localCache*: TIdTable # local cache for remembering already replaced
# types during instantiation of meta types
# (they are not stored in the global cache)
info*: TLineInfo
allowMetaTypes*: bool # allow types such as seq[Number]
# i.e. the result contains unresolved generics
skipTypedesc*: bool # wether we should skip typeDescs
skipTypedesc*: bool # whether we should skip typeDescs
isReturnType*: bool
owner*: PSym # where this instantiation comes from
recursionLimit: int
@@ -249,7 +249,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
return s
# XXX: Bound symbols in default parameter expressions may reach here.
# We cannot process them, becase `sym.n` may point to a proc body with
# We cannot process them, because `sym.n` may point to a proc body with
# cyclic references that will lead to an infinite recursion.
# Perhaps we should not use a black-list here, but a whitelist instead
# (e.g. skGenericParam and skType).
@@ -589,7 +589,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
for i in 0 ..< len(result):
if result.sons[i] != nil:
if result.sons[i].kind == tyGenericBody:
localError(cl.c.config, t.sym.info,
localError(cl.c.config, if t.sym != nil: t.sym.info else: cl.info,
"cannot instantiate '" &
typeToString(result.sons[i], preferDesc) &
"' inside of type definition: '" &

View File

@@ -134,11 +134,14 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
initIdTable(c.bindings)
proc put(c: var TCandidate, key, val: PType) {.inline.} =
## Given: proc foo[T](x: T); foo(4)
## key: 'T'
## val: 'int' (typeof(4))
when false:
let old = PType(idTableGet(c.bindings, key))
if old != nil:
echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old)
if typeToString(old) == "seq[string]":
if typeToString(old) == "float32":
writeStackTrace()
if c.c.module.name.s == "temp3":
echo "binding ", key, " -> ", val
@@ -2551,13 +2554,18 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
formal.name.s)
if nfDefaultRefsParam in formal.ast.flags:
m.call.flags.incl nfDefaultRefsParam
var def = copyTree(formal.ast)
if def.kind == nkNilLit:
def = implicitConv(nkHiddenStdConv, formal.typ, def, m, c)
var defaultValue = copyTree(formal.ast)
if defaultValue.kind == nkNilLit:
defaultValue = implicitConv(nkHiddenStdConv, formal.typ, defaultValue, m, c)
# proc foo(x: T = 0.0)
# foo()
if {tfImplicitTypeParam, tfGenericTypeParam} * formal.typ.flags != {}:
put(m, formal.typ, def.typ)
def.flags.incl nfDefaultParam
setSon(m.call, formal.position + 1, def)
let existing = PType(idTableGet(m.bindings, formal.typ))
if existing == nil or existing.kind == tyTypeDesc:
# see bug #11600:
put(m, formal.typ, defaultValue.typ)
defaultValue.flags.incl nfDefaultParam
setSon(m.call, formal.position + 1, defaultValue)
inc(f)
# forget all inferred types if the overload matching failed
if m.state == csNoMatch:

View File

@@ -16,11 +16,12 @@ proc align(address, alignment: int): int =
result = (address + (alignment - 1)) and not (alignment - 1)
const
## a size is concidered "unknown" when it is an imported type from C
## a size is considered "unknown" when it is an imported type from C
## or C++.
szUnknownSize* = -3
szIllegalRecursion* = -2
szUncomputedSize* = -1
szTooBigSize* = -4
type IllegalTypeRecursionError = object of Exception
@@ -33,14 +34,14 @@ type
offset: int
proc inc(arg: var OffsetAccum; value: int) =
if unlikely(value == szIllegalRecursion): raiseIllegalTypeRecursion()
if unlikely(value == szIllegalRecursion): raiseIllegalTypeRecursion()
if value == szUnknownSize or arg.offset == szUnknownSize:
arg.offset = szUnknownSize
else:
arg.offset += value
proc alignmentMax(a,b: int): int =
if unlikely(a == szIllegalRecursion or b == szIllegalRecursion): raiseIllegalTypeRecursion()
if unlikely(a == szIllegalRecursion or b == szIllegalRecursion): raiseIllegalTypeRecursion()
if a == szUnknownSize or b == szUnknownSize:
szUnknownSize
else:
@@ -57,7 +58,7 @@ proc align(arg: var OffsetAccum; value: int) =
proc mergeBranch(arg: var OffsetAccum; value: OffsetAccum) =
if value.maxAlign == szUnknownSize or arg.maxAlign == szUnknownSize or
value.offset == szUnknownSize or arg.offset == szUnknownSize:
value.offset == szUnknownSize or arg.offset == szUnknownSize:
arg.maxAlign = szUnknownSize
arg.offset = szUnknownSize
else:
@@ -111,7 +112,7 @@ proc setOffsetsToUnknown(n: PNode) =
for i in 0 ..< safeLen(n):
setOffsetsToUnknown(n[i])
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, accum: var OffsetAccum): void =
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, accum: var OffsetAccum) =
## ``offset`` is the offset within the object, after the node has been written, no padding bytes added
## ``align`` maximum alignment from all sub nodes
assert n != nil
@@ -256,7 +257,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
typ.size = elemSize
typ.align = int16(elemSize)
else:
typ.size = toInt64(lengthOrd(conf, typ.sons[0]) * int32(elemSize))
typ.size = toInt64Checked(lengthOrd(conf, typ.sons[0]) * int32(elemSize), szTooBigSize)
typ.align = typ.sons[1].align
of tyUncheckedArray:

View File

@@ -65,7 +65,7 @@ proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: P
vpart.sons[2] = if varInit.isNil: v else: vpart[1]
varSection.add vpart
if varInit != nil:
if useShallowCopy and typeNeedsNoDeepCopy(typ) or optNimV2 in g.config.globalOptions:
if useShallowCopy and typeNeedsNoDeepCopy(typ) or optTinyRtti in g.config.globalOptions:
varInit.add newFastAsgnStmt(newSymNode(result), v)
else:
let deepCopyCall = newNodeI(nkCall, varInit.info, 3)

View File

@@ -663,7 +663,6 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
t = arg.typ
# generate a temporary and produce an assignment statement:
var temp = newTemp(c, t, formal.info)
#temp.sym.flags.incl sfCursor
addVar(v, temp)
add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode))
idNodeTablePut(newC.mapping, formal, temp)
@@ -877,7 +876,7 @@ proc hoistParamsUsedInDefault(c: PTransf, call, letSection, defExpr: PNode): PNo
# The recursion may confuse you. It performs two duties:
#
# 1) extracting all referenced params from default expressions
# into a let section preceeding the call
# into a let section preceding the call
#
# 2) replacing the "references" within the default expression
# with these extracted skLet symbols.
@@ -915,7 +914,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
oldDeferAnchor = c.deferAnchor
c.deferAnchor = n
if (n.typ != nil and tfHasAsgn in n.typ.flags) or
optNimV2 in c.graph.config.globalOptions:
optSeqDestructors in c.graph.config.globalOptions:
c.needsDestroyPass = true
case n.kind
of nkSym:
@@ -1140,7 +1139,7 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
let cache = cache or prc.typ.callConv == ccInline
if cache:
# genProc for inline procs will be called multiple times from diffrent modules,
# genProc for inline procs will be called multiple times from different modules,
# it is important to transform exactly once to get sym ids and locations right
prc.transformedBody = result
else:

View File

@@ -303,7 +303,7 @@ proc analyseObjectWithTypeFieldAux(t: PType,
proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult =
# this does a complex analysis whether a call to ``objectInit`` needs to be
# made or intializing of the type field suffices or if there is no type field
# made or initializing of the type field suffices or if there is no type field
# at all in this type.
var marker = initIntSet()
result = analyseObjectWithTypeFieldAux(t, marker)
@@ -814,11 +814,8 @@ proc floatRangeCheck*(x: BiggestFloat, t: PType): bool =
false
proc lengthOrd*(conf: ConfigRef; t: PType): Int128 =
case t.skipTypes(tyUserTypeClasses).kind
of tyInt64, tyInt32, tyInt:
# XXX: this is just wrong
result = lastOrd(conf, t)
of tyDistinct: result = lengthOrd(conf, t.sons[0])
if t.skipTypes(tyUserTypeClasses).kind == tyDistinct:
result = lengthOrd(conf, t.sons[0])
else:
let last = lastOrd(conf, t)
let first = firstOrd(conf, t)

View File

@@ -156,7 +156,7 @@ proc createStrKeepNode(x: var TFullReg; keepNode=true) =
x.node = newNode(nkStrLit)
# It not only hackey, it is also wrong for tgentemplate. The primary
# cause of bugs like these is that the VM does not properly distinguish
# between variable defintions (var foo = e) and variable updates (foo = e).
# between variable definitions (var foo = e) and variable updates (foo = e).
include vmhooks
@@ -280,7 +280,7 @@ type
ExceptionGotoUnhandled
proc findExceptionHandler(c: PCtx, f: PStackFrame, exc: PNode):
tuple[why: ExceptionGoto, where: int] =
tuple[why: ExceptionGoto, where: int] =
let raisedType = exc.typ.skipTypes(abstractPtrs)
while f.safePoints.len > 0:
@@ -357,7 +357,7 @@ proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
result = -1
# Traverse the stack starting from the end in order to execute the blocks in
# the inteded order
# the intended order
for i in 1 .. f.safePoints.len:
var pc = f.safePoints[^i]
# Skip the `except` blocks
@@ -436,12 +436,8 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
let destDist = (sizeof(dest.intVal) - desttyp.size) * 8
var value = cast[BiggestUInt](src.intVal)
when system.cpuEndian == bigEndian:
value = (value shr srcDist) shl srcDist
value = (value shr destDist) shl destDist
else:
value = (value shl srcDist) shr srcDist
value = (value shl destDist) shr destDist
value = (value shl srcDist) shr srcDist
value = (value shl destDist) shr destDist
dest.intVal = cast[BiggestInt](value)
of tyFloat..tyFloat64:
if dest.kind != rkFloat:
@@ -475,7 +471,8 @@ template handleJmpBack() {.dirty.} =
dec(c.loopIterations)
proc recSetFlagIsRef(arg: PNode) =
arg.flags.incl(nfIsRef)
if arg.kind notin {nkStrLit..nkTripleStrLit}:
arg.flags.incl(nfIsRef)
for i in 0 ..< arg.safeLen:
arg.sons[i].recSetFlagIsRef
@@ -714,7 +711,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of rkNode:
if regs[ra].node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
assert nfIsRef in regs[ra].node.flags
regs[ra].node[] = regs[rc].regToNode[]
regs[ra].node.flags.incl nfIsRef
else: stackTrace(c, tos, pc, errNilAccess)
@@ -1189,7 +1185,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
tos.pushSafePoint(pc + rbx)
assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
of opcExcept:
# This opcode is never executed, it only holds informations for the
# This opcode is never executed, it only holds information for the
# exception handling routines.
doAssert(false)
of opcFinally:
@@ -1275,7 +1271,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
# opcLdNull really is the gist of the VM's problems: should it load
# a fresh null to regs[ra].node or to regs[ra].node[]? This really
# depends on whether regs[ra] represents the variable itself or wether
# depends on whether regs[ra] represents the variable itself or whether
# it holds the indirection! Due to the way registers are re-used we cannot
# say for sure here! --> The codegen has to deal with it
# via 'genAsgnPatch'.
@@ -1320,9 +1316,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcQuit:
if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
message(c.config, c.debug[pc], hintQuitCalled)
msgQuit(int8(toInt(getOrdValue(regs[ra].regToNode))))
msgQuit(int8(toInt(getOrdValue(regs[ra].regToNode, onError = toInt128(1)))))
else:
return TFullReg(kind: rkNone)
of opcInvalidField:
stackTrace(c, tos, pc, errFieldXNotFound & regs[ra].node.strVal)
of opcSetLenStr:
decodeB(rkNode)
#createStrKeepNode regs[ra]
@@ -1567,19 +1565,20 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
c.module, c.config)
of opcGorge:
decodeBC(rkNode)
inc pc
let rd = c.code[pc].regA
createStr regs[ra]
if defined(nimsuggest) or c.config.cmd == cmdCheck:
discard "don't run staticExec for 'nim suggest'"
regs[ra].node.strVal = ""
else:
when defined(nimcore):
decodeBC(rkNode)
inc pc
let rd = c.code[pc].regA
createStr regs[ra]
regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
regs[rc].node.strVal, regs[rd].node.strVal,
c.debug[pc], c.config)[0]
else:
regs[ra].node.strVal = ""
globalError(c.config, c.debug[pc], "VM is not built with 'gorge' support")
of opcNError, opcNWarning, opcNHint:
decodeB(rkNode)

View File

@@ -72,7 +72,7 @@ type
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
opcIsNil, opcOf, opcIs,
opcSubStr, opcParseFloat, opcConv, opcCast,
opcQuit,
opcQuit, opcInvalidField,
opcNarrowS, opcNarrowU,
opcSignExtend,

View File

@@ -8,6 +8,7 @@
#
import ast, types, msgs, os, options, idents, lineinfos
from pathutils import AbsoluteFile
proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): string =
try:
@@ -17,6 +18,7 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): str
result = readFile(filename)
# we produce a fake include statement for every slurped filename, so that
# the module dependencies are accurate:
discard conf.fileInfoIdx(AbsoluteFile filename)
appendToModule(module, newNode(nkIncludeStmt, info, @[
newStrNode(nkStrLit, filename)]))
except IOError:

View File

@@ -127,7 +127,7 @@ proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
ctx.debug.add(n.info)
proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
# Takes the `b` register and the immediate `imm`, appies the operation `opc`,
# Takes the `b` register and the immediate `imm`, applies the operation `opc`,
# and stores the output value into `a`.
# `imm` is signed and must be within [-128, 127]
if imm >= -128 and imm <= 127:
@@ -202,29 +202,41 @@ proc bestEffort(c: PCtx): TLineInfo =
else:
c.module.info
proc getTemp(cc: PCtx; tt: PType): TRegister =
let typ = tt.skipTypesOrNil({tyStatic})
proc getFreeRegister(cc: PCtx; k: TSlotKind; start: int): TRegister =
let c = cc.prc
# we prefer the same slot kind here for efficiency. Unfortunately for
# discardable return types we may not know the desired type. This can happen
# for e.g. mNAdd[Multiple]:
let k = if typ.isNil: slotTempComplex else: typ.getSlotKind
for i in 0 .. c.maxSlots-1:
for i in start .. c.maxSlots-1:
if c.slots[i].kind == k and not c.slots[i].inUse:
c.slots[i].inUse = true
return TRegister(i)
# if register pressure is high, we re-use more aggressively:
if c.maxSlots >= HighRegisterPressure and false:
for i in 0 .. c.maxSlots-1:
if c.maxSlots >= high(TRegister):
for i in start .. c.maxSlots-1:
if not c.slots[i].inUse:
c.slots[i] = (inUse: true, kind: k)
return TRegister(i)
if c.maxSlots >= high(TRegister):
globalError(cc.config, cc.bestEffort, "VM problem: too many registers required")
result = TRegister(c.maxSlots)
c.slots[c.maxSlots] = (inUse: true, kind: k)
inc c.maxSlots
result = TRegister(max(c.maxSlots, start))
c.slots[result] = (inUse: true, kind: k)
c.maxSlots = result + 1
proc getTemp(cc: PCtx; tt: PType): TRegister =
let typ = tt.skipTypesOrNil({tyStatic})
# we prefer the same slot kind here for efficiency. Unfortunately for
# discardable return types we may not know the desired type. This can happen
# for e.g. mNAdd[Multiple]:
let k = if typ.isNil: slotTempComplex else: typ.getSlotKind
result = getFreeRegister(cc, k, start = 0)
when false:
# enable this to find "register" leaks:
if result == 4:
echo "begin ---------------"
writeStackTrace()
echo "end ----------------"
proc freeTemp(c: PCtx; r: TRegister) =
let c = c.prc
@@ -278,7 +290,9 @@ proc gen(c: PCtx; n: PNode; dest: TRegister; flags: TGenFlags = {}) =
proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) =
var tmp: TDest = -1
gen(c, n, tmp, flags)
#if n.typ.isEmptyType: InternalAssert tmp < 0
if tmp >= 0:
freeTemp(c, tmp)
#if n.typ.isEmptyType: internalAssert tmp < 0
proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
var tmp: TDest = -1
@@ -335,7 +349,15 @@ proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
c.gen(n.sons[1], dest)
for i in oldRegisterCount ..< c.prc.maxSlots:
if c.prc.slots[i].kind in {slotFixedVar, slotFixedLet}:
#if c.prc.slots[i].kind in {slotFixedVar, slotFixedLet}:
if i != dest:
when not defined(release):
if c.prc.slots[i].inUse and c.prc.slots[i].kind in {slotTempUnknown,
slotTempInt,
slotTempFloat,
slotTempStr,
slotTempComplex}:
doAssert false, "leaking temporary " & $i & " " & $c.prc.slots[i].kind
c.prc.slots[i] = (inUse: false, kind: slotEmpty)
c.clearDest(n, dest)
@@ -752,6 +774,7 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
tmp = c.genx(n.sons[2])
c.gABC(n, opc, dest, tmp, 0)
c.freeTemp(tmp)
c.freeTemp(dest)
proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
var x = n.sons[1]
@@ -762,6 +785,7 @@ proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
c.gABC(n, opc, dest, tmp, 0)
#c.genAsgnPatch(n.sons[1], dest)
c.freeTemp(tmp)
c.freeTemp(dest)
proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
let tmp = c.genx(n.sons[1])
@@ -948,9 +972,13 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.genAddSubInt(n, dest, opcAddInt)
of mInc, mDec:
unused(c, n, dest)
let opc = if m == mInc: opcAddInt else: opcSubInt
let isUnsigned = n.sons[1].typ.skipTypes(abstractVarRange).kind in {tyUInt..tyUInt64}
let opc = if not isUnsigned:
if m == mInc: opcAddInt else: opcSubInt
else:
if m == mInc: opcAddu else: opcSubu
let d = c.genx(n.sons[1])
if n.sons[2].isInt8Lit:
if n.sons[2].isInt8Lit and not isUnsigned:
c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
else:
let tmp = c.genx(n.sons[2])
@@ -1081,6 +1109,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
c.genAsgnPatch(n.sons[1], d)
c.freeTemp(tmp)
c.freeTemp(d)
of mSwap:
unused(c, n, dest)
c.gen(lowerSwap(c.graph, n, if c.prc == nil: c.module else: c.prc.sym))
@@ -1316,7 +1345,6 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mMove:
let arg = n[1]
let a = c.genx(arg)
assert dest >= 0
if dest < 0: dest = c.getTemp(arg.typ)
gABC(c, arg, whichAsgnOpc(arg, requiresCopy=false), dest, a)
# XXX use ldNullOpcode() here?
@@ -1421,6 +1449,7 @@ proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
assert n.typ != nil
if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
c.gABC(n, opcNodeToReg, dest, dest)
c.freeTemp(tmp)
proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
let tmp = c.genx(ri)
@@ -1431,13 +1460,7 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
proc setSlot(c: PCtx; v: PSym) =
# XXX generate type initialization here?
if v.position == 0:
if c.prc.maxSlots == 0: c.prc.maxSlots = 1
if c.prc.maxSlots >= high(TRegister):
globalError(c.config, v.info, "cannot generate code; too many registers required")
v.position = c.prc.maxSlots
c.prc.slots[v.position] = (inUse: true,
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
inc c.prc.maxSlots
v.position = getFreeRegister(c, if v.kind == skLet: slotFixedLet else: slotFixedVar, start = 1)
proc cannotEval(c: PCtx; n: PNode) {.noinline.} =
globalError(c.config, n.info, "cannot evaluate at compile time: " &
@@ -1460,7 +1483,10 @@ proc checkCanEval(c: PCtx; n: PNode) =
if {sfCompileTime, sfGlobal} <= s.flags: return
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl:
cannotEval(c, n)
# little hack ahead for bug #12612: assume gensym'ed variables
# are in the right scope:
if sfGenSym in s.flags and c.prc.sym == nil: discard
else: cannotEval(c, n)
elif s.kind in {skProc, skFunc, skConverter, skMethod,
skIterator} and sfForward in s.flags:
cannotEval(c, n)
@@ -1498,6 +1524,8 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
else:
c.preventFalseAlias(le, opcWrArr, dest, idx, tmp)
c.freeTemp(tmp)
c.freeTemp(idx)
c.freeTemp(dest)
of nkCheckedFieldExpr:
var objR: TDest = -1
genCheckedObjAccessAux(c, le, objR, {gfNode})
@@ -1505,17 +1533,21 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
let tmp = c.genx(ri)
c.preventFalseAlias(le[0], opcWrObj, objR, idx, tmp)
c.freeTemp(tmp)
c.freeTemp(idx)
c.freeTemp(objR)
of nkDotExpr:
let dest = c.genx(le.sons[0], {gfNode})
let idx = genField(c, le.sons[1])
let tmp = c.genx(ri)
c.preventFalseAlias(le, opcWrObj, dest, idx, tmp)
c.freeTemp(idx)
c.freeTemp(tmp)
c.freeTemp(dest)
of nkDerefExpr, nkHiddenDeref:
let dest = c.genx(le.sons[0], {gfNode})
let tmp = c.genx(ri)
c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp)
c.freeTemp(dest)
c.freeTemp(tmp)
of nkSym:
let s = le.sym
@@ -1529,7 +1561,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
else:
if s.kind == skForVar: c.setSlot s
internalAssert c.config, s.position > 0 or (s.position == 0 and
s.kind in {skParam,skResult})
s.kind in {skParam, skResult})
var dest: TRegister = s.position + ord(s.kind == skParam)
assert le.typ != nil
if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}:
@@ -1542,6 +1574,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
else:
let dest = c.genx(le, {gfNodeAddr})
genAsgn(c, dest, ri, requiresCopy)
c.freeTemp(dest)
proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
var n = newNode(nkType)
@@ -1608,7 +1641,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
else:
if s.kind == skForVar and c.mode == emRepl: c.setSlot(s)
if s.position > 0 or (s.position == 0 and
s.kind in {skParam,skResult}):
s.kind in {skParam, skResult}):
if dest < 0:
dest = s.position + ord(s.kind == skParam)
internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp)
@@ -1625,8 +1658,8 @@ template needsRegLoad(): untyped =
{gfNode, gfNodeAddr} * flags == {} and
fitsRegister(n.typ.skipTypes({tyVar, tyLent, tyStatic}))
proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
flags: TGenFlags) =
proc genArrAccessOpcode(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
flags: TGenFlags) =
let a = c.genx(n.sons[0], flags)
let b = c.genIndex(n.sons[1], n.sons[0].typ)
if dest < 0: dest = c.getTemp(n.typ)
@@ -1679,12 +1712,18 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
let setLit = c.genx(checkExpr[1])
var rs = c.getTemp(getSysType(c.graph, n.info, tyBool))
c.gABC(n, opcContainsSet, rs, setLit, discVal)
c.freeTemp(discVal)
c.freeTemp(setLit)
# If the check fails let the user know
let lab1 = c.xjmp(n, if negCheck: opcFJmp else: opcTJmp, rs)
c.freeTemp(rs)
# Not ideal but will do for the moment
c.gABC(n, opcQuit)
let strType = getSysType(c.graph, n.info, tyString)
var fieldNameRegister: TDest = c.getTemp(strType)
let strLit = newStrNode($accessExpr[1], accessExpr[1].info)
strLit.typ = strType
c.genLit(strLit, fieldNameRegister)
c.gABC(n, opcInvalidField, fieldNameRegister)
c.freeTemp(fieldNameRegister)
c.patch(lab1)
proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
@@ -1712,11 +1751,11 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
let arrayType = n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
if arrayType in {tyString, tyCString}:
genArrAccess2(c, n, dest, opcLdStrIdx, {})
genArrAccessOpcode(c, n, dest, opcLdStrIdx, {})
elif arrayType == tyTypeDesc:
c.genTypeLit(n.typ, dest)
else:
genArrAccess2(c, n, dest, opcLdArr, flags)
genArrAccessOpcode(c, n, dest, opcLdArr, flags)
proc getNullValueAux(t: PType; obj: PNode, result: PNode; conf: ConfigRef; currPosition: var int) =
if t != nil and t.len > 0 and t.sons[0] != nil:
@@ -2096,7 +2135,10 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
of nkComesFrom:
discard "XXX to implement for better stack traces"
else:
globalError(c.config, n.info, "cannot generate VM code for " & $n)
if n.typ != nil and n.typ.isCompileTimeOnly:
genTypeLit(c, n.typ, dest)
else:
globalError(c.config, n.info, "cannot generate VM code for " & $n)
proc removeLastEof(c: PCtx) =
let last = c.code.len-1

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
# Unforunately this cannot be a module yet:
# Unfortunately this cannot be a module yet:
#import vmdeps, vm
from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
@@ -148,7 +148,11 @@ proc registerAdditionalOps*(c: PCtx) =
systemop getCurrentException
registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
systemop gorgeEx
if defined(nimsuggest) or c.config.cmd == cmdCheck:
discard "don't run staticExec for 'nim suggest'"
else:
systemop gorgeEx
macrosop getProjectPath
registerCallback c, "stdlib.os.getCurrentCompilerExe", proc (a: VmArgs) {.nimcall.} =

View File

@@ -37,8 +37,6 @@ type
wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
wIntDefine, wStrDefine, wBoolDefine
wCursor,
wImmediate, wConstructor, wDestructor, wDelegator, wOverride,
wImportCpp, wImportObjC,
wImportCompilerProc,
@@ -125,8 +123,6 @@ const
"magic", "thread", "final", "profiler", "memtracker", "objchecks",
"intdefine", "strdefine", "booldefine",
"cursor",
"immediate", "constructor", "destructor", "delegator", "override",
"importcpp", "importobjc",
"importcompilerproc", "importc", "importjs", "exportc", "exportcpp", "exportnims",

View File

@@ -208,6 +208,7 @@ doc.file = """<?xml version="1.0" encoding="utf-8" ?>
<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>

View File

@@ -99,6 +99,7 @@ Advanced options:
--putenv:key=value set an environment variable
--NimblePath:PATH add a path for Nimble support
--noNimblePath deactivate the Nimble path
--clearNimblePath empty the list of Nimble package search paths
--noCppExceptions use default exception handling with C++ backend
--cppCompileToNamespace:namespace
use the provided namespace for the generated C++ code,

View File

@@ -157,7 +157,7 @@ AST:
As a side note, if you choose to use infix operators in a prefix form, the AST
behaves as a
[parenthetical function call](./macros.html#calls-expressions-call-with) with
[parenthetical function call](#callsslashexpressions-call-with) with
``nnkAccQuoted``, as follows:
Concrete syntax:
@@ -237,7 +237,7 @@ Call with raw string literal
----------------------------
This is used, for example, in the ``bindSym`` examples
[here](http://nim-lang.org/docs/manual.html#macros-bindsym) and with
[here](manual.html#macros-bindsym) and with
``re"some regexp"`` in the regular expression module.
Concrete syntax:
@@ -902,7 +902,7 @@ as the compiler needs to know the type somehow (which it can infer from
the given assignment).
This is not the same AST for all uses of ``var``. See
[Procedure declaration](http://nim-lang.org/docs/macros.html#statements-procedure-declaration)
[Procedure declaration](macros.html#statements-procedure-declaration)
for details.
Let section
@@ -1361,7 +1361,7 @@ Template declaration
Templates (as well as macros, as we'll see) have a slightly expanded AST when
compared to procs and iterators. The reason for this is [term-rewriting
macros](http://nim-lang.org/docs/manual.html#term-rewriting-macros). Notice
macros](manual.html#term-rewriting-macros). Notice
the ``nnkEmpty()`` as the second argument to ``nnkProcDef`` and
``nnkIteratorDef`` above? That's where the term-rewriting macros go.

View File

@@ -107,12 +107,13 @@ Nim code calling the backend
Nim code can interface with the backend through the `Foreign function
interface <manual.html#foreign-function-interface>`_ mainly through the
`importc pragma <manual.html#importc-pragma>`_. The ``importc`` pragma is the
*generic* way of making backend symbols available in Nim and is available
in all the target backends (JavaScript too). The C++ or Objective-C backends
have their respective `ImportCpp <manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
`ImportObjC <manual.html#implementation-specific-pragmas-importobjc-pragma>`_ pragmas to call methods from
classes.
`importc pragma <manual.html#foreign-function-interface-importc-pragma>`_.
The ``importc`` pragma is the *generic* way of making backend symbols available
in Nim and is available in all the target backends (JavaScript too). The C++
or Objective-C backends have their respective `ImportCpp
<manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
`ImportObjC <manual.html#implementation-specific-pragmas-importobjc-pragma>`_
pragmas to call methods from classes.
Whenever you use any of these pragmas you need to integrate native code into
your final binary. In the case of JavaScript this is no problem at all, the
@@ -124,18 +125,18 @@ statically or dynamically. The preferred way of integrating native code is to
use dynamic linking because it allows you to compile Nim programs without
the need for having the related development libraries installed. This is done
through the `dynlib pragma for import
<manual.html#dynlib-pragma-for-import>`_, though more specific control can be
gained using the `dynlib module <dynlib.html>`_.
<manual.html#foreign-function-interface-dynlib-pragma-for-import>`_, though
more specific control can be gained using the `dynlib module <dynlib.html>`_.
The `dynlibOverride <nimc.html#dynliboverride>`_ command line switch allows
to avoid dynamic linking if you need to statically link something instead.
Nim wrappers designed to statically link source files can use the `compile
pragma <nimc.html#compile-pragma>`_ if there are few sources or providing
them along the Nim code is easier than using a system library. Libraries
installed on the host system can be linked in with the `PassL pragma
<nimc.html#passl-pragma>`_.
pragma <manual.html#implementation-specific-pragmas-compile-pragma>`_ if
there are few sources or providing them along the Nim code is easier than using
a system library. Libraries installed on the host system can be linked in with
the `PassL pragma <manual.html#implementation-specific-pragmas-passl-pragma>`_.
To wrap native code, take a look at the `c2nim tool <https://nim-lang.org/docs/c2nim.html>`_ which helps
To wrap native code, take a look at the `c2nim tool <https://github.com/nim-lang/c2nim/blob/master/doc/c2nim.rst>`_ which helps
with the process of scanning and transforming header files into a Nim
interface.
@@ -215,12 +216,12 @@ Backend code calling Nim
------------------------
Backend code can interface with Nim code exposed through the `exportc
pragma <manual.html#exportc-pragma>`_. The ``exportc`` pragma is the *generic*
way of making Nim symbols available to the backends. By default the Nim
compiler will mangle all the Nim symbols to avoid any name collision, so
the most significant thing the ``exportc`` pragma does is maintain the Nim
symbol name, or if specified, use an alternative symbol for the backend in
case the symbol rules don't match.
pragma <manual.html#foreign-function-interface-exportc-pragma>`_. The
``exportc`` pragma is the *generic* way of making Nim symbols available to
the backends. By default the Nim compiler will mangle all the Nim symbols to
avoid any name collision, so the most significant thing the ``exportc`` pragma
does is maintain the Nim symbol name, or if specified, use an alternative
symbol for the backend in case the symbol rules don't match.
The JavaScript target doesn't have any further interfacing considerations
since it also has garbage collection, but the C targets require you to
@@ -329,8 +330,8 @@ Nimcache naming logic
The `nimcache`:idx: directory is generated during compilation and will hold
either temporary or final files depending on your backend target. The default
name for the directory depends on the used backend and on your OS but you can
use the ``--nimcache`` `compiler switch <nimc.html#command-line-switches>`_ to
change it.
use the ``--nimcache`` `compiler switch
<nimc.html#compiler-usage-command-line-switches>`_ to change it.
Memory management
@@ -349,14 +350,14 @@ Strings and C strings
---------------------
The manual mentions that `Nim strings are implicitly convertible to
cstrings <manual.html#cstring-type>`_ which makes interaction usually
cstrings <manual.html#types-cstring-type>`_ which makes interaction usually
painless. Most C functions accepting a Nim string converted to a
``cstring`` will likely not need to keep this string around and by the time
they return the string won't be needed any more. However, for the rare cases
where a Nim string has to be preserved and made available to the C backend
as a ``cstring``, you will need to manually prevent the string data from being
freed with `GC_ref <system.html#GC_ref>`_ and `GC_unref
<system.html#GC_unref>`_.
freed with `GC_ref <system.html#GC_ref,string>`_ and `GC_unref
<system.html#GC_unref,string>`_.
A similar thing happens with C code invoking Nim code which returns a
``cstring``. Consider the following proc:
@@ -382,10 +383,10 @@ Custom data types
Just like strings, custom data types that are to be shared between Nim and
the backend will need careful consideration of who controls who. If you want
to hand a Nim reference to C code, you will need to use `GC_ref
<system.html#GC_ref>`_ to mark the reference as used, so it does not get
<system.html#GC_ref,ref.T>`_ to mark the reference as used, so it does not get
freed. And for the C backend you will need to expose the `GC_unref
<system.html#GC_unref>`_ proc to clean up this memory when it is not required
any more.
<system.html#GC_unref,ref.T>`_ proc to clean up this memory when it is not
required any more.
Again, if you are wrapping a library which *mallocs* and *frees* data
structures, you need to expose the appropriate *free* function to Nim so

View File

@@ -191,7 +191,7 @@ the old name and introduce a new name:
type Barz = enum baz0, baz1 {.deprecated.}, baz2
See also `Deprecated <https://nim-lang.org/docs/manual.html#pragmas-deprecated-pragma>`_
See also `Deprecated <manual.html#pragmas-deprecated-pragma>`_
pragma in the manual.
@@ -216,8 +216,7 @@ as well as ``testament`` and guarantee they stay in sync.
assert "baz".addBar == "bazBar"
result = a & "Bar"
See `parentDir <https://nim-lang.github.io/Nim/os.html#parentDir%2Cstring>`_
example.
See `parentDir <os.html#parentDir,string>`_ example.
The RestructuredText Nim uses has a special syntax for including code snippets
embedded in documentation; these are not run by ``nim doc`` and therefore are
@@ -360,7 +359,8 @@ General commit rules
2. If you introduce changes which affect backwards compatibility,
make breaking changes, or have PR which is tagged as ``[feature]``,
the changes should be mentioned in `<changelog.md>`_.
the changes should be mentioned in `the changelog
<https://github.com/nim-lang/Nim/blob/devel/changelog.md>`_.
3. All changes introduced by the commit (diff lines) must be related to the
subject of the commit.

View File

@@ -295,8 +295,8 @@ The relationship of type to suffix is made by the proc ``complexName`` in the
``compiler/docgen.nim`` file. Here are some examples of complex names for
symbols in the `system module <system.html>`_.
* ``type SignedInt = int | int8 | int16 | int32 | int64`` **=>**
`#SignedInt <system.html#SignedInt>`_
* ``type SomeSignedInt = int | int8 | int16 | int32 | int64`` **=>**
`#SomeSignedInt <system.html#SomeSignedInt>`_
* ``var globalRaiseHook: proc (e: ref E_Base): bool {.nimcall.}`` **=>**
`#globalRaiseHook <system.html#globalRaiseHook>`_
* ``const NimVersion = "0.0.0"`` **=>**
@@ -307,23 +307,25 @@ symbols in the `system module <system.html>`_.
`#len,seq[T] <system.html#len,seq[T]>`_
* ``iterator pairs[T](a: seq[T]): tuple[key: int, val: T] {.inline.}`` **=>**
`#pairs.i,seq[T] <system.html#pairs.i,seq[T]>`_
* ``template newException[](exceptn: type; message: string): expr`` **=>**
`#newException.t,type,string
<system.html#newException.t,type,string>`_
* ``template newException[](exceptn: typedesc; message: string;
parentException: ref Exception = nil): untyped`` **=>**
`#newException.t,typedesc,string,ref.Exception
<system.html#newException.t,typedesc,string,ref.Exception>`_
Index (idx) file format
=======================
Files with the ``.idx`` extension are generated when you use the `Index
switch`_ along with commands to generate documentation from source or text
files. You can programatically generate indices with the `setIndexTerm()
<rstgen.html#setIndexTerm>`_ and `writeIndexFile()
<rstgen.html#writeIndexFile>`_ procs. The purpose of ``idx`` files is to hold
the interesting symbols and their HTML references so they can be later
concatenated into a big index file with `mergeIndexes()
<rstgen.html#mergeIndexes>`_. This section documents the file format in
detail.
switch <#related-options-index-switch>`_ along with commands to generate
documentation from source or text files. You can programatically generate
indices with the `setIndexTerm()
<rstgen.html#setIndexTerm,RstGenerator,string,string,string,string,string>`_
and `writeIndexFile() <rstgen.html#writeIndexFile,RstGenerator,string>`_ procs.
The purpose of ``idx`` files is to hold the interesting symbols and their HTML
references so they can be later concatenated into a big index file with
`mergeIndexes() <rstgen.html#mergeIndexes,string>`_. This section documents
the file format in detail.
Index files are line oriented and tab separated (newline and tab characters
have to be escaped). Each line represents a record with at least two fields,
@@ -368,7 +370,7 @@ final index, and TOC entries found in ``.nim`` files are discarded.
Additional resources
====================
`Nim Compiler User Guide <nimc.html#command-line-switches>`_
`Nim Compiler User Guide <nimc.html#compiler-usage-command-line-switches>`_
`RST Quick Reference
<http://docutils.sourceforge.net/docs/user/rst/quickref.html>`_

View File

@@ -119,9 +119,12 @@ procs ``GC_ref`` and ``GC_unref`` to mark objects as referenced to avoid them
being freed by the GC. Other useful procs from `system <system.html>`_ you can
use to keep track of memory are:
* getTotalMem(): returns the amount of total memory managed by the GC.
* getOccupiedMem(): bytes reserved by the GC and used by objects.
* getFreeMem(): bytes reserved by the GC and not in use.
* ``getTotalMem()`` Returns the amount of total memory managed by the GC.
* ``getOccupiedMem()`` Bytes reserved by the GC and used by objects.
* ``getFreeMem()`` Bytes reserved by the GC and not in use.
These numbers are usually only for the running thread, not for the whole heap,
with the exception of ``--gc:boehm`` and ``--gc:go``.
In addition to ``GC_ref`` and ``GC_unref`` you can avoid the GC by manually
allocating memory with procs like ``alloc``, ``allocShared``, or
@@ -144,3 +147,25 @@ The numbers count the number of objects in all GC heaps, they refer to
all running threads, not only to the current thread. (The current thread
would be the thread that calls ``dumpNumberOfInstances``.) This might
change in later versions.
Garbage collector options
-------------------------
You can choose which garbage collector to use when compiling source code,
you can pass ``--gc:`` on the compile command with the choosed garbage collector.
- ``--gc:refc`` Deferred `reference counting <https://en.wikipedia.org/wiki/Reference_counting>`_ with cycle detection, `thread local heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_, default.
- ``--gc:markAndSweep`` `Mark-And-Sweep <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Copying_vs._mark-and-sweep_vs._mark-and-don't-sweep>`_ based garbage collector, `thread local heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_.
- ``--gc:boehm`` `Boehm <https://en.wikipedia.org/wiki/Boehm_garbage_collector>`_ based garbage collector, `stop-the-world <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Stop-the-world_vs._incremental_vs._concurrent>`_, `shared heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_.
- ``--gc:go`` Go lang like garbage collector, `stop-the-world <https://en.wikipedia.org/wiki/Tracing_garbage_collection#Stop-the-world_vs._incremental_vs._concurrent>`_, `shared heap <https://en.wikipedia.org/wiki/Heap_(programming)>`_.
- ``--gc:regions`` `Stack <https://en.wikipedia.org/wiki/Memory_management#Stack_allocation>`_ based garbage collector.
- ``--gc:none`` No garbage collector.
The same Nim code can be compiled to use any of the garbage collectors;
the Nim syntax generally will not change from one garbage collector to another.
No garbage collector is used for `JavaScript and NodeJS
<backends.html#backends-the-javascript-target>`_ compilation targets.
`NimScript <nims.html>`_ target uses Nim VM garbage collector.
If you are new to Nim and just starting, the default garbage collector is balanced to fit most common use cases.

View File

@@ -54,53 +54,52 @@ identOrLiteral = generalizedLit | symbol | literal
| castExpr
tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
| doBlocks
primarySuffix = '(' (exprColonEqExpr comma?)* ')'
| '.' optInd symbol generalizedLit?
| '[' optInd indexExprList optPar ']'
| '{' optInd indexExprList optPar '}'
| '[' optInd exprColonEqExprList optPar ']'
| '{' optInd exprColonEqExprList optPar '}'
| &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
condExpr = expr colcom expr optInd
('elif' expr colcom expr optInd)*
'else' colcom expr
ifExpr = 'if' condExpr
whenExpr = 'when' condExpr
pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
identVis = symbol opr? # postfix position
identVisDot = symbol '.' optInd symbol opr?
pragma = '{.' optInd (exprColonEqExpr comma?)* optPar ('.}' | '}')
identVis = symbol OPR? # postfix position
identVisDot = symbol '.' optInd symbol OPR?
identWithPragma = identVis pragma?
identWithPragmaDot = identVisDot pragma?
declColonEquals = identWithPragma (comma identWithPragma)* comma?
(':' optInd typeDesc)? ('=' optInd expr)?
identColonEquals = ident (comma ident)* comma?
identColonEquals = IDENT (comma IDENT)* comma?
(':' optInd typeDesc)? ('=' optInd expr)?)
inlTupleDecl = 'tuple'
[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
'[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
extTupleDecl = 'tuple'
COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
tupleClass = 'tuple'
paramList = '(' declColonEquals ^* (comma/semicolon) ')'
paramListArrow = paramList? ('->' optInd typeDesc)?
paramListColon = paramList? (':' optInd typeDesc)?
doBlock = 'do' paramListArrow pragmas? colcom stmt
procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
doBlock = 'do' paramListArrow pragma? colcom stmt
procExpr = 'proc' paramListColon pragma? ('=' COMMENT? stmt)?
distinct = 'distinct' optInd typeDesc
forStmt = 'for' (identWithPragma ^+ comma) 'in' expr colcom stmt
forExpr = forStmt
expr = (blockExpr
| ifExpr
| whenExpr
| caseExpr
| forExpr
| caseStmt
| forExpr
| tryExpr)
/ simpleExpr
typeKeyw = 'var' | 'out' | 'ref' | 'ptr' | 'shared' | 'tuple'
| 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
primary = typeKeyw typeDescK
primary = typeKeyw optInd typeDesc
/ prefixOperator* identOrLiteral primarySuffix*
/ 'bind' primary
typeDesc = simpleExpr
typeDefAux = simpleExpr
typeDesc = simpleExpr ('not' expr)?
typeDefAux = simpleExpr ('not' expr)?
| 'concept' typeClass
postExprBlocks = ':' stmt? ( IND{=} doBlock
| IND{=} 'of' exprList ':' stmt
@@ -110,14 +109,16 @@ postExprBlocks = ':' stmt? ( IND{=} doBlock
exprStmt = simpleExpr
(( '=' optInd expr colonBody? )
/ ( expr ^+ comma
doBlocks
/ macroColon
postExprBlocks
))?
importStmt = 'import' optInd expr
((comma expr)*
/ 'except' optInd (expr ^+ comma))
exportStmt = 'export' optInd expr
((comma expr)*
/ 'except' optInd (expr ^+ comma))
includeStmt = 'include' optInd expr ^+ comma
fromStmt = 'from' moduleName 'import' optInd expr (comma expr)*
fromStmt = 'from' expr 'import' optInd expr (comma expr)*
returnStmt = 'return' optInd expr?
raiseStmt = 'raise' optInd expr?
yieldStmt = 'yield' optInd expr?
@@ -157,9 +158,8 @@ indAndComment = (IND{>} COMMENT)? | COMMENT?
routine = optInd identVis pattern? genericParamList?
paramListColon pragma? ('=' COMMENT? stmt)? indAndComment
commentStmt = COMMENT
section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
constant = identWithPragma (colon typeDesc)? '=' optInd expr indAndComment
enum = 'enum' optInd (symbol optInd ('=' optInd expr COMMENT?)? comma?)+
section(RULE) = COMMENT? RULE / (IND{>} (RULE / COMMENT)^+IND{=} DED)
enum = 'enum' optInd (symbol pragma? optInd ('=' optInd expr COMMENT?)? comma?)+
objectWhen = 'when' expr colcom objectPart COMMENT?
('elif' expr colcom objectPart COMMENT?)*
('else' colcom objectPart COMMENT?)?
@@ -177,10 +177,12 @@ typeClassParam = ('var' | 'out')? symbol
typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
&IND{>} stmt
typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
indAndComment? / identVisDot genericParamList? pragma '=' optInd typeDefAux
indAndComment?
varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
colonBody = colcom stmt doBlocks?
colonBody = colcom stmt postExprBlocks?
variable = (varTuple / identColonEquals) colonBody? indAndComment
constant = (varTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
bindStmt = 'bind' optInd qualifiedIdent ^+ comma
mixinStmt = 'mixin' optInd qualifiedIdent ^+ comma
pragmaStmt = pragma (':' COMMENT? stmt)?

View File

@@ -124,9 +124,9 @@ separators!).
The typical usage scenario for this option is to call it after the
user has typed the dot character for `the object oriented call
syntax <tut2.html#method-call-syntax>`_. Idetools will try to return
the suggestions sorted first by scope (from innermost to outermost)
and then by item name.
syntax <tut2.html#object-oriented-programming-method-call-syntax>`_.
Idetools will try to return the suggestions sorted first by scope
(from innermost to outermost) and then by item name.
Invocation context
@@ -359,7 +359,8 @@ defined, since at that point in the file the parser hasn't processed
the full line yet. The signature will be returned complete in
posterior instances of the method.
Methods imply `dynamic dispatch <tut2.html#dynamic-dispatch>`_ and
Methods imply `dynamic dispatch
<tut2.html#object-oriented-programming-dynamic-dispatch>`_ and
idetools performs a static analysis on the code. For this reason
idetools may not return the definition of the correct method you
are querying because it may be impossible to know until the code

View File

@@ -216,7 +216,7 @@ The solution is to **re-play** the module's top level statements.
This solves the problem without having to special case the logic
that fills the internal seqs which are affected by the pragmas.
In fact, this decribes how the AST should be stored in the database,
In fact, this describes how the AST should be stored in the database,
as a "shallow" tree. Let's assume we compile module ``m`` with the
following contents:
@@ -667,3 +667,91 @@ 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``!
Integer literals:
-----------------
In Nim, there is a redundant way to specify the type of an
integer literal. First of all, it should be unsurprising that every
node has a node kind. The node of an integer literal can be any of the
following values:
nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit,
nkUIntLit, nkUInt8Lit, nkUInt16Lit, nkUInt32Lit, nkUInt64Lit
On top of that, there is also the `typ` field for the type. It the
kind of the `typ` field can be one of the following ones, and it
should be matching the literal kind:
tyInt, tyInt8, tyInt16, tyInt32, tyInt64, tyUInt, tyUInt8,
tyUInt16, tyUInt32, tyUInt64
Then there is also the integer literal type. This is a specific type
that is implicitly convertible into the requested type if the
requested type can hold the value. For this to work, the type needs to
know the concrete value of the literal. For example an expression
`321` will be of type `int literal(321)`. This type is implicitly
convertible to all integer types and ranges that contain the value
`321`. That would be all builtin integer types except `uint8` and
`int8` where `321` would be out of range. When this literal type is
assigned to a new `var` or `let` variable, it's type will be resolved
to just `int`, not `int literal(321)` unlike constants. A constant
keeps the full `int literal(321)` type. Here is an example where that
difference matters.
.. code-block:: nim
proc foo(arg: int8) =
echo "def"
const tmp1 = 123
foo(tmp1) # OK
let tmp2 = 123
foo(tmp2) # Error
In a context with multiple overloads, the integer literal kind will
always prefer the `int` type over all other types. If none of the
overloads is of type `int`, then there will be an error because of
ambiguity.
.. code-block:: nim
proc foo(arg: int) =
echo "abc"
proc foo(arg: int8) =
echo "def"
foo(123) # output: abc
proc bar(arg: int16) =
echo "abc"
proc bar(arg: int8) =
echo "def"
bar(123) # Error ambiguous call
In the compiler these integer literal types are represented with the
node kind `nkIntLit`, type kind `tyInt` and the member `n` of the type
pointing back to the integer literal node in the ast containing the
integer value. These are the properties that hold true for integer
literal types.
n.kind == nkIntLit
n.typ.kind == tyInt
n.typ.n == n
Other literal types, such as `uint literal(123)` that would
automatically convert to other integer types, but prefers to
become a `uint` are not part of the Nim language.
In an unchecked AST, the `typ` field is nil. The type checker will set
the `typ` field accordingly to the node kind. Nodes of kind `nkIntLit`
will get the integer literal type (e.g. `int literal(123)`). Nodes of
kind `nkUIntLit` will get type `uint` (kind `tyUint`), etc.
This also means that it is not possible to write a literal in an
unchecked AST that will after sem checking just be of type `int` and
not implicitly convertible to other integer types. This only works for
all integer types that are not `int`.

View File

@@ -40,14 +40,15 @@ options:
After compilation is finished you will hopefully end up with the nim
compiler in the ``bin`` directory. You can add Nim's ``bin`` directory to
your ``$PATH`` or use the `install command`_ to place it where it will be
your ``$PATH`` or use the install command to place it where it will be
found.
csource command
---------------
The `csource`:idx: command builds the C sources for installation. It accepts
the same options as you would pass to the `boot command`_.
the same options as you would pass to the `boot command
<#commands-boot-command>`_.
temp command
------------
@@ -55,7 +56,7 @@ temp command
The temp command builds the Nim compiler but with a different final name
(``nim_temp``), so it doesn't overwrite your normal compiler. You can use
this command to test different options, the same you would issue for the `boot
command`_.
command <#commands-boot-command>`_.
test command
------------

View File

@@ -208,6 +208,7 @@ Generic Operating System Services
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.
See `packaging <packaging.html>`_ for hints on distributing Nim using OS packages.
* `dynlib <dynlib.html>`_
This module implements the ability to access symbols from shared libraries.
@@ -248,7 +249,7 @@ Math libraries
* `fenv <fenv.html>`_
Floating-point environment. Handling of floating-point rounding and
exceptions (overflow, zero-devide, etc.).
exceptions (overflow, zero-divide, etc.).
* `math <math.html>`_
Mathematical operations like cosine, square root.
@@ -329,7 +330,7 @@ Threading
---------
* `threadpool <threadpool.html>`_
Implements Nim's `spawn <manual.html#parallel-amp-spawn>`_.
Implements Nim's `spawn <manual_experimental.html#parallel-amp-spawn>`_.
Parsers
@@ -441,8 +442,7 @@ Miscellaneous
browser.
* `colors <colors.html>`_
This module implements color handling for Nim. It is used by
the ``graphics`` module.
This module implements color handling for Nim.
* `coro <coro.html>`_
This module implements experimental coroutines in Nim.
@@ -450,9 +450,6 @@ Miscellaneous
* `logging <logging.html>`_
This module implements a simple logger.
* `quitprocs <quitprocs>`_
Better implementation of ``system.addQuitProc``.
* `segfaults <segfaults.html>`_
Turns access violations or segfaults into a ``NilAccessError`` exception.
@@ -531,7 +528,8 @@ UNIX specific
* `posix <posix.html>`_
Contains a wrapper for the POSIX standard.
* `posix_utils <posix_utils.html>`_
Contains helpers for the POSIX standard or specialized for Linux and BSDs.
Regular expressions
-------------------

View File

@@ -552,6 +552,9 @@ following characters::
@ $ ~ & % |
! ? ^ . : \
(The grammar uses the terminal OPR to refer to operator symbols as
defined here.)
These keywords are also operators:
``and or not xor shl shr div mod in notin is isnot of``.
@@ -1479,7 +1482,8 @@ order. The *names* of the fields also have to be identical.
The assignment operator for tuples copies each component.
The default assignment operator for objects copies each component. Overloading
of the assignment operator is described in `type-bound-operations-operator`_.
of the assignment operator is described `here
<manual_experimental.html#type-bound-operations>`_.
.. code-block:: nim
@@ -1640,7 +1644,7 @@ object branch, the initialization is considered valid. This analysis only works
for immutable discriminators of an ordinal type and disregards ``elif``
branches. For discriminator values with a ``range`` type, the compiler
checks if the entire range of possible values for the discriminator value is
valid for the choosen object branch.
valid for the chosen object branch.
A small example:
@@ -2129,7 +2133,7 @@ conversions from ``string`` to ``SQL`` are allowed:
Now we have compile-time checking against SQL injection attacks. Since
``"".SQL`` is transformed to ``SQL("")`` no new syntax is needed for nice
looking ``SQL`` string literals. The hypothetical ``SQL`` type actually
exists in the library as the `TSqlQuery type <db_sqlite.html#TSqlQuery>`_ of
exists in the library as the `SqlQuery type <db_common.html#SqlQuery>`_ of
modules like `db_sqlite <db_sqlite.html>`_.
@@ -2640,7 +2644,7 @@ tuple[x: A, y: B, ...] (default(A), default(B), ...)
(analogous for objects)
array[0..., T] [default(T), ...]
range[T] default(T); this may be out of the valid range
T = enum cast[T](0); this may be an invalid value
T = enum cast[T]\(0); this may be an invalid value
============================ ==============================================
@@ -3184,6 +3188,7 @@ has lots of advantages:
Type conversions
----------------
Syntactically a `type conversion` is like a procedure call, but a
type name replaces the procedure name. A type conversion is always
safe in the sense that a failure to convert a type to another
@@ -3203,6 +3208,19 @@ A type conversion can also be used to disambiguate overloaded routines:
let procVar = (proc(x: string))(p)
procVar("a")
Since operations on unsigned numbers wrap around and are unchecked so are
type conversion to unsigned integers and between unsigned integers. The
rationale for this is mostly better interoperability with the C Programming
language when algorithms are ported from C to Nim.
Exception: Values that are converted to an unsigned type at compile time
are checked so that code like ``byte(-1)`` does not compile.
**Note**: Historically the operations
were unchecked and the conversions were sometimes checked but starting with
the revision 1.0.4 of this document and the language implementation the
conversions too are now *always unchecked*.
Type casts
----------
@@ -3422,14 +3440,14 @@ different; for this a special setter syntax is needed:
## setter of hostAddr.
## This accesses the 'host' field and is not a recursive call to
## ``host=`` because the builtin dot access is preferred if it is
## avaliable:
## available:
s.host = value
proc host*(s: Socket): int {.inline.} =
## getter of hostAddr
## This accesses the 'host' field and is not a recursive call to
## ``host`` because the builtin dot access is preferred if it is
## avaliable:
## available:
s.host
.. code-block:: nim
@@ -3481,8 +3499,8 @@ more argument in this case:
assert x == y
The command invocation syntax also can't have complex expressions as arguments.
For example: (`anonymous procs`_), ``if``, ``case`` or ``try``.
Function calls with no arguments still needs () to
For example: (`anonymous procs <#procedures-anonymous-procs>`_), ``if``,
``case`` or ``try``. Function calls with no arguments still needs () to
distinguish between a call and the function itself as a first class value.
@@ -3502,14 +3520,14 @@ Creating closures in loops
~~~~~~~~~~~~~~~~~~~~~~~~~~
Since closures capture local variables by reference it is often not wanted
behavior inside loop bodies. See `closureScope <system.html#closureScope>`_
for details on how to change this behavior.
behavior inside loop bodies. See `closureScope
<system.html#closureScope.t,untyped>`_ for details on how to change this behavior.
Anonymous Procs
---------------
Procs can also be treated as expressions, in which case it's allowed to omit
the proc's name.
Unnamed procedures can be used as lambda expressions to pass into other
procedures:
.. code-block:: nim
var cities = @["Frankfurt", "Tokyo", "New York", "Kyiv"]
@@ -3519,7 +3537,9 @@ the proc's name.
Procs as expressions can appear both as nested procs and inside top level
executable code.
executable code. The `sugar <sugar.html>`_ module contains the `=>` macro
which enables a more succinct syntax for anonymous procedures resembling
lambdas as they are in languages like JavaScript, C#, etc.
Func
@@ -3659,7 +3679,7 @@ a syntax like:
proc foo(other: Y; container: var X): var T from container
Here ``var T from container`` explicitly exposes that the
location is deviated from the second parameter (called
location is derived from the second parameter (called
'container' in this case). The syntax ``var T from p`` specifies a type
``varTy[T, 2]`` which is incompatible with ``varTy[T, 1]``.
@@ -3691,7 +3711,7 @@ type.
method eval(e: Expression): int {.base.} =
# override this base method
quit "to override!"
raise newException(CatchableError, "Method without implementation override")
method eval(e: Literal): int = return e.x
@@ -4109,6 +4129,23 @@ error message from ``e``, and for such situations it is enough to use
except:
echo getCurrentExceptionMsg()
Custom exceptions
-----------------
Is it possible to create custom exceptions. These make it easy to distinguish between exceptions raised by nim and those from your own code.
A custom exception is a custom type:
.. code-block:: nim
type
LoadError* = object of Exception
Ending the custom exception's name with ``Error`` is recommended.
Custom exceptions can be raised like any others, e.g.:
.. code-block:: nim
raise newException(LoadError, "Failed to load data")
Defer statement
---------------
@@ -5370,7 +5407,7 @@ expression by coercing it to a corresponding ``static`` type:
echo static(fac(5)), " ", static[bool](16.isPowerOfTwo)
The complier will report any failure to evaluate the expression or a
The compiler will report any failure to evaluate the expression or a
possible type mismatch error.
typedesc[T]
@@ -5382,7 +5419,7 @@ all values must have a type, ``typedesc`` is considered their special type.
``typedesc`` acts like a generic type. For instance, the type of the symbol
``int`` is ``typedesc[int]``. Just like with regular generic types, when the
generic param is ommited, ``typedesc`` denotes the type class of all types.
generic param is omitted, ``typedesc`` denotes the type class of all types.
As a syntactic convenience, you can also use ``typedesc`` as a modifier.
Procs featuring ``typedesc`` params are considered implicitly generic.
@@ -5890,9 +5927,9 @@ or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static
error to mark a proc/iterator to have no side effect if the compiler cannot
verify this.
As a special semantic rule, the built-in `debugEcho <system.html#debugEcho>`_
pretends to be free of side effects, so that it can be used for debugging
routines marked as ``noSideEffect``.
As a special semantic rule, the built-in `debugEcho
<system.html#debugEcho,varargs[typed,]>`_ pretends to be free of side effects,
so that it can be used for debugging routines marked as ``noSideEffect``.
``func`` is syntactic sugar for a proc with no side effects:
@@ -6163,7 +6200,8 @@ factor.
immediate pragma
----------------
The immediate pragma is obsolete. See `Typed vs untyped parameters`_.
The immediate pragma is obsolete. See `Typed vs untyped parameters
<#templates-typed-vs-untyped-parameters>`_.
compilation option pragmas
@@ -6219,6 +6257,25 @@ but are used to override the settings temporarily. Example:
# ... some code ...
{.pop.} # restore old settings
`push/pop`:idx: can switch on/off some standard library pragmas, example:
.. code-block:: nim
{.push inline.}
proc thisIsInlined(): int = 42
func willBeInlined(): float = 42.0
{.pop.}
proc notInlined(): int = 9
{.push discardable, boundChecks: off, compileTime, noSideEffect, experimental.}
template example(): string = "https://nim-lang.org"
{.pop.}
{.push deprecated, hint[LineTooLong]: off, used, stackTrace: off.}
proc sample(): bool = true
{.pop.}
For third party pragmas it depends on its implementation, but uses the same syntax.
register pragma
---------------
@@ -6326,12 +6383,18 @@ is uncertain (it may be removed any time).
Example:
.. code-block:: nim
import threadpool
{.experimental: "parallel".}
proc threadedEcho(s: string, i: int) =
echo(s, " ", $i)
proc useParallel() =
parallel:
for i in 0..4:
echo "echo in parallel"
spawn threadedEcho("echo in parallel", i)
useParallel()
As a top level statement, the experimental pragma enables a feature for the
@@ -6595,15 +6658,6 @@ The compiler needs to be told to generate C++ (command ``cpp``) for
this to work. The conditional symbol ``cpp`` is defined when the compiler
emits C++ code.
ImportJs pragma
---------------
Similar to the `importcpp pragma for C++ <#foreign-function-interface-importc-pragma>`_,
the ``importjs`` pragma can be used to import Javascript methods or
symbols in general. The generated code then uses the Javascript method
calling syntax: ``obj.method(arg)``.
Namespaces
~~~~~~~~~~
@@ -6786,6 +6840,15 @@ Produces:
std::vector<int>::iterator x;
ImportJs pragma
---------------
Similar to the `importcpp pragma for C++ <#foreign-function-interface-importc-pragma>`_,
the ``importjs`` pragma can be used to import Javascript methods or
symbols in general. The generated code then uses the Javascript method
calling syntax: ``obj.method(arg)``.
ImportObjC pragma
-----------------
Similar to the `importc pragma for C
@@ -7008,7 +7071,7 @@ is not set to C, other pragmas are available:
* `importcpp <manual.html#implementation-specific-pragmas-importcpp-pragma>`_
* `importobjc <manual.html#implementation-specific-pragmas-importobjc-pragma>`_
* `importjs <manul.html#implementation-specific-pragmas-importjs-pragma>`_
* `importjs <manual.html#implementation-specific-pragmas-importjs-pragma>`_
.. code-block:: Nim
proc p(s: cstring) {.importc: "prefix$1".}

View File

@@ -1,15 +1,15 @@
Memory safety for returning by ``var T`` is ensured by a simple borrowing
rule: If ``result`` does not refer to a location pointing to the heap
(that is in ``result = X`` the ``X`` involves a ``ptr`` or ``ref`` access)
then it has to be deviated by the routine's first parameter:
then it has to be derived from the routine's first parameter:
.. code-block:: nim
proc forward[T](x: var T): var T =
result = x # ok, deviated from the first parameter.
result = x # ok, derived from the first parameter.
proc p(param: var int): var int =
var x: int
# we know 'forward' provides a view into the location deviated by
# we know 'forward' provides a view into the location derived from
# its first argument 'x'.
result = forward(x) # Error: location is derived from ``x``
# which is not p's first parameter and lives

View File

@@ -27,7 +27,7 @@ Package level objects
Every Nim module resides in a (nimble) package. An object type can be attached
to the package it resides in. If that is done, the type can be referenced from
other modules as an `incomplete`:idx: object type. This feature allows to
break up recursive type dependencies accross module boundaries. Incomplete
break up recursive type dependencies across module boundaries. Incomplete
object types are always passed ``byref`` and can only be used in pointer like
contexts (``var/ref/ptr IncompleteObject``) in general since the compiler does
not yet know the size of the object. To complete an incomplete object
@@ -203,9 +203,10 @@ useful only when interfacing with imported types having such semantics.
Automatic dereferencing
=======================
If the `experimental mode <#pragmas-experimental-pragma>`_ is active and no other match
is found, the first argument ``a`` is dereferenced automatically if it's a
pointer type and overloading resolution is tried with ``a[]`` instead.
If the `experimental mode <manual.html#pragmas-experimental-pragma>`_ is active
and no other match is found, the first argument ``a`` is dereferenced
automatically if it's a pointer type and overloading resolution is tried
with ``a[]`` instead.
Automatic self insertions
@@ -266,7 +267,7 @@ calls can use the ``do`` keyword:
``do`` is written after the parentheses enclosing the regular proc params.
The proc expression represented by the do block is appended to them.
In calls using the command syntax, the do block will bind to the immediately
preceeding expression, transforming it in a call.
preceding expression, transforming it in a call.
``do`` with parentheses is an anonymous ``proc``; however a ``do`` without
parentheses is just a block of code. The ``do`` notation can be used to
@@ -814,7 +815,7 @@ This mechanism will be used by most data structures that support shared memory
like channels to implement thread safe automatic memory management.
The builtin ``deepCopy`` can even clone closures and their environments. See
the documentation of `spawn`_ for details.
the documentation of `spawn <#parallel-amp-spawn-spawn-statement>`_ for details.
Case statement macros
@@ -1617,7 +1618,7 @@ Aliasing restrictions in parameter passing
==========================================
**Note**: The aliasing restrictions are currently not enforced by the
implementation and need to be fleshed out futher.
implementation and need to be fleshed out further.
"Aliasing" here means that the underlying storage locations overlap in memory
at runtime. An "output parameter" is a parameter of type ``var T``, an input

View File

@@ -114,7 +114,8 @@ Level Description
===== ============================================
0 Minimal output level for the compiler.
1 Displays compilation of all the compiled files, including those imported
by other modules or through the `compile pragma<#compile-pragma>`_.
by other modules or through the `compile pragma
<manual.html#implementation-specific-pragmas-compile-pragma>`_.
This is the default level.
2 Displays compilation statistics, enumerates the dynamic
libraries that will be loaded by the final binary and dumps to
@@ -130,9 +131,10 @@ Compile time symbols
Through the ``-d:x`` or ``--define:x`` switch you can define compile time
symbols for conditional compilation. The defined switches can be checked in
source code with the `when statement <manual.html#when-statement>`_ and
`defined proc <system.html#defined>`_. The typical use of this switch is to
enable builds in release mode (``-d:release``) where optimizations are
source code with the `when statement
<manual.html#statements-and-expressions-when-statement>`_ and
`defined proc <system.html#defined,untyped>`_. The typical use of this switch is
to enable builds in release mode (``-d:release``) where optimizations are
enabled for better performance. Another common use is the ``-d:ssl`` switch to
activate SSL sockets.
@@ -215,7 +217,7 @@ The ``_r`` suffix is used for release builds, ``_d`` is for debug builds.
This makes it easy to delete all generated files.
The ``--nimcache``
`compiler switch <nimc.html#command-line-switches>`_ can be used to
`compiler switch <#compiler-usage-command-line-switches>`_ can be used to
to change the ``nimcache`` directory.
However, the generated C code is not platform independent. C code generated for
@@ -483,7 +485,6 @@ number information are given if the program crashes or an uncaught exception
is raised.
DynlibOverride
==============
@@ -497,14 +498,6 @@ on Linux::
nim c --dynlibOverride:lua --passL:liblua.lib program.nim
Cursor pragma
=============
The ``.cursor`` pragma is a temporary tool for optimization purposes
and this property will be computed by Nim's optimizer eventually. Thus it
remains undocumented.
Backend language options
========================

View File

@@ -105,9 +105,9 @@ completion symbols at some point in the file.
The typical usage scenario for this option is to call it after the
user has typed the dot character for `the object oriented call
syntax <tut2.html#method-call-syntax>`_. Nimsuggest will try to return
the suggestions sorted first by scope (from innermost to outermost)
and then by item name.
syntax <tut2.html#object-oriented-programming-method-call-syntax>`_.
Nimsuggest will try to return the suggestions sorted first by scope
(from innermost to outermost) and then by item name.
Invocation context

View File

@@ -2,6 +2,9 @@
Packaging Nim
=============
This page provide hints on distributing Nim using OS packages.
See `distros <distros.html>`_ for tools to detect Linux distribution at runtime.
Supported architectures
-----------------------

View File

@@ -83,4 +83,4 @@ Note how the set turns enum values into powers of 2.
If using enums and sets with C, use distinct cint.
For interoperability with C see also the
`bitsize pragma <#implementation-specific-pragmas-bitsize-pragma>`_.
`bitsize pragma <manual.html#implementation-specific-pragmas-bitsize-pragma>`_.

View File

@@ -20,7 +20,7 @@ The standard distribution ships with the following tools:
- | `C2nim <https://github.com/nim-lang/c2nim/blob/master/doc/c2nim.rst>`_
| C to Nim source converter. Translates C header files to Nim.
- | `niminst <https://nim-lang.org/docs/niminst.html>`_
- | `niminst <niminst.html>`_
| niminst is a tool to generate an installer for a Nim program.
- | `nimgrep <nimgrep.html>`_
@@ -29,3 +29,11 @@ The standard distribution ships with the following tools:
- | nimpretty
| ``nimpretty`` is a Nim source code beautifier,
to format code according to the official style guide.
- | testament
| ``testament`` is an advanced automatic *unittests runner* for Nim tests,
is used for the development of Nim itself, offers process isolation for your tests,
it can generate statistics about test cases, supports multiple targets (C, JS, etc),
`simulated Dry-Runs <https://en.wikipedia.org/wiki/Dry_run_(testing)>`_,
has logging, can generate HTML reports, skip tests from a file and more,
so can be useful to run your tests, even the most complex ones.

View File

@@ -67,8 +67,8 @@ done with spaces only, tabulators are not allowed.
String literals are enclosed in double quotes. The ``var`` statement declares
a new variable named ``name`` of type ``string`` with the value that is
returned by the `readLine <system.html#readLine,File>`_ procedure. Since the
compiler knows that `readLine <system.html#readLine,File>`_ returns a string,
returned by the `readLine <io.html#readLine,File>`_ procedure. Since the
compiler knows that `readLine <io.html#readLine,File>`_ returns a string,
you can leave out the type in the declaration (this is called `local type
inference`:idx:). So this will work too:
@@ -80,7 +80,7 @@ Note that this is basically the only form of type inference that exists in
Nim: it is a good compromise between brevity and readability.
The "hello world" program contains several identifiers that are already known
to the compiler: ``echo``, `readLine <system.html#readLine,File>`_, etc.
to the compiler: ``echo``, `readLine <io.html#readLine,File>`_, etc.
These built-ins are declared in the system_ module which is implicitly
imported by any other module.
@@ -142,15 +142,6 @@ comments can also be nested.
]#
]#
You can also use the `discard statement <#procedures-discard-statement>`_ together with *long string
literals* to create block comments:
.. code-block:: nim
:test: "nim c $1"
discard """ You can have any Nim code text commented
out inside this with no indentation restrictions.
yes("May I ask a pointless question?") """
Numbers
-------
@@ -335,10 +326,11 @@ the compiler that for every other value nothing should be done:
of 3, 8: echo "The number is 3 or 8"
else: discard
The empty `discard statement`_ is a *do nothing* statement. The compiler knows
that a case statement with an else part cannot fail and thus the error
disappears. Note that it is impossible to cover all possible string values:
that is why string cases always need an ``else`` branch.
The empty `discard statement <#procedures-discard-statement>`_ is a *do
nothing* statement. The compiler knows that a case statement with an else part
cannot fail and thus the error disappears. Note that it is impossible to cover
all possible string values: that is why string cases always need an ``else``
branch.
In general the case statement is used for subrange types or enumerations where
it is of great help that the compiler checks that you covered any possible
@@ -368,8 +360,8 @@ For statement
-------------
The ``for`` statement is a construct to loop over any element an *iterator*
provides. The example uses the built-in `countup <system.html#countup>`_
iterator:
provides. The example uses the built-in `countup
<system.html#countup.i,T,T,Positive>`_ iterator:
.. code-block:: nim
:test: "nim c $1"
@@ -380,8 +372,8 @@ iterator:
The variable ``i`` is implicitly declared by the
``for`` loop and has the type ``int``, because that is what `countup
<system.html#countup>`_ returns. ``i`` runs through the values 1, 2, .., 10.
Each value is ``echo``-ed. This code does the same:
<system.html#countup.i,T,T,Positive>`_ returns. ``i`` runs through the values
1, 2, .., 10. Each value is ``echo``-ed. This code does the same:
.. code-block:: nim
echo "Counting to 10: "
@@ -400,7 +392,7 @@ Counting down can be achieved as easily (but is less often needed):
# --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
Since counting up occurs so often in programs, Nim also has a `..
<system.html#...i,S,T>`_ iterator that does the same:
<system.html#...i,T,T>`_ iterator that does the same:
.. code-block:: nim
for i in 1..10:
@@ -579,10 +571,10 @@ an expression is allowed:
Procedures
==========
To define new commands like `echo <system.html#echo>`_ and `readLine
<system.html#readLine,File>`_ in the examples, the concept of a `procedure`
is needed. (Some languages call them *methods* or *functions*.) In Nim new
procedures are defined with the ``proc`` keyword:
To define new commands like `echo <system.html#echo,varargs[typed,]>`_
and `readLine <io.html#readLine,File>`_ in the examples, the concept of a
`procedure` is needed. (Some languages call them *methods* or *functions*.)
In Nim new procedures are defined with the ``proc`` keyword:
.. code-block:: nim
:test: "nim c $1"
@@ -653,7 +645,7 @@ is possible, and actually an idiom:
:test: "nim c $1"
proc printSeq(s: seq, nprinted: int = -1) =
var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len)
for i in 0 .. <nprinted:
for i in 0 ..< nprinted:
echo s[i]
If the procedure needs to modify the argument for the
@@ -697,9 +689,6 @@ been declared with the ``discardable`` pragma:
p(3, 4) # now valid
The ``discard`` statement can also be used to create block comments as
described in the `Comments`_ section.
Named arguments
---------------
@@ -762,7 +751,7 @@ Nim provides the ability to overload procedures similar to C++:
echo toString(13) # calls the toString(x: int) proc
echo toString(true) # calls the toString(x: bool) proc
(Note that ``toString`` is usually the `$ <system.html#$>`_ operator in
(Note that ``toString`` is usually the `$ <dollars.html>`_ operator in
Nim.) The compiler chooses the most appropriate proc for the ``toString``
calls. How this overloading resolution algorithm works exactly is not
discussed here (it will be specified in the manual soon). However, it does
@@ -854,8 +843,8 @@ Let's return to the simple counting example:
for i in countup(1, 10):
echo i
Can a `countup <system.html#countup>`_ proc be written that supports this
loop? Lets try:
Can a `countup <system.html#countup.i,T,T,Positive>`_ proc be written that
supports this loop? Lets try:
.. code-block:: nim
proc countup(a, b: int): int =
@@ -1019,8 +1008,8 @@ floats and follow the IEEE-754 standard.
Automatic type conversion in expressions with different kinds of floating
point types is performed: the smaller type is converted to the larger. Integer
types are **not** converted to floating point types automatically, nor vice
versa. Use the `toInt <system.html#toInt>`_ and `toFloat <system.html#toFloat>`_
procs for these conversions.
versa. Use the `toInt <system.html#toInt,float>`_ and
`toFloat <system.html#toFloat,int>`_ procs for these conversions.
Type Conversion
@@ -1040,13 +1029,13 @@ type as a function:
Internal type representation
============================
As mentioned earlier, the built-in `$ <system.html#$>`_ (stringify) operator
As mentioned earlier, the built-in `$ <dollars.html>`_ (stringify) operator
turns any basic type into a string, which you can then print to the console
using the ``echo`` proc. However, advanced types, and your own custom types,
won't work with the ``$`` operator until you define it for them.
Sometimes you just want to debug the current value of a complex type without
having to write its ``$`` operator. You can use then the `repr
<system.html#repr>`_ proc which works with any type and even complex data
<system.html#repr,T>`_ proc which works with any type and even complex data
graphs with cycles. The following example shows that even for basic types
there is a difference between the ``$`` and ``repr`` outputs:
@@ -1136,9 +1125,9 @@ Operation Comment
``pred(x, n)`` returns the `n`'th predecessor of `x`
----------------- --------------------------------------------------------
The `inc <system.html#inc>`_, `dec <system.html#dec>`_, `succ
<system.html#succ>`_ and `pred <system.html#pred>`_ operations can fail by
raising an `EOutOfRange` or `EOverflow` exception. (If the code has been
The `inc <system.html#inc,T,int>`_, `dec <system.html#dec,T,int>`_, `succ
<system.html#succ,T,int>`_ and `pred <system.html#pred,T,int>`_ operations can
fail by raising an `EOutOfRange` or `EOverflow` exception. (If the code has been
compiled with the proper runtime checks turned on.)
@@ -1159,8 +1148,8 @@ compile-time or runtime error. Assignments from the base type to one of its
subrange types (and vice versa) are allowed.
The ``system`` module defines the important `Natural <system.html#Natural>`_
type as ``range[0..high(int)]`` (`high <system.html#high>`_ returns the
maximal value). Other programming languages may suggest the use of unsigned
type as ``range[0..high(int)]`` (`high <system.html#high,typedesc[T]>`_ returns
the maximal value). Other programming languages may suggest the use of unsigned
integers for natural numbers. This is often **unwise**: you don't want unsigned
arithmetic (which wraps around) just because the numbers cannot be negative.
Nim's ``Natural`` type helps to avoid this common programming error.
@@ -1198,8 +1187,9 @@ Arrays are value types, like any other Nim type. The assignment operator
copies the whole array contents.
The built-in `len <system.html#len,TOpenArray>`_ proc returns the array's
length. `low(a) <system.html#low>`_ returns the lowest valid index for the
array `a` and `high(a) <system.html#high>`_ the highest valid index.
length. `low(a) <system.html#low,openArray[T]>`_ returns the lowest valid index
for the array `a` and `high(a) <system.html#high,openArray[T]>`_ the highest
valid index.
.. code-block:: nim
:test: "nim c $1"
@@ -1274,9 +1264,9 @@ during runtime (like strings). Since sequences are resizable they are always
allocated on the heap and garbage collected.
Sequences are always indexed with an ``int`` starting at position 0. The `len
<system.html#len,seq[T]>`_, `low <system.html#low>`_ and `high
<system.html#high>`_ operations are available for sequences too. The notation
``x[i]`` can be used to access the i-th element of ``x``.
<system.html#len,seq[T]>`_, `low <system.html#low,openArray[T]>`_ and `high
<system.html#high,openArray[T]>`_ operations are available for sequences too.
The notation ``x[i]`` can be used to access the i-th element of ``x``.
Sequences can be constructed by the array constructor ``[]`` in conjunction
with the array to sequence operator ``@``. Another way to allocate space for
@@ -1327,10 +1317,10 @@ Open arrays
Often fixed size arrays turn out to be too inflexible; procedures should be
able to deal with arrays of different sizes. The `openarray`:idx: type allows
this. Openarrays are always indexed with an ``int`` starting at position 0.
The `len <system.html#len,TOpenArray>`_, `low <system.html#low>`_ and `high
<system.html#high>`_ operations are available for open arrays too. Any array
with a compatible base type can be passed to an openarray parameter, the index
type does not matter.
The `len <system.html#len,TOpenArray>`_, `low <system.html#low,openArray[T]>`_
and `high <system.html#high,openArray[T]>`_ operations are available for open
arrays too. Any array with a compatible base type can be passed to an
openarray parameter, the index type does not matter.
.. code-block:: nim
:test: "nim c $1"
@@ -1386,8 +1376,8 @@ type conversions in this context:
# is transformed by the compiler to:
myWriteln(stdout, [$123, $"abc", $4.0])
In this example `$ <system.html#$>`_ is applied to any argument that is passed
to the parameter ``a``. Note that `$ <system.html#$>`_ applied to strings is a
In this example `$ <dollars.html>`_ is applied to any argument that is passed
to the parameter ``a``. Note that `$ <dollars.html>`_ applied to strings is a
nop.
@@ -1403,7 +1393,7 @@ define operators which accept Slice objects to define ranges.
:test: "nim c $1"
var
a = "Nim is a progamming language"
a = "Nim is a programming language"
b = "Slices are useless."
echo a[7..12] # --> 'a prog'
@@ -1570,8 +1560,8 @@ having the same field types.
Tuples can be *unpacked* during variable assignment (and only then!). This can
be handy to assign directly the fields of the tuples to individually named
variables. An example of this is the `splitFile <os.html#splitFile>`_ proc
from the `os module <os.html>`_ which returns the directory, name and
variables. An example of this is the `splitFile <os.html#splitFile,string>`_
proc from the `os module <os.html>`_ which returns the directory, name and
extension of a path at the same time. For tuple unpacking to work you must
use parentheses around the values you want to assign the unpacking to,
otherwise you will be assigning the same value to all the individual

View File

@@ -28,7 +28,7 @@ Examples of things that can be implemented in macros:
* 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``
``3*a*pow(x,2) + 2*b*x + c``
Macro Arguments

View File

@@ -169,6 +169,10 @@ proc bundleNimsuggest(args: string) =
proc buildVccTool(args: string) =
nimCompileFold("Compile Vcc", "tools/vccexe/vccexe.nim ", options = args)
proc bundleNimpretty(args: string) =
nimCompileFold("Compile nimpretty", "nimpretty/nimpretty.nim",
options = "-d:release " & args)
proc bundleWinTools(args: string) =
nimCompile("tools/finish.nim", outputDir = "", options = args)
@@ -185,6 +189,7 @@ proc bundleWinTools(args: string) =
proc zip(latest: bool; args: string) =
bundleNimbleExe(latest, args)
bundleNimsuggest(args)
bundleNimpretty(args)
bundleWinTools(args)
nimexec("cc -r $2 --var:version=$1 --var:mingw=none --main:compiler/nim.nim scripts compiler/installer.ini" %
[VersionAsString, compileNimInst])
@@ -214,8 +219,7 @@ proc buildTools(args: string = "") =
nimCompileFold("Compile nimgrep", "tools/nimgrep.nim",
options = "-d:release " & args)
when defined(windows): buildVccTool(args)
nimCompileFold("Compile nimpretty", "nimpretty/nimpretty.nim",
options = "-d:release " & args)
bundleNimpretty(args)
nimCompileFold("Compile nimfind", "tools/nimfind.nim",
options = "-d:release " & args)
nimCompileFold("Compile testament", "testament/testament.nim",
@@ -316,8 +320,8 @@ proc boot(args: string) =
# jsonbuild then uses the $project.json file to build the Nim binary.
exec "$# $# $# $# --nimcache:$# --compileOnly compiler" / "nim.nim" %
[nimi, bootOptions, extraOption, args, smartNimcache]
exec "$# jsonscript --nimcache:$# compiler" / "nim.nim" %
[nimi, smartNimcache]
exec "$# jsonscript $# --nimcache:$# compiler" / "nim.nim" %
[nimi, args, smartNimcache]
if sameFileContent(output, i.thVersion):
copyExe(output, finalDest)

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