Compare commits

..

762 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
narimiran
f7a8fc46c0 Revert "improvements for httpcore (#12228)"
This reverts commit b865c2a54b.
2019-09-23 19:06:55 +02:00
narimiran
5b43c98897 version 1.0 2019-09-23 14:42:19 +02:00
Andreas Rumpf
f388817a79 update the Nimble version we ship with Nim (#12236) 2019-09-23 14:24:36 +02:00
Andreas Rumpf
b865c2a54b improvements for httpcore (#12228)
* improvements for httpcore
* further improvements, now stable API but needs extensions later on
2019-09-23 12:38:35 +02:00
Ray Imber
6e681b546f fixes #9026 adds a readLineImpl to streams so that FileStreams can be fast (#12234) 2019-09-23 08:25:26 +02:00
PMunch
2565d3d102 Fix issue with long wait for passed timer [bugfix] (#12221)
* Fix issue with long wait for passed timer [bugfix]

This fixes a small issue where a timer that had been completed while
code executed would still wait for more events before being considered
completed. This would in some scenarios incur a 500ms delay to the
completion of a timer.

* Refactor logic into

* Add test case based on original issue

* Use longer timeouts to be more lenient in checking

* Revert to short timeouts, but widen the accepted range

* Widen accepted range further, it is meant to check for a 500ms delay after all

* Increase poll timeout to make it easier to detect mistakes
2019-09-22 07:24:14 +02:00
Andreas Rumpf
39185b46ca living in unix-land, eye to eye, where nothing ever works; fixes #12226 2019-09-21 19:07:25 +02:00
Andreas Rumpf
e0f2b3ba8f documentation updates 2019-09-21 11:53:09 +02:00
Andreas Rumpf
b04ef2973d cleanup importjs implementation 2019-09-21 11:19:09 +02:00
cooldome
be82d11576 fixes #12224 (#12225)
* fixes #12224

* improve test
2019-09-21 06:45:27 +02:00
Andreas Rumpf
c2fced129f makes tests green again 2019-09-21 06:43:37 +02:00
Araq
5abe880469 last stdlib cleanups 2019-09-21 06:43:37 +02:00
Araq
9776f926a2 htmlgen update; don't use deprecated callsite feature 2019-09-21 06:43:37 +02:00
Araq
908b553215 asyndispatch: removed deprecated setEvent proc 2019-09-21 06:43:37 +02:00
Araq
96b3bae99b json: removed deprecatedGet pragma 2019-09-21 06:43:37 +02:00
Araq
a404ec540a updated lib.rst and added some useful missing modules 2019-09-21 06:43:37 +02:00
Araq
dea9e38d26 removed the deprecatedGet pragma 2019-09-21 06:43:37 +02:00
Araq
c623ab62cc updated comment in ast.nim 2019-09-21 06:43:37 +02:00
Araq
f576df2bcc smtp: renamed starttls to startTls 2019-09-21 06:43:37 +02:00
Araq
05e80e1cda lib\pure\htmlgen.nim
avoid callsite for htmlgen
2019-09-21 06:43:37 +02:00
Araq
7839658323 mark events.nim as unstable 2019-09-21 06:43:37 +02:00
Araq
1b20f768c7 lib.rst cleanups and reorderings 2019-09-21 06:43:37 +02:00
Arne Döring
38ab51c445 importjs symbol (#12218)
* importjs symbol
* importjs warning message, minor warning fixes
2019-09-20 20:26:30 +02:00
Andreas Rumpf
7bc5bf8334 consistent floating point output (#12219)
* unify float printing
* makes tests green
2019-09-20 10:41:40 +02:00
Araq
04c803d6df expose more fields of TNimType 2019-09-19 20:54:17 +02:00
Andreas Rumpf
162d74db91 fixes #10981; fixes #7261 (#12217) 2019-09-19 14:34:56 +02:00
treeform
363d0ada50 Update Android and iOS cross compile docs. (#12215)
* Update Cross compilation, add noMain section.

* Small world update, note about XCode clean.
2019-09-19 13:22:07 +02:00
treeform
a948deebb3 Add --os:ios switch and docs. (#12204) 2019-09-18 20:03:51 +02:00
Arne Döring
188ce5f3ee add nodeId proc to macros (#11456)
* add nodeId proc to macros

* add doc comment.

* fix typo
2019-09-18 20:02:30 +02:00
Araq
f8000d4ba1 fixes #12186 2019-09-18 12:16:52 +02:00
Araq
48537fec81 fixes #12209 2019-09-18 12:16:52 +02:00
Arne Döring
638a4d9d9f rename cast opcodes, fix for 32bit cast, fix python pretty printer (#12207) 2019-09-18 09:04:37 +02:00
Vitor Oliveira
93f74e4f93 Fix typo (#12210) [ci skip] 2019-09-18 07:17:38 +02:00
treeform
910ed5888e Add -d:androidNDK to fix echo on Android NDK builds. (#12203)
* Add -d:echoToAndroidLog to fix echo.

* Change to androidNDK and add docs.

* Some word changes to docs.
2019-09-17 23:00:06 +02:00
Miran
618316beb9 fix #12200, cannot 'inc' CountTable by a negative value (#12208)
* fix #12200, cannot 'inc' CountTable by a negative value

* use Positive
2019-09-17 21:29:25 +02:00
Araq
ea8a049af3 fixes the testcase 2019-09-17 15:15:12 +02:00
Araq
c9f3a8b269 added a testcase for #12195; testament now supports a 'timeout' spec field 2019-09-17 15:15:12 +02:00
Araq
f1b7c0494e fixes #12195 2019-09-17 15:15:12 +02:00
Andreas Rumpf
62aa1a3cfe gc:destructors progress 2019-09-16 23:54:31 +02:00
Andreas Rumpf
77c6425e65 gc_common: typo 2019-09-16 23:54:31 +02:00
Andreas Rumpf
754531fff3 make --useVersion's documentation reflect reality 2019-09-16 23:54:31 +02:00
Andreas Rumpf
059a16b34d fixes #12193 (#12199) 2019-09-16 15:38:07 +02:00
Andreas Rumpf
2a59f499e9 some gc:destructors progress 2019-09-16 13:54:58 +02:00
Araq
6c487a6309 fixes #12196 2019-09-16 12:12:44 +02:00
Araq
8b4c17a140 better implementation 2019-09-16 12:12:44 +02:00
Andreas Rumpf
3f87453981 fixes a weird quote do regression 2019-09-16 12:12:44 +02:00
Andreas Rumpf
1c03604ec6 make tests green again 2019-09-13 20:11:01 +02:00
Araq
fd63443419 changed name mangling for generated C files 2019-09-13 19:11:48 +02:00
Araq
5018e7f304 fixes #12172 2019-09-13 18:12:38 +02:00
narimiran
ee6df5bd24 close #7104 by writing a test 2019-09-13 07:59:38 +02:00
narimiran
d79fb77974 close #6731 by writing a test case 2019-09-13 07:46:46 +02:00
Andreas Rumpf
eb241f4241 count 64 bits at a time instead of 8 (#12159)
* count 64 bits at a time

* spacing

* only do 64bts on x86

* add amd64

* use while
2019-09-12 08:20:53 +02:00
Jasper Jenkins
ca7bf3be8b no commas for empty importcpp splat params (#12183) 2019-09-12 08:19:53 +02:00
Brent Pedersen
5b923cd149 use while 2019-09-11 15:40:34 -06:00
Yuriy Glukhov
5783cd67a8 Fixed c filenames mangling (#12161) 2019-09-11 20:47:58 +02:00
Andreas Rumpf
e134a722de fixes #12152 (#12165)
* fixes #12152

* makes test green
2019-09-11 20:28:24 +02:00
Andreas Rumpf
8c81cddf7e fixes #12170 (#12176) 2019-09-11 20:01:09 +02:00
Andreas Rumpf
560eef5bbe fixes #12171 (#12173) 2019-09-11 18:35:13 +02:00
Brent Pedersen
944bab4c3c add amd64 2019-09-11 08:39:33 -06:00
Brent Pedersen
5a520a8454 only do 64bts on x86 2019-09-11 08:35:44 -06:00
Andreas Rumpf
33b8a00aa8 Revert "Refactored injectdestructors.nim (#11926)" (#12169)
This reverts commit 20dec10722.
2019-09-11 15:39:40 +02:00
Arne Döring
c55ceafd9a add tensordsl test (#12166)
* add tensordsl test

* simpler
2019-09-11 13:36:35 +02:00
Araq
99425ff21d fixes #12174 2019-09-11 11:59:12 +02:00
Benny Elgazar
ee36931f26 Fix to the relevant path of the docs. (#12162) 2019-09-10 17:50:03 +02:00
Araq
cf99c9bfb5 fixes #12051 2019-09-10 09:43:37 +02:00
Andreas Rumpf
d363eced3a closureiters.nim: finish the bugfix 2019-09-10 08:50:05 +02:00
Andreas Rumpf
1fa1024ddf typo 2019-09-10 08:36:24 +02:00
Andreas Rumpf
58077450cc parsejson: typo 2019-09-10 08:36:24 +02:00
Yuriy Glukhov
5d9c1544bf Allow ProcTy in addPragma and friends (#12158) 2019-09-10 07:54:51 +02:00
Yuriy Glukhov
60911304b4 Fixed yield in nnkChckRange (#12160) 2019-09-10 07:54:06 +02:00
Brent Pedersen
81c23bba7b spacing 2019-09-09 20:20:35 -06:00
Brent Pedersen
92f2d68802 count 64 bits at a time 2019-09-09 20:00:28 -06:00
Clyybber
ed1d41c51e Small ast.nim cleanup (#12156)
* Remove sonsLen
* Use Indexable
2019-09-09 11:54:15 +02:00
Andreas Rumpf
aa95ae6af9 Merge pull request #12153 from dumjyl/get_type-range
fix range.getType crash
2019-09-08 23:09:41 +02:00
Andreas Rumpf
f915064e07 fix #12130 ; improve naming scheme in fakePackageName (#12149)
* fix #12130 ; improve naming scheme in fakePackageName

* fix tests
2019-09-08 20:33:18 +02:00
Jasper Jenkins
e5139b0662 error for NimNode index kind (#12154) 2019-09-08 20:31:22 +02:00
Araq
18135cc194 proper bugfix 2019-09-08 13:08:41 +02:00
Araq
790f5bac01 added a simple debugging helper 2019-09-08 13:08:41 +02:00
Araq
3255b55266 fixes #11675 2019-09-08 13:08:41 +02:00
Araq
8362d92e47 fixes #12091 2019-09-08 13:08:41 +02:00
Araq
4bbafb47dc streams.nim: indentation change 2019-09-08 13:08:41 +02:00
Timothee Cour
3eb89481cb fix tests 2019-09-06 15:49:25 -07:00
Timothee Cour
4129993689 fix #12130 ; improve naming scheme in fakePackageName 2019-09-06 11:26:48 -07:00
pgkos
5a8fddf29b Fix mode_t posix definitions (fixes #12119) (#12132)
* fixes #12119
2019-09-06 20:15:07 +02:00
Andreas Rumpf
e0f3e8432a fixes a critical --gc:boehm regression 2019-09-06 18:06:08 +02:00
Euan
0e01a5f76c Fix #12133 - use libgc.so.4.0 for OpenBSD (#12134) 2019-09-06 14:31:39 +02:00
Euan
24f52d855c #12141 Define SDL lib name for OpenBSD and FreeBSD (#12143)
* Define SDL lib name for OpenBSD and FreeBSD

* Merge Linux and FreeBSD definitions
2019-09-06 12:57:38 +02:00
Timothee Cour
32769c478b exportc now mangles same as importc, fixes #10578 (#12144)
* fixes #10578
* add tests
* add changelog
* add {.exportcpp.}
2019-09-06 12:54:44 +02:00
Andreas Rumpf
8397554315 fixes #12125 (#12131)
* fixes #12125
2019-09-06 07:23:59 +02:00
Jasper Jenkins
40c5175145 fix range.getType crash 2019-09-05 15:56:44 -07:00
Andreas Rumpf
488f3ed085 fixes yet another gensym regression (#12145) 2019-09-06 00:45:00 +02:00
Araq
0882a09986 fixes a subtle tables.nim regression 2019-09-05 16:45:07 +02:00
Araq
49f63d3aae ic: update to serialize paddingAtEnd 2019-09-05 16:45:07 +02:00
Andreas Rumpf
a5e2db2ac5 allows access to .compileTime vars at runtime (#12128) 2019-09-05 11:56:32 +02:00
Andreas Rumpf
58bcf6cd46 fixes #12121 (#12126) 2019-09-05 08:21:01 +02:00
Andreas Rumpf
c2ba0ee144 Merge pull request #12124 from narimiran/nimsuggest-108
fixes nimsuggest/#108: RangeError with d:release
2019-09-05 00:31:37 +02:00
narimiran
92c012d86d fix commands for testing packages 2019-09-04 14:58:22 +02:00
narimiran
a9c7fb2fcc fixes nimsuggest/#108: RangeError with d:release 2019-09-04 13:31:59 +02:00
Araq
fa5707e7e2 fixes #11713, fixes #1034 2019-09-04 11:20:30 +02:00
Andreas Rumpf
cb0450398a introduce --oldgensym:on rather than --useVersion 2019-09-03 20:15:27 +02:00
Andreas Rumpf
07a986afa1 disable IC and the SQLite dependency for version 1 2019-09-03 18:43:57 +02:00
Andreas Rumpf
ea1a26294f prepare sqlite3 wrapper for static linking 2019-09-03 18:43:23 +02:00
Andreas Rumpf
459fbb9525 appveyor config: don't stop after testing failures; keep testing Nimble packages 2019-09-03 17:24:57 +02:00
Andreas Rumpf
4972d797e4 gcbench: better memory usage report 2019-09-03 12:39:49 +02:00
Chris Heller
35f1519ad6 Add delOutputFormatter proc to unittest.nim (#12032) 2019-09-03 08:14:19 +01:00
Andreas Rumpf
79f1b8592a Merge pull request #12107 from nim-lang/uint-range-checks
Uint range checks
2019-09-03 07:47:56 +02:00
Andreas Rumpf
ac6fcab7a4 Merge branch 'devel' into uint-range-checks 2019-09-02 22:03:10 +02:00
Andreas Rumpf
d70e292571 makes more tests green 2019-09-02 22:03:06 +02:00
Andreas Rumpf
5a03eea518 revert #12100; typeof(nil) is weird enough, don't allow it as the return type 2019-09-02 17:48:06 +02:00
narimiran
545ddf4a4f mark nimprof as used when profiling 2019-09-02 16:00:26 +02:00
Andreas Rumpf
f8f96d816c sink as lvalue (#12108) 2019-09-02 15:49:01 +02:00
Andreas Rumpf
7ef85db9a9 fixes #12020 (#12106) 2019-09-02 15:47:56 +02:00
Araq
18ca1788f0 makes test green again 2019-09-02 14:23:05 +02:00
Araq
fc7fe636e2 improvement for 'unused import' warnings 2019-09-02 12:49:31 +02:00
Araq
23c44f009a weaking unsigned/signed indexing requirements in order to not break too much existing code 2019-09-02 12:07:36 +02:00
Arne Döring
3d4ad9739c fix min/max for float numbers (#12068) 2019-09-02 11:21:26 +02:00
Andrii Riabushenko
ba18c12005 sink as lvalue 2019-09-02 10:11:51 +01:00
Araq
755c4428fe added more tests and updated the changelog 2019-09-02 11:03:08 +02:00
Araq
2396f0ee71 make test green 2019-09-02 10:56:51 +02:00
Araq
e765687646 Merge branch 'devel' into uint-range-checks 2019-09-02 10:27:35 +02:00
Araq
e6ec88d4c3 renamed and moved test 2019-09-02 10:27:33 +02:00
Araq
ad82e65387 gc:destructors progress 2019-09-01 23:28:26 +02:00
Miran
ab48d7901e hashes: implement murmur3 (#12022)
* hashes: implement murmur3
* refactoring; there is only one murmurHash and it works at compile-time via VM hooks
* fixes JS tests
* makes toOpenArrayByte work with C++
* make it bootstrap in C++ mode for 0.20
2019-09-01 00:04:10 +02:00
Oscar Nihlgård
35268c500f Fix int literals and range interaction (#11197)
* Fix int literals and range interaction

* Fix test

* remove float range fix; update changelog
2019-08-31 19:34:08 +02:00
Arne Döring
6e01be34ef fixes #11903 (#11908) 2019-08-31 19:32:59 +02:00
Andreas Rumpf
326a333c8b Merge pull request #12099 from cooldome/destructor_too_late
fixes #12092
2019-08-31 19:25:19 +02:00
Andreas Rumpf
15213028b7 Return typeof(nil) (#12100)
* Allow typeof(nil) as a return type

* $typeof(nil) is now "typeof(nil)", not "nil"
2019-08-31 19:24:44 +02:00
cooldome
2b565aad89 Support iterators returning lent T (#11938)
* lent iterators
* rebase tests
* update changelog
* fix comments, more tests
2019-08-31 19:23:54 +02:00
Albert Safin
a6428657e9 $typeof(nil) is now "typeof(nil)", not "nil" 2019-08-31 10:16:26 +00:00
Albert Safin
efe1bed82e Allow typeof(nil) as a return type 2019-08-31 10:16:26 +00:00
Andrii Riabushenko
a388c35741 support forward declared destructors 2019-08-31 09:56:39 +01:00
Andrii Riabushenko
a055f628f4 fixes #12092 2019-08-31 09:49:47 +01:00
Timothee Cour
9ae0dd611f typeToString can now show (recursively) resolved type aliases; fixes #8569 #8083 #8570 (#11678)
* nested typeToString
* typeToString: preferResolved
* add test
* fix test
* preferMixed
* fix tests
2019-08-31 08:26:45 +02:00
Clyybber
f9600b7207 Remove ENDB (#12095) 2019-08-31 07:44:53 +02:00
Andreas Rumpf
82d5e773e3 make testament a tool we ship with Nim; fixes #12084 (#12088)
* make testament a tool we ship with Nim; fixes #12084
* moved config to fit
* adapt testament tests to use the testament binary
2019-08-30 15:43:07 +02:00
narimiran
25581c796f enable testing of more packages 2019-08-30 08:47:58 +02:00
Clyybber
029dcc6259 fix #12037 (#12089) 2019-08-30 06:41:26 +02:00
Andreas Rumpf
2a3b056314 fixes #12042 (#12083)
* fixes #12042

* make tests green again
2019-08-29 19:09:54 +02:00
Araq
d0e5bd2305 fixes a critical type checking regression 2019-08-29 12:10:31 +02:00
Andreas Rumpf
9203d3a982 fixes 5870 (#11704)
* fixes #5870
* make tclosure test green again
* this check is correct but breaks some Nimble packages
2019-08-29 07:49:58 +02:00
Andreas Rumpf
cd106cf680 fixes #12074 (#12080) 2019-08-29 07:43:35 +02:00
Andreas Rumpf
5f7a6aff06 fixes #11941 (#12079) 2019-08-29 00:35:05 +02:00
Andreas Rumpf
21fc8b4d4d refactor sizealignoffset (#12077)
* small refactoring
* refactor computeObjectOffsetFoldFunction with AccumObject
* refactor packed object offstes fold function
* refactor compute union object offsets fold function
* merge normal/packed object offset fold function
* compiletime offsetof in c++ inheritance objects
* enable c++ inheritance offsetof tests
* correct alignment for big sets/enums on weird 32bit platforms
* uncomputedSize -> unknownSize
* workaround for travis
* fixes win32 alignment problems
2019-08-28 19:36:29 +02:00
Jacek Sieka
42d2e68bca only store finally block in exception stack (#11876) 2019-08-28 12:08:54 +02:00
cooldome
c9f49cbc0a lift destructor for openarray (#12073)
* destroy for sink openarray
2019-08-28 12:07:46 +02:00
Ico Doornekamp
84351da9d8 Fixes #12044 (#12071) 2019-08-28 12:05:07 +02:00
Andreas Rumpf
d4af0554c4 remove unicode.Rune16 without deprecation period; fixes https://github.com/nim-lang/RFCs/issues/151 (#12072) 2019-08-28 10:25:13 +02:00
Clyybber
20dec10722 Refactored injectdestructors.nim (#11926)
One improvement over #devel is visible in the transformation of getEnv. With this approach we move to result whenever possible.
2019-08-28 00:02:48 +02:00
Andreas Rumpf
eaebbfa785 Fix several float range issues (supersedes #11905) (#12067)
* Fix several float range issues

* address the comments
2019-08-27 23:19:41 +02:00
Arne Döring
d564130a3b Fix to int to biggest int (#12066)
* fix to(Biggest)Int
* kill toFloat magics as well
2019-08-27 23:18:46 +02:00
Vindaar
eff0837ff4 fixes #12015 by also checking kind of typeNode (#12016)
* fixes #12015 by also checking kind of `typeNode`

If a tuple field is aliased it'll appear the same as a ref type in a
call to `getType` if only for the kind of the resulting `NimNode` is
checked (that is a `nnkBracketExpr`)

* fix test case due to #12017 and add more realistic test case

Adds an additional test case, which includes generics and is closer to
the real failure I encountered

* remove previous fix and fix differently after all

The previous fix was incomplete, because it failed for generics.

Note that the `of "tuple"` is not actually needed, the
`nnkBracketExpr` branch in the `else` branch would catch it too, but I
decided to introduce it for clarity. However, the latter is actually
needed, because it seems for aliases of `seq` we end up in it.

* update comment about global `%` proc in json test
2019-08-27 22:23:47 +02:00
Andreas Rumpf
00d46ca1c0 fixes #12024 (#12065) 2019-08-27 20:05:40 +02:00
Andreas Rumpf
114da04cbb fixes #12029; finish the 'unused import' feature (#12064) 2019-08-27 19:18:56 +02:00
Artem V L
d8177a3980 Typos fixed, handleRefillChar() described (#12062) 2019-08-27 16:16:32 +02:00
Andreas Rumpf
8df745a42e fixes #12056 (#12063) 2019-08-27 16:15:37 +02:00
narimiran
3f5599b344 disable testing of 'norm' package 2019-08-27 15:03:06 +02:00
narimiran
329e169e96 address the comments 2019-08-27 14:49:32 +02:00
Oscar Nihlgård
def6234903 Fix several float range issues 2019-08-27 14:45:19 +02:00
Jacek Sieka
66a8856152 abort is noreturn (#12061) 2019-08-27 14:27:44 +02:00
Arne Döring
ab8241ad42 minor stuff 2019-08-27 12:28:18 +02:00
Araq
1ccff0324c manual: more precise rules about evaluation order 2019-08-27 12:13:06 +02:00
Araq
ddc155af64 fixes #12040 2019-08-27 10:20:12 +02:00
Andreas Rumpf
b044523c5a fixes 9195 (#12055) 2019-08-27 10:07:42 +02:00
Andreas Rumpf
5a9edb222b unicode.nim: fixed spacing to something sane 2019-08-26 23:30:35 +02:00
Andreas Rumpf
97d77bf37e semtypes.nim: more refactorings for liftParamType 2019-08-26 23:30:35 +02:00
Andreas Rumpf
0c41fd0f50 semtypes.nim: little refactoring for liftParamType 2019-08-26 23:30:35 +02:00
Andreas Rumpf
d8d2a9e985 manual: better documentation for implicit generics 2019-08-26 23:30:35 +02:00
Dominik Picheta
8117a949c5 Remove old and unused parseBody/parseResponse procs in httpclient. (#11949) 2019-08-26 20:27:44 +02:00
Arne Döring
ae9bb4474b fixes #12033 (#12039) 2019-08-26 20:14:21 +02:00
Palash Nigam
88814bbe98 fixes #11832 (#12049) 2019-08-26 20:13:41 +02:00
Andreas Rumpf
931ee0ca82 fixes #7258 (#12054) 2019-08-26 20:12:22 +02:00
Viktor Kirilov
5df7d72afe HCR: tests for the fixes for #11608 and #11996 (#12047)
* tests for #11996 and #11608

* removed unnecessary comment
2019-08-26 20:08:18 +02:00
nc-x
73dd73f961 [ci skip] Add note to nimhcr.nim (#12050) 2019-08-26 19:20:24 +02:00
Andreas Rumpf
ce7f29e8e6 fixes #11833 (#12018) 2019-08-24 06:25:47 +02:00
Viktor Kirilov
f2e8c39e85 - adding _actual as a suffix only for calls to an actual proc and not through a global function pointer - fixes https://github.com/nim-lang/Nim/issues/11996 (#12007)
- adding forward declarations for reloadable functions within a module - fix compilation errors when 2 such functions reference each other - fixes https://github.com/nim-lang/Nim/issues/11608
- preserve permissions of copied executable binaries
2019-08-23 22:50:34 +02:00
Andreas Rumpf
547fcd69c3 rdstdin: remove cruft that shouldn't have been exported or added (#12014) 2019-08-23 21:34:22 +02:00
Andreas Rumpf
c3c5839329 Add build support for FreeBSD/PowerPC64 (#12011)
* Add build support for FreeBSD PowerPC64

* Add build support for FreeBSD PowerPC64

* Add build support for FreeBSD PowerPC64
2019-08-23 18:59:52 +02:00
Andreas Rumpf
fbb2763204 fixes #11958 (#12013) 2019-08-23 18:58:55 +02:00
Andreas Rumpf
b07694cd90 new gensym handling (#11985)
* new .gensym implementation
* make astspec test green again
* introduce a --useVersion switch to group compatibility switches
* fixes #10180
* fixes #11494 
* fixes #11483
* object constructor fields and named parameters are also not gensym'ed
* disabled broken package
2019-08-23 16:15:02 +02:00
lenoil98
2212a90458 Add build support for FreeBSD PowerPC64 2019-08-23 07:56:56 -04:00
lenoil98
e1539c7344 Add build support for FreeBSD PowerPC64 2019-08-23 07:54:02 -04:00
lenoil98
806f3b592f Add build support for FreeBSD PowerPC64 2019-08-23 07:50:50 -04:00
Palash Nigam
f28a47ea7b fixes #11834 (#12000) 2019-08-23 07:42:33 +02:00
Andreas Rumpf
9aad99bdfd closes #7117 2019-08-22 19:08:35 +02:00
Andreas Rumpf
085fbcea6f fixes #10854 2019-08-22 18:57:41 +02:00
Andreas Rumpf
9eee15f668 thavlak: code style changes 2019-08-21 22:03:04 +02:00
Federico Ceratto
170cb4f4cb Update OpenSSL example (#11896)
* Update OpenSSL example

Fix privkey filename.
Bump up RSA key size.
Add ECDSA example.
2019-08-21 20:01:17 +02:00
Arne Döring
a562de2d91 squashed and merged with devel 2019-08-21 19:24:36 +02:00
Timothee Cour
2b2efe3dbe fix compiletimeFFI (#11991) 2019-08-21 09:28:16 +02:00
Arne Döring
5304b16a55 Fix typos. Apply title case. (#11987) 2019-08-21 00:04:01 +02:00
Oscar Nihlgård
4264e9576d Consider range type of runtime discrim [feature] (#11432) 2019-08-20 17:39:49 +02:00
Andreas Rumpf
d00c8febee Nimpretty: fix #11937 (#11978)
* cosmetic improvements

* remove unused imports
* make 'openPars' and 'closedPars' more readable

* nimpretty: fix #11937 (wrong indentation)
2019-08-20 16:03:04 +02:00
Araq
b1b0960c36 fixes #11972 2019-08-20 15:47:04 +02:00
Miran
75baaa5e25 nim check, fix #11927, no more empty strings (#11979) 2019-08-19 22:25:21 +02:00
narimiran
ceb742351a nimpretty: fix #11937 (wrong indentation) 2019-08-19 13:35:10 +02:00
narimiran
cf4390a24a cosmetic improvements
* remove unused imports
* make 'openPars' and 'closedPars' more readable
2019-08-19 13:29:45 +02:00
Andreas Rumpf
742862b847 more enhancements for #11618 (#11976)
* finish the Windows IO layer changes; refs #11618
* added system.getOsFileHandle which is less error-prone on Windows
* make tests green again
2019-08-18 22:57:56 +02:00
nc-x
ac7a365137 Fix HCR crash because certain procs were hcrGetProc'ed before being hcrRegisterProc'ed (#11971) 2019-08-18 14:16:51 +02:00
nc-x
d5840e1e3d Implement isExported for symbols in macros (#11963)
* Implement isExported for macros

* Reimplement isExported using VM callback mechanism

* VM does not support exceptions, use stacktrace() instead.
2019-08-18 11:51:28 +02:00
Andreas Rumpf
7cb31455ee fixes #11618 (#11969) 2019-08-17 21:19:57 +02:00
nc-x
b68380f09b fixes #11872; include now gives a proper error message for all invalid infix operators (#11965) 2019-08-17 19:45:47 +02:00
Andreas Rumpf
db9e27dffd Fixes #11118 (#11964)
* fixes #11118

* Reset closure iter exception before rethrowing
2019-08-17 10:37:38 +02:00
nc-x
cf09ef47b8 Remove duplicate line number from 'invalid forward declaration' error (#11966) 2019-08-17 10:35:25 +02:00
Andreas Rumpf
15e681ce66 fixes 'e' command handling; now only does what advopt.txt claims it does (#11961)
* fixes 'e' command handling; now only does what advopt.txt claims it does
* address Timothee's remark
2019-08-16 18:19:30 +02:00
Yuriy Glukhov
721ca3e830 Reset closure iter exception before rethrowing 2019-08-16 17:26:00 +02:00
Araq
39f4a3e418 fixes #11801 2019-08-16 15:20:39 +02:00
Araq
b9dd972c32 fixes #11770 2019-08-16 14:48:32 +02:00
Araq
7023241aaf fixes #11819 2019-08-16 14:37:52 +02:00
Araq
bebda3851f fixes #1188 2019-08-16 13:29:58 +02:00
Araq
c7e77edecc fixes #11925 2019-08-16 12:33:31 +02:00
Andreas Rumpf
ba577c7e1b better tojsstr (#11954)
* JS: rewrote toJSStr
* JS: don't raise exceptions in primitives
2019-08-16 12:18:51 +02:00
Timothee Cour
cf22dec584 genSym symbols rendered as b1_416049 instead of b1416049 (#11960) 2019-08-16 12:17:20 +02:00
Araq
1fb9a6d946 added destructors.rst spec to the build documentation 2019-08-16 12:14:39 +02:00
Yuriy Glukhov
d31404ac27 Merge branch 'cpp_reraise_fix' into yield-in-try-fix 2019-08-16 10:25:09 +02:00
Timothee Cour
922e2a5098 refs #11956 (#11957) 2019-08-16 07:19:34 +02:00
Timothee Cour
511298242d fixes #10053 (#11951) 2019-08-15 15:55:48 +02:00
pgkos
296dfae8af Fixes splitfile (#11918) [bugfix] 2019-08-15 15:22:14 +02:00
Dominik Picheta
b095203f28 Fixes regression introduced by #11904. (#11948) 2019-08-15 06:05:38 +02:00
Timothee Cour
630e18a6eb refs #11947; FieldError fixed (#11950) 2019-08-15 06:04:38 +02:00
Arne Döring
a25d43ca6b fix warnings in system.nim (#11944) 2019-08-14 17:48:11 +02:00
Arne Döring
65ed2d7fe8 fixes #11942 (#11945) 2019-08-14 17:41:44 +02:00
Clyybber
e6cb7e34ef Make name mangling reversable unambiguously (#11939) [bugfix] 2019-08-14 08:11:50 +02:00
cooldome
5ef62fcb25 newruntime for vcc (#11934) [bugfix] 2019-08-14 08:10:59 +02:00
narimiran
1874b3e786 [nobackport] add a changelog entry for the previous commit 2019-08-13 07:38:07 +02:00
Fabian Keller
83397a69fc Consistent behavior of exec; Improved docs around exec, staticExec, gorgeEx, etc. (#10967)
* improved docs around exec, staticExec, gorgeEx, etc.
* incorporate review comment; made behavior of exec consistent
2019-08-13 07:41:08 +02:00
Andreas Rumpf
433613e267 fixes #11844 (#11935) 2019-08-13 06:37:37 +02:00
Araq
322ce1872f fixes #10689 2019-08-12 14:06:48 +02:00
Araq
289b5e9ef9 fixes #11254 2019-08-12 13:58:35 +02:00
sschwarzer
c9c28bf85e Update documentation on xmltree.items/mitems (#11930)
* Update documentation on `xmltree.items`/`mitems`

So far the documentation on `items` and `mitems` wasn't explicit about whether the iteration recurses down the node's children or not. I assumed recursion, which was wrong.

* Improve wording in comment

Use the more common and shorter word "direct".
2019-08-12 11:12:22 +02:00
Andreas Rumpf
da64c8762f destructors: spec reflects reality, =sink is here to stay 2019-08-11 21:55:47 +02:00
Andreas Rumpf
212ae2f125 fixes #11891 2019-08-10 15:41:24 +02:00
Araq
0e4a8bfb28 fixes 'unused module' feature for 32 bit builds of Nim for good [nobackport] 2019-08-09 16:38:10 +02:00
Araq
da37177ac2 make tests green again on 32bit systems 2019-08-09 10:12:32 +02:00
Andreas Rumpf
3b8f721460 merged #11813 manually [bugfix] 2019-08-08 23:09:27 +02:00
Zachary Carter
082c440f13 Fixes effect error in pure/logging.nim (#11898)
* Fix effect error in pure/logging.nim

Currently calling `logging.log` will produce - `Error: can have an unlisted effect: RootEffect`. Add `RootEffect` to list of tags.

* the only tag necessary is RootEffect since all other Effects are descendants of RootEffect
2019-08-08 22:48:25 +02:00
Andreas Rumpf
81ddc67785 [refactoring] compiler: simplified markUsed 2019-08-08 22:43:58 +02:00
Andreas Rumpf
04708742e7 fixes #11809 2019-08-08 21:41:05 +02:00
Andreas Rumpf
e3c0bf48c5 tiny style change [refactoring] 2019-08-08 18:30:10 +02:00
Andreas Rumpf
0d5bd7e8b5 removed unused imports [refactoring] 2019-08-08 17:03:19 +02:00
Arne Döring
44e7a7b6c2 Lock semchecked ast for macros (#11883) [bugfix]
* reject to modify type checked AST
* add flag to back out
* Introduce legacy feature set.
2019-08-08 16:57:06 +02:00
Timothee Cour
fda51b6ca2 fix crash on sigmatch (#11913) 2019-08-08 14:41:23 +02:00
Dmitry Matveyev
756fabb979 Fix typo (#11910) 2019-08-08 13:17:53 +02:00
Arne Döring
48968f3c84 delete expensive call (#11909) [refactoring] 2019-08-08 09:16:07 +02:00
konradmb
addd7b5e20 Fix issue #10726 - HTTP response without Content-Length is not accessible (#11904)
* Add patch by @xenogenesi

* Async test for HTTP/1.1 without Content-Length

* Apply suggestions from code review

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>
2019-08-08 08:41:56 +02:00
Andreas Rumpf
c8cffaf420 Incremental compilation (IC): Improvements (#11881)
* IC: C codegen is aware of IC
* manual: minor change to make VSCode's RST plugin render it properly
* IC: minor refactoring
* testament: code refactorings
* rodutils: removed dead code
* IC: always build the compiler with the IC feature
* IC: C codegen improvements
* IC: implement the undocumented -d:nimMustCache option for testing purposes
* IC: added first basic tests
* IC: extensive testing of the deserialization feature
* testament: refactoring; better IC tests
* IC: removes 'nimMustCache' flag; readonly does the same
* testament: minor refactoring
* update Nimble version
* testament: removed dead code and imports; IC: added simple test
* IC: progress
2019-08-08 08:41:05 +02:00
Andreas Rumpf
c0d240b8cd fixes #11807 (#11900)
* fixes #11807
* make tests green again
2019-08-07 22:40:58 +02:00
amzak
f34ae81971 Fixed handling of empty strings for encodings conversions (#11897) 2019-08-07 19:56:42 +02:00
awr1
9321b33cd2 Typeclass/Variant clarification in Manual (#11901)
* [Docs] clarified what type classes do in manual

* [Docs] fixed 'dynamism', added to object variant section
2019-08-07 16:03:32 +02:00
Arne Döring
afbcd1b330 int128 on firstOrd, lastOrd and lengthOrd (#11701)
* fixes #11847
2019-08-07 15:53:16 +02:00
Andy Davidoff
8407a57499 note set[T].len alias in future changelog (#11893)
per comments in #11885
2019-08-06 21:07:26 +02:00
amzak
3d7d5cf121 Fixed utf8<->utf16 conversions on windows (#11888) 2019-08-06 03:30:47 -04:00
Arne Döring
ce148e71ef disallow static in return type (#9686) [nobackport] 2019-08-06 01:26:53 +02:00
Andreas Rumpf
42e83ac24c fixes #11817 (#11889) 2019-08-05 16:48:26 +02:00
Andy Davidoff
d208d7a995 set[T].len is an alias for set[T].card (#11885) [feature] 2019-08-05 14:27:45 +02:00
Araq
61c66abbfe newruntime: make system.delete and friends work with owned ref (bugfix); reported on the forum 2019-08-05 00:14:30 +02:00
Araq
7024bb800c fixes #11844 2019-08-04 23:54:29 +02:00
John Paul Adrian Glaubitz
65d1140d11 Add build support for Linux/ia64 (#11880) [feature]
* compiler: Add ia64 as target architecture on Linux
* build.sh: Enable CPU detection for ia64
2019-08-04 23:16:30 +02:00
Arne Döring
b73d097d36 fixes #9829 (#11849) 2019-08-04 19:31:55 +02:00
Chris Heller
343ace8194 Skip db_postgres.setRow if getRow returns 0 rows (#11859)
Fixes nim-lang/Nim#11821
2019-08-04 19:28:24 +02:00
Leorize
51d998390c tgetaddrinfo: disable ICMP tests for Haiku
They're not supported by Haiku's getaddrinfo()
2019-08-04 12:15:17 +01:00
Leorize
df32c45757 tgetaddrinfo: use sizeof() instead of hardcoding
OS like Haiku have a bigger sockaddr_in struct for legacy(?) reasons.
Using sizeof() should account for the different struct sizes.
2019-08-04 12:15:17 +01:00
Oscar Nihlgård
bcfb540e57 Allow typeof(nil) as generic parameter (#11869) 2019-08-03 10:16:07 +02:00
Oscar Nihlgård
50e921bb94 VM exception fixes (#11868) 2019-08-02 22:59:04 +01:00
Jjp137
a906b3952b random: minor documentation updates (#11831)
Add docs for the sample procs that take in sets, and clean up a
few other minor things.
2019-08-02 02:42:18 -04:00
Oscar Nihlgård
829f719670 Fix VM conversion to var type [bugfix] (#11866) 2019-08-01 17:44:12 +02:00
Arne Döring
803406d07c fix #11854 (#11857) 2019-07-30 17:24:42 +02:00
Dominik Picheta
bb949a75db Fixes subtle SSL recvInto bug.
This resulted in a "value out of range: -1" exception inside `recvInto`
(on the `copyMem` line). Basically readIntoBuf was returning `-1`.
2019-07-27 19:06:56 +01:00
Andreas Rumpf
ceb1a1b688 IR: minor refactoring 2019-07-27 14:01:28 +02:00
Andreas Rumpf
f58d87cb43 IC: some progress 2019-07-27 14:01:28 +02:00
Andreas Rumpf
c9c8fa99cc destructors spec: be more precise about temporaries 2019-07-27 14:01:28 +02:00
Andreas Rumpf
b9c15371a3 nimgrep: introduce the --rex option 2019-07-27 14:01:28 +02:00
Andreas Rumpf
f7c99838e2 nimgrep: fixes the -w option 2019-07-27 14:01:28 +02:00
Andreas Rumpf
25e6c53bb5 makes the -d:nimIncremental compiler mode compile again 2019-07-27 14:01:28 +02:00
Arne Döring
1a77040278 fix #11812 (#11829)
* fixes #11812
* fixes #10899
* fixes #11367
2019-07-27 07:21:47 +02:00
Giovanni Petrantoni
2fdba334da Use proper types according to MSDN and fix clang build of windows dynlib (#11828) 2019-07-26 10:11:21 +02:00
Andrii Riabushenko
4c73139316 revert changes 2019-07-25 23:18:20 +01:00
Andrii Riabushenko
95856ab8d3 add test 2019-07-25 23:07:43 +01:00
Andrii Riabushenko
d7bc4e43a2 fixes #11826 2019-07-25 23:02:04 +01:00
Miran
3bb6d1916e fix #11772, JS random seed was too large (#11820) 2019-07-25 04:53:50 -04:00
narimiran
3ccda773d6 close #11166 by adding a test 2019-07-25 10:05:02 +02:00
narimiran
13190435a6 close #9891 by adding a test 2019-07-25 09:25:18 +02:00
genotrance
44aadd50cf Fix #10630 - fix broken separators in nim doc (#11814) 2019-07-24 14:45:05 +02:00
narimiran
5484352d26 fix asyncftpclient examples [ci skip] 2019-07-24 11:49:06 +02:00
Timothee Cour
8c93c692b9 run runnableExamples in the module scope (#11732) [feature] 2019-07-22 16:22:57 +02:00
narimiran
30f2cec671 fix failing JS tests 2019-07-22 11:41:20 +02:00
Benjamin Summerton
46f2271968 Add opacity to JS Style
I noticed this was missing.  It has cross browser support: https://developer.mozilla.org/en-US/docs/Web/CSS/opacity#Browser_compatibility
2019-07-21 23:15:36 +01:00
cooldome
d563efb719 fixes #11792 (#11793) 2019-07-21 16:53:22 +02:00
Araq
67a6effb7b fixes #11745 2019-07-19 22:38:35 +02:00
Araq
affe1be47c fixes #11790 [nobackport] 2019-07-19 22:24:56 +02:00
Araq
dc38b88f7e bugfix: it should be [UnusedImport] [nobackport] 2019-07-19 19:33:56 +02:00
Araq
1868cbc449 revert the bugfix for #11747 as it really was a new, poorly though-out feature 2019-07-19 19:32:13 +02:00
Araq
5a020d641d style improvements; fixes #11774 2019-07-19 17:25:04 +02:00
Araq
313cc337f2 fixes a 'nim check' regression 2019-07-19 17:09:11 +02:00
Araq
de69e1856f installer: ship nimpretty.exe on Windows 2019-07-19 16:48:27 +02:00
Andreas Rumpf
70e8551e37 async macro: general stability improvements [bugfix] (#11787) 2019-07-19 16:47:38 +02:00
Jörg Wollenschläger
903d06bab8 Fix the range of destroyed elements when shrinking a seq (#11785) 2019-07-19 16:46:47 +02:00
Andreas Rumpf
a5d6080a81 Merge pull request #11766 from nim-lang/araq-detect-unused-imports
[feature] detect unused imports
2019-07-19 01:06:45 +02:00
Andreas Rumpf
fbb0642e27 Merge branch 'devel' into araq-detect-unused-imports 2019-07-18 18:16:32 +02:00
Andreas Rumpf
9852cf804b warn about unused imports; fixes an 'export' regression [nobackport] 2019-07-18 18:16:25 +02:00
Araq
6d8913ee14 nimpretty: fixes #11616 2019-07-18 12:13:22 +02:00
Araq
7deb49e992 nimpretty: fixes #11699 2019-07-18 11:28:25 +02:00
Araq
5b7273b4f8 [refactoring] nimpretty 2019-07-18 11:00:29 +02:00
Andreas Rumpf
4becd5a2a8 Merge pull request #11771 from nim-lang/araq-remove-unused-imports
[refactoring] remove unused imports in the compiler and in some stdli…
2019-07-18 08:48:11 +02:00
Araq
07d465ca42 [refactoring] remove unused imports in the compiler and in some stdlib modules 2019-07-18 00:36:03 +02:00
Araq
4137a4dbf3 [feature] detect unused imports 2019-07-17 22:36:23 +02:00
narimiran
f50e4500c2 update changelogs [ci skip] 2019-07-17 21:20:28 +02:00
Andreas Rumpf
745669ac25 fixes #11758 [nobackport] 2019-07-17 20:06:10 +02:00
Kaushal Modi
d40872bf9b [bugfix] Make std/unicode compile with --styleCheck:error (#11763) 2019-07-17 19:48:15 +02:00
Kaushal Modi
404b224945 [bugfix] Make std/unittest compile with --styleCheck:error (#11762) 2019-07-17 19:47:50 +02:00
Andreas Rumpf
210988c532 [refactoring] don't use 'defer' 2019-07-17 16:36:40 +02:00
Andreas Rumpf
1acb9bae94 Merge pull request #11743 from GULPF/stdlib-monotimes [feature]
Use std/monotimes in the stdlib [feature]
2019-07-17 16:06:34 +02:00
Andreas Rumpf
e11494f1cf Merge pull request #11680 from timotheecour/pr_fix_sigmatch_errmsg
fixes #8305; fixes #7808; fixes #10285; fixes #11061 + other bugs with type mismatch error msgs
2019-07-17 16:01:44 +02:00
Andreas Rumpf
326860e84c Merge pull request #11751 from nim-lang/araq-fixes-11474
fixes #11747
2019-07-17 15:21:07 +02:00
Andreas Rumpf
15d2a92be0 fixes #11747 2019-07-17 15:19:25 +02:00
Andreas Rumpf
bae08d0961 Merge pull request #11753 from kaushalmodi/fix-compilation-warning-in-macros
[bugfix] Fix compilation warning in macros.nim
2019-07-17 15:17:45 +02:00
Andreas Rumpf
43940294c5 fixes a critical 'nim secret' regression 2019-07-17 15:10:02 +02:00
Kaushal Modi
44d80dd863 [bugfix] critbits styleCheck fix: consistent var naming (#11752) 2019-07-16 21:24:09 +02:00
Kaushal Modi
3f7142fcfd [bugfix] openssl styleCheck fix: consistent var naming (#11750) 2019-07-16 21:23:12 +02:00
Kaushal Modi
0b511b15ea styleCheck fix: type naming: s/outType/OutType/ (#11749) 2019-07-16 21:22:34 +02:00
Kaushal Modi
dcbb2d66da Fix compilation warning in macros.nim
Fixes:

> macros.nim(1423, 35) Warning: `typed` will change its meaning in future versions of
  Nim. `void` or no return type declaration at all has the same
  meaning as the current meaning of `typed` as return type declaration. [Deprecated]
2019-07-16 15:03:44 -04:00
Oscar Nihlgård
1f32498a47 Use std/monotimes in the stdlib 2019-07-16 11:05:42 +02:00
Andreas Rumpf
102b71f42e Merge pull request #11740 from nim-lang/araq-fixes-11723
fixes #11723
2019-07-16 09:08:15 +02:00
Tristano Ajmone
8550a8127c Fix Typos in Internal Docs (#11735) [ci skip] 2019-07-15 19:05:23 +02:00
Araq
76f9ddb6ab fixes #11723 2019-07-15 17:22:01 +02:00
Kartik Saranathan
ec9d0ee86d fix broken link (#11736) [ci skip] 2019-07-15 16:05:43 +02:00
Andreas Rumpf
8513f50a8d Add std/monotimes which implements monotonic timestamps (#11712)
* [feature] Added std/monotimes

* [other] Minor optimization in times
2019-07-15 13:47:30 +02:00
Araq
dd7dd1b6dc styleCheck fixes [bugfix] 2019-07-15 13:16:02 +02:00
Araq
ad67a46e5d styleCheck fixes [bugfix] 2019-07-15 12:03:21 +02:00
Araq
52cbd0c558 styleCheck fixes [bugfix] 2019-07-15 10:56:55 +02:00
Araq
edbe02b4e1 newruntime: progress to make 'async' work with --newruntime 2019-07-15 10:56:55 +02:00
Andreas Rumpf
df53c68a36 makes devel green again 2019-07-14 17:14:51 +02:00
Araq
58e0dad371 'nim check' stability improvements 2019-07-14 16:11:42 +02:00
Araq
e06046ab51 makes --styleCheck:error the default for the Nim compiler itself 2019-07-14 16:08:52 +02:00
Araq
fab70e4fe3 minor update for the genode target 2019-07-14 16:08:15 +02:00
Araq
44c12d9d20 make 'koch temp' work again 2019-07-14 16:07:30 +02:00
Araq
9db369063c [refactoring] moves transformation for 'spawn' into its own spawn.nim implementation 2019-07-14 12:13:19 +02:00
alaviss
a59fb5b352 os: confine osErrorMsg example to Linux (#11725)
POSIX does **not** define the exact number for each errors. This caused
a failure in docs building on Haiku.
2019-07-13 16:16:09 +02:00
Jacek Sieka
cf36e4a44a times: use posix constant instead of import (#11692)
* times: use posix constant instead of import

* simplify clock id usage
2019-07-13 08:39:20 +02:00
Andreas Rumpf
de1ede77fe fixes #11715 (#11721) 2019-07-13 07:55:56 +02:00
Araq
d55cc0888d better run also considers the command line; fixes #11719 [feature] 2019-07-12 21:53:46 +02:00
Araq
423e8cca91 newruntime: refchecks:on|off switch 2019-07-12 21:53:46 +02:00
Araq
416ba133ad made --newruntime ready for multi-threading 2019-07-12 21:53:46 +02:00
Araq
bb5ca0772e atomics.nim: minor improvements 2019-07-12 21:53:45 +02:00
Araq
f45a1b927a documented --newruntime switch 2019-07-12 21:53:45 +02:00
Araq
03ded27021 preparations to be able to use atomics in runtime_v2.nim 2019-07-12 21:53:45 +02:00
Andreas Rumpf
2895ad70c8 fixes tcompiletimerange [bugfix] (#11720) 2019-07-12 15:37:54 +02:00
Ico Doornekamp
38b836b49e Moved 'Case statement macros' documentation out of manual into manual_experimental (#11716) 2019-07-12 14:41:54 +02:00
Araq
7606efc0bf [bugfix] VM: finally do inheritance properly 2019-07-12 12:15:30 +02:00
Araq
6d125da93f koch/nim: completion of the 'better run' feature 2019-07-12 10:48:29 +02:00
Araq
13253f4154 document 'nim' defines prefix 2019-07-12 10:48:07 +02:00
Araq
5bf3734984 nimpretty: implement a --maxLineLen command line option 2019-07-12 10:23:21 +02:00
Oscar Nihlgård
974362c98f [other] Minor optimization in times 2019-07-12 10:15:12 +02:00
Oscar Nihlgård
fd24a8923e [feature] Added std/monotimes 2019-07-12 10:15:06 +02:00
Araq
eaf4b42ff9 JS codegen: supports toOpenArray [bugfix] 2019-07-12 10:11:59 +02:00
Araq
511b6ae27c koch temp bugfix 2019-07-12 10:11:34 +02:00
Miran
2f0a50fa51 nimpretty: fix #11700, no extra newlines (#11714) 2019-07-12 09:14:21 +02:00
Andreas Rumpf
3d88d06b32 better run [feature] (#11709)
* track the checksums of all involved Nim files for smarter 'nim c -r' recompiles
* don't recompile unless necessary for 'nim c -r' [feature]
* [feature] koch boot uses a two step process in order to free the RAM before the GCC/Clang invocations
* fixes a serious regression
2019-07-11 21:36:23 +02:00
Dominik Picheta
b8be1ccb85 Give NilAccessError a message (#11706) 2019-07-11 11:14:38 +02:00
Andreas Rumpf
ac458448d8 make async tests green again 2019-07-11 11:09:10 +02:00
Araq
cb3c3c306c minor style changes 2019-07-11 00:28:20 +02:00
Araq
38bdf1cd7f minor style changes 2019-07-10 23:55:56 +02:00
Araq
b2f9447896 make tests green again 2019-07-10 23:32:04 +02:00
Araq
87a2ced1ba there is only one style -- my style 2019-07-10 19:17:06 +02:00
Araq
73cc029fec fixes linter regressions 2019-07-10 18:59:27 +02:00
Araq
dc0bbba3fa make editdistance work with --styleCheck:error 2019-07-10 18:58:59 +02:00
Araq
78174857f8 fixes #10901 2019-07-10 16:10:20 +02:00
Araq
b03421d087 fixes #11683 2019-07-10 16:00:05 +02:00
Araq
bc7733827d make more parts of the stdlib compile with --styleCheck:error 2019-07-10 15:48:30 +02:00
Araq
6663dbbe57 fixes #11691 2019-07-10 15:28:35 +02:00
Huy
e5425b5f2f [feature] add unsafeColumnAt procs, that return unsafe cstring from InstantRow (#11647) 2019-07-10 14:56:09 +02:00
Araq
c94647aeca styleCheck: make the compiler and large parts of the stdlib compatible with --styleCheck:error 2019-07-10 12:42:41 +02:00
Ivan Bobev
96523cdd3e Make public additional types from sha1 module [feature] (#11694)
* Make public additional types from sha1 module

After making public newSha1State, update and finalize methods from the
sha1 module was forgotten to be made public Sha1Digest and Sha1State
types used by the new public methods.

* Update changelog.md with sha1 module changes
2019-07-10 10:20:08 +02:00
Araq
18182e4bfd linter: refactorings 2019-07-10 09:07:03 +02:00
Araq
ff4a9a226f style changes 2019-07-10 09:06:54 +02:00
Araq
bd689849f2 nim styleChecker: implemented all the missing features (bugfix) 2019-07-10 00:29:58 +02:00
Araq
c6c9e30379 minor system.nim style changes 2019-07-10 00:29:58 +02:00
Araq
7a39eb13a5 koch temp: use -d:leanCompiler if possible 2019-07-10 00:29:58 +02:00
Miran
2255d8795b [other] prettify collections (#11695) 2019-07-09 22:45:23 +02:00
Araq
55e8aefbea newruntime: async progress 2019-07-09 20:15:57 +02:00
Araq
73c570d1d9 control flow graph: don't ignore yield statements 2019-07-09 20:15:57 +02:00
Araq
ad58ed344a newruntime: map system.reset to =destroy 2019-07-09 20:15:57 +02:00
Arne Döring
eb059fa848 closes #11551 (#11693) 2019-07-09 19:38:38 +02:00
Araq
a85e20c125 newruntime: 'owned distinct' is a valid construct (required by async) 2019-07-09 15:23:46 +02:00
Araq
fa982b43f0 make tests green again 2019-07-09 13:29:16 +02:00
narimiran
96d49608c0 nimpretty: more comment indentation fixes 2019-07-09 13:15:35 +02:00
Araq
eefcea8892 nimpretty: more improvements 2019-07-09 11:38:01 +02:00
Araq
fc34193483 nimpretty: code cleanups 2019-07-09 11:38:01 +02:00
Araq
0193c8ad2e nimpretty: yet another improvement 2019-07-09 11:38:01 +02:00
Araq
7993d61d00 async: more 'owned' annotations 2019-07-09 11:38:00 +02:00
Araq
2c2f2de614 asyncmacro produces 'owned' types 2019-07-09 11:38:00 +02:00
Araq
f64179e7fe bugfix: allow type conversions between 'owned ref' types 2019-07-09 11:38:00 +02:00
Araq
7c62de0cb7 better error message for invalid types 2019-07-09 11:38:00 +02:00
Arne Döring
11dad688fe Offsetof fixes (#11690)
* first fixes

* more tests and fixes

* code normalization
2019-07-09 09:07:45 +02:00
Timothee Cour
063ae96a66 address comments 2019-07-08 15:24:20 -07:00
Timothee Cour
5ddea6a98f add tests for #8305 #7808 #10285 #11061 + other bugs 2019-07-08 15:24:20 -07:00
Timothee Cour
5fce81edfd make tests/concepts/t3330.nim disabled again: the order of candidates is machine dependent 2019-07-08 15:24:20 -07:00
Timothee Cour
6375df4c53 make tests/concepts/t3330.nim disabled again: the order of candidates is machine dependent 2019-07-08 15:24:20 -07:00
Timothee Cour
b80d70b0f3 fix tests 2019-07-08 15:24:20 -07:00
Timothee Cour
a6526695f0 fix #8305 #7808 #10285 #11061 + other bugs with type mismatch error msgs 2019-07-08 15:24:20 -07:00
Miran
b50ae6817a [other] test more packages (#11687) 2019-07-08 22:22:15 +02:00
Andreas Rumpf
124a584eb2 fixes #11530 2019-07-08 19:40:42 +02:00
Timothee Cour
655cb08461 [refactoring] nimbase.h: remove dead code which was confusing (#11682) 2019-07-08 10:36:02 +02:00
Jacek Sieka
9e7d885f35 dynlib: use posix module (#11623) 2019-07-08 09:14:35 +02:00
Miran
d0616ed115 nimpretty: don't introduce extra spaces after a colon or a comma (#11672) 2019-07-07 20:13:10 +02:00
Araq
085a21ebf4 fixes #11350 2019-07-07 17:17:14 +02:00
Andreas Rumpf
bab1f67971 fixes #11660 (#11677) 2019-07-07 15:25:25 +02:00
awr1
6a7f8e8ab5 [HCR] Added warning for using performCodeReload() in main module (#11667)
* [HCR] Added error for using performCodeReload() in main module

* [HCR] changed this to a warning, clarified usage

* [HCR] fixed typo
2019-07-07 09:18:33 +02:00
Andreas Rumpf
3258c1e2a3 fixes #11671 2019-07-07 00:29:43 +02:00
Andreas Rumpf
465815e894 improved the error message for #11494; closes #11494 2019-07-06 23:59:23 +02:00
Andreas Rumpf
6ce6bce12e fixes a finish.exe regression 2019-07-06 22:48:22 +02:00
Andreas Rumpf
d2684cdfd2 fixes #11447 2019-07-06 21:20:16 +02:00
Andreas Rumpf
cab0c3e544 fixes #3333 2019-07-06 20:38:10 +02:00
Andreas Rumpf
64e1408920 fixes #8316 (#11673) 2019-07-06 20:02:50 +02:00
Andreas Rumpf
2678fa679a fixes #7057 2019-07-06 15:24:14 +02:00
Andreas Rumpf
02b9af2f75 ABI fixes for OSX/BSD; fixes #6860 (#11666) 2019-07-06 13:00:29 +02:00
Juan Carlos
25cd8a5490 Documentation Diff, Typo (#11566)
* Documentation for Diff, add Examples and runnableExamples
2019-07-06 09:45:48 +02:00
Miran
34c09a98c7 nimpretty: improved detection of commas and semicolons (#11661)
* nimpretty: improved detection of commas and semicolons

* address the comments
2019-07-06 00:21:21 +02:00
Arne Döring
7d5d9f7703 introduce internal Int128 type, use it to fix case stmt checks (#11652)
* initial version of int128
* use int128 in case stmt
* fixes #11552
2019-07-05 22:45:32 +02:00
Miran
176eaf5c90 nimpretty: don't touch formatted multiline comments (#11663) 2019-07-05 21:47:01 +02:00
cooldome
d1f6c820dd Fixes #11662: render ops priority (#11664) 2019-07-05 21:25:36 +02:00
narimiran
2c0c0e772c nimpretty: nicer debugging [ci skip] 2019-07-05 10:08:52 +02:00
Miran
96a19ea1b4 nimpretty: relax line length rules when dealing with (inline) comments (#11657) 2019-07-05 09:32:56 +02:00
Timothee Cour
95f2f2396f fix #11651 exportc symbol not exported, leading to link error (#11658) 2019-07-05 07:53:21 +02:00
Andreas Rumpf
28c9c062a4 fixes #11610 (#11659) 2019-07-05 07:26:06 +02:00
Tomohiro
b64dd795b1 manual: document block expression (#11638) 2019-07-05 01:43:14 +02:00
Andreas Rumpf
5f515410af newruntime for async (#11650)
* fixes overloading resolution for passing owned(Future[string]) to Future[T]
* WIP: make --newruntime work with .async
* memtracker: make it compile again
* make Nimble compile again
2019-07-05 01:42:17 +02:00
Ivan Bobev
d914dca513 Make public some sha1 module procedures (#11655) [feature]
Make "newSha1State", "update" and "finalize" procedures from the sha1
module public in order to be possible to compute single sha1 hash of
multiple separate blocks of data.
2019-07-04 22:29:03 +02:00
Akito13
0a501932c2 Corrected example shown in documentation (#11654) [ci skip]
Used template within example was added to imports.
2019-07-04 15:59:29 +02:00
Graeme Cross
dad3c40f55 Fix the broken link in math.nim (#11653) [ci skip] 2019-07-04 13:24:19 +02:00
narimiran
4450fca6fd nimpretty: fix out of bounds error [ci skip] 2019-07-04 12:02:35 +02:00
Araq
a59f0adc50 nimpretty: nimpretty now understands splitting newlines 2019-07-04 11:32:15 +02:00
Araq
7d29f8b1a4 nimpretty: distinguish between the different kinds of newlines in Nim 2019-07-04 10:44:04 +02:00
Timothee Cour
64168d4aea fixes #8405: -d:useNimRtl now works even when {.rtl.} procs are used at compile time; CTFFI now works with {dynlib} (#11635) 2019-07-03 23:57:52 +02:00
Miran
0718d6c2cd [bugfix] fix wrong nimpretty unidents, refs #11616 (#11645) 2019-07-03 18:55:15 +02:00
Andreas Rumpf
045eeab6b4 fixes #11585 2019-07-03 15:38:24 +02:00
Timothee Cour
0ca71dd92c [bugfix] fix mach_absolute_time header; refs #11591 (#11593) 2019-07-03 14:59:07 +02:00
Miran
1e9316e23c [bugfix] fix #11484, acknowledge 'danger' flag (#11486) 2019-07-03 13:01:22 +02:00
Araq
c0db1705dc fixes #11510 2019-07-03 12:54:11 +02:00
Araq
476b4ff372 fixes #11636 2019-07-03 12:54:11 +02:00
Liam Sc
a157c2baef Added 'keys' iterator to JsonNode (#11597) [feature] 2019-07-03 08:06:22 +02:00
Arne Döring
20d0ef8afb [backport] fix #11320 (#11538)
* [backport] fix #11320
* fix test for 32 bit test
2019-07-03 08:00:40 +02:00
Hugo Locurcio
0a1cb631a2 Implement some custom formatting for input fields in the documentation (#11632)
* Implement some custom formatting for input fields in the documentation

Aside of resulting in more consistent appearance across browsers,
this also fixes input form rendering when using Firefox with a
dark system theme on Linux.

* change the expected html in the tests
2019-07-03 07:40:24 +02:00
Graeme Cross
ab6dec6e90 Documentation improvements to the times module (#11639)
* Typo and grammar fixes for the times module
* Minor typo fixes to the times module
2019-07-03 07:39:19 +02:00
Andreas Rumpf
71b7383f12 fixes #11479 (#11641) 2019-07-03 07:22:30 +02:00
Miran
c522a455df [bugfix] nimpretty indents multiline comments correctly (#11607) 2019-07-02 10:52:46 +02:00
Andreas Rumpf
cce8a739da fixes #11633 2019-07-01 23:53:41 +02:00
Andreas Rumpf
766960dc15 fixes #11515 (#11624)
* fixes #11515

* better fix for #11515; make tests green
2019-07-01 18:08:50 +02:00
Andreas Rumpf
9b949855c7 fixes #11618 (#11631) 2019-07-01 14:10:08 +02:00
alaviss
2c10b246ec assertions: fixes #11545 (#11605)
* assertions: properly fix #11545

* tests/assert: enable excessiveStackTrace

* tests/assert: add test case for #11545

* tfailedassert_stacktrace: disable excessiveStackTrace

* assertions: weird workaround for failing tests

This fixes megatest on *nix, but have no idea why
2019-07-01 13:19:07 +02:00
Araq
bd55c862a6 fixes #11617 2019-07-01 13:12:04 +02:00
Araq
c352892232 fixes #11628 2019-07-01 12:34:19 +02:00
Araq
413dff03a0 fixes #11614 2019-07-01 12:29:03 +02:00
Ico Doornekamp
a5686961bd Make repr use 'ptr' for ptr types instead of 'ref' (#11626) 2019-07-01 11:59:27 +02:00
Juan Carlos
d7a7662a7f Remove IO.js compat (long dead vanished project,superseed by NodeJS) (#11627) 2019-07-01 11:59:02 +02:00
Araq
dd39b11b13 [bugfix] make -d:nimSetUtf8CodePage switch work again 2019-07-01 10:35:52 +02:00
Andreas Rumpf
d37c4e44d3 added destructors.rst document 2019-07-01 08:51:47 +02:00
alaviss
e259f80fc7 msgs, ccgstmts: fixes #11572 (#11621)
* [refactor] msgs: toFilename now return just the filename

The C codegen uses just the file name for stacktrace when
excessiveStackTrace is off (see quotedName),
so there aren't any reason for other codegen to not do the same.

The file name is now cached in TFileInfo.shortName, which was introduced
for nimsuggest, and went unused after several refactoring of the
compiler.

A toProjPath() proc has been added for the previous behavior of
toFilename().

* ccgstmt: use quotedFilename() for raiseExceptionEx

This is the same proc used for stacktrace when --stacktrace:on

Fixes #11572

* msgs: handle case where file name is not available
2019-06-30 12:30:37 +02:00
Andreas Rumpf
7113c1e931 [other] additions to the manual 2019-06-29 23:41:25 +02:00
Araq
3606e035f5 fixes #11606 2019-06-28 21:13:03 +02:00
Araq
7ddb31262e fixes #11611 2019-06-28 21:04:49 +02:00
Ivan Bobev
5be5bf0222 Pass additional koch options to the nim compiler (#11615)
Add possibility when "koch tools" command is used, nim compiler options
to be passed. The current options are kept and the new user specified
options will be added to the end of the command line if present.

Example:
> koch --latest tools -d:danger --debugInfo --lineDir:on
bin\nim.exe c -o:bin\nimsuggest.exe -d:release -d:danger -d:danger
 --debugInfo --lineDir:on nimsuggest/nimsuggest.nim
...
bin\nim.exe c -o:bin\nimgrep.exe -d:release -d:danger --debugInfo
 --lineDir:on tools/nimgrep.nim
...
bin\nim.exe c -o:bin\vccexe.exe -d:danger --debugInfo --lineDir:on
 tools/vccexe/vccexe.nim
...
bin\nim.exe c -o:bin\nimpretty.exe -d:release -d:danger --debugInfo
 --lineDir:on nimpretty/nimpretty.nim
...
bin\nim.exe c -o:bin\nimfind.exe -d:release -d:danger --debugInfo
 --lineDir:on tools/nimfind.nim
...
bin\nim.exe c -o:bin\nimble.exe --noNimblePath --nilseqs:on -d:release
 -d:danger --debugInfo --lineDir:on dist\nimble\src\nimble.nim
2019-06-28 18:06:43 +02:00
Araq
284a8cb58a nimpretty: bugfix [bugfix] 2019-06-28 11:45:21 +02:00
Andreas Rumpf
d72edfb14b Merge pull request #11609 from zestyr/xmltree-typo
Fix typo in xmltree docs
2019-06-27 21:36:49 +02:00
Andreas Rumpf
765ff4b67b contributing.rst guide: Make the rules reflect the reality. 2019-06-27 21:28:53 +02:00
Andreas Rumpf
17bbce7c8a manual: typo 2019-06-27 21:25:07 +02:00
Andreas Rumpf
d9604d7d0b manual: document how accessors are resolved; fixes #11514 2019-06-27 21:25:07 +02:00
Zestyr
bab83c4d8b Fix typo in xmltree docs [ci skip] 2019-06-27 20:44:42 +02:00
Araq
f36a61e6d4 make tests green again 2019-06-27 17:10:11 +02:00
Andreas Rumpf
fb878330a9 fixes #11445 2019-06-27 14:46:38 +02:00
Andreas Rumpf
135fdde6a9 fixes #11523 2019-06-26 23:41:20 +02:00
Andreas Rumpf
19b142401c fixes #11525 2019-06-26 23:15:58 +02:00
Andreas Rumpf
48cbf1c496 Merge pull request #11598 from narimiran/fix-sharedtables
[bugfix] fix #11588, don't check if SharedTable is initialized
2019-06-26 23:11:34 +02:00
Andreas Rumpf
ce2777af5a fixes #11600 (#11602) 2019-06-26 23:10:20 +02:00
Miran
f65eaa51f1 [bugfix] fix #11532, nimpretty should ignore source code filters (#11603) 2019-06-26 23:09:57 +02:00
Andreas Rumpf
e083a1533b fixes #11098 2019-06-26 19:34:05 +02:00
narimiran
326e3ad09d [bugfix] fix #11588, don't check if SharedTable is initialized 2019-06-26 17:16:55 +02:00
Araq
b6fb47df77 fixes #11600 2019-06-26 15:55:27 +02:00
Miran
f288e1b11a [bugfix] fix #11469, new rules for a newline in nimpretty (#11512)
* [bugfix] fix #11469, new rules for a newline in nimpretty
* concatenate two lines if they have the same indentation level
2019-06-26 15:36:44 +02:00
Araq
0a81b038fd fixes #11577 2019-06-26 15:33:51 +02:00
alaviss
993b3909a8 [refactor] compiler/[msgs, reorder, semstmts]: use toMsgFilename where appropriate (#11595)
* compiler/msgs: toMsgFilename now operates on FileIndex
* compiler/reorder: use toMsgFilename for compiler messages
* compiler/semstmts: respect listFullPaths for recursive deps error
2019-06-26 14:38:19 +02:00
Toshiyuki-Tega
b7f8031e98 VCC discovery using vswhere (#6540) (#11559) 2019-06-26 10:52:22 +02:00
Juan Carlos
206f2478b8 Documentation highlite (#11596)
* Add Documentation with examples for highlite

* Add Documentation with examples for highlite
2019-06-26 10:28:11 +02:00
Andreas Rumpf
0f868b587b fixes #11563 (#11594) 2019-06-26 06:55:43 +02:00
alaviss
2f1a1b7106 compiler/[msgs, options]: confine --listFullPaths to compiler messages (#11583)
* compiler/[msgs, options]: make toFilename independent of listFullPaths

toFilename is used mainly in codegen, as such it should not follow
--listFullPaths

* compiler/msgs: use toMsgFilename for toFileLineCol

This proc is mainly used for compiler messages, so it should follow
--listFullPaths

* compiler/msgs: remove toFileLine

unused proc

* compiler/msgs: cleanup toMsgFilename

Also improved path choosing logic, /home should now be preferred over
../home on *nix
2019-06-26 02:40:10 +02:00
cooldome
0d50b0c8a7 increase dfa instruction limit (#11579) 2019-06-24 22:34:54 -07:00
Jasper Jenkins
91f0626dcb [bugfix] remove dangling ref (#11576) 2019-06-25 02:04:15 +02:00
Gérôme Fournier
181350f6c9 Fix out of bound access in cgi module (#11578)
When an HTTP request with a zero CONTENT_LENGTH is made,
attempting to access addr(result[0]) raise an exception as the 0 index
is out of bound
2019-06-25 02:03:44 +02:00
WhiteDuke
2a7cf71db3 Fix typo (#11573) 2019-06-25 00:24:51 +02:00
alaviss
403fd3ac43 assertions: make assert follow excessiveStackTrace (#11574) 2019-06-25 00:23:22 +02:00
alaviss
e9a23cee0a nim.cfg: disable excessiveStackTrace on release (#11575) 2019-06-25 00:22:30 +02:00
narimiran
436f570651 [documentation] fix #4630, document unsupported functions for JS 2019-06-24 12:52:54 +02:00
Arne Döring
e90d91f0e4 [refactoring] remove zeroExtend and friends from the compiler builtins. (#11531)
* remove zeroExtend and friends from the compiler builtins.
* fix jssys
2019-06-24 09:19:02 +02:00
Simon Krauter
800bc661b6 Spelling fixes in nimc.rst (#11569) 2019-06-23 15:15:55 -07:00
Juan Carlos
bb9b60604b [other] Documentation NimScript (#11548)
* Documentation of NimScript, update and expand, mention the benefits aside of its limitations, add examples, update the list of usable std lib modules
2019-06-23 20:08:21 +02:00
Giovanni Petrantoni
b81fd958d1 [feature] Add dynlib (required on windows/cpp) to nimCoroutines related gc_common procs (#11567) 2019-06-23 18:05:10 +02:00
Miran
3d50f7e2a1 [bugfix] fix OrderedTable iterators (#11562) 2019-06-22 22:28:45 -07:00
Andreas Rumpf
79c721d418 [bugfix] fixes #11524 2019-06-22 01:52:49 +02:00
Andreas Rumpf
0db3c670ac closes #11533 2019-06-21 20:45:00 +02:00
Andreas Rumpf
35df59b3ce [bugfix] fixes #11556 2019-06-21 20:38:18 +02:00
narimiran
12eebf48b6 [documentation] fix wrong link [ci skip] 2019-06-21 12:04:43 +02:00
Kaushal Modi
a4c613c110 [other] Improve the "tabs are not allowed" error message (#11554) 2019-06-20 22:16:06 +02:00
Miran
23e95dc629 [bugfix] fix delete in strutils and sequtils (#11535) 2019-06-20 21:04:37 +02:00
Miran
d6b0e46ee4 [bugfix] correct 'source' for documentation (#11540) 2019-06-20 21:03:48 +02:00
Miran
45bbf1ef5b [bugfix] fix OrderedTable default initialization (#11549) 2019-06-20 21:03:11 +02:00
Andreas Rumpf
55da84e141 [other] new experimental pragma .nodestroy for easier custom destructors 2019-06-20 19:41:03 +02:00
Andreas Rumpf
f310cf5250 [other] added system.dispose for owned refs 2019-06-20 19:40:18 +02:00
Andreas Rumpf
280193cc07 [bugfix] system.nim: make pop work with --newruntime 2019-06-20 19:39:42 +02:00
Andreas Rumpf
7e4748beee [bugfix] proper destruction for strings/seqs for --newruntime 2019-06-20 19:39:19 +02:00
Andreas Rumpf
bc9fb4885b [bugfix] system.nim: make pop work with --newruntime 2019-06-20 19:38:25 +02:00
Araq
678beb8ef9 [other] newruntime: add a simple closure iterator test 2019-06-20 11:31:21 +02:00
Araq
6adcc09877 [bugfix] newruntime: trivial closure iterator works 2019-06-20 11:31:20 +02:00
Araq
c83914b435 [refactoring] closureiters.nim: style change 2019-06-20 11:31:20 +02:00
Araq
50afafdb38 wip 2019-06-20 11:31:19 +02:00
Andreas Rumpf
af10788dcc WIP: closures for the newruntime [ci skip] 2019-06-20 11:30:42 +02:00
narimiran
16d81fa205 [bugfix] fix #11546, correct link for sequtils 2019-06-20 09:41:06 +02:00
narimiran
96bed814d2 [bugfix] fix #11543, add std/sums to theindex.html 2019-06-20 09:37:21 +02:00
Andreas Rumpf
0adb1c6223 newruntime: added yet another test 2019-06-20 08:38:29 +02:00
Andreas Rumpf
c65a5d754b [bugfix] owned closures (#11544) 2019-06-20 07:40:45 +02:00
Arne Döring
1a074fffa4 change newLit on Seq (#11542) 2019-06-19 20:14:54 +02:00
Araq
ab36ffbeb1 [bugfix] fixes #11517 2019-06-19 17:39:52 +02:00
Araq
ff89f7e33a libffi: style changes 2019-06-19 16:54:34 +02:00
narimiran
de88fdb86e Revert "makes travis OSX green again"
This reverts commit 79a23fe805.
2019-06-19 15:53:42 +02:00
Miran
ae5a4cea98 [other] update homebrew, fix travis fails on OSX (#11541) 2019-06-19 15:54:40 +02:00
narimiran
cf47c2c60c [other] documentation: deprecation comments are now auto-generated 2019-06-19 14:21:46 +02:00
alaviss
24ac13f653 [bugfix] gc_common: export foreign thread gc docs (#11536) 2019-06-19 12:41:22 +02:00
Araq
f67be92512 [feature] cleanup PR, refs #11424 2019-06-19 09:54:01 +02:00
Araq
296c48de5e fixes #11436 2019-06-19 09:48:55 +02:00
Araq
79a23fe805 makes travis OSX green again 2019-06-19 09:48:55 +02:00
Phạm Ngọc Quang Nam
7c637c2faf [bugfix] Fix smtp.nim unhandled exception (#11498) 2019-06-19 00:26:59 +02:00
Jasper Jenkins
8ee0f14ab6 literal array indices (#11424) 2019-06-18 14:16:33 +02:00
Araq
c99ce5051e add HCR document to the tools.rst list 2019-06-18 12:19:14 +02:00
Araq
38f05bb9a3 HCR: better documentation 2019-06-18 12:17:26 +02:00
Benjamin Summerton
a009cbdc2f Add cbrt() bindings for the JS Target (#11528)
`Math.cbrt()` exists:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cbrt

The binding was missing for the JavaScript backend.
2019-06-18 02:26:47 -04:00
yatsen1
c8268330be [feature] Add boehm gc finalizer (#11446) 2019-06-17 20:47:18 +02:00
Miran
ac3449b93b [bugfix] fix #11450, random.initRand crashes in JS backend (#11522) 2019-06-17 20:46:04 +02:00
Miran
6cad5c7861 [bugfix] fix #11482, fix nimsuggest range error (#11519)
The default starting parameters for `line` and `col` were switched.

See line 141: "line starts at 1, column at 0, dirtyfile is optional".
Also, in `TLineInfo` object, `line` is uint16, `col` is int16.
2019-06-17 20:41:41 +02:00
narimiran
b70fd0400e [other] introduce a separate changelog for backports, update
contributing guidelines
2019-06-17 12:15:47 +02:00
Juan Carlos
eb087b3546 [bugfix] Fixes #11434 , Update Tools Documentation (#11449) 2019-06-17 11:17:28 +02:00
Juan Carlos
aa7f23e1ee [bugfix] Fixes #11495 , Remove TinyC from help (#11508) 2019-06-17 11:03:18 +02:00
Phạm Ngọc Quang Nam
9f6187b46c Add starttls for smtp (#11500)
* Add starttls for smtp

* Update smtp.nim
2019-06-16 23:50:56 +01:00
Kaushal Modi
7182922622 [feature] Added os.delEnv; add delEnv support to nimscript too (#11466)
[feature] Fixes https://github.com/nim-lang/Nim/issues/11452.
2019-06-15 11:32:26 +02:00
Andreas Rumpf
eadea343ef [bugfix] fixes https://github.com/nim-lang/Nim/issues/11430
[bugfix] fixes https://github.com/nim-lang/Nim/issues/11430
2019-06-15 11:29:10 +02:00
Charles Blake
6dc6487311 Disambiguate idents now that all 3 rfind's are included in the RTL. 2019-06-15 03:46:21 -04:00
Andreas Rumpf
68cce40510 [bugfix] Add .47 as supported libssl version (#11503) 2019-06-14 23:03:00 +02:00
Kaushal Modi
d1ce86fdc6 [bugfix] Fix the link to "For Loop Macro" section (#11505) 2019-06-14 23:02:30 +02:00
SolitudeSF
e96afd6324 [bugfix] Add .47 as supported libssl version 2019-06-14 20:00:23 +03:00
Kaushal Modi
c656714623 [bugfix] Minor formatting fix in tut2 [ci skip] (#11501)
Monospace `untyped` like elsewhere in the tutorial.
2019-06-14 15:13:44 +02:00
Araq
57a83df745 [bugfix] nimpretty: better alignment; fixes #11467 2019-06-14 11:16:39 +02:00
Juan Carlos
80320c72d3 [bugfix] document the norewrite pragma (#11453)
* fixes #9454
* Peer review feedback, wording, move to experimental manual
2019-06-13 19:37:17 +02:00
Jasper Jenkins
bda9fd149c [refactoring] error instead of quit for basename (#11491) 2019-06-13 19:34:41 +02:00
Charles Blake
e11d582fa1 Merge branch 'devel' of https://github.com/nim-lang/Nim into devel 2019-06-13 10:21:11 -04:00
Charles Blake
e7188cdfa8 Add missing ,int to type signature in doc comment references. 2019-06-13 10:20:43 -04:00
Jasper Jenkins
06ef56ba72 [bugfix] fix quit errormsg in nimvm (#11490) 2019-06-13 15:30:30 +02:00
Simon Krauter
e2f99a2026 Update tut1: -d:release does not turn off *allruntime checks off anymore (#11492)
According to https://nim-lang.org/blog/2019/06/06/version-0200-released.html
"The -d:release switch now does not disable runtime checks anymore. "
2019-06-13 15:16:38 +02:00
Araq
165ea46284 [bugfix] nimpretty: fixes #11470 2019-06-13 10:58:27 +02:00
Araq
af39f26a3a [bugfix] nimpretty: fixes #11468 2019-06-13 10:42:37 +02:00
Araq
b70295c768 [other] nimsuggest: adhere to our style guide 2019-06-13 09:59:03 +02:00
alaviss
08fdffc717 [other] appveyor: use official dlls on nim-lang.org (#11473) 2019-06-12 17:09:36 +02:00
Dominik Picheta
73c44c6e9b [bugfix] Fixes async IO operations stalling even after socket is closed. (#11232) 2019-06-12 17:07:05 +02:00
Charles Blake
bde899d4f8 Attempt to close https://github.com/nim-lang/Nim/issues/11430 2019-06-12 07:44:56 -04:00
Jasper Jenkins
da035e9c83 [bugfix] fix nimpretty for absolute paths (#11480) 2019-06-12 11:59:25 +02:00
Araq
b056d32a79 [refactoring] liftdestructors.nim is callable from lambdalifting; refs #11217 2019-06-12 10:44:45 +02:00
Arne Döring
e4d0f4fee0 fix regression in semfold for old right shift (#11477) 2019-06-12 09:26:30 +02:00
Araq
c07973e313 [refactoring] liftdestructors is now a module of its own 2019-06-12 08:45:47 +02:00
Araq
549d8cc0c6 [other] make typeAllowed easier to debug by using structured programming 2019-06-12 08:45:47 +02:00
Andreas Rumpf
572b7c37a5 [other] preparations for --styleCheck:error for the Nim compiler (#11478) 2019-06-12 08:35:32 +02:00
Arne Döring
c7e1c665a1 [refactoring] refactor the compiler and stdlib to deprecation warnings (#11419) 2019-06-11 16:49:56 +02:00
Juan Carlos
3d13103443 [bugfix] Add .nimf to mimetypes (#11417) 2019-06-11 16:46:15 +02:00
Hitesh Jasani
a9aef65b2d [feature] Enable Oid usage in hashtables (#11472) 2019-06-11 15:06:46 +02:00
Miran
b3d2cd738a [other] better error message for IndexError for empty containers (#11476) 2019-06-11 14:34:21 +02:00
Andrii Riabushenko
7cfc7cfb26 fixes #11118 2019-04-30 21:46:45 +01:00
495 changed files with 11813 additions and 8231 deletions

View File

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

View File

@@ -15,10 +15,6 @@ cache:
- '%MINGW_ARCHIVE%'
- '%DLLS_ARCHIVE%'
matrix:
#allow_failures:
# - NIM_TEST_PACKAGES: true
fast_finish: true
install:
- ps: Install-Product node 8 # node 8 or later is required to test js async stuff

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

@@ -1,37 +1,41 @@
# v1.1 - XXXX-XX-XX
# v1.1 - xxxx-xx-xx
## Changes affecting backwards compatibility
### Breaking changes in the standard library
### Breaking changes in the compiler
## Library additions
## Library changes
- Added `os.delEnv` and `nimscript.delEnv`. (#11466)
- Enable Oid usage in hashtables. (#11472)
#
# Language additions
## Language additions
## Language changes
### Tool changes
### Compiler changes
- VM can now cast integer type arbitrarily. (#11459)
## Bugfixes

View File

@@ -1,31 +0,0 @@
# v0.20.4 - xxxx-xx-xx
## Changes affecting backwards compatibility
### Breaking changes in the standard library
### Breaking changes in the compiler
## Library additions
## Library changes
## Language additions
## Language changes
### Tool changes
### Compiler changes
## Bugfixes

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,138 @@
# v1.0 - 2019-09-23
## Changes affecting backwards compatibility
- The switch ``-d:nimBinaryStdFiles`` does not exist anymore. Instead
stdin/stdout/stderr are binary files again. This change only affects
Windows.
- On Windows console applications the code-page is set at program startup
to UTF-8. Use the new switch `-d:nimDontSetUtf8CodePage` to disable this
feature.
- The language definition and compiler are now stricter about ``gensym``'ed
symbols in hygienic templates. See the section in the
[manual](https://nim-lang.org/docs/manual.html#templates-hygiene-in-templates)
for further details. Use the compiler switch `--oldgensym:on` for a
transition period.
### Breaking changes in the standard library
- We removed `unicode.Rune16` without any deprecation period as the name
was wrong (see the [RFC](https://github.com/nim-lang/RFCs/issues/151) for details)
and we didn't find any usages of it in the wild. If you still need it, add this
piece of code to your project:
```nim
type
Rune16* = distinct int16
```
- `exportc` now uses C instead of C++ mangling with `nim cpp`, matching behavior
of `importc`, see #10578.
Use the new `exportcpp` to mangle as C++ when using `nim cpp`.
### Breaking changes in the compiler
- A bug allowing `int` to be implicitly converted to range types of smaller size
(e.g `range[0'i8..10'i8]`) has been fixed.
## Library additions
- `encodings.getCurrentEncoding` now distinguishes between the console's
encoding and the OS's encoding. This distinction is only meaningful on
Windows.
- Added `system.getOsFileHandle` which is usually more useful
than `system.getFileHandle`. This distinction is only meaningful on
Windows.
- Added a `json.parseJsonFragments` iterator that can be used to speedup
JSON processing substantially when there are JSON fragments separated
by whitespace.
## Library changes
- Added `os.delEnv` and `nimscript.delEnv`. (#11466)
- Enabled Oid usage in hashtables. (#11472)
- Added `unsafeColumnAt` procs, that return unsafe cstring from InstantRow. (#11647)
- Make public `Sha1Digest` and `Sha1State` types and `newSha1State`,
`update` and `finalize` procedures from `sha1` module. (#11694)
- Added the `std/monotimes` module which implements monotonic timestamps.
- Consistent error handling of two `exec` overloads. (#10967)
- Officially the following modules now have an unstable API:
- std/varints
- core/allocators
- core/hotcodereloading
- asyncstreams
- base64
- browsers
- collections/rtarrays
- collections/sharedlist
- collections/sharedtable
- concurrency/atomics
- concurrency/cpuload
- concurrency/threadpool
- coro
- endians
- httpcore
- parsesql
- pathnorm
- reservedmem
- typetraits
Every other stdlib module is API stable with respect to version 1.
## Language additions
- Inline iterators returning `lent T` types are now supported, similarly to
iterators returning `var T`:
```nim
iterator myitems[T](x: openarray[T]): lent T
iterator mypairs[T](x: openarray[T]): tuple[idx: int, val: lent T]
```
- Added an `importjs` pragma that can now be used instead of `importcpp`
and `importc` to import symbols from JavaScript. `importjs` for routines always
takes a "pattern" for maximum flexibility.
## Language changes
- `uint64` is now finally a regular ordinal type. This means `high(uint64)` compiles
and yields the correct value.
### Tool changes
- The Nim compiler now does not recompile the Nim project via ``nim c -r`` if
no dependent Nim file changed. This feature can be overridden by
the ``--forceBuild`` command line option.
- The Nim compiler now warns about unused module imports. You can use a
top level ``{.used.}`` pragma in the module that you want to be importable
without producing this warning.
- The "testament" testing tool's name was changed
from `tester` to `testament` and is generally available as a tool to run Nim
tests automatically.
### Compiler changes
- VM can now cast integer type arbitrarily. (#11459)
## Bugfixes

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

@@ -13,7 +13,7 @@
## Library additions
- `set[T].len` is now an alias for `set[T].card` (cardinality)
## Library changes

View File

@@ -22,14 +22,14 @@ proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
result = arNo
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result = isPartOfAux(n.sons[i], b, marker)
if result == arYes: return
of nkRecCase:
assert(n.sons[0].kind == nkSym)
result = isPartOfAux(n.sons[0], b, marker)
if result == arYes: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
@@ -52,7 +52,7 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
of tyGenericInst, tyDistinct, tyAlias, tySink:
result = isPartOfAux(lastSon(a), b, marker)
of tyArray, tySet, tyTuple:
for i in 0 ..< sonsLen(a):
for i in 0 ..< len(a):
result = isPartOfAux(a.sons[i], b, marker)
if result == arYes: return
else: discard
@@ -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

@@ -10,7 +10,9 @@
# abstract syntax tree + symbol table
import
lineinfos, hashes, options, ropes, idents, idgen
lineinfos, hashes, options, ropes, idents, idgen, int128
export int128
type
TCallingConvention* = enum
@@ -183,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
@@ -226,7 +228,7 @@ type
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # already 36 flags!
TSymFlag* = enum # already 38 flags!
sfUsed, # read access of sym (for warnings) or simply used
sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed
@@ -237,6 +239,7 @@ type
sfForward, # symbol is forward declared
sfImportc, # symbol is external; imported
sfExportc, # symbol is exported (under a specified name)
sfMangleCpp, # mangle as cpp (combines with `sfExportc`)
sfVolatile, # variable is volatile
sfRegister, # variable should be placed in a register
sfPure, # object is "pure" that means it has no type-information
@@ -269,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
@@ -280,6 +283,7 @@ type
sfGeneratedOp # proc is a generated '='; do not inject destructors in it
# variable is generated closure environment; requires early
# destruction for --newruntime.
sfTemplateParam # symbol is a template parameter
TSymFlags* = set[TSymFlag]
@@ -287,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
@@ -531,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]
@@ -577,7 +578,6 @@ type
const
routineKinds* = {skProc, skFunc, skMethod, skIterator,
skConverter, skMacro, skTemplate}
tfIncompleteStruct* = tfVarargs
tfUnion* = tfNoSideEffect
tfGcSafe* = tfThread
tfObjHasKids* = tfEnumHasHoles
@@ -606,7 +606,6 @@ type
mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI,
mMinI, mMaxI,
mMinF64, mMaxF64,
mAddU, mSubU, mMulU, mDivU, mModU,
mEqI, mLeI, mLtI,
mEqF64, mLeF64, mLtF64,
@@ -619,9 +618,7 @@ type
mXor, mEqCString, mEqProc,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
mToFloat, mToBiggestFloat,
mToInt, mToBiggestInt,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
@@ -665,7 +662,8 @@ type
mInstantiationInfo, mGetTypeInfo,
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
mSymIsInstantiationOf
mSymIsInstantiationOf, mNodeId
# things that we can evaluate safely at compile time, even if not asked for it:
const
@@ -678,7 +676,6 @@ const
mAddF64, mSubF64, mMulF64, mDivF64,
mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
mMinI, mMaxI,
mMinF64, mMaxF64,
mAddU, mSubU, mMulU, mDivU, mModU,
mEqI, mLeI, mLtI,
mEqF64, mLeF64, mLtF64,
@@ -689,9 +686,7 @@ const
mEqB, mLeB, mLtB,
mEqRef, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
mToFloat, mToBiggestFloat,
mToInt, mToBiggestInt,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
@@ -854,7 +849,6 @@ type
# for modules, an unique index corresponding
# to the module's fileIdx
# for variables a slot index for the evaluator
# for routines a superop-ID
offset*: int # offset of record field
loc*: TLoc
annex*: PLib # additional fields (seldom used, so we use a
@@ -901,6 +895,7 @@ type
size*: BiggestInt # the size of the type in bytes
# -1 means that the size is unkwown
align*: int16 # the type's alignment requirements
paddingAtEnd*: int16 #
lockLevel*: TLockLevel # lock level as required for deadlock checking
loc*: TLoc
typeInst*: PType # for generic instantiations the tyGenericInst that led to this
@@ -1024,7 +1019,9 @@ proc isCallExpr*(n: PNode): bool =
proc discardSons*(father: PNode)
proc len*(n: PNode): int {.inline.} =
type Indexable = PNode | PType
proc len*(n: Indexable): int {.inline.} =
when defined(nimNoNilSeqs):
result = len(n.sons)
else:
@@ -1048,8 +1045,6 @@ proc add*(father, son: PNode) =
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
type Indexable = PNode | PType
template `[]`*(n: Indexable, i: int): Indexable = n.sons[i]
template `[]=`*(n: Indexable, i: int; x: Indexable) = n.sons[i] = x
@@ -1057,7 +1052,7 @@ template `[]`*(n: Indexable, i: BackwardsIndex): Indexable = n[n.len - i.int]
template `[]=`*(n: Indexable, i: BackwardsIndex; x: Indexable) = n[n.len - i.int] = x
when defined(useNodeIds):
const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879
const nodeIdToDebug* = -1 # 2322968
var gNodeId: int
proc newNode*(kind: TNodeKind): PNode =
@@ -1235,10 +1230,48 @@ proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
result = newNode(kind)
result.intVal = intVal
proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode =
result = newIntNode(kind, intVal)
proc newIntNode*(kind: TNodeKind, intVal: Int128): PNode =
result = newNode(kind)
result.intVal = castToInt64(intVal)
proc lastSon*(n: Indexable): Indexable = n.sons[^1]
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
## Used throughout the compiler code to test whether a type tree contains or
## doesn't contain a specific type/types - it is often the case that only the
## last child nodes of a type tree need to be searched. This is a really hot
## path within the compiler!
result = t
while result.kind in kinds: result = lastSon(result)
proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
# 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}
case skipTypes(typ, abstractVarRange).kind
of tyInt: result = newNode(nkIntLit)
of tyInt8: result = newNode(nkInt8Lit)
of tyInt16: result = newNode(nkInt16Lit)
of tyInt32: result = newNode(nkInt32Lit)
of tyInt64: result = newNode(nkInt64Lit)
of tyChar: result = newNode(nkCharLit)
of tyUInt: result = newNode(nkUIntLit)
of tyUInt8: result = newNode(nkUInt8Lit)
of tyUInt16: result = newNode(nkUInt16Lit)
of tyUInt32: result = newNode(nkUInt32Lit)
of tyUInt64: result = newNode(nkUInt64Lit)
else: # tyBool, tyEnum
# XXX: does this really need to be the kind nkIntLit?
result = newNode(nkIntLit)
result.intVal = intVal
result.typ = typ
proc newIntTypeNode*(intVal: Int128, typ: PType): PNode =
# XXX: introduce range check
newIntTypeNode(castToInt64(intVal), typ)
proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
result = newNode(kind)
result.floatVal = floatVal
@@ -1305,7 +1338,7 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
if a.lode == nil: a.lode = b.lode
if a.r == nil: a.r = b.r
proc newSons*(father: PNode, length: int) =
proc newSons*(father: Indexable, length: int) =
when defined(nimNoNilSeqs):
setLen(father.sons, length)
else:
@@ -1314,21 +1347,6 @@ proc newSons*(father: PNode, length: int) =
else:
setLen(father.sons, length)
proc newSons*(father: PType, length: int) =
when defined(nimNoNilSeqs):
setLen(father.sons, length)
else:
if isNil(father.sons):
newSeq(father.sons, length)
else:
setLen(father.sons, length)
proc sonsLen*(n: PType): int = n.sons.len
proc len*(n: PType): int = n.sons.len
proc sonsLen*(n: PNode): int = n.sons.len
proc lastSon*(n: PNode): PNode = n.sons[^1]
proc lastSon*(n: PType): PType = n.sons[^1]
proc assignType*(dest, src: PType) =
dest.kind = src.kind
dest.flags = src.flags
@@ -1346,8 +1364,8 @@ proc assignType*(dest, src: PType) =
mergeLoc(dest.sym.loc, src.sym.loc)
else:
dest.sym = src.sym
newSons(dest, sonsLen(src))
for i in 0 ..< sonsLen(src): dest.sons[i] = src.sons[i]
newSons(dest, len(src))
for i in 0 ..< len(src): dest.sons[i] = src.sons[i]
proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
result = newType(t.kind, owner)
@@ -1423,14 +1441,6 @@ proc initNodeTable*(x: var TNodeTable) =
x.counter = 0
newSeq(x.data, StartSize)
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
## Used throughout the compiler code to test whether a type tree contains or
## doesn't contain a specific type/types - it is often the case that only the
## last child nodes of a type tree need to be searched. This is a really hot
## path within the compiler!
result = t
while result.kind in kinds: result = lastSon(result)
proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =
result = t
var i = maxIters
@@ -1469,14 +1479,14 @@ proc propagateToOwner*(owner, elem: PType) =
if tfHasAsgn in elem.flags:
let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink})
if o2.kind in {tyTuple, tyObject, tyArray,
tySequence, tyOpt, tySet, tyDistinct}:
tySequence, tyOpt, tySet, tyDistinct, tyOpenArray, tyVarargs}:
o2.flags.incl tfHasAsgn
owner.flags.incl tfHasAsgn
if tfHasOwned in elem.flags:
let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink})
if o2.kind in {tyTuple, tyObject, tyArray,
tySequence, tyOpt, tySet, tyDistinct}:
tySequence, tyOpt, tySet, tyDistinct, tyOpenArray, tyVarargs}:
o2.flags.incl tfHasOwned
owner.flags.incl tfHasOwned
@@ -1509,7 +1519,7 @@ proc delSon*(father: PNode, idx: int) =
if father.len == 0: return
else:
if isNil(father.sons): return
var length = sonsLen(father)
var length = len(father)
for i in idx .. length - 2: father.sons[i] = father.sons[i + 1]
setLen(father.sons, length - 1)
@@ -1550,7 +1560,7 @@ proc shallowCopy*(src: PNode): PNode =
of nkSym: result.sym = src.sym
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
else: newSeq(result.sons, sonsLen(src))
else: newSeq(result.sons, len(src))
proc copyTree*(src: PNode): PNode =
# copy a whole syntax tree; performs deep copying
@@ -1571,12 +1581,12 @@ proc copyTree*(src: PNode): PNode =
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
else:
newSeq(result.sons, sonsLen(src))
for i in 0 ..< sonsLen(src):
newSeq(result.sons, len(src))
for i in 0 ..< len(src):
result.sons[i] = copyTree(src.sons[i])
proc hasSonWith*(n: PNode, kind: TNodeKind): bool =
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if n.sons[i].kind == kind:
return true
result = false
@@ -1594,30 +1604,43 @@ proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
case n.kind
of nkEmpty..nkNilLit: result = n.kind in kinds
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if n.kind in kinds or containsNode(n.sons[i], kinds): return true
proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
case n.kind
of nkEmpty..nkNilLit: result = n.kind == kind
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
return true
result = false
proc getInt*(a: PNode): BiggestInt =
proc getInt*(a: PNode): Int128 =
case a.kind
of nkCharLit..nkUInt64Lit: result = a.intVal
of nkCharLit, nkUIntLit..nkUInt64Lit:
result = toInt128(cast[uint64](a.intVal))
of nkInt8Lit..nkInt64Lit:
result = toInt128(a.intVal)
of nkIntLit:
# XXX: enable this assert
# assert a.typ.kind notin {tyChar, tyUint..tyUInt64}
result = toInt128(a.intVal)
else:
raiseRecoverableError("cannot extract number from invalid AST node")
proc getInt64*(a: PNode): int64 {.deprecated: "use getInt".} =
case a.kind
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
result = a.intVal
else:
raiseRecoverableError("cannot extract number from invalid AST node")
#internalError(a.info, "getInt")
#doAssert false, "getInt"
#result = 0
proc getFloat*(a: PNode): BiggestFloat =
case a.kind
of nkFloatLiterals: result = a.floatVal
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
result = BiggestFloat a.intVal
else:
raiseRecoverableError("cannot extract number from invalid AST node")
#doAssert false, "getFloat"

View File

@@ -31,6 +31,15 @@ when declared(echo):
proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.}
proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.}
proc typekinds*(t: PType) {.deprecated.} =
var t = t
var s = ""
while t != nil and t.len > 0:
s.add $t.kind
s.add " "
t = t.lastSon
echo s
template debug*(x: PSym|PType|PNode) {.deprecated.} =
when compiles(c.config):
debug(c.config, x)
@@ -77,7 +86,6 @@ proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
# ---------------------------------------------------------------------------
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym
proc lookupInRecord*(n: PNode, field: PIdent): PSym
proc mustRehash*(length, counter: int): bool
proc nextTry*(h, maxHash: Hash): Hash {.inline.}
@@ -117,7 +125,7 @@ proc sameValue*(a, b: PNode): bool =
result = false
case a.kind
of nkCharLit..nkUInt64Lit:
if b.kind in {nkCharLit..nkUInt64Lit}: result = a.intVal == b.intVal
if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) == getInt(b)
of nkFloatLit..nkFloat64Lit:
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit:
@@ -131,8 +139,8 @@ proc leValue*(a, b: PNode): bool =
# a <= b?
result = false
case a.kind
of nkCharLit..nkUInt32Lit:
if b.kind in {nkCharLit..nkUInt32Lit}: result = a.intVal <= b.intVal
of nkCharLit..nkUInt64Lit:
if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) <= getInt(b)
of nkFloatLit..nkFloat64Lit:
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal
of nkStrLit..nkTripleStrLit:
@@ -152,14 +160,14 @@ proc lookupInRecord(n: PNode, field: PIdent): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result = lookupInRecord(n.sons[i], field)
if result != nil: return
of nkRecCase:
if (n.sons[0].kind != nkSym): return nil
result = lookupInRecord(n.sons[0], field)
if result != nil: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
result = lookupInRecord(lastSon(n.sons[i]), field)
@@ -174,14 +182,54 @@ proc getModule*(s: PSym): PSym =
assert((result.kind == skModule) or (result.owner != result))
while result != nil and result.kind != skModule: result = result.owner
proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym =
for i in start ..< sonsLen(list):
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym =
for i in start ..< len(list):
if list.sons[i].kind == nkSym:
result = list.sons[i].sym
if result.name.id == ident.id: return
else: return nil
result = nil
proc sameIgnoreBacktickGensymInfo(a, b: string): bool =
if a[0] != b[0]: return false
var alen = a.len - 1
while alen > 0 and a[alen] != '`': dec(alen)
if alen <= 0: alen = a.len
var i = 1
var j = 1
while true:
while i < alen and a[i] == '_': inc i
while j < b.len and b[j] == '_': inc j
var aa = if i < alen: toLowerAscii(a[i]) else: '\0'
var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
if aa != bb: return false
# the characters are identical:
if i >= alen:
# both cursors at the end:
if j >= b.len: return true
# not yet at the end of 'b':
return false
elif j >= b.len:
return false
inc i
inc j
proc getNamedParamFromList*(list: PNode, ident: PIdent): PSym =
## Named parameters are special because a named parameter can be
## gensym'ed and then they have '`<number>' suffix that we need to
## ignore, see compiler / evaltempl.nim, snippet:
##
## .. code-block:: nim
##
## result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
## if c.instLines: actual.info else: templ.info)
for i in 1 ..< len(list):
let it = list[i].sym
if it.name.id == ident.id or
sameIgnoreBacktickGensymInfo(it.name.s, ident.s): return it
proc hashNode(p: RootRef): Hash =
result = hash(cast[pointer](p))
@@ -279,9 +327,9 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope(
strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
else:
if sonsLen(n) > 0:
if len(n) > 0:
sonsRope = rope("[")
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if i > 0: add(sonsRope, ",")
addf(sonsRope, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n.sons[i],
marker, indent + 4, maxRecDepth - 1)])
@@ -328,9 +376,9 @@ proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
else:
addf(result, ",$N$1\"ident\": null", [istr])
else:
if sonsLen(n) > 0:
if len(n) > 0:
addf(result, ",$N$1\"sons\": [", [istr])
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if i > 0: add(result, ",")
addf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n.sons[i],
marker, indent + 4, maxRecDepth - 1)])
@@ -515,12 +563,12 @@ proc value(this: var DebugPrinter; value: PType) =
this.key "n"
this.value value.n
if sonsLen(value) > 0:
if len(value) > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
for i in 0 ..< len(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
if i != len(value) - 1:
this.comma
this.closeBracket
@@ -568,12 +616,12 @@ proc value(this: var DebugPrinter; value: PNode) =
if this.renderSymType and value.typ != nil:
this.key "typ"
this.value value.typ
if sonsLen(value) > 0:
if len(value) > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
for i in 0 ..< len(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
if i != len(value) - 1:
this.comma
this.closeBracket

View File

@@ -120,7 +120,7 @@ proc hashType(c: var MD5Context, t: PType) =
case t.kind
of tyGenericBody, tyGenericInst, tyGenericInvocation:
for i in 0 ..< sonsLen(t)-ord(t.kind != tyGenericInvocation):
for i in 0 ..< len(t)-ord(t.kind != tyGenericInvocation):
c.hashType t.sons[i]
of tyUserTypeClass:
internalAssert t.sym != nil and t.sym.owner != nil
@@ -128,7 +128,7 @@ proc hashType(c: var MD5Context, t: PType) =
of tyUserTypeClassInst:
let body = t.base
c.hashSym body.sym
for i in 1 .. sonsLen(t) - 2:
for i in 1 .. len(t) - 2:
c.hashType t.sons[i]
of tyFromExpr:
c.hashTree(t.n)
@@ -137,15 +137,15 @@ proc hashType(c: var MD5Context, t: PType) =
c.hashType(t.sons[1])
of tyTuple:
if t.n != nil:
assert(sonsLen(t.n) == sonsLen(t))
for i in 0 ..< sonsLen(t.n):
assert(len(t.n) == len(t))
for i in 0 ..< len(t.n):
assert(t.n.sons[i].kind == nkSym)
c &= t.n.sons[i].sym.name.s
c &= ":"
c.hashType(t.sons[i])
c &= ","
else:
for i in 0 ..< sonsLen(t): c.hashType t.sons[i]
for i in 0 ..< len(t): c.hashType t.sons[i]
of tyRange:
c.hashTree(t.n)
c.hashType(t.sons[0])
@@ -238,7 +238,7 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
encodeVInt(n.sym.id, result)
pushSym(w, n.sym)
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
encodeNode(w, n.info, n.sons[i], result)
add(result, ')')
@@ -304,7 +304,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
add(result, '=')
encodeVInt(t.align, result)
encodeLoc(w, t.loc, result)
for i in 0 ..< sonsLen(t):
for i in 0 ..< len(t):
if t.sons[i] == nil:
add(result, "^()")
else:

View File

@@ -79,9 +79,19 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc openArrayLoc(p: BProc, n: PNode): Rope =
var a: TLoc
let q = skipConv(n)
var q = skipConv(n)
var skipped = false
while q.kind == nkStmtListExpr and q.len > 0:
skipped = true
q = q.lastSon
if getMagic(q) == mSlice:
# magic: pass slice to openArray:
if skipped:
q = skipConv(n)
while q.kind == nkStmtListExpr and q.len > 0:
for i in 0..q.len-2:
genStmts(p, q[i])
q = q.lastSon
var b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
@@ -90,21 +100,23 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
let dest = getTypeDesc(p.module, n.typ.sons[0])
case ty.kind
of tyArray:
let first = firstOrd(p.config, ty)
let first = toInt64(firstOrd(p.config, ty))
if first == 0:
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
result = "($4*)(($1)+($2)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
else:
result = "($1)+(($2)-($4)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first)]
of tyOpenArray, tyVarargs, tyUncheckedArray:
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
result = "($5*)($1)+(($2)-($4)), ($3)-($2)+1" %
[rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first), dest]
of tyOpenArray, tyVarargs, tyUncheckedArray, tyCString:
result = "($4*)($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
of tyString, tySequence:
if skipTypes(n.typ, abstractInst).kind == tyVar and
not compileToCpp(p.module):
result = "(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p)]
result = "($5*)(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
result = "$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p)]
result = "($5*)$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
else:
@@ -174,7 +186,7 @@ proc genArgNoParam(p: BProc, n: PNode): Rope =
result = rdLoc(a)
template genParamLoop(params) {.dirty.} =
if i < sonsLen(typ):
if i < len(typ):
assert(typ.n.sons[i].kind == nkSym)
let paramType = typ.n.sons[i]
if not paramType.typ.isCompileTimeOnly:
@@ -184,8 +196,8 @@ template genParamLoop(params) {.dirty.} =
if params != nil: add(params, ~", ")
add(params, genArgNoParam(p, ri.sons[i]))
proc addActualPrefixForHCR(res: var Rope, module: PSym, sym: PSym) =
if sym.flags * {sfImportc, sfNonReloadable} == {} and
proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
if sym.flags * {sfImportc, sfNonReloadable} == {} and sym.loc.k == locProc and
(sym.typ.callConv == ccInline or sym.owner.id == module.id):
res = res & "_actual".rope
@@ -197,13 +209,13 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInstOwned)
assert(typ.kind == tyProc)
assert(sonsLen(typ) == sonsLen(typ.n))
var length = sonsLen(ri)
assert(len(typ) == len(typ.n))
var length = len(ri)
for i in 1 ..< length:
genParamLoop(params)
var callee = rdLoc(op)
if p.hcrOn and ri.sons[0].kind == nkSym:
callee.addActualPrefixForHCR(p.module.module, ri.sons[0].sym)
callee.addActualSuffixForHCR(p.module.module, ri.sons[0].sym)
fixupCall(p, le, ri, d, callee, params)
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
@@ -222,9 +234,9 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
var typ = skipTypes(ri.sons[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
var length = len(ri)
for i in 1 ..< length:
assert(sonsLen(typ) == sonsLen(typ.n))
assert(len(typ) == len(typ.n))
genParamLoop(pl)
template genCallPattern {.dirty.} =
@@ -236,7 +248,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
let rawProc = getRawProcType(p, typ)
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
if sonsLen(ri) > 1: add(pl, ~", ")
if len(ri) > 1: add(pl, ~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
# Great, we can use 'd':
@@ -268,7 +280,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
genCallPattern()
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
if i < sonsLen(typ):
if i < len(typ):
# 'var T' is 'T&' in C++. This means we ignore the request of
# any nkHiddenAddr when it's a 'var T'.
let paramType = typ.n.sons[i]
@@ -345,7 +357,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
# for better or worse c2nim translates the 'this' argument to a 'var T'.
# However manual wrappers may also use 'ptr T'. In any case we support both
# for convenience.
internalAssert p.config, i < sonsLen(typ)
internalAssert p.config, i < len(typ)
assert(typ.n.sons[i].kind == nkSym)
# if the parameter is lying (tyVar) and thus we required an additional deref,
# skip the deref:
@@ -382,11 +394,14 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
while i < pat.len:
case pat[i]
of '@':
if j < ri.len:
result.add genOtherArg(p, ri, j, typ)
for k in j+1 ..< ri.len:
result.add(~", ")
result.add genOtherArg(p, ri, k, typ)
var first = true
for k in j ..< ri.len:
let arg = genOtherArg(p, ri, k, typ)
if arg.len > 0:
if not first:
result.add(~", ")
first = false
result.add arg
inc i
of '#':
if i+1 < pat.len and pat[i+1] in {'+', '@'}:
@@ -436,8 +451,8 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
assert(sonsLen(typ) == sonsLen(typ.n))
var length = len(ri)
assert(len(typ) == len(typ.n))
# don't call '$' here for efficiency:
let pat = ri.sons[0].sym.loc.r.data
internalAssert p.config, pat.len > 0
@@ -472,7 +487,7 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var params: Rope
for i in 2 ..< length:
if params != nil: params.add(~", ")
assert(sonsLen(typ) == sonsLen(typ.n))
assert(len(typ) == len(typ.n))
add(params, genOtherArg(p, ri, i, typ))
fixupCall(p, le, ri, d, pl, params)
@@ -484,8 +499,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
assert(sonsLen(typ) == sonsLen(typ.n))
var length = len(ri)
assert(len(typ) == len(typ.n))
# don't call '$' here for efficiency:
let pat = ri.sons[0].sym.loc.r.data
@@ -507,8 +522,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
add(pl, ~": ")
add(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
for i in start ..< length:
assert(sonsLen(typ) == sonsLen(typ.n))
if i >= sonsLen(typ):
assert(len(typ) == len(typ.n))
if i >= len(typ):
internalError(p.config, ri.info, "varargs for objective C method?")
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
@@ -518,7 +533,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
add(pl, genArg(p, ri.sons[i], param, ri))
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
if sonsLen(ri) > 1: add(pl, ~" ")
if len(ri) > 1: add(pl, ~" ")
# beware of 'result = p(result)'. We always allocate a temporary:
if d.k in {locTemp, locNone}:
# We already got a temp. Great, special case it:

View File

@@ -30,6 +30,9 @@ proc intLiteral(i: BiggestInt): Rope =
else:
result = ~"(IL64(-9223372036854775807) - IL64(1))"
proc intLiteral(i: Int128): Rope =
intLiteral(toInt64(i))
proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
case n.kind
of nkCharLit..nkUInt64Lit:
@@ -585,8 +588,6 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mBitxorI: applyFormat("($4)($1 ^ $2)")
of mMinI: applyFormat("(($1 <= $2) ? $1 : $2)")
of mMaxI: applyFormat("(($1 >= $2) ? $1 : $2)")
of mMinF64: applyFormat("(($1 <= $2) ? $1 : $2)")
of mMaxF64: applyFormat("(($1 >= $2) ? $1 : $2)")
of mAddU: applyFormat("($4)((NU$3)($1) + (NU$3)($2))")
of mSubU: applyFormat("($4)((NU$3)($1) - (NU$3)($2))")
of mMulU: applyFormat("($4)((NU$3)($1) * (NU$3)($2))")
@@ -660,17 +661,6 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
applyFormat("$1")
of mUnaryMinusF64:
applyFormat("-($1)")
of mAbsF64:
applyFormat("($1 < 0? -($1) : ($1))")
# BUGFIX: fabs() makes problems for Tiny C
of mToFloat:
applyFormat("((double) ($1))")
of mToBiggestFloat:
applyFormat("((double) ($1))")
of mToInt:
applyFormat("float64ToInt32($1)")
of mToBiggestInt:
applyFormat("float64ToInt64($1)")
else:
assert false, $op
@@ -807,7 +797,7 @@ proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
var test, u, v: TLoc
for i in 1 ..< sonsLen(e):
for i in 1 ..< len(e):
var it = e.sons[i]
assert(it.kind in nkCallKinds)
assert(it.sons[0].kind == nkSym)
@@ -822,7 +812,8 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
v.r.add(".")
v.r.add(disc.sym.loc.r)
genInExprAux(p, it, u, v, test)
let strLit = genStringLiteral(p.module, newStrNode(nkStrLit, field.name.s))
let msg = genFieldError(field, disc.sym)
let strLit = genStringLiteral(p.module, newStrNode(nkStrLit, msg))
if op.magic == mNot:
linefmt(p, cpsStmts,
"if ($1) #raiseFieldError($2);$n",
@@ -1036,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:
@@ -1096,7 +1087,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
var L = 0
var appends: Rope = nil
var lens: Rope = nil
for i in 0 .. sonsLen(e) - 2:
for i in 0 .. len(e) - 2:
# compute the length expression:
initLocExpr(p, e.sons[i + 1], a)
if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
@@ -1135,7 +1126,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
assert(d.k == locNone)
var L = 0
initLocExpr(p, e.sons[1], dest)
for i in 0 .. sonsLen(e) - 3:
for i in 0 .. len(e) - 3:
# compute the length expression:
initLocExpr(p, e.sons[i + 2], a)
if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
@@ -1202,6 +1193,8 @@ proc genDefault(p: BProc; n: PNode; d: var TLoc) =
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
else: resetLoc(p, d)
proc trivialDestructor(s: PSym): bool {.inline.} = s.ast[bodyPos].len == 0
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
var sizeExpr = sizeExpr
let typ = a.t
@@ -1213,13 +1206,13 @@ 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, {})
else:
let ti = genTypeInfo(p.module, typ, a.lode.info)
if bt.destructor != nil:
if bt.destructor != nil and not trivialDestructor(bt.destructor):
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
# convention at least:
@@ -1409,7 +1402,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
elif d.k == locNone:
getTemp(p, n.typ, d)
let l = intLiteral(sonsLen(n))
let l = intLiteral(len(n))
if p.config.selectedGC == gcDestructors:
let seqtype = n.typ
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
@@ -1419,7 +1412,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
# generate call to newSeq before adding the elements per hand:
genNewSeqAux(p, dest[], l,
optNilSeqs notin p.options and n.len == 0)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
initLoc(arr, locExpr, n[i], OnHeap)
arr.r = ropecg(p.module, "$1$3[$2]", [rdLoc(dest[]), intLiteral(i), dataField(p)])
arr.storage = OnHeap # we know that sequences are on the heap
@@ -1440,7 +1433,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
if d.k == locNone:
getTemp(p, n.typ, d)
# generate call to newSeq before adding the elements per hand:
let L = int(lengthOrd(p.config, n.sons[1].typ))
let L = toInt(lengthOrd(p.config, n.sons[1].typ))
if p.config.selectedGC == gcDestructors:
let seqtype = n.typ
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
@@ -1491,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:
@@ -1542,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)
@@ -1735,7 +1728,7 @@ proc fewCmps(conf: ConfigRef; s: PNode): bool =
elif elemType(s.typ).kind in {tyInt, tyInt16..tyInt64}:
result = true # better not emit the set if int is basetype!
else:
result = sonsLen(s) <= 8 # 8 seems to be a good value
result = len(s) <= 8 # 8 seems to be a good value
template binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
putIntoDest(p, d, e, frmt % [rdLoc(a), rdSetElemLoc(p.config, b, a.t)])
@@ -1768,7 +1761,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
e.sons[2]
initLocExpr(p, ea, a)
initLoc(b, locExpr, e, OnUnknown)
var length = sonsLen(e.sons[1])
var length = len(e.sons[1])
if length > 0:
b.r = rope("(")
for i in 0 ..< length:
@@ -1938,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)
@@ -2032,7 +2026,7 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
resetLoc(p, a)
proc genDestroy(p: BProc; n: PNode) =
if optNimV2 in p.config.globalOptions:
if p.config.selectedGC == gcDestructors:
let arg = n[1].skipAddr
let t = arg.typ.skipTypes(abstractInst)
case t.kind
@@ -2090,7 +2084,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
case op
of mOr, mAnd: genAndOr(p, e, d, op)
of mNot..mToBiggestInt: unaryArith(p, e, d, op)
of mNot..mUnaryMinusF64: unaryArith(p, e, d, op)
of mUnaryMinusI..mAbsI: unaryArithOverflow(p, e, d, op)
of mAddF64..mDivF64: binaryFloatArith(p, e, d, op)
of mShrI..mXor: binaryArith(p, e, d, op)
@@ -2155,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)
@@ -2272,7 +2266,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
of mSlice:
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
" 'toOpenArray' is only valid within a call expression")
"'toOpenArray' is only valid within a call expression")
else:
when defined(debugMagics):
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
@@ -2330,7 +2324,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
let t = n.typ
discard getTypeDesc(p.module, t) # so that any fields are initialized
if d.k == locNone: getTemp(p, t, d)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it.kind == nkExprColonExpr: it = it.sons[1]
initLoc(rec, locExpr, it, d.storage)
@@ -2372,7 +2366,7 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
var arr: TLoc
if not handleConstExpr(p, n, d):
if d.k == locNone: getTemp(p, n.typ, d)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
arr.r = "$1[$2]" % [rdLoc(d), intLiteral(i)]
expr(p, n.sons[i], arr)
@@ -2430,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)
@@ -2542,6 +2536,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of skVar, skForVar, skResult, skLet:
if {sfGlobal, sfThread} * sym.flags != {}:
genVarPrototype(p.module, n)
if sfCompileTime in sym.flags:
genSingleVar(p, sym, n, astdef(sym))
if sym.loc.r == nil or sym.loc.t == nil:
#echo "FAILED FOR PRCO ", p.prc.name.s
#echo renderTree(p.prc.ast, {renderIds})
@@ -2752,7 +2749,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
getNullValueAux(p, t, it, cons, result, count)
of nkRecCase:
getNullValueAux(p, t, obj.sons[0], cons, result, count)
for i in 1 ..< sonsLen(obj):
for i in 1 ..< len(obj):
getNullValueAux(p, t, lastSon(obj.sons[i]), cons, result, count)
of nkSym:
if count > 0: result.add ", "
@@ -2800,7 +2797,7 @@ proc genConstObjConstr(p: BProc; n: PNode): Rope =
result = "{$1}$n" % [result]
proc genConstSimpleList(p: BProc, n: PNode): Rope =
var length = sonsLen(n)
var length = len(n)
result = rope("{")
for i in 0 .. length - 2:
addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])])

View File

@@ -7,6 +7,8 @@
# distribution, for details about the copyright.
#
# included from cgen.nim
## This include file contains the logic to produce constant string
## and seq literals. The code here is responsible that
## ``const x = ["a", "b"]`` works without hidden runtime creation code.
@@ -19,7 +21,7 @@ template detectVersion(field, corename) =
if core == nil or core.kind != skConst:
m.g.field = 1
else:
m.g.field = int ast.getInt(core.ast)
m.g.field = toInt(ast.getInt(core.ast))
result = m.g.field
proc detectStrVersion(m: BModule): int =

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 :-)
@@ -62,7 +62,7 @@ proc endBlock(p: BProc)
proc genVarTuple(p: BProc, n: PNode) =
var tup, field: TLoc
if n.kind != nkVarTuple: internalError(p.config, n.info, "genVarTuple")
var L = sonsLen(n)
var L = len(n)
# if we have a something that's been captured, use the lowering instead:
for i in 0 .. L-3:
@@ -199,7 +199,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# Called by return and break stmts.
# Deals with issues faced when jumping out of try/except/finally stmts,
var stack = newSeq[tuple[n: PNode, inExcept: bool]](0)
var stack = newSeq[tuple[fin: PNode, inExcept: bool]](0)
for i in 1 .. howManyTrys:
let tryStmt = p.nestedTryStmts.pop
@@ -214,9 +214,9 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# Find finally-stmt for this try-stmt
# and generate a copy of its sons
var finallyStmt = lastSon(tryStmt.n)
if finallyStmt.kind == nkFinally:
genStmts(p, finallyStmt.sons[0])
var finallyStmt = tryStmt.fin
if finallyStmt != nil:
genStmts(p, finallyStmt[0])
# push old elements again:
for i in countdown(howManyTrys-1, 0):
@@ -246,10 +246,10 @@ proc genGotoState(p: BProc, n: PNode) =
lineF(p, cpsStmts, " goto BeforeRet_;$n", [])
var statesCounter = lastOrd(p.config, n.sons[0].typ)
if n.len >= 2 and n[1].kind == nkIntLit:
statesCounter = n[1].intVal
statesCounter = getInt(n[1])
let prefix = if n.len == 3 and n[2].kind == nkStrLit: n[2].strVal.rope
else: rope"STATE"
for i in 0i64 .. statesCounter:
for i in 0i64 .. toInt64(statesCounter):
lineF(p, cpsStmts, "case $2: goto $1$2;$n", [prefix, rope(i)])
lineF(p, cpsStmts, "}$n", [])
@@ -271,19 +271,16 @@ proc genGotoVar(p: BProc; value: PNode) =
else:
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
proc genSingleVar(p: BProc, a: PNode) =
let vn = a.sons[0]
let v = vn.sym
if sfCompileTime in v.flags: return
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
if sfGoto in v.flags:
# translate 'var state {.goto.} = X' into 'goto LX':
genGotoVar(p, a.sons[2])
genGotoVar(p, value)
return
var targetProc = p
var traverseProc: Rope
if sfGlobal in v.flags:
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
a.sons[2].kind == nkEmpty and
value.kind == nkEmpty and
v.loc.flags * {lfHeader, lfNoDecl} != {}:
return
if sfPure in v.flags:
@@ -313,14 +310,13 @@ proc genSingleVar(p: BProc, a: PNode) =
if traverseProc != nil and not p.hcrOn:
registerTraverseProc(p, v, traverseProc)
else:
let value = a.sons[2]
let imm = isAssignedImmediately(p.config, value)
if imm and p.module.compileToCpp and p.splitDecls == 0 and
not containsHiddenPointer(v.typ):
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
# parameterless constructor followed by an assignment operator. So we
# generate better code here: 'Foo f = x;'
genLineDir(p, a)
genLineDir(p, vn)
let decl = localVarDecl(p, vn)
var tmp: TLoc
if value.kind in nkCallKinds and value[0].kind == nkSym and
@@ -330,7 +326,7 @@ proc genSingleVar(p: BProc, a: PNode) =
assert(typ.kind == tyProc)
for i in 1..<value.len:
if params != nil: params.add(~", ")
assert(sonsLen(typ) == sonsLen(typ.n))
assert(len(typ) == len(typ.n))
add(params, genOtherArg(p, value, i, typ))
if params == nil:
lineF(p, cpsStmts, "$#;$n", [decl])
@@ -363,12 +359,17 @@ proc genSingleVar(p: BProc, a: PNode) =
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
startBlock(targetProc)
if a.sons[2].kind != nkEmpty:
genLineDir(targetProc, a)
loadInto(targetProc, a.sons[0], a.sons[2], v.loc)
if value.kind != nkEmpty:
genLineDir(targetProc, vn)
loadInto(targetProc, vn, value, v.loc)
if forHcr:
endBlock(targetProc)
proc genSingleVar(p: BProc, a: PNode) =
let v = a[0].sym
if sfCompileTime in v.flags: return
genSingleVar(p, v, a[0], a.sons[2])
proc genClosureVar(p: BProc, a: PNode) =
var immediateAsgn = a.sons[2].kind != nkEmpty
var v: TLoc
@@ -428,7 +429,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
else:
expr(p, it.sons[1], d)
endBlock(p)
if sonsLen(n) > 1:
if len(n) > 1:
lineF(p, cpsStmts, "goto $1;$n", [lend])
fixLabel(p, lelse)
elif it.len == 1:
@@ -436,7 +437,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
expr(p, it.sons[0], d)
endBlock(p)
else: internalError(p.config, n.info, "genIf()")
if sonsLen(n) > 1: fixLabel(p, lend)
if len(n) > 1: fixLabel(p, lend)
proc genReturnStmt(p: BProc, t: PNode) =
if nfPreventCg in t.flags: return
@@ -494,7 +495,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
if aSize > 10_000:
localError(p.config, it.info,
"case statement has too many cases for computed goto"); return
arraySize = aSize.int
arraySize = toInt(aSize)
if firstOrd(p.config, it.sons[0].typ) != 0:
localError(p.config, it.info,
"case statement has to start at 0 for computed goto"); return
@@ -527,7 +528,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
return
let val = getOrdValue(it.sons[j])
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)])
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(toInt64(val)+id+1)])
genStmts(p, it.lastSon)
@@ -564,7 +565,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
# significantly worse code
var
a: TLoc
assert(sonsLen(t) == 2)
assert(len(t) == 2)
inc(p.withinLoop)
genLineDir(p, t)
@@ -611,7 +612,7 @@ proc genBlock(p: BProc, n: PNode, d: var TLoc) =
endBlock(p)
proc genParForStmt(p: BProc, t: PNode) =
assert(sonsLen(t) == 3)
assert(len(t) == 3)
inc(p.withinLoop)
genLineDir(p, t)
@@ -622,12 +623,12 @@ proc genParForStmt(p: BProc, t: PNode) =
#initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
#discard mangleName(forLoopVar)
let call = t.sons[1]
assert(sonsLen(call) in {4, 5})
assert(len(call) in {4, 5})
initLocExpr(p, call.sons[1], rangeA)
initLocExpr(p, call.sons[2], rangeB)
# $n at the beginning because of #9710
if call.sonsLen == 4: # `||`(a, b, annotation)
if call.len == 4: # `||`(a, b, annotation)
lineF(p, cpsStmts, "$n#pragma omp $4$n" &
"for ($1 = $2; $1 <= $3; ++$1)",
[forLoopVar.loc.rdLoc,
@@ -675,8 +676,8 @@ proc genRaiseStmt(p: BProc, t: PNode) =
if p.nestedTryStmts.len > 0 and p.nestedTryStmts[^1].inExcept:
# if the current try stmt have a finally block,
# we must execute it before reraising
var finallyBlock = p.nestedTryStmts[^1].n[^1]
if finallyBlock.kind == nkFinally:
let finallyBlock = p.nestedTryStmts[^1].fin
if finallyBlock != nil:
genSimpleBlock(p, finallyBlock[0])
if t[0].kind != nkEmpty:
var a: TLoc
@@ -691,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)
@@ -705,7 +706,7 @@ template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
rangeFormat, eqFormat: FormatStr, labl: TLabel) =
var
x, y: TLoc
var length = sonsLen(b)
var length = len(b)
for i in 0 .. length - 2:
if b.sons[i].kind == nkRange:
initLocExpr(p, b.sons[i].sons[0], x)
@@ -724,7 +725,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
lineF(p, cpsStmts, "LA$1_: ;$n", [rope(labId + i)])
if t.sons[i].kind == nkOfBranch:
var length = sonsLen(t.sons[i])
var length = len(t.sons[i])
exprBlock(p, t.sons[i].sons[length - 1], d)
lineF(p, cpsStmts, "goto $1;$n", [lend])
else:
@@ -758,13 +759,13 @@ template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: FormatStr) =
var a: TLoc
initLocExpr(p, t.sons[0], a)
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a)
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, len(t)-1, a)
fixLabel(p, lend)
proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
branches: var openArray[Rope]) =
var x: TLoc
var length = sonsLen(b)
var length = len(b)
for i in 0 .. length - 2:
assert(b.sons[i].kind != nkRange)
initLocExpr(p, b.sons[i], x)
@@ -776,16 +777,16 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
# count how many constant strings there are in the case:
var strings = 0
for i in 1 ..< sonsLen(t):
if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
for i in 1 ..< len(t):
if t.sons[i].kind == nkOfBranch: inc(strings, len(t.sons[i]) - 1)
if strings > stringCaseThreshold:
var bitMask = math.nextPowerOfTwo(strings) - 1
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 ..< sonsLen(t):
for i in 1 ..< len(t):
inc(p.labels)
if t.sons[i].kind == nkOfBranch:
genCaseStringBranch(p, t.sons[i], a, "LA" & rope(p.labels) & "_",
@@ -801,16 +802,16 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
lineF(p, cpsStmts, "case $1: $n$2break;$n",
[intLiteral(j), branches[j]])
lineF(p, cpsStmts, "}$n", []) # else statement:
if t.sons[sonsLen(t)-1].kind != nkOfBranch:
if t.sons[len(t)-1].kind != nkOfBranch:
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
# third pass: generate statements
var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
var lend = genCaseSecondPass(p, t, d, labId, len(t)-1)
fixLabel(p, lend)
else:
genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
proc branchHasTooBigRange(b: PNode): bool =
for i in 0 .. sonsLen(b)-2:
for i in 0 .. len(b)-2:
# last son is block
if (b.sons[i].kind == nkRange) and
b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit:
@@ -924,7 +925,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
getTemp(p, t.typ, d)
genLineDir(p, t)
discard cgsym(p.module, "popCurrentExceptionEx")
add(p.nestedTryStmts, (t, false))
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
add(p.nestedTryStmts, (fin, false))
startBlock(p, "try {$n")
expr(p, t[0], d)
endBlock(p)
@@ -1021,8 +1023,9 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
else:
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t)
add(p.nestedTryStmts, (t, quirkyExceptions))
let length = len(t)
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
add(p.nestedTryStmts, (fin, quirkyExceptions))
expr(p, t.sons[0], d)
if not quirkyExceptions:
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
@@ -1039,7 +1042,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
while (i < length) and (t.sons[i].kind == nkExceptBranch):
# bug #4230: avoid false sharing between branches:
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
var blen = sonsLen(t.sons[i])
var blen = len(t.sons[i])
if blen == 1:
# general except section:
if i > 1: lineF(p, cpsStmts, "else", [])
@@ -1054,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)
@@ -1159,36 +1162,10 @@ proc genEmit(p: BProc, t: PNode) =
genLineDir(p, t)
line(p, cpsStmts, s)
proc genBreakPoint(p: BProc, t: PNode) =
var name: string
if optEndb in p.options:
if t.kind == nkExprColonExpr:
assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
name = normalize(t.sons[1].strVal)
else:
inc(p.module.g.breakPointId)
name = "bp" & $p.module.g.breakPointId
genLineDir(p, t) # BUGFIX
appcg(p.module, p.module.g.breakpoints,
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
toLinenumber(t.info), makeCString(toFilename(p.config, t.info)),
makeCString(name)])
proc genWatchpoint(p: BProc, n: PNode) =
if optEndb notin p.options: return
var a: TLoc
initLocExpr(p, n.sons[1], a)
let typ = skipTypes(n.sons[1].typ, abstractVarRange)
lineCg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
[addrLoc(p.config, a), makeCString(renderTree(n.sons[1])),
genTypeInfo(p.module, typ, n.info)])
proc genPragma(p: BProc, n: PNode) =
for it in n.sons:
case whichPragma(it)
of wEmit: genEmit(p, it)
of wBreakpoint: genBreakPoint(p, it)
of wWatchPoint: genWatchpoint(p, it)
of wInjectStmt:
var p = newProc(nil, p.module)
p.options = p.options - {optLineTrace, optStackTrace}
@@ -1211,7 +1188,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
var t = skipTypes(objtype, abstractVar)
assert t.kind == tyObject
discard genTypeInfo(p.module, t, a.lode.info)
var L = lengthOrd(p.config, field.typ)
var L = toInt64(lengthOrd(p.config, field.typ))
if not containsOrIncl(p.module.declaredThings, field.id):
appcg(p.module, cfsVars, "extern $1",
[discriminatorTableDecl(p.module, t, field)])
@@ -1243,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)
@@ -28,7 +28,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
if n == nil: return
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
genTraverseProc(c, accessor, n.sons[i], typ)
of nkRecCase:
if (n.sons[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
@@ -38,7 +38,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
if disc.loc.t == nil:
internalError(c.p.config, n.info, "genTraverseProc()")
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
let branch = n.sons[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
@@ -87,14 +87,14 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
else:
lineF(p, cpsStmts, "}$n", [])
of tyObject:
for i in 0 ..< sonsLen(typ):
for i in 0 ..< len(typ):
var x = typ.sons[i]
if x != nil: x = x.skipTypes(skipPtrs)
genTraverseProc(c, accessor.parentObj(c.p.module), x)
if typ.n != nil: genTraverseProc(c, accessor, typ.n, typ)
of tyTuple:
let typ = getUniqueType(typ)
for i in 0 ..< sonsLen(typ):
for i in 0 ..< len(typ):
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ.sons[i])
of tyRef:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
@@ -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
@@ -155,6 +155,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tyNone, tyTyped: result = ctVoid
of tyBool: result = ctBool
of tyChar: result = ctChar
of tyNil: result = ctPtr
of tySet: result = mapSetType(conf, typ)
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctArray
of tyObject, tyTuple: result = ctStruct
@@ -286,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)
@@ -449,7 +451,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
rettype = ~"void"
else:
rettype = getTypeDescAux(m, t.sons[0], check)
for i in 1 ..< sonsLen(t.n):
for i in 1 ..< len(t.n):
if t.n.sons[i].kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
var param = t.n.sons[i].sym
if isCompileTimeOnly(param.typ): continue
@@ -469,7 +471,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
add(params, param.loc.r)
# declare the len field for open arrays:
var arr = param.typ
if arr.kind in {tyVar, tyLent}: arr = arr.lastSon
if arr.kind in {tyVar, tyLent, tySink}: arr = arr.lastSon
var j = 0
while arr.kind in {tyOpenArray, tyVarargs}:
# this fixes the 'sort' bug:
@@ -477,7 +479,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
# need to pass hidden parameter:
addf(params, ", NI $1Len_$2", [param.loc.r, j.rope])
inc(j)
arr = arr.sons[0]
arr = arr.sons[0].skipTypes({tySink})
if t.sons[0] != nil and isInvalidReturnType(m.config, t.sons[0]):
var arr = t.sons[0]
if params != nil: add(params, ", ")
@@ -510,7 +512,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
add(result, genRecordFieldsAux(m, n.sons[i], rectype, check))
of nkRecCase:
if n.sons[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
@@ -518,7 +520,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
# prefix mangled name with "_U" to avoid clashes with other field names,
# since identifiers are not allowed to start with '_'
var unionBody: Rope = nil
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
let k = lastSon(n.sons[i])
@@ -633,7 +635,7 @@ proc getTupleDesc(m: BModule, typ: PType, name: Rope,
check: var IntSet): Rope =
result = "$1 $2 {$n" % [structOrUnion(typ), name]
var desc: Rope = nil
for i in 0 ..< sonsLen(typ):
for i in 0 ..< len(typ):
addf(desc, "$1 Field$2;$n",
[getTypeDescAux(m, typ.sons[i], check), rope(i)])
if desc == nil: add(result, "char dummy;\L")
@@ -805,7 +807,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
let foo = getTypeDescAux(m, t.sons[0], check)
addf(m.s[cfsTypes], "typedef $1 $2[1];$n", [foo, result])
of tyArray:
var n: BiggestInt = lengthOrd(m.config, t)
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
if n <= 0: n = 1 # make an array of at least one element
result = getTypeName(m, origTyp, sig)
m.typeCache[sig] = result
@@ -956,7 +958,7 @@ proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
fillLoc(prc.loc, locProc, prc.ast[namePos], mangleName(m, prc), OnUnknown)
genProcParams(m, prc.typ, rettype, params, check)
# handle the 2 options for hotcodereloading codegen - function pointer
# (instead of forward declaration) or header for function budy with "_actual" postfix
# (instead of forward declaration) or header for function body with "_actual" postfix
let asPtrStr = rope(if asPtr: "_PTR" else: "")
var name = prc.loc.r
if isReloadable(m, prc) and not asPtr:
@@ -1027,7 +1029,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
info: TLineInfo) =
var base: Rope
if sonsLen(typ) > 0 and typ.lastSon != nil:
if len(typ) > 0 and typ.lastSon != nil:
var x = typ.lastSon
if typ.kind == tyObject: x = x.skipTypes(skipPtrs)
if typ.kind == tyPtr and x.kind == tyObject and incompleteType(x):
@@ -1047,6 +1049,8 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
internalError(m.config, d.info, "anonymous obj with discriminator")
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]
proc rope(arg: Int128): Rope = rope($arg)
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
discard cgsym(m, "TNimNode")
var tmp = discriminatorTableName(m, objtype, d)
@@ -1064,7 +1068,7 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
info: TLineInfo) =
case n.kind
of nkRecList:
var L = sonsLen(n)
var L = len(n)
if L == 1:
genObjectFields(m, typ, origType, n.sons[0], expr, info)
elif L > 0:
@@ -1095,18 +1099,18 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
makeCString(field.name.s),
tmp, rope(L)])
addf(m.s[cfsData], "TNimNode* $1[$2];$n", [tmp, rope(L+1)])
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var b = n.sons[i] # branch
var tmp2 = getNimNode(m)
genObjectFields(m, typ, origType, lastSon(b), tmp2, info)
case b.kind
of nkOfBranch:
if sonsLen(b) < 2:
if len(b) < 2:
internalError(m.config, b.info, "genObjectFields; nkOfBranch broken")
for j in 0 .. sonsLen(b) - 2:
for j in 0 .. len(b) - 2:
if b.sons[j].kind == nkRange:
var x = int(getOrdValue(b.sons[j].sons[0]))
var y = int(getOrdValue(b.sons[j].sons[1]))
var x = toInt(getOrdValue(b.sons[j].sons[0]))
var y = toInt(getOrdValue(b.sons[j].sons[1]))
while x <= y:
addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(x), tmp2])
inc(x)
@@ -1152,7 +1156,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo
proc genTupleInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo) =
genTypeInfoAuxBase(m, typ, typ, name, rope("0"), info)
var expr = getNimNode(m)
var length = sonsLen(typ)
var length = len(typ)
if length > 0:
var tmp = getTempName(m) & "_" & $length
genTNimNodeArray(m, tmp, rope(length))
@@ -1178,7 +1182,7 @@ proc genEnumInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
# anyway. We generate a cstring array and a loop over it. Exceptional
# positions will be reset after the loop.
genTypeInfoAux(m, typ, typ, name, info)
var length = sonsLen(typ.n)
var length = len(typ.n)
var nodePtrs = getTempName(m) & "_" & $length
genTNimNodeArray(m, nodePtrs, rope(length))
var enumNames, specialCases: Rope
@@ -1361,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

@@ -113,6 +113,9 @@ proc cgFormatValue(result: var string; value: string): void =
proc cgFormatValue(result: var string; value: BiggestInt): void =
result.addInt value
proc cgFormatValue(result: var string; value: Int128): void =
result.addInt128 value
# TODO: please document
macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
args.expectKind nnkBracket
@@ -261,13 +264,7 @@ proc genLineDir(p: BProc, t: PNode) =
if optEmbedOrigSrc in p.config.globalOptions:
add(p.s(cpsStmts), ~"//" & sourceLine(p.config, t.info) & "\L")
genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config)
if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
(p.prc == nil or sfPure notin p.prc.flags):
if freshLineInfo(p, t.info):
linefmt(p, cpsStmts, "#endb($1, $2);$N",
[line, makeCString(toFilename(p.config, t.info))])
elif ({optLineTrace, optStackTrace} * p.options ==
{optLineTrace, optStackTrace}) and
if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
if freshLineInfo(p, t.info):
linefmt(p, cpsStmts, "nimln_($1, $2);$n",
@@ -350,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:
@@ -476,19 +473,6 @@ proc deinitGCFrame(p: BProc): Rope =
result = ropecg(p.module,
"if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n", [])
proc localDebugInfo(p: BProc, s: PSym, retType: PType) =
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
# XXX work around a bug: No type information for open arrays possible:
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
var a = "&" & s.loc.r
if s.kind == skParam and ccgIntroducedPtr(p.config, s, retType): a = s.loc.r
lineF(p, cpsInit,
"FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n",
[p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a,
genTypeInfo(p.module, s.loc.t, s.info)])
inc(p.maxFrameLen)
inc p.blocks[p.blocks.len-1].frameLen
proc localVarDecl(p: BProc; n: PNode): Rope =
let s = n.sym
if s.loc.k == locNone:
@@ -512,7 +496,6 @@ proc assignLocalVar(p: BProc, n: PNode) =
let nl = if optLineDir in p.config.options: "" else: "\L"
let decl = localVarDecl(p, n) & ";" & nl
line(p, cpsLocals, decl)
localDebugInfo(p, n.sym, nil)
include ccgthreadvars
@@ -559,17 +542,10 @@ proc assignGlobalVar(p: BProc, n: PNode) =
if p.withinLoop > 0:
# fixes tests/run/tzeroarray:
resetLoc(p, s.loc)
if p.module.module.options * {optStackTrace, optEndb} ==
{optStackTrace, optEndb}:
appcg(p.module, p.module.s[cfsDebugInit],
"#dbgRegisterGlobal($1, &$2, $3);$n",
[makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
s.loc.r, genTypeInfo(p.module, s.typ, n.info)])
proc assignParam(p: BProc, s: PSym, retType: PType) =
assert(s.loc.r != nil)
scopeMangledParam(p, s)
localDebugInfo(p, s, retType)
proc fillProcLoc(m: BModule; n: PNode) =
let sym = n.sym
@@ -686,7 +662,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
[loadlib, genStringLiteral(m, lib.path)])
else:
var p = newProc(nil, m)
p.options = p.options - {optStackTrace, optEndb}
p.options = p.options - {optStackTrace}
var dest: TLoc
initLoc(dest, locTemp, lib.path, OnStack)
dest.r = getTempName(m)
@@ -781,7 +757,7 @@ proc cgsym(m: BModule, name: string): Rope =
rawMessage(m.config, errGenerated, "system module needs: " & name)
result = sym.loc.r
if m.hcrOn and sym != nil and sym.kind in {skProc..skIterator}:
result.addActualPrefixForHCR(m.module, sym)
result.addActualSuffixForHCR(m.module, sym)
proc generateHeaders(m: BModule) =
add(m.s[cfsHeaders], "\L#include \"nimbase.h\"\L")
@@ -955,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])
@@ -1014,23 +991,29 @@ proc genProcAux(m: BModule, prc: PSym) =
#incl(res.loc.flags, lfIndirect)
res.loc.storage = OnUnknown
for i in 1 ..< sonsLen(prc.typ.n):
for i in 1 ..< len(prc.typ.n):
let param = prc.typ.n.sons[i].sym
if param.typ.isCompileTimeOnly: continue
assignParam(p, param, prc.typ[0])
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:
generatedProc = ropecg(p.module, "$N$1 {$N", [header])
if m.hcrOn and isReloadable(m, prc):
# Add forward declaration for "_actual"-suffixed functions defined in the same module (or inline).
# 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.add ropecg(p.module, "$1 {", [header])
add(generatedProc, initGCFrame(p))
if optStackTrace in prc.options:
add(generatedProc, p.s(cpsLocals))
@@ -1058,7 +1041,8 @@ proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
result = (sfCompileToCpp in m.module.flags and
sfCompileToCpp notin sym.getModule().flags and
m.config.cmd != cmdCompileToCpp) or (
sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and
sym.flags * {sfInfixCall, sfCompilerProc, sfMangleCpp} == {} and
sym.flags * {sfImportc, sfExportc} != {} and
sym.magic == mNone and
m.config.cmd == cmdCompileToCpp)
@@ -1273,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
@@ -1310,7 +1294,6 @@ proc genMainProc(m: BModule) =
PreMainBody = "$N" &
"void PreMainInner(void) {$N" &
"$2" &
"$3" &
"}$N$N" &
PosixCmdLine &
"void PreMain(void) {$N" &
@@ -1400,17 +1383,11 @@ proc genMainProc(m: BModule) =
elif m.config.target.targetOS == osGenode:
m.includeHeader("<libc/component.h>")
if optEndb in m.config.options:
for i in 0..<m.config.m.fileInfos.len:
m.g.breakpoints.addf("dbgRegisterFilename($1);$N",
[m.config.m.fileInfos[i].projPath.string.makeCString])
let initStackBottomCall =
if m.config.target.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", [])
inc(m.labels)
appcg(m, m.s[cfsProcs], PreMainBody, [
m.g.mainDatInit, m.g.breakpoints, m.g.otherModsInit])
appcg(m, m.s[cfsProcs], PreMainBody, [m.g.mainDatInit, m.g.otherModsInit])
if m.config.target.targetOS == osWindows and
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
@@ -1539,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
@@ -1583,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)
@@ -1771,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)
@@ -2016,11 +1993,6 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
discard cgsym(m, "initThreadVarsEmulation")
if m.g.breakpoints != nil:
discard cgsym(m, "dbgRegisterBreakpoint")
if optEndb in m.config.options:
discard cgsym(m, "dbgRegisterFilename")
if m.g.forwardedProcs.len == 0:
incl m.flags, objHasKidsValid
let disp = generateMethodDispatchers(graph)

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
@@ -73,7 +73,7 @@ type
noSafePoints*: bool # the proc doesn't use safe points in exception handling
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
currLineInfo*: TLineInfo # AST codegen will make this superfluous
nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]
nestedTryStmts*: seq[tuple[fin: PNode, inExcept: bool]]
# in how many nested try statements we are
# (the vars must be volatile then)
# bool is true when are in the except part of a try block
@@ -117,8 +117,6 @@ type
modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
generatedHeader*: BModule
breakPointId*: int
breakpoints*: Rope # later the breakpoints are inserted into the main proc
typeInfoMarker*: TypeCacheWithOwner
config*: ConfigRef
graph*: ModuleGraph
@@ -152,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

@@ -48,7 +48,7 @@ proc methodCall*(n: PNode; conf: ConfigRef): PNode =
if disp != nil:
result.sons[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in 1 ..< sonsLen(result):
for i in 1 ..< len(result):
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true, conf)
else:
localError(conf, n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
@@ -58,10 +58,10 @@ type
proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
if a.name.id != b.name.id: return
if sonsLen(a.typ) != sonsLen(b.typ):
if len(a.typ) != len(b.typ):
return
for i in 1 ..< sonsLen(a.typ):
for i in 1 ..< len(a.typ):
var aa = a.typ.sons[i]
var bb = b.typ.sons[i]
while true:
@@ -118,7 +118,7 @@ proc createDispatcher(s: PSym): PSym =
disp.ast.sons[bodyPos] = newNodeI(nkEmpty, s.info)
disp.loc.r = nil
if s.typ.sons[0] != nil:
if disp.ast.sonsLen > resultPos:
if disp.ast.len > resultPos:
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
else:
# We've encountered a method prototype without a filled-in
@@ -136,7 +136,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
# from later definitions, particularly the resultPos slot. Also,
# the lock level of the dispatcher needs to be updated/checked
# against that of the method.
if disp.ast.sonsLen > resultPos and meth.ast.sonsLen > resultPos and
if disp.ast.len > resultPos and meth.ast.len > resultPos and
disp.ast.sons[resultPos].kind == nkEmpty:
disp.ast.sons[resultPos] = copyTree(meth.ast.sons[resultPos])
@@ -198,7 +198,7 @@ proc relevantCol(methods: seq[PSym], col: int): bool =
return true
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
for col in 1 ..< sonsLen(a.typ):
for col in 1 ..< len(a.typ):
if contains(relevantCols, col):
var aa = skipTypes(a.typ.sons[col], skipPtrs)
var bb = skipTypes(b.typ.sons[col], skipPtrs)
@@ -228,7 +228,7 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
var base = methods[0].ast[dispatcherPos].sym
result = base
var paramLen = sonsLen(base.typ)
var paramLen = len(base.typ)
var nilchecks = newNodeI(nkStmtList, base.info)
var disp = newNodeI(nkIfStmt, base.info)
var ands = getSysMagic(g, unknownLineInfo(), "and", mAnd)
@@ -288,7 +288,7 @@ proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList)
for bucket in 0 ..< len(g.methods):
var relevantCols = initIntSet()
for col in 1 ..< sonsLen(g.methods[bucket].methods[0].typ):
for col in 1 ..< len(g.methods[bucket].methods[0].typ):
if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col)
if optMultiMethods notin g.config.globalOptions:
# if multi-methods are not enabled, we are interested only in the first field

View File

@@ -90,9 +90,6 @@
# :unrollFinally = true
# goto nearestFinally (or -1 if not exists)
#
# Every finally block calls closureIterEndFinally() upon its successful
# completion.
#
# Example:
#
# try:
@@ -126,6 +123,7 @@
# if :curExc.isNil:
# return :tmpResult
# else:
# closureIterSetupExc(nil)
# raise
# state = -1 # Goto next state. In this case we just exit
# break :stateLoop
@@ -174,7 +172,7 @@ proc newStateAssgn(ctx: var Ctx, toValue: PNode): PNode =
proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode =
# Creates state assignment:
# :state = stateNo
ctx.newStateAssgn(newIntTypeNode(nkIntLit, stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
result = newSym(skVar, getIdent(ctx.g.cache, name), ctx.fn, ctx.fn.info)
@@ -359,7 +357,7 @@ proc addElseToExcept(ctx: var Ctx, n: PNode) =
block: # :unrollFinally = true
branchBody.add(newTree(nkAsgn,
ctx.newUnrollFinallyAccess(n.info),
newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool))))
newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool))))
block: # :curExc = getCurrentException()
branchBody.add(newTree(nkAsgn,
@@ -603,7 +601,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(n)
result.add(ctx.newEnvVarAccess(tmp))
of nkCallKinds:
of nkCallKinds, nkChckRange, nkChckRangeF, nkChckRange64:
var ns = false
for i in 0 ..< n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
@@ -685,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)
@@ -759,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:
@@ -809,10 +808,11 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
let retStmt = newTree(nkReturnStmt, asgn)
let branch = newTree(nkElifBranch, cmp, retStmt)
# The C++ backend requires `getCurrentException` here.
let raiseStmt = newTree(nkRaiseStmt, ctx.g.callCodegenProc("getCurrentException"))
let nullifyExc = newTree(nkCall, newSymNode(ctx.g.getCompilerProc("closureIterSetupExc")), nilnode)
nullifyExc.info = info
let raiseStmt = newTree(nkRaiseStmt, curExc)
raiseStmt.info = info
let elseBranch = newTree(nkElse, raiseStmt)
let elseBranch = newTree(nkElse, newTree(nkStmtList, nullifyExc, raiseStmt))
let ifBody = newTree(nkIfStmt, branch, elseBranch)
let elifBranch = newTree(nkElifBranch, ctx.newUnrollFinallyAccess(info), ifBody)
@@ -832,7 +832,7 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
block: # :unrollFinally = true
let asgn = newNodeI(nkAsgn, n.info)
asgn.add(ctx.newUnrollFinallyAccess(n.info))
asgn.add(newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool)))
asgn.add(newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool)))
result.add(asgn)
if n[0].kind != nkEmpty:
@@ -1162,7 +1162,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
let cond = newTree(nkCall,
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
ctx.newStateAccess(),
newIntTypeNode(nkIntLit, 0, intTyp))
newIntTypeNode(0, intTyp))
cond.typ = boolTyp
let raiseStmt = newTree(nkRaiseStmt, ctx.g.emptyNode)
@@ -1174,7 +1174,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
block:
let cond = newTree(nkCall,
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
newIntTypeNode(nkIntLit, 0, intTyp),
newIntTypeNode(0, intTyp),
ctx.newStateAccess())
cond.typ = boolTyp
@@ -1186,7 +1186,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
let cond = newTree(nkCall,
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
ctx.newStateAccess(),
newIntTypeNode(nkIntLit, 0, intTyp))
newIntTypeNode(0, intTyp))
cond.typ = boolTyp
let negateState = newTree(nkCall,
@@ -1287,9 +1287,9 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
ctx.fn = fn
if getEnvParam(fn).isNil:
# Lambda lifting was not done yet. Use temporary :state sym, which
# 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)
@@ -1310,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

@@ -13,6 +13,8 @@ import
options, idents, nimconf, scriptconfig, extccomp, commands, msgs,
lineinfos, modulegraphs, condsyms, os, pathutils
from strutils import normalize
type
NimProg* = ref object
suggestMode*: bool
@@ -72,7 +74,11 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
runNimScriptIfExists(scriptFile)
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile == conf.projectFull:
return false
if conf.command == "":
conf.command = "e"
return false
elif conf.command.normalize == "e":
return false
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile)
@@ -81,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

@@ -266,7 +266,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
of "stacktrace": result = contains(conf.options, optStackTrace)
of "linetrace": result = contains(conf.options, optLineTrace)
of "debugger": result = contains(conf.options, optEndb)
of "debugger": result = contains(conf.globalOptions, optCDebug)
of "profiler": result = contains(conf.options, optProfiler)
of "memtracker": result = contains(conf.options, optMemTracker)
of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
@@ -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
@@ -437,30 +440,31 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optWholeProject}, arg, pass, info)
of "gc":
expectArg(conf, switch, arg, pass, info)
case arg.normalize
of "boehm":
conf.selectedGC = gcBoehm
defineSymbol(conf.symbols, "boehmgc")
of "refc":
conf.selectedGC = gcRefc
of "v2":
message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
of "markandsweep":
conf.selectedGC = gcMarkAndSweep
defineSymbol(conf.symbols, "gcmarkandsweep")
of "destructors":
conf.selectedGC = gcDestructors
defineSymbol(conf.symbols, "gcdestructors")
of "go":
conf.selectedGC = gcGo
defineSymbol(conf.symbols, "gogc")
of "none":
conf.selectedGC = gcNone
defineSymbol(conf.symbols, "nogc")
of "stack", "regions":
conf.selectedGC= gcRegions
defineSymbol(conf.symbols, "gcregions")
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
if pass in {passCmd2, passPP}:
case arg.normalize
of "boehm":
conf.selectedGC = gcBoehm
defineSymbol(conf.symbols, "boehmgc")
of "refc":
conf.selectedGC = gcRefc
of "v2":
message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
of "markandsweep":
conf.selectedGC = gcMarkAndSweep
defineSymbol(conf.symbols, "gcmarkandsweep")
of "destructors":
conf.selectedGC = gcDestructors
defineSymbol(conf.symbols, "gcdestructors")
of "go":
conf.selectedGC = gcGo
defineSymbol(conf.symbols, "gogc")
of "none":
conf.selectedGC = gcNone
defineSymbol(conf.symbols, "nogc")
of "stack", "regions":
conf.selectedGC= gcRegions
defineSymbol(conf.symbols, "gcregions")
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
of "warnings", "w":
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
@@ -473,24 +477,18 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
of "debugger":
case arg.normalize
of "on", "endb":
conf.options.incl optEndb
defineSymbol(conf.symbols, "endb")
of "off":
conf.options.excl optEndb
undefSymbol(conf.symbols, "endb")
of "native", "gdb":
incl(conf.globalOptions, optCDebug)
conf.options = conf.options + {optLineDir} - {optEndb}
of "on", "native", "gdb":
conf.globalOptions.incl optCDebug
conf.options.incl optLineDir
#defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
undefSymbol(conf.symbols, "endb")
of "off":
conf.globalOptions.excl optCDebug
else:
localError(conf, info, "expected endb|gdb but found " & arg)
localError(conf, info, "expected native|gdb|on|off but found " & arg)
of "g": # alias for --debugger:native
incl(conf.globalOptions, optCDebug)
conf.options = conf.options + {optLineDir} - {optEndb}
conf.globalOptions.incl optCDebug
conf.options.incl optLineDir
#defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
undefSymbol(conf.symbols, "endb")
of "profiler":
processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
@@ -619,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":
@@ -763,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")
@@ -788,13 +786,22 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "expandmacro":
expectArg(conf, switch, arg, pass, info)
conf.macrosToExpand[arg] = "T"
of "oldgensym":
processOnOffSwitchG(conf, {optNimV019}, arg, pass, info)
of "useversion":
expectArg(conf, switch, arg, pass, info)
case arg
of "1.0":
discard "the default"
else:
localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
of "":
conf.projectName = "-"
else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
else: invalidCmdLineOption(conf, pass, switch, info)
template gCmdLineInfo*(): untyped = newLineInfo(config, AbsoluteFile"command line", 1, 1)
template gCmdLineInfo*(): untyped = newLineInfo(commandLineIdx, 1, 1)
proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
var cmd, arg: string

View File

@@ -87,6 +87,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasDefault")
defineSymbol("nimMacrosSizealignof")
defineSymbol("nimNoZeroExtendMagic")
defineSymbol("nimMacrosGetNodeId")
for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f)
@@ -97,3 +98,5 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimFixedOwned")
defineSymbol("nimHasStyleChecks")
defineSymbol("nimToOpenArrayCString")
defineSymbol("nimHasUsed")

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

@@ -34,14 +34,14 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
let b = Backend(g.graph.backend)
case n.kind
of nkImportStmt:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var imported = getModuleName(g.config, n.sons[i])
addDependencyAux(b, g.module.name.s, imported)
of nkFromStmt, nkImportExceptStmt:
var imported = getModuleName(g.config, n.sons[0])
addDependencyAux(b, g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
for i in 0 ..< sonsLen(n): discard addDotDependency(c, n.sons[i])
for i in 0 ..< len(n): discard addDotDependency(c, n.sons[i])
else:
discard

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)
@@ -607,14 +607,9 @@ proc aliases(obj, field: PNode): bool =
if sameTrees(obj, n): return true
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenDeref, nkDerefExpr:
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr, nkBracketExpr,
nkHiddenDeref, nkDerefExpr:
n = n[0]
of nkBracketExpr:
let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
n = x
else:
break
else:
break
return false
@@ -652,7 +647,7 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv:
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr, nkBracketExpr:
n = n[0]
of nkHiddenDeref, nkDerefExpr:
# We "own" sinkparam[].loc but not ourVar[].location as it is a nasty
@@ -660,12 +655,6 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
n = n[0]
return n.kind == nkSym and n.sym.owner == owner and (isSinkParam(n.sym) or
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
of nkBracketExpr:
let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
n = x
else:
break
else:
break
# XXX Allow closure deref operations here if we know

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),
@@ -406,6 +408,7 @@ proc runAllExamples(d: PDoc) =
elif isDefined(d.conf, "objc"): "objc"
else: "c"
if os.execShellCmd(os.getAppFilename() & " " & backend &
" --warning[UnusedImport]:off" &
" --path:" & quoteShell(d.conf.projectPath) &
" --nimcache:" & quoteShell(outputDir) &
" -r " & quoteShell(outp)) != 0:
@@ -415,12 +418,6 @@ proc runAllExamples(d: PDoc) =
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
removeFile(outp.changeFileExt(ExeExt))
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
proc prepareExamples(d: PDoc; n: PNode) =
var docComment = newTree(nkCommentStmt)
@@ -430,12 +427,20 @@ proc prepareExamples(d: PDoc; n: PNode) =
docComment,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
for a in n.lastSon: runnableExamples.add a
testExample(d, runnableExamples)
when false:
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
if n.info.fileIndex != orig.info.fileIndex: return
@@ -589,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.
@@ -628,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
@@ -845,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)
@@ -853,29 +864,29 @@ 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 ..< sonsLen(n):
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 ..< sonsLen(n): generateDoc(d, n.sons[i], orig)
for i in 0 ..< len(n): generateDoc(d, n.sons[i], orig)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
@@ -884,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:
@@ -923,13 +938,13 @@ proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if n.sons[i].kind != nkCommentStmt:
# order is always 'type var let const':
d.add genJsonItem(d, n.sons[i], n.sons[i].sons[0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
generateJson(d, n.sons[i], includeComments)
of nkWhenStmt:
# generate documentation for the first branch only:
@@ -966,13 +981,13 @@ proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if n.sons[i].kind != nkCommentStmt:
# order is always 'type var let const':
r.add genTagsItem(d, n.sons[i], n.sons[i].sons[0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
generateTags(d, n.sons[i], r)
of nkWhenStmt:
# generate documentation for the first branch only:
@@ -1166,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)
@@ -138,13 +138,13 @@ proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer)
proc getField(conf: ConfigRef, n: PNode; position: int): PSym =
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result = getField(conf, n.sons[i], position)
if result != nil: return
of nkRecCase:
result = getField(conf, n.sons[0], position)
if result != nil: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
result = getField(conf, lastSon(n.sons[i]), position)
@@ -158,7 +158,7 @@ proc packObject(conf: ConfigRef, x: PNode, typ: PType, res: pointer) =
internalAssert conf, x.kind in {nkObjConstr, nkPar, nkTupleConstr}
# compute the field's offsets:
discard getSize(conf, typ)
for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
for i in ord(x.kind == nkObjConstr) ..< len(x):
var it = x.sons[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
@@ -245,7 +245,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode
proc unpackObjectAdd(conf: ConfigRef, x: pointer, n, result: PNode) =
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
unpackObjectAdd(conf, x, n.sons[i], result)
of nkRecCase:
globalError(conf, result.info, "case objects cannot be unpacked")
@@ -275,7 +275,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
globalError(conf, n.info, "cannot map value from FFI")
if typ.n.isNil:
globalError(conf, n.info, "cannot unpack unnamed tuple")
for i in ord(n.kind == nkObjConstr) ..< sonsLen(n):
for i in ord(n.kind == nkObjConstr) ..< len(n):
var it = n.sons[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
@@ -289,7 +289,7 @@ proc unpackArray(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
if n.isNil:
result = newNode(nkBracket)
result.typ = typ
newSeq(result.sons, lengthOrd(conf, typ).int)
newSeq(result.sons, lengthOrd(conf, typ).toInt)
else:
result = n
if result.kind != nkBracket:

View File

@@ -10,7 +10,7 @@
## Template evaluation engine. Now hygienic.
import
strutils, options, ast, astalgo, msgs, renderer, lineinfos
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents
type
TemplCtx = object
@@ -20,6 +20,7 @@ type
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
# new symbol
config: ConfigRef
ic: IdentCache
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
result = copyNode(a)
@@ -37,7 +38,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
of nkSym:
var s = templ.sym
if (s.owner == nil and s.kind == skParam) or s.owner == c.owner:
if s.kind == skParam and sfGenSym notin s.flags:
if s.kind == skParam and {sfGenSym, sfTemplateParam} * s.flags == {sfTemplateParam}:
handleParam actual.sons[s.position]
elif (s.owner != nil) and (s.kind == skGenericParam or
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
@@ -52,7 +53,11 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
#if x.kind == skParam and x.owner.kind == skModule:
# internalAssert c.config, false
idTablePut(c.mapping, s, x)
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
if sfGenSym in s.flags and optNimV019 notin c.config.globalOptions:
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
if c.instLines: actual.info else: templ.info)
else:
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
else:
result.add copyNode(c, templ, actual)
of nkNone..nkIdent, nkType..nkNilLit: # atom
@@ -63,7 +68,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
# "declarative" context (bug #9235).
if c.isDeclarative:
var res = copyNode(c, templ, actual)
for i in 0 ..< sonsLen(templ):
for i in 0 ..< len(templ):
evalTemplateAux(templ.sons[i], actual, c, res)
result.add res
else:
@@ -77,7 +82,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
c.isDeclarative = true
isDeclarative = true
var res = copyNode(c, templ, actual)
for i in 0 ..< sonsLen(templ):
for i in 0 ..< len(templ):
evalTemplateAux(templ.sons[i], actual, c, res)
result.add res
if isDeclarative: c.isDeclarative = false
@@ -130,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]
@@ -160,7 +165,9 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
result.typ = res.typ
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
conf: ConfigRef; fromHlo=false): PNode =
conf: ConfigRef;
ic: IdentCache;
fromHlo=false): PNode =
inc(conf.evalTemplateCounter)
if conf.evalTemplateCounter > evalTemplateLimit:
globalError(conf, n.info, errTemplateInstantiationTooNested)
@@ -172,6 +179,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.owner = tmpl
ctx.genSymOwner = genSymOwner
ctx.config = conf
ctx.ic = ic
initIdTable(ctx.mapping)
let body = tmpl.getBody

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.
#
@@ -947,7 +947,9 @@ proc callCCompiler*(conf: ConfigRef) =
generateScript(conf, script)
#from json import escapeJson
import json
import json, std / sha1
template hashNimExe(): string = $secureHashFile(os.getAppFilename())
proc writeJsonBuildInstructions*(conf: ConfigRef) =
template lit(x: untyped) = f.write x
@@ -960,17 +962,17 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
f.write escapeJson(x)
proc cfiles(conf: ConfigRef; f: File; buf: var string; clist: CfileList, isExternal: bool) =
var pastStart = false
var i = 0
for it in clist:
if CfileFlag.Cached in it.flags: continue
let compileCmd = getCompileCFileCmd(conf, it)
if pastStart: lit "],\L"
if i > 0: lit ",\L"
lit "["
str it.cname.string
lit ", "
str compileCmd
pastStart = true
lit "]\L"
lit "]"
inc i
proc linkfiles(conf: ConfigRef; f: File; buf, objfiles: var string; clist: CfileList;
llist: seq[string]) =
@@ -994,6 +996,20 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
pastStart = true
lit "\L"
proc depfiles(conf: ConfigRef; f: File) =
var i = 0
for it in conf.m.fileInfos:
let path = it.fullPath.string
if isAbsolute(path): # TODO: else?
if i > 0: lit "],\L"
lit "["
str path
lit ", "
str $secureHashFile(path)
inc i
lit "]\L"
var buf = newStringOfCap(50)
let jsonFile = conf.getNimcacheDir / RelativeFile(conf.projectName & ".json")
@@ -1009,9 +1025,48 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
lit "],\L\"linkcmd\": "
str getLinkCmd(conf, conf.absOutFile, objfiles)
if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"):
lit ",\L\"cmdline\": "
str conf.commandLine
lit ",\L\"depfiles\":[\L"
depfiles(conf, f)
lit "],\L\"nimexe\": \L"
str hashNimExe()
lit "\L"
lit "\L}\L"
close(f)
proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile): bool =
let jsonFile = toGeneratedFile(conf, projectfile, "json")
if not fileExists(jsonFile): return true
if not fileExists(conf.absOutFile): return true
result = false
try:
let data = json.parseFile(jsonFile.string)
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 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 depFilename = p[0].getStr
let oldHashValue = p[1].getStr
let newHashValue = $secureHashFile(depFilename)
if oldHashValue != newHashValue:
return true
except IOError, OSError, ValueError:
echo "Warning: JSON processing failed: ", getCurrentExceptionMsg()
result = true
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
let jsonFile = toGeneratedFile(conf, projectfile, "json")
try:
@@ -1026,7 +1081,7 @@ proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
add(cmds, c[1].getStr)
let (_, name, _) = splitFile(c[0].getStr)
add(prettyCmds, "CC: " & name)
add(prettyCmds, "CC: " & demanglePackageName(name))
let prettyCb = proc (idx: int) =
when declared(echo):

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

@@ -20,7 +20,7 @@ proc invalidPragma(conf: ConfigRef; n: PNode) =
proc getArg(conf: ConfigRef; n: PNode, name: string, pos: int): PNode =
result = nil
if n.kind in {nkEmpty..nkNilLit}: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if n.sons[i].kind == nkExprEqExpr:
if n.sons[i].sons[0].kind != nkIdent: invalidPragma(conf, n)
if cmpIgnoreStyle(n.sons[i].sons[0].ident.s, name) == 0:

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

@@ -10,7 +10,7 @@
## This module implements the 'implies' relation for guards.
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
saturate, modulegraphs, options, lineinfos
saturate, modulegraphs, options, lineinfos, int128
const
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
@@ -35,8 +35,8 @@ const
someMul = {mMulI, mMulF64}
someDiv = {mDivI, mDivF64}
someMod = {mModI}
someMax = {mMaxI, mMaxF64}
someMin = {mMinI, mMinF64}
someMax = {mMaxI}
someMin = {mMinI}
someBinaryOp = someAdd+someSub+someMul+someMax+someMin
proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit}
@@ -436,14 +436,14 @@ 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
of nkEmpty, nkNilLit: result = true
else:
if sonsLen(a) == sonsLen(b):
for i in 0 ..< sonsLen(a):
if len(a) == len(b):
for i in 0 ..< len(a):
if not sameTree(a.sons[i], b.sons[i]): return
result = true
@@ -522,7 +522,7 @@ proc geImpliesIn(x, c, aSet: PNode): TImplication =
var value = newIntNode(c.kind, c.intVal)
let max = lastOrd(nil, x.typ)
# don't iterate too often:
if max - value.intVal < 1000:
if max - getInt(value) < toInt128(1000):
var i, pos, neg: int
while value.intVal <= max:
if inSet(aSet, value): inc pos

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

@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, msgs, options, idents, lookups,
semdata, modulepaths, sigmatch, lineinfos
semdata, modulepaths, sigmatch, lineinfos, sets
proc readExceptSet*(c: PContext, n: PNode): IntSet =
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
@@ -27,11 +27,11 @@ 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)
proc rawImportSymbol(c: PContext, s: PSym) =
proc rawImportSymbol(c: PContext, s, origin: PSym) =
# This does not handle stubs, because otherwise loading on demand would be
# pointless in practice. So importing stubs is fine here!
# check if we have already a symbol of the same name:
@@ -47,7 +47,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
if s.kind == skType:
var etyp = s.typ
if etyp.kind in {tyBool, tyEnum}:
for j in 0 ..< sonsLen(etyp.n):
for j in 0 ..< len(etyp.n):
var e = etyp.n.sons[j].sym
if e.kind != skEnumField:
internalError(c.config, s.info, "rawImportSymbol")
@@ -63,13 +63,14 @@ proc rawImportSymbol(c: PContext, s: PSym) =
check = nextIdentIter(it, c.importTable.symbols)
if e != nil:
if sfPure notin s.flags:
rawImportSymbol(c, e)
rawImportSymbol(c, e, origin)
else:
importPureEnumField(c, e)
else:
# rodgen assures that converters and patterns are no stubs
if s.kind == skConverter: addConverter(c, s)
if hasPattern(s): addPattern(c, s)
if s.owner != origin:
c.exportIndirections.incl((origin.id, s.id))
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
let ident = lookups.considerQuotedIdent(c, n)
@@ -88,10 +89,10 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
while e != nil:
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
if s.kind in ExportableSymKinds:
rawImportSymbol(c, e)
rawImportSymbol(c, e, fromMod)
e = nextIdentIter(it, fromMod.tab)
else:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
@@ -103,14 +104,14 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
if s.kind notin ExportableSymKinds:
internalError(c.config, s.info, "importAllSymbols: " & $s.kind & " " & s.name.s)
if exceptSet.isNil or s.name.id notin exceptSet:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
s = nextIter(i, fromMod.tab)
proc importAllSymbols*(c: PContext, fromMod: PSym) =
var exceptSet: IntSet
importAllSymbolsExcept(c, fromMod, exceptSet)
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym) =
if n.isNil: return
case n.kind
of nkExportStmt:
@@ -120,15 +121,16 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
if s.kind == skModule:
importAllSymbolsExcept(c, s, exceptSet)
elif exceptSet.isNil or s.name.id notin exceptSet:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
of nkExportExceptStmt:
localError(c.config, n.info, "'export except' not implemented")
else:
for i in 0..safeLen(n)-1:
importForwarded(c, n.sons[i], exceptSet)
importForwarded(c, n.sons[i], exceptSet, fromMod)
proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
result = realModule
c.unusedImports.add((realModule, n.info))
if n.kind != nkImportAs: discard
elif n.len != 2 or n.sons[1].kind != nkIdent:
localError(c.config, n.info, "module alias must be an identifier")
@@ -151,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
@@ -185,11 +191,11 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
# ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m, it.info) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, emptySet)
#importForwarded(c, m.ast, emptySet)
#importForwarded(c, m.ast, emptySet, m)
proc evalImport*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
let it = n.sons[i]
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
let sep = it[0]
@@ -219,7 +225,7 @@ proc evalFrom*(c: PContext, n: PNode): PNode =
if m != nil:
n.sons[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if n.sons[i].kind != nkNilLit:
importSymbol(c, n.sons[i], m)
@@ -232,4 +238,4 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
n.sons[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, readExceptSet(c, n))
#importForwarded(c, m.ast, exceptSet)
#importForwarded(c, m.ast, exceptSet, m)

View File

@@ -10,7 +10,7 @@
## Basic type definitions the module graph needs in order to support
## incremental compilations.
const nimIncremental* = true # defined(nimIncremental)
const nimIncremental* = defined(nimIncremental)
import options, lineinfos

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, msgs, renderer, magicsys, types, idents,
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
@@ -322,7 +160,7 @@ proc makePtrType(c: Con, baseType: PType): PType =
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
var op = t.attachedOps[kind]
if op == nil:
if op == nil or op.ast[genericParamsPos].kind != nkEmpty:
# give up and find the canonical type instead:
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
let canon = c.graph.canonTypes.getOrDefault(h)
@@ -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,204 +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 isAnalysableFieldAccess(arg, c.owner) and isLastRead(arg, c):
result = destructiveMoveVar(arg, c)
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) =
@@ -717,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:
@@ -736,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
@@ -876,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)
@@ -892,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
@@ -900,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

@@ -6,10 +6,10 @@ Name: "Nim"
Version: "$version"
Platforms: """
windows: i386;amd64
linux: i386;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
linux: i386;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
macosx: i386;amd64;powerpc64
solaris: i386;amd64;sparc;sparc64
freebsd: i386;amd64
freebsd: i386;amd64;powerpc64
netbsd: i386;amd64
openbsd: i386;amd64
dragonfly: i386;amd64
@@ -65,6 +65,7 @@ Files: "compiler"
Files: "doc"
Files: "doc/html"
Files: "tools"
Files: "tools/nim-gdb.py"
Files: "nimpretty"
Files: "testament"
Files: "nimsuggest"
@@ -87,6 +88,7 @@ Files: "bin/nimble.exe"
Files: "bin/vccexe.exe"
Files: "bin/nimgrab.exe"
Files: "bin/nimpretty.exe"
Files: "bin/testament.exe"
Files: "koch.exe"
Files: "finish.exe"

View File

@@ -1,4 +1,9 @@
## This module is for compiler internal use only. For reliable error
## messages and range checks, the compiler needs a data type that can
## hold all from ``low(BiggestInt)`` to ``high(BiggestUInt)``, This
## type is for that purpose.
from math import trunc
type
Int128* = object
@@ -11,19 +16,13 @@ template sdata(arg: Int128, idx: int): int32 =
# encoding least significant int first (like LittleEndian)
type
InvalidArgument = object of Exception
template require(cond: bool) =
if unlikely(not cond):
raise newException(InvalidArgument, "")
const
Zero* = Int128(udata: [0'u32,0,0,0])
One* = Int128(udata: [1'u32,0,0,0])
Ten* = Int128(udata: [10'u32,0,0,0])
Min = Int128(udata: [0'u32,0,0,0x80000000'u32])
Max = Int128(udata: [high(uint32),high(uint32),high(uint32),uint32(high(int32))])
NegOne* = Int128(udata: [0xffffffff'u32,0xffffffff'u32,0xffffffff'u32,0xffffffff'u32])
template low*(t: typedesc[Int128]): Int128 = Min
template high*(t: typedesc[Int128]): Int128 = Max
@@ -74,11 +73,94 @@ 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")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
arg.sdata(0)
proc toInt16*(arg: Int128): int16 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
int16(arg.sdata(0))
proc toInt8*(arg: Int128): int8 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
int8(arg.sdata(0))
proc toInt*(arg: Int128): int =
when sizeof(int) == 4:
cast[int](toInt32(arg))
else:
cast[int](toInt64(arg))
proc toUInt64*(arg: Int128): uint64 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
bitconcat(arg.udata[1], arg.udata[0])
proc toUInt32*(arg: Int128): uint32 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
arg.udata[0]
proc toUInt16*(arg: Int128): uint16 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
uint16(arg.udata[0])
proc toUInt8*(arg: Int128): uint8 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
uint8(arg.udata[0])
proc toUInt*(arg: Int128): uint =
when sizeof(int) == 4:
cast[uint](toInt32(arg))
else:
cast[uint](toInt64(arg))
proc castToInt64*(arg: Int128): int64 =
## Conversion to int64 without range check.
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc castToUInt64*(arg: Int128): uint64 =
## Conversion to uint64 without range check.
cast[uint64](bitconcat(arg.udata[1], arg.udata[0]))
proc addToHex(result: var string; arg: uint32) =
for i in 0 ..< 8:
let idx = (arg shr ((7-i) * 4)) and 0xf
@@ -206,7 +288,6 @@ proc `shl`*(a: Int128, b: int): Int128 =
result.udata[2] = 0
result.udata[3] = a.udata[0] shl (b and 31)
proc `+`*(a,b: Int128): Int128 =
let tmp0 = uint64(a.udata[0]) + uint64(b.udata[0])
result.udata[0] = cast[uint32](tmp0)
@@ -254,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
@@ -275,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])
@@ -298,10 +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):
echo result
assert(false, "overflow")
proc `*=`*(a: var Int128, b: Int128) =
a = a * b
@@ -319,18 +393,25 @@ proc fastLog2*(a: Int128): int =
proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
assert(divisor != Zero)
let isNegative = isNegative(dividend) xor isNegative(divisor)
let isNegativeA = isNegative(dividend)
let isNegativeB = isNegative(divisor)
var dividend = abs(dividend)
let divisor = abs(divisor)
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
@@ -351,8 +432,14 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
denominator = denominator shr 1
result.quotient = quotient
result.remainder = dividend
if isNegativeA xor isNegativeB:
result.quotient = -quotient
else:
result.quotient = quotient
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
proc `div`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
@@ -362,28 +449,32 @@ proc `mod`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
return b
proc `$`*(a: Int128): string =
if a == Zero:
result = "0"
elif a == low(Int128):
result = "-170141183460469231731687303715884105728"
proc addInt128*(result: var string; value: Int128) =
let initialSize = result.len
if value == Zero:
result.add "0"
elif value == low(Int128):
result.add "-170141183460469231731687303715884105728"
else:
let isNegative = isNegative(a)
var a = abs(a)
while a > Zero:
let (quot, rem) = divMod(a, Ten)
let isNegative = isNegative(value)
var value = abs(value)
while value > Zero:
let (quot, rem) = divMod(value, Ten)
result.add "0123456789"[rem.toInt64]
a = quot
value = quot
if isNegative:
result.add '-'
var i = 0
var i = initialSize
var j = high(result)
while i < j:
swap(result[i], result[j])
i += 1
j -= 1
proc `$`*(a: Int128): string =
result.addInt128(a)
proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
assert(pos < arg.len)
assert(arg[pos] in {'-','0'..'9'})
@@ -435,6 +526,75 @@ proc `+`*(a: BiggestInt, b: Int128): Int128 =
proc `+`*(a: Int128, b: BiggestInt): Int128 =
a + toInt128(b)
proc toFloat64*(arg: Int128): float64 =
let isNegative = isNegative(arg)
let arg = abs(arg)
let a = float64(bitconcat(arg.udata[1], arg.udata[0]))
let b = float64(bitconcat(arg.udata[3], arg.udata[2]))
result = a + 18446744073709551616'f64 * b # a + 2^64 * b
if isNegative:
result = -result
proc ldexp(x: float64, exp: cint): float64 {.importc: "ldexp", header: "<math.h>".}
template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
proc toInt128*(arg: float64): Int128 =
let isNegative = arg < 0
let v0 = ldexp(abs(arg), -100)
let w0 = uint64(trunc(v0))
let v1 = ldexp(v0 - float64(w0), 50)
let w1 = uint64(trunc(v1))
let v2 = ldexp(v1 - float64(w1), 50)
let w2 = uint64(trunc(v2))
let res = bitor(toInt128(w0) shl 100, toInt128(w1) shl 50, toInt128(w2))
if isNegative:
return -res
else:
return res
proc maskUInt64*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0]
result.udata[1] = arg.udata[1]
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt32*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0]
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt16*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0] and 0xffff
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt8*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0] and 0xff
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
case numbytes
of 1:
return maskUInt8(arg)
of 2:
return maskUInt16(arg)
of 4:
return maskUInt32(arg)
of 8:
return maskUInt64(arg)
else:
assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
when isMainModule:
let (a,b) = divMod(Ten,Ten)
@@ -514,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

@@ -389,8 +389,6 @@ const # magic checked op; magic unchecked op;
["", ""], # BitxorI
["nimMin", "nimMin"], # MinI
["nimMax", "nimMax"], # MaxI
["nimMin", "nimMin"], # MinF64
["nimMax", "nimMax"], # MaxF64
["", ""], # addU
["", ""], # subU
["", ""], # mulU
@@ -430,11 +428,6 @@ const # magic checked op; magic unchecked op;
["", ""], # BitnotI
["", ""], # UnaryPlusF64
["", ""], # UnaryMinusF64
["", ""], # AbsF64
["", ""], # ToFloat
["", ""], # ToBiggestFloat
["", ""], # ToInt
["", ""], # ToBiggestInt
["nimCharToStr", "nimCharToStr"],
["nimBoolToStr", "nimBoolToStr"],
["cstrToNimstr", "cstrToNimstr"],
@@ -535,7 +528,7 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
xLoc,yLoc: Rope
let i = ord(optOverflowCheck notin p.options)
useMagic(p, jsMagics[op][i])
if sonsLen(n) > 2:
if len(n) > 2:
gen(p, n.sons[1], x)
gen(p, n.sons[2], y)
xLoc = x.rdLoc
@@ -570,8 +563,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
of mMinI: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
of mMaxI: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
of mMinF64: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
of mMaxF64: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
of mAddU: applyFormat("", "")
of mSubU: applyFormat("", "")
of mMulU: applyFormat("", "")
@@ -611,11 +602,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mBitnotI: applyFormat("~($1)", "~($1)")
of mUnaryPlusF64: applyFormat("+($1)", "+($1)")
of mUnaryMinusF64: applyFormat("-($1)", "-($1)")
of mAbsF64: applyFormat("Math.abs($1)", "Math.abs($1)")
of mToFloat: applyFormat("$1", "$1")
of mToBiggestFloat: applyFormat("$1", "$1")
of mToInt: applyFormat("Math.trunc($1)", "Math.trunc($1)")
of mToBiggestInt: applyFormat("Math.trunc($1)", "Math.trunc($1)")
of mCharToStr: applyFormat("nimCharToStr($1)", "nimCharToStr($1)")
of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)")
of mIntToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
@@ -666,11 +652,7 @@ proc genLineDir(p: PProc, n: PNode) =
if optLineDir in p.options:
lineF(p, "// line $2 \"$1\"$n",
[rope(toFilename(p.config, n.info)), rope(line)])
if {optStackTrace, optEndb} * p.options == {optStackTrace, optEndb} and
((p.prc == nil) or sfPure notin p.prc.flags):
useMagic(p, "endb")
lineF(p, "endb($1);$n", [rope(line)])
elif hasFrameInfo(p):
if hasFrameInfo(p):
lineF(p, "F.line = $1;$n", [rope(line)])
proc genWhileStmt(p: PProc, n: PNode) =
@@ -731,7 +713,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
r.res = getTemp(p)
inc(p.unique)
var i = 1
var length = sonsLen(n)
var length = len(n)
var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch
if catchBranchesExist:
add(p.body, "++excHandler;\L")
@@ -749,7 +731,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
" lastJSError = EXC;$n --excHandler;$n", [])
line(p, "framePtr = $1;$n" % [tmpFramePtr])
while i < length and n.sons[i].kind == nkExceptBranch:
let blen = sonsLen(n.sons[i])
let blen = len(n.sons[i])
if blen == 1:
# general except section:
generalCatchBranchExists = true
@@ -840,11 +822,11 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
if not isEmptyType(n.typ):
r.kind = resVal
r.res = getTemp(p)
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
let it = n.sons[i]
case it.kind
of nkOfBranch:
for j in 0 .. sonsLen(it) - 2:
for j in 0 .. len(it) - 2:
let e = it.sons[j]
if e.kind == nkRange:
var v = copyNode(e.sons[0])
@@ -912,7 +894,7 @@ proc genBreakStmt(p: PProc, n: PNode) =
proc genAsmOrEmitStmt(p: PProc, n: PNode) =
genLineDir(p, n)
p.body.add p.indentLine(nil)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
let it = n[i]
case it.kind
of nkStrLit..nkTripleStrLit:
@@ -950,9 +932,9 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
if not isEmptyType(n.typ):
r.kind = resVal
r.res = getTemp(p)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
let it = n.sons[i]
if sonsLen(it) != 1:
if len(it) != 1:
if i > 0:
lineF(p, "else {$n", [])
inc(toClose)
@@ -969,7 +951,7 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
proc generateHeader(p: PProc, typ: PType): Rope =
result = nil
for i in 1 ..< sonsLen(typ.n):
for i in 1 ..< len(typ.n):
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
if isCompileTimeOnly(param.typ): continue
@@ -982,7 +964,7 @@ proc generateHeader(p: PProc, typ: PType): Rope =
add(result, "_Idx")
proc countJsParams(typ: PType): int =
for i in 1 ..< sonsLen(typ.n):
for i in 1 ..< len(typ.n):
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
if isCompileTimeOnly(param.typ): continue
@@ -1157,9 +1139,10 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
useMagic(p, "raiseFieldError")
useMagic(p, "makeNimstrLit")
let msg = genFieldError(field, disc)
lineF(p, "if ($1[$2.$3]$4undefined) { raiseFieldError(makeNimstrLit($5)); }$n",
setx.res, tmp, disc.loc.r, if negCheck: ~"!==" else: ~"===",
makeJSString(field.name.s))
makeJSString(msg))
if addrTyp != nil and mapType(p, addrTyp) == etyBaseIndex:
r.typ = etyBaseIndex
@@ -1173,7 +1156,7 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
var
a, b: TCompRes
first: BiggestInt
first: Int128
r.typ = etyBaseIndex
let m = if n.kind == nkHiddenAddr: n.sons[0] else: n
gen(p, m.sons[0], a)
@@ -1182,11 +1165,11 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
let (x, tmp) = maybeMakeTemp(p, m[0], a)
r.address = x
var typ = skipTypes(m.sons[0].typ, abstractPtrs)
if typ.kind == tyArray: first = firstOrd(p.config, typ.sons[0])
else: first = 0
if typ.kind == tyArray:
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:
@@ -1312,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)
@@ -1422,13 +1409,13 @@ proc genArgs(p: PProc, n: PNode, r: var TCompRes; start=1) =
var typ = skipTypes(n.sons[0].typ, abstractInst)
assert(typ.kind == tyProc)
assert(sonsLen(typ) == sonsLen(typ.n))
assert(len(typ) == len(typ.n))
var emitted = start-1
for i in start ..< sonsLen(n):
for i in start ..< len(n):
let it = n.sons[i]
var paramType: PNode = nil
if i < sonsLen(typ):
if i < len(typ):
assert(typ.n.sons[i].kind == nkSym)
paramType = typ.n.sons[i]
if paramType.typ.isCompileTimeOnly: continue
@@ -1456,7 +1443,7 @@ proc genOtherArg(p: PProc; n: PNode; i: int; typ: PType;
" but got only: " & $(n.len-1))
let it = n[i]
var paramType: PNode = nil
if i < sonsLen(typ):
if i < len(typ):
assert(typ.n.sons[i].kind == nkSym)
paramType = typ.n.sons[i]
if paramType.typ.isCompileTimeOnly: return
@@ -1544,7 +1531,7 @@ proc genEcho(p: PProc, n: PNode, r: var TCompRes) =
useMagic(p, "toJSStr") # Used in rawEcho
useMagic(p, "rawEcho")
add(r.res, "rawEcho(")
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
let it = n.sons[i]
if it.typ.isCompileTimeOnly: continue
if i > 0: add(r.res, ", ")
@@ -1560,11 +1547,11 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope
proc createRecordVarAux(p: PProc, rec: PNode, excludedFieldIDs: IntSet, output: var Rope) =
case rec.kind
of nkRecList:
for i in 0 ..< sonsLen(rec):
for i in 0 ..< len(rec):
createRecordVarAux(p, rec.sons[i], excludedFieldIDs, output)
of nkRecCase:
createRecordVarAux(p, rec.sons[0], excludedFieldIDs, output)
for i in 1 ..< sonsLen(rec):
for i in 1 ..< len(rec):
createRecordVarAux(p, lastSon(rec.sons[i]), excludedFieldIDs, output)
of nkSym:
# Do not produce code for void types
@@ -1611,8 +1598,10 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
result = putToSeq("{}", indirect)
of tyBool:
result = putToSeq("false", indirect)
of tyNil:
result = putToSeq("null", indirect)
of tyArray:
let length = int(lengthOrd(p.config, t))
let length = toInt(lengthOrd(p.config, t))
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
if jsTyp.len > 0:
@@ -1634,7 +1623,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
if indirect: result = "[$1]" % [result]
of tyTuple:
result = rope("{")
for i in 0..<t.sonsLen:
for i in 0..<t.len:
if i > 0: add(result, ", ")
addf(result, "Field$1: $2", [i.rope,
createVar(p, t.sons[i], false)])
@@ -1735,7 +1724,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
lineF(p, "}$n")
proc genVarStmt(p: PProc, n: PNode) =
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind != nkCommentStmt:
if a.kind == nkVarTuple:
@@ -1747,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):
@@ -1793,15 +1786,15 @@ proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
else:
r.res.add("($1 || []).concat(" % [a.res])
for i in 2 .. sonsLen(n) - 2:
for i in 2 .. len(n) - 2:
gen(p, n.sons[i], a)
if skipTypes(n.sons[i].typ, abstractVarRange).kind == tyChar:
r.res.add("[$1]," % [a.res])
else:
r.res.add("$1 || []," % [a.res])
gen(p, n.sons[sonsLen(n) - 1], a)
if skipTypes(n.sons[sonsLen(n) - 1].typ, abstractVarRange).kind == tyChar:
gen(p, n.sons[len(n) - 1], a)
if skipTypes(n.sons[len(n) - 1].typ, abstractVarRange).kind == tyChar:
r.res.add("[$1])" % [a.res])
else:
r.res.add("$1 || [])" % [a.res])
@@ -1901,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
@@ -2025,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)
@@ -2048,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]);
@@ -2058,7 +2062,7 @@ proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) =
useMagic(p, "setConstr")
r.res = rope("setConstr(")
r.kind = resExpr
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if i > 0: add(r.res, ", ")
var it = n.sons[i]
if it.kind == nkRange:
@@ -2080,7 +2084,7 @@ proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
var a: TCompRes
r.res = rope("[")
r.kind = resExpr
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if i > 0: add(r.res, ", ")
gen(p, n.sons[i], a)
if a.typ == etyBaseIndex:
@@ -2097,7 +2101,7 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) =
var a: TCompRes
r.res = rope("{")
r.kind = resExpr
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if i > 0: add(r.res, ", ")
var it = n.sons[i]
if it.kind == nkExprColonExpr: it = it.sons[1]
@@ -2117,7 +2121,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
r.kind = resExpr
var initList : Rope
var fieldIDs = initIntSet()
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if i > 1: add(initList, ", ")
var it = n.sons[i]
internalAssert p.config, it.kind == nkExprColonExpr
@@ -2162,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")
@@ -2451,7 +2458,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
# this shows the distinction is nice for backends and should be kept
# in the frontend
let isExpr = not isEmptyType(n.typ)
for i in 0 ..< sonsLen(n) - isExpr.ord:
for i in 0 ..< len(n) - isExpr.ord:
genStmt(p, n.sons[i])
if isExpr:
gen(p, lastSon(n), r)
@@ -2588,7 +2595,7 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
attachProc(p, prc)
var disp = generateMethodDispatchers(graph)
for i in 0..sonsLen(disp)-1:
for i in 0..len(disp)-1:
let prc = disp.sons[i].sym
if not globals.generatedSyms.containsOrIncl(prc.id):
var p = newProc(globals, m, nil, m.module.options)

View File

@@ -7,8 +7,12 @@
# distribution, for details about the copyright.
#
# included from jsgen.nim
## Type info generation for the JS backend.
proc rope(arg: Int128): Rope = rope($arg)
proc genTypeInfo(p: PProc, typ: PType): Rope
proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
var
@@ -19,7 +23,7 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
result = nil
case n.kind
of nkRecList:
length = sonsLen(n)
length = len(n)
if length == 1:
result = genObjectFields(p, typ, n.sons[0])
else:
@@ -37,7 +41,7 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
[mangleName(p.module, field), s,
makeJSString(field.name.s)]
of nkRecCase:
length = sonsLen(n)
length = len(n)
if (n.sons[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
field = n.sons[0].sym
s = genTypeInfo(p, field.typ)
@@ -46,9 +50,9 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
u = nil
case b.kind
of nkOfBranch:
if sonsLen(b) < 2:
if len(b) < 2:
internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
for j in 0 .. sonsLen(b) - 2:
for j in 0 .. len(b) - 2:
if u != nil: add(u, ", ")
if b.sons[j].kind == nkRange:
addf(u, "[$1, $2]", [rope(getOrdValue(b.sons[j].sons[0])),
@@ -101,7 +105,7 @@ proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
let length = sonsLen(typ.n)
let length = len(typ.n)
var s: Rope = nil
for i in 0 ..< length:
if (typ.n.sons[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")

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:
@@ -933,7 +940,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
var loopBody = newNodeI(nkStmtList, body.info, 3)
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(g, body.info, tyBool))
whileLoop.sons[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
whileLoop.sons[1] = loopBody
result.add whileLoop

View File

@@ -9,10 +9,7 @@
## Layouter for nimpretty.
import idents, lexer, lineinfos, llstream, options, msgs, strutils,
pathutils
from os import changeFileExt
from sequtils import delete
import idents, lexer, lineinfos, llstream, options, msgs, strutils, pathutils
const
MinLineLen = 15
@@ -314,11 +311,11 @@ proc removeSpaces(em: var Emitter) =
const
openPars = {tkParLe, tkParDotLe,
tkBracketLe, tkBracketLeColon, tkCurlyDotLe,
tkCurlyLe}
tkBracketLe, tkBracketDotLe, tkBracketLeColon,
tkCurlyDotLe, tkCurlyLe}
closedPars = {tkParRi, tkParDotRi,
tkBracketRi, tkCurlyDotRi,
tkCurlyRi, tkBracketDotRi}
tkBracketRi, tkBracketDotRi,
tkCurlyDotRi, tkCurlyRi}
splitters = openPars + {tkComma, tkSemiColon} # do not add 'tkColon' here!
oprSet = {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
@@ -444,6 +441,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
em.indentLevel = tok.indent
elif (em.lastTok in (splitters + oprSet) and
tok.tokType notin (closedPars - {tkBracketDotRi})):
if tok.tokType in openPars and tok.indent > em.indentStack[^1]:
while em.indentStack[^1] < tok.indent:
em.indentStack.add(em.indentStack[^1] + em.indWidth)
# aka: we are in an expression context:
let alignment = max(tok.indent - em.indentStack[^1], 0)
em.indentLevel = alignment + em.indentStack.high * em.indWidth
@@ -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
@@ -565,7 +565,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
case result.tokType
of floatTypes:
result.fNumber = parseFloat(result.literal)
of tkUInt64Lit:
of tkUInt64Lit, tkUIntLit:
var iNumber: uint64
var len: int
try:
@@ -864,7 +864,9 @@ proc getCharacter(L: var TLexer, tok: var TToken) =
inc(L.bufpos) # skip '
var c = L.buf[L.bufpos]
case c
of '\0'..pred(' '), '\'': lexMessage(L, errGenerated, "invalid character literal")
of '\0'..pred(' '), '\'':
lexMessage(L, errGenerated, "invalid character literal")
tok.literal = $c
of '\\': getEscapedChar(L, tok)
else:
tok.literal = $c

View File

@@ -129,7 +129,7 @@ proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newOpCall(op, y))
proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} =
result = optNimV2 in c.g.config.globalOptions and
result = c.g.config.selectedGC == gcDestructors and
({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem)
proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
@@ -142,7 +142,7 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
field: var PSym): bool =
if optNimV2 in c.g.config.globalOptions:
if c.g.config.selectedGC == gcDestructors:
let op = field
if field != nil and sfOverriden in field.flags:
if sfError in op.flags:
@@ -182,8 +182,16 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
body.add newAsgnCall(c.g, op, x, y)
result = true
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode) =
proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
let t = orig.skipTypes(abstractInst)
var op = t.destructor
if op != nil and sfOverriden in op.flags:
if op.ast[genericParamsPos].kind != nkEmpty:
# patch generic destructor:
op = instantiateGeneric(c, op, t, t.typeInst)
t.attachedOps[attachedDestructor] = op
if op == nil and useNoGc(c, t):
op = produceSym(c.g, c.c, t, attachedDestructor, c.info)
doAssert op != nil
@@ -288,7 +296,7 @@ proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let i = declareCounter(c, body, firstOrd(c.g.config, t))
let i = declareCounter(c, body, toInt64(firstOrd(c.g.config, t)))
let whileLoop = genWhileLoop(c, i, x)
let elemType = t.lastSon
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
@@ -396,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)
@@ -449,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:
@@ -461,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)
@@ -506,7 +514,11 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tyTuple:
fillBodyTup(c, t, body, x, y)
of tyVarargs, tyOpenArray:
localError(c.g.config, c.info, "cannot copy openArray")
if c.kind == attachedDestructor:
forallElements(c, t, body, x, y)
else:
discard "cannot copy openArray"
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
@@ -559,7 +571,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
typ.attachedOps[kind] = result
var tk: TTypeKind
if optNimV2 in g.config.globalOptions:
if g.config.selectedGC == gcDestructors:
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
else:
tk = tyNone # no special casing for strings and seqs
@@ -626,10 +638,10 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
var canon = g.canonTypes.getOrDefault(h)
var overwrite = false
if canon == nil:
let typ = orig.skipTypes({tyGenericInst, tyAlias})
let typ = orig.skipTypes({tyGenericInst, tyAlias, tySink})
g.canonTypes[h] = typ
canon = typ
elif canon != orig:
if canon != orig:
overwrite = true
# multiple cases are to distinguish here:

View File

@@ -13,7 +13,7 @@
import ropes, tables, pathutils
const
explanationsBaseUrl* = "https://nim-lang.org/docs/manual"
explanationsBaseUrl* = "https://nim-lang.org/docs"
type
TMsgKind* = enum
@@ -33,12 +33,14 @@ type
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnUnusedImportX,
warnEachIdentIsTuple,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnCaseTransition, warnUser,
hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintLineTooLong, hintXDeclaredButNotUsed,
hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
@@ -78,6 +80,7 @@ const
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
warnWriteToForeignHeap: "write to foreign heap",
warnUnsafeCode: "unsafe code: '$1'",
warnUnusedImportX: "imported and not used: '$1'",
warnEachIdentIsTuple: "each identifier is a tuple",
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
warnProveField: "cannot prove that field '$1' is accessible",
@@ -133,14 +136,15 @@ const
"LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored",
"TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple",
"UnsafeCode", "UnusedImport", "EachIdentIsTuple",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "CaseTransition", "User"]
HintsToStr* = [
"Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"XDeclaredButNotUsed",
"ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro",
@@ -240,8 +244,10 @@ type
Severity* {.pure.} = enum ## VS Code only supports these three
Hint, Warning, Error
const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
const
trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
commandLineIdx* = FileIndex(-3)
type
MsgConfig* = object ## does not need to be stored in the incremental cache

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))
@@ -430,7 +430,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimOtherModule:
result = nextIdentIter(o.it, o.m.tab).skipAlias(n, c.config)
of oimSymChoice:
if o.symChoiceIndex < sonsLen(n):
if o.symChoiceIndex < len(n):
result = n.sons[o.symChoiceIndex].sym
incl(o.inSymChoice, result.id)
inc o.symChoiceIndex

View File

@@ -21,8 +21,8 @@ proc newDeref*(n: PNode): PNode {.inline.} =
proc newTupleAccess*(g: ModuleGraph; tup: PNode, i: int): PNode =
if tup.kind == nkHiddenAddr:
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar}))
result.addSon(newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar}).sons[i]))
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent}))
result.addSon(newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent}).sons[i]))
addSon(result[0], tup[0])
var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
lit.intVal = i
@@ -152,7 +152,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
proc rawAddField*(obj: PType; field: PSym) =
assert field.kind == skField
field.position = sonsLen(obj.n)
field.position = len(obj.n)
addSon(obj.n, newSymNode(field))
propagateToOwner(obj, field.typ)
@@ -179,14 +179,14 @@ proc lookupInRecord(n: PNode, id: int): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result = lookupInRecord(n.sons[i], id)
if result != nil: return
of nkRecCase:
if n.sons[0].kind != nkSym: return
result = lookupInRecord(n.sons[0], id)
if result != nil: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
result = lookupInRecord(lastSon(n.sons[i]), id)
@@ -206,7 +206,7 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) =
field.typ = t
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = sonsLen(obj.n)
field.position = len(obj.n)
addSon(obj.n, newSymNode(field))
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} =
@@ -219,7 +219,7 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable
field.typ = t
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = sonsLen(obj.n)
field.position = len(obj.n)
addSon(obj.n, newSymNode(field))
result = field
@@ -330,7 +330,7 @@ proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
proc genHigh*(g: ModuleGraph; n: PNode): PNode =
if skipTypes(n.typ, abstractVar).kind == tyArray:
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)))
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar))))
else:
result = newNodeI(nkCall, n.info, 2)
result.typ = getSysType(g, n.info, tyInt)
@@ -339,7 +339,7 @@ proc genHigh*(g: ModuleGraph; n: PNode): PNode =
proc genLen*(g: ModuleGraph; n: PNode): PNode =
if skipTypes(n.typ, abstractVar).kind == tyArray:
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1)
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1))
else:
result = newNodeI(nkCall, n.info, 2)
result.typ = getSysType(g, n.info, tyInt)

View File

@@ -18,7 +18,7 @@ import
sem, idents, passes, extccomp,
cgen, json, nversion,
platform, nimconf, passaux, depends, vm, idgen,
parser, modules,
modules,
modulegraphs, tables, rod, lineinfos, pathutils
when not defined(leanCompiler):
@@ -82,6 +82,13 @@ proc commandCompileToC(graph: ModuleGraph) =
semanticPasses(graph)
registerPass(graph, cgenPass)
if {optRun, optForceFullMake} * conf.globalOptions == {optRun} or isDefined(conf, "nimBetterRun"):
let proj = changeFileExt(conf.projectFull, "")
if not changeDetectedViaJsonBuildInstructions(conf, proj):
# nothing changed
graph.config.notes = graph.config.mainPackageNotes
return
compileProject(graph)
if graph.config.errorCounter > 0:
return # issue #9933
@@ -143,14 +150,6 @@ const evalPasses = [verbosePass, semPass, evalPass]
proc evalNim(graph: ModuleGraph; nodes: PNode, module: PSym) =
carryPasses(graph, nodes, module, evalPasses)
proc commandEval(graph: ModuleGraph; exp: string) =
if graph.systemModule == nil:
interactivePasses(graph)
compileSystemModule(graph)
let echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
evalNim(graph, echoExp.parseString(graph.cache, graph.config),
makeStdinModule(graph))
proc commandScan(cache: IdentCache, config: ConfigRef) =
var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt)
var stream = llStreamOpen(f, fmRead)
@@ -338,8 +337,11 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdInteractive
commandInteractive(graph)
of "e":
incl conf.globalOptions, optWasNimscript
commandEval(graph, mainCommandArg(conf))
if not fileExists(conf.projectFull):
rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string)
elif not conf.projectFull.string.endsWith(".nims"):
rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string)
# main NimScript logic handled in cmdlinehelper.nim.
of "nop", "help":
# prevent the "success" message:
conf.cmd = cmdDump

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]
@@ -98,7 +98,7 @@ const
proc toBase64a(s: cstring, len: int): string =
## encodes `s` into base64 representation.
result = newStringOfCap(((len + 2) div 3) * 4)
result.add '_'
result.add "__"
var i = 0
while i < len - 2:
let a = ord(s[i])
@@ -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

@@ -50,7 +50,6 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
setLen(graph.modules, int(fileIdx) + 1)
graph.modules[result.position] = result
incl(result.flags, sfUsed)
initStrTable(result.tab)
strTableAdd(result.tab, result) # a module knows itself
strTableAdd(packSym.tab, result)

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
@@ -160,19 +161,25 @@ proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
if i >=% L: result = unknownLineInfo()
else: result = conf.m.msgContext[i].info
const
commandLineDesc = "command line"
template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil:
"???"
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
else:
conf.m.fileInfos[fileIdx.int32].shortName
proc toProjPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil: "???"
if fileIdx.int32 < 0 or conf == nil:
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
else: conf.m.fileInfos[fileIdx.int32].projPath.string
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil: result = "???"
else: result = conf.m.fileInfos[fileIdx.int32].fullPath.string
if fileIdx.int32 < 0 or conf == nil:
result = (if fileIdx == commandLineIdx: commandLineDesc else: "???")
else:
result = conf.m.fileInfos[fileIdx.int32].fullPath.string
proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: AbsoluteFile) =
assert fileIdx.int32 >= 0
@@ -189,7 +196,7 @@ proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile =
if fileIdx.int32 < 0:
result = AbsoluteFile"???"
result = AbsoluteFile(if fileIdx == commandLineIdx: commandLineDesc else: "???")
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isEmpty:
result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else:

View File

@@ -7,6 +7,8 @@ define:nimcore
#define:nimIncremental
#import:"$projectpath/testability"
#define:staticSqlite
@if windows:
cincludes: "$lib/wrappers/libffi/common"
@end

View File

@@ -40,20 +40,40 @@ 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.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.quoteShell
if p.key == " ":
p.key = "-"
if processArgument(pass, p, argsCount, config): break
else:
processSwitch(pass, p, config)
of cmdArgument:
config.commandLine.add " "
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

@@ -17,7 +17,7 @@ proc inSet*(s: PNode, elem: PNode): bool =
if s.kind != nkCurly:
#internalError(s.info, "inSet")
return false
for i in 0 ..< sonsLen(s):
for i in 0 ..< len(s):
if s.sons[i].kind == nkRange:
if leValue(s.sons[i].sons[0], elem) and
leValue(elem, s.sons[i].sons[1]):
@@ -47,7 +47,7 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
if s.kind != nkCurly:
#internalError(s.info, "SomeInSet")
return false
for i in 0 ..< sonsLen(s):
for i in 0 ..< len(s):
if s.sons[i].kind == nkRange:
if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
@@ -59,17 +59,17 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
result = false
proc toBitSet*(conf: ConfigRef; s: PNode, b: var TBitSet) =
var first, j: BiggestInt
var first, j: Int128
first = firstOrd(conf, s.typ.sons[0])
bitSetInit(b, int(getSize(conf, s.typ)))
for i in 0 ..< sonsLen(s):
for i in 0 ..< len(s):
if s.sons[i].kind == nkRange:
j = getOrdValue(s.sons[i].sons[0], first)
while j <= getOrdValue(s.sons[i].sons[1], first):
bitSetIncl(b, j - first)
bitSetIncl(b, toInt64(j - first))
inc(j)
else:
bitSetIncl(b, getOrdValue(s.sons[i], first) - first)
bitSetIncl(b, toInt64(getOrdValue(s.sons[i]) - first))
proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
var
@@ -77,7 +77,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
elemType: PType
n: PNode
elemType = settype.sons[0]
first = firstOrd(conf, elemType)
first = firstOrd(conf, elemType).toInt64
result = newNodeI(nkCurly, info)
result.typ = settype
result.info = info
@@ -90,7 +90,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
inc(b)
if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
dec(b)
let aa = newIntTypeNode(nkIntLit, a + first, elemType)
let aa = newIntTypeNode(a + first, elemType)
aa.info = info
if a == b:
addSon(result, aa)
@@ -98,7 +98,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
n = newNodeI(nkRange, info)
n.typ = elemType
addSon(n, aa)
let bb = newIntTypeNode(nkIntLit, b + first, elemType)
let bb = newIntTypeNode(b + first, elemType)
bb.info = info
addSon(n, bb)
addSon(result, n)
@@ -149,7 +149,7 @@ proc setHasRange*(s: PNode): bool =
assert s.kind == nkCurly
if s.kind != nkCurly:
return false
for i in 0 ..< sonsLen(s):
for i in 0 ..< len(s):
if s.sons[i].kind == nkRange:
return true
result = false

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

@@ -30,7 +30,6 @@ type # please make sure we have under 32 options
optAssert, optLineDir, optWarns, optHints,
optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
optLineTrace, # line tracing support (includes stack tracing)
optEndb, # embedded debugger
optByRef, # use pass by ref for objects
# (for interfacing with C)
optProfiler, # profiler turned on
@@ -82,8 +81,13 @@ 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
TGlobalOptions* = set[TGlobalOption]
@@ -110,7 +114,7 @@ type
cmdJsonScript # compile a .json build file
TStringSeq* = seq[string]
TGCMode* = enum # the selected GC
gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
gcRefc, gcV2, gcGo
# gcRefc and the GCs that follow it use a write barrier,
# as far as usesWriteBarrier() is concerned
@@ -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
@@ -236,6 +244,7 @@ type
projectMainIdx*: FileIndex # the canonical path id of the main module
command*: string # the main command (e.g. cc, check, scan, etc)
commandArgs*: seq[string] # any arguments after the main command
commandLine*: string
keepComments*: bool # whether the parser needs to keep comments
implicitImports*: seq[string] # modules that are to be implicitly imported
implicitIncludes*: seq[string] # modules that are to be implicitly included
@@ -342,6 +351,7 @@ proc newConfigRef*(): ConfigRef =
projectMainIdx: FileIndex(0'i32), # the canonical path id of the main module
command: "", # the main command (e.g. cc, check, scan, etc)
commandArgs: @[], # any arguments after the main command
commandLine: "",
keepComments: true, # whether the parser needs to keep comments
implicitImports: @[], # modules that are to be implicitly imported
implicitIncludes: @[], # modules that are to be implicitly included
@@ -395,7 +405,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
result = conf.target.targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osDragonfly, osMacosx,
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
osAndroid, osNintendoSwitch}
of "linux":
result = conf.target.targetOS in {osLinux, osAndroid}
@@ -405,8 +415,10 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
result = platform.OS[conf.target.targetOS].props.contains(ospLacksThreadVars)
of "msdos": result = conf.target.targetOS == osDos
of "mswindows", "win32": result = conf.target.targetOS == osWindows
of "macintosh": result = conf.target.targetOS in {osMacos, osMacosx}
of "osx": result = conf.target.targetOS == osMacosx
of "macintosh":
result = conf.target.targetOS in {osMacos, osMacosx, osIos}
of "osx", "macosx":
result = conf.target.targetOS in {osMacosx, osIos}
of "sunos": result = conf.target.targetOS == osSolaris
of "nintendoswitch":
result = conf.target.targetOS == osNintendoSwitch
@@ -469,12 +481,16 @@ proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): Absolute
conf.outDir / changeFileExt(filename, ext)
proc absOutFile*(conf: ConfigRef): AbsoluteFile =
conf.outDir / conf.outFile
result = conf.outDir / conf.outFile
if dirExists(result.string):
result.string.add ".out"
proc prepareToWriteOutput*(conf: ConfigRef): AbsoluteFile =
## Create the output directory and returns a full path to the output file
createDir conf.outDir
return conf.outDir / conf.outFile
result = conf.outDir / conf.outFile
if dirExists(result.string):
result.string.add ".out"
proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
## Gets the prefix dir, usually the parent directory where the binary resides.
@@ -532,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 =
@@ -560,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 =
@@ -716,3 +733,13 @@ proc `$`*(c: IdeCmd): string =
of ideOutline: "outline"
of ideKnown: "known"
of ideMsg: "msg"
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.
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
# to 4bytes (except with -malign-double)
return 4
return 8

View File

@@ -39,22 +39,17 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
if parents <= 0: break
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
# foo/../bar becomes foo7_7bar
result = relativeTo(path, conf.projectPath, '/').string.multiReplace(
{"/": "7", "..": "_", "7": "77", "_": "__", ":": "8", "8": "88"})
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@", ":": "@c"})
proc demanglePackageName*(path: string): string =
result = path.multiReplace(
{"88": "8", "8": ":", "77": "7", "__": "_", "_7": "../", "7": "/"})
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

@@ -218,20 +218,22 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
of nkSym:
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
else: {skVar, skResult, skTemp}
if n.sym.kind in kinds:
if n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}:
result = arLValue
elif isUnsafeAddr and n.sym.kind == skParam:
result = arLValue
elif n.sym.kind in kinds:
if owner != nil and owner == n.sym.owner and
sfGlobal notin n.sym.flags:
result = arLocalLValue
else:
result = arLValue
elif n.sym.kind == skParam and n.sym.typ.kind == tyVar:
result = arLValue
elif n.sym.kind == skType:
let t = n.sym.typ.skipTypes({tyTypeDesc})
if t.kind == tyVar: result = arStrange
of nkDotExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}:
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue
elif isUnsafeAddr and t.kind == tyLent:
result = arLValue
@@ -242,7 +244,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arDiscriminant
of nkBracketExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}:
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue
elif isUnsafeAddr and t.kind == tyLent:
result = arLValue

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

@@ -97,7 +97,6 @@ proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
proc processImplicits(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
a: var TPassContextArray; m: PSym) =
# XXX fixme this should actually be relative to the config file!
let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
let relativeTo = toFullPath(graph.config, m.info)
for module in items(implicits):
# implicit imports should not lead to a module importing itself

View File

@@ -58,8 +58,8 @@ proc sameTrees*(a, b: PNode): bool =
of nkEmpty, nkNilLit: result = true
of nkType: result = sameTypeOrNil(a.typ, b.typ)
else:
if sonsLen(a) == sonsLen(b):
for i in 0 ..< sonsLen(a):
if len(a) == len(b):
for i in 0 ..< len(a):
if not sameTrees(a.sons[i], b.sons[i]): return
result = true
@@ -112,7 +112,7 @@ proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
rpn: bool): bool =
result = true
if n.kind in nkCallKinds and matches(c, op.sons[1], n.sons[0]):
for i in 1..sonsLen(n)-1:
for i in 1..len(n)-1:
if not matchStarAux(c, op, n[i], arglist, rpn): return false
if rpn: arglist.add(n.sons[0])
elif n.kind == nkHiddenStdConv and n.sons[1].kind == nkBracket:
@@ -174,35 +174,35 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
of nkEmpty, nkNilLit, nkType:
result = true
else:
var plen = sonsLen(p)
var plen = len(p)
# special rule for p(X) ~ f(...); this also works for stuff like
# partial case statements, etc! - Not really ... :-/
let v = lastSon(p)
if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs:
var arglist: PNode
if plen <= sonsLen(n):
if plen <= len(n):
for i in 0 .. plen - 2:
if not matches(c, p.sons[i], n.sons[i]): return
if plen == sonsLen(n) and lastSon(n).kind == nkHiddenStdConv and
if plen == len(n) and lastSon(n).kind == nkHiddenStdConv and
lastSon(n).sons[1].kind == nkBracket:
# unpack varargs:
let n = lastSon(n).sons[1]
arglist = newNodeI(nkArgList, n.info, n.len)
for i in 0..<n.len: arglist.sons[i] = n.sons[i]
else:
arglist = newNodeI(nkArgList, n.info, sonsLen(n) - plen + 1)
arglist = newNodeI(nkArgList, n.info, len(n) - plen + 1)
# f(1, 2, 3)
# p(X)
for i in 0 .. sonsLen(n) - plen:
for i in 0 .. len(n) - plen:
arglist.sons[i] = n.sons[i + plen - 1]
return bindOrCheck(c, v.sym, arglist)
elif plen-1 == sonsLen(n):
elif plen-1 == len(n):
for i in 0 .. plen - 2:
if not matches(c, p.sons[i], n.sons[i]): return
arglist = newNodeI(nkArgList, n.info)
return bindOrCheck(c, v.sym, arglist)
if plen == sonsLen(n):
for i in 0 ..< sonsLen(p):
if plen == len(n):
for i in 0 ..< len(p):
if not matches(c, p.sons[i], n.sons[i]): return
result = true
@@ -250,7 +250,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
var ctx: TPatternContext
ctx.owner = s
ctx.c = c
ctx.formals = sonsLen(s.typ)-1
ctx.formals = len(s.typ)-1
var m = matchStmtList(ctx, s.ast.sons[patternPos], n)
if isNil(m): return nil
# each parameter should have been bound; we simply setup a call and
@@ -295,7 +295,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
# constraint not fulfilled:
if not ok: return nil
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
if ctx.subMatch:
assert m.len == 3
m.sons[1] = result

View File

@@ -21,7 +21,7 @@ type
# conditionals to condsyms (end of module).
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxWorks
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch
type
@@ -139,6 +139,10 @@ const
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "iOS", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "Haiku", parDir: "..", dllFrmt: "lib$1.so", altDirSep: ":",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",

View File

@@ -17,25 +17,24 @@ proc semLocals*(c: PContext, n: PNode): PNode =
var tupleType = newTypeS(tyTuple, c)
result = newNodeIT(nkPar, n.info, tupleType)
tupleType.n = newNodeI(nkRecList, n.info)
let owner = getCurrOwner(c)
# for now we skip openarrays ...
for scope in walkScopes(c.currentScope):
if scope == c.topLevelScope: break
for it in items(scope.symbols):
# XXX parameters' owners are wrong for generics; this caused some pain
# for closures too; we should finally fix it.
#if it.owner != c.p.owner: return result
if it.kind in skLocalVars and
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}:
var field = newSym(skField, it.name, getCurrOwner(c), n.info)
field.typ = it.typ.skipTypes({tyVar})
field.position = counter
inc(counter)
if it.owner == owner:
var field = newSym(skField, it.name, owner, n.info)
field.typ = it.typ.skipTypes({tyVar})
field.position = counter
inc(counter)
addSon(tupleType.n, newSymNode(field))
addSonSkipIntLit(tupleType, field.typ)
addSon(tupleType.n, newSymNode(field))
addSonSkipIntLit(tupleType, field.typ)
var a = newSymNode(it, result.info)
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
result.add(a)
var a = newSymNode(it, result.info)
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
result.add(a)

View File

@@ -19,55 +19,57 @@ const
LastCallConv* = wNoconv
const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed}
## common pragmas for declarations, to a good approximation
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
wCompilerProc, wNonReloadable, wCore, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wCodegenDecl,
wCompilerProc, wNonReloadable, wCore, wProcVar, wVarargs, wCompileTime, wMerge,
wBorrow, wImportCompilerProc, wThread,
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wConstructor, wExportNims, wUsed, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
converterPragmas* = procPragmas - {wNoDestroy}
methodPragmas* = procPragmas+{wBase}-{wImportCpp, wNoDestroy}
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
wDelegator, wExportNims, wUsed, wPragma}
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc,
wNodecl, wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
wExportNims, wUsed}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe, wExportNims, wUsed}
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore,
wDiscardable, wGensym, wInject, wDelegator}
iteratorPragmas* = declPragmas + {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
wMagic, wBorrow,
wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe}
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNoSideEffect}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
wBoundChecks, wOverflowChecks, wNilChecks, wStyleChecks, wAssertions,
wWarnings, wHints,
wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError,
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
wBreakpoint, wWatchPoint, wPassl, wPassc,
wPassl, wPassc,
wDeadCodeElimUnused, # deprecated, always on
wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental, wThis}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wInjectStmt, wExperimental, wThis, wUsed}
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wThread, wAsmNoStackFrame,
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
typePragmas* = declPragmas + {wMagic, wAcyclic,
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe, wExportNims, wPartial, wUsed, wExplain, wPackage}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerProc, wCore, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed, wCursor}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
wIntDefine, wStrDefine, wBoolDefine, wUsed, wCompilerProc, wCore}
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
fieldPragmas* = declPragmas + {
wGuard, wBitsize} - {wExportNims, wNodecl} # why exclude these?
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
wThread, wRaises, wLocks, wTags, wGcSafe}
@@ -83,7 +85,8 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode =
it[0].ident.id == ord(name):
return it[1]
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
isStatement: bool = false)
proc recordPragma(c: PContext; n: PNode; key, val: string; val2 = "") =
var recorded = newNodeI(nkCommentStmt, n.info)
@@ -104,7 +107,7 @@ proc illegalCustomPragma*(c: PContext, n: PNode, s: PSym) =
proc pragmaAsm*(c: PContext, n: PNode): char =
result = '\0'
if n != nil:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
let it = n.sons[i]
if it.kind in nkPragmaCallKinds and it.len == 2 and it.sons[0].kind == nkIdent:
case whichKeyword(it.sons[0].ident)
@@ -345,7 +348,7 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
of wLineDir: {optLineDir}
of wStackTrace: {optStackTrace}
of wLineTrace: {optLineTrace}
of wDebugger: {optEndb}
of wDebugger: {optNone}
of wProfiler: {optProfiler, optMemTracker}
of wMemTracker: {optMemTracker}
of wByRef: {optByRef}
@@ -415,15 +418,8 @@ 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)
for i in start ..< sonsLen(n):
var x = pushOptionEntry(c)
for i in start ..< len(n):
if not tryProcessOption(c, n.sons[i], c.config.options):
# simply store it somewhere:
if x.otherPragmas.isNil:
@@ -441,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
@@ -513,15 +506,6 @@ proc processLink(c: PContext, n: PNode) =
extccomp.addExternalFileToLink(c.config, found)
recordPragma(c, n, "link", found.string)
proc pragmaBreakpoint(c: PContext, n: PNode) =
discard getOptionalStr(c, n, "")
proc pragmaWatchpoint(c: PContext, n: PNode) =
if n.kind in nkPragmaCallKinds and n.len == 2:
n.sons[1] = c.semExpr(c, n.sons[1])
else:
invalidPragma(c, n)
proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
case n.sons[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
@@ -726,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:
@@ -754,7 +738,8 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
result.kind = n.kind
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
validPragmas: TSpecialWords, comesFromPush: bool) : bool =
validPragmas: TSpecialWords,
comesFromPush, isStatement: bool) : bool =
var it = n.sons[i]
var key = if it.kind in nkPragmaCallKinds and it.len > 1: it.sons[0] else: it
if key.kind == nkBracketExpr:
@@ -774,7 +759,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if c.instCounter > 100:
globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s)
pragma(c, sym, userPragma.ast, validPragmas)
pragma(c, sym, userPragma.ast, validPragmas, isStatement)
n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty
dec c.instCounter
@@ -784,8 +769,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
checkPragmaUse(c.config, key.info, k, ident.s)
case k
of wExportc:
of wExportc, wExportCpp:
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
if k == wExportCpp:
if c.config.cmd != cmdCompileToCpp:
localError(c.config, it.info, "exportcpp requires `nim cpp`, got " & $c.config.cmd)
else:
incl(sym.flags, sfMangleCpp)
incl(sym.flags, sfUsed) # avoid wrong hints
of wImportc:
let name = getOptionalStr(c, it, "$1")
@@ -803,6 +793,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else: invalidPragma(c, it)
of wImportCpp:
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
of wImportJs:
if c.config.cmd != cmdCompileToJS:
localError(c.config, it.info, "`importjs` pragma requires the JavaScript target")
let name = getOptionalStr(c, it, "$1")
incl(sym.flags, sfImportc)
incl(sym.flags, sfInfixCall)
if sym.kind in skProcKinds and {'(', '#', '@'} notin name:
localError(c.config, n.info, "`importjs` for routines requires a pattern")
setExternName(c, sym, name, it.info)
of wImportObjC:
processImportObjC(c, sym, getOptionalStr(c, it, "$1"), it.info)
of wAlign:
@@ -816,12 +815,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if sym.typ == nil: invalidPragma(c, it)
var size = expectIntLit(c, it)
case size
of 1, 2, 4, 8:
of 1, 2, 4:
sym.typ.size = size
if size == 8 and c.config.target.targetCPU == cpuI386:
sym.typ.align = 4
else:
sym.typ.align = int16(size)
sym.typ.align = int16 size
of 8:
sym.typ.size = 8
sym.typ.align = floatInt64Align(c.config)
else:
localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
of wNodecl:
@@ -848,7 +847,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wCompileTime:
noVal(c, it)
incl(sym.flags, sfCompileTime)
incl(sym.loc.flags, lfNoDecl)
#incl(sym.loc.flags, lfNoDecl)
of wGlobal:
noVal(c, it)
incl(sym.flags, sfGlobal)
@@ -971,7 +970,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
recordPragma(c, it, "warning", s)
message(c.config, it.info, warnUser, s)
of wError:
if sym != nil and (sym.isRoutine or sym.kind == skType) and wUsed in validPragmas:
if sym != nil and (sym.isRoutine or sym.kind == skType) and not isStatement:
# This is subtle but correct: the error *statement* is only
# allowed when 'wUsed' is not in validPragmas. Here this is the easiest way to
# distinguish properly between
@@ -996,8 +995,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
let s = expectStrLit(c, it)
extccomp.addCompileOption(c.config, s)
recordPragma(c, it, "passc", s)
of wBreakpoint: pragmaBreakpoint(c, it)
of wWatchPoint: pragmaWatchpoint(c, it)
of wPush:
processPush(c, n, i + 1)
result = true
@@ -1096,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)
@@ -1142,7 +1134,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
elif comesFromPush and whichKeyword(ident) in {wTags, wRaises}:
discard "ignore the .push pragma; it doesn't apply"
else:
if sym == nil or (sym != nil and sym.kind in {skVar, skLet, skParam,
if sym == nil or (sym.kind in {skVar, skLet, skParam,
skField, skProc, skFunc, skConverter, skMethod, skType}):
n.sons[i] = semCustomPragma(c, it)
elif sym != nil:
@@ -1172,7 +1164,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
pushInfoContext(c.config, n.info)
var i = 0
while i < o.len:
if singlePragma(c, sym, o, i, validPragmas, true):
if singlePragma(c, sym, o, i, validPragmas, true, false):
internalError(c.config, n.info, "implicitPragmas")
inc i
popInfoContext(c.config)
@@ -1197,14 +1189,16 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
return false
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
isStatement: bool) =
if n == nil: return
var i = 0
while i < n.len:
if singlePragma(c, sym, n, i, validPragmas, false): break
if singlePragma(c, sym, n, i, validPragmas, false, isStatement): break
inc i
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
isStatement: bool) =
if n == nil: return
pragmaRec(c, sym, n, validPragmas)
pragmaRec(c, sym, n, validPragmas, isStatement)
implicitPragmas(c, sym, n, validPragmas)

View File

@@ -14,8 +14,8 @@ import
ast, astalgo, msgs, semdata, types, trees, strutils
proc equalGenericParams(procA, procB: PNode): bool =
if sonsLen(procA) != sonsLen(procB): return false
for i in 0 ..< sonsLen(procA):
if len(procA) != len(procB): return false
for i in 0 ..< len(procA):
if procA.sons[i].kind != nkSym:
return false
if procB.sons[i].kind != nkSym:
@@ -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
@@ -72,8 +72,8 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
of paramsEqual:
if (sfExported notin result.flags) and (sfExported in fn.flags):
let message = ("public implementation '$1' has non-public " &
"forward declaration in $2") %
[getProcHeader(c.config, result), c.config$result.info]
"forward declaration at $2") %
[getProcHeader(c.config, result, getDeclarationPath = false), c.config$result.info]
localError(c.config, fn.info, message)
return
of paramsIncompatible:
@@ -95,9 +95,9 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
when false:
proc paramsFitBorrow(child, parent: PNode): bool =
var length = sonsLen(child)
var length = len(child)
result = false
if length == sonsLen(parent):
if length == len(parent):
for i in 1 ..< length:
var m = child.sons[i].sym
var n = parent.sons[i].sym
@@ -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

@@ -9,6 +9,11 @@
# This module implements the renderer of the standard Nim representation.
when defined(nimHasUsed):
# 'import renderer' is so useful for debugging
# that Nim shouldn't produce a warning for that:
{.used.}
import
lexer, options, idents, strutils, ast, msgs, lineinfos
@@ -330,8 +335,7 @@ proc ulitAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
else: result = $x
# XXX proper unsigned output!
else: result = $cast[BiggestUInt](x)
proc atom(g: TSrcGen; n: PNode): string =
when defined(nimpretty):
@@ -391,7 +395,7 @@ proc atom(g: TSrcGen; n: PNode): string =
proc lcomma(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
assert(theEnd < 0)
result = 0
for i in start .. sonsLen(n) + theEnd:
for i in start .. len(n) + theEnd:
let param = n.sons[i]
if nfDefaultParam notin param.flags:
inc(result, lsub(g, param))
@@ -402,7 +406,7 @@ proc lcomma(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
proc lsons(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
assert(theEnd < 0)
result = 0
for i in start .. sonsLen(n) + theEnd: inc(result, lsub(g, n.sons[i]))
for i in start .. len(n) + theEnd: inc(result, lsub(g, n.sons[i]))
proc lsub(g: TSrcGen; n: PNode): int =
# computes the length of a tree
@@ -432,7 +436,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkTableConstr:
result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}")
of nkClosedSymChoice, nkOpenSymChoice:
result = lsons(g, n) + len("()") + sonsLen(n) - 1
result = lsons(g, n) + len("()") + len(n) - 1
of nkTupleTy: result = lcomma(g, n) + len("tuple[]")
of nkTupleClassTy: result = len("tuple")
of nkDotExpr: result = lsons(g, n) + 1
@@ -444,7 +448,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkDo: result = lsons(g, n) + len("do__:_")
of nkConstDef, nkIdentDefs:
result = lcomma(g, n, 0, - 3)
var L = sonsLen(n)
var L = len(n)
if n.sons[L - 2].kind != nkEmpty: result = result + lsub(g, n.sons[L - 2]) + 2
if n.sons[L - 1].kind != nkEmpty: result = result + lsub(g, n.sons[L - 1]) + 3
of nkVarTuple: result = lcomma(g, n, 0, - 3) + len("() = ") + lsub(g, lastSon(n))
@@ -453,7 +457,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkChckRange: result = len("chckRange") + 2 + lcomma(g, n)
of nkObjDownConv, nkObjUpConv:
result = 2
if sonsLen(n) >= 1: result = result + lsub(g, n.sons[0])
if len(n) >= 1: result = result + lsub(g, n.sons[0])
result = result + lcomma(g, n, 1)
of nkExprColonExpr: result = lsons(g, n) + 2
of nkInfix: result = lsons(g, n) + 2
@@ -487,16 +491,16 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkIteratorTy: result = lsons(g, n) + len("iterator_")
of nkSharedTy: result = lsons(g, n) + len("shared_")
of nkEnumTy:
if sonsLen(n) > 0:
if len(n) > 0:
result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + len("enum_")
else:
result = len("enum")
of nkEnumFieldDef: result = lsons(g, n) + 3
of nkVarSection, nkLetSection:
if sonsLen(n) > 1: result = MaxLineLen + 1
if len(n) > 1: result = MaxLineLen + 1
else: result = lsons(g, n) + len("var_")
of nkUsingStmt:
if sonsLen(n) > 1: result = MaxLineLen + 1
if len(n) > 1: result = MaxLineLen + 1
else: result = lsons(g, n) + len("using_")
of nkReturnStmt:
if n.len > 0 and n[0].kind == nkAsgn:
@@ -552,7 +556,7 @@ proc hasCom(n: PNode): bool =
case n.kind
of nkEmpty..nkNilLit: discard
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if hasCom(n.sons[i]): return true
proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
@@ -561,8 +565,8 @@ proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
theEnd: int = - 1, separator = tkComma) =
for i in start .. sonsLen(n) + theEnd:
var c = i < sonsLen(n) + theEnd
for i in start .. len(n) + theEnd:
var c = i < len(n) + theEnd
var sublen = lsub(g, n.sons[i]) + ord(c)
if not fits(g, sublen) and (ind + sublen < MaxLineLen): optNL(g, ind)
let oldLen = g.tokens.len
@@ -596,15 +600,15 @@ proc gsemicolon(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) =
proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
theEnd: int = - 1) =
for i in start .. sonsLen(n) + theEnd: gsub(g, n.sons[i], c)
for i in start .. len(n) + theEnd: gsub(g, n.sons[i], c)
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType,
k: string) =
if sonsLen(n) == 0: return # empty var sections are possible
if len(n) == 0: return # empty var sections are possible
putWithSpace(g, kind, k)
gcoms(g)
indentNL(g)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
optNL(g)
gsub(g, n.sons[i], c)
gcoms(g)
@@ -614,7 +618,7 @@ proc longMode(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): bool =
result = n.comment.len > 0
if not result:
# check further
for i in start .. sonsLen(n) + theEnd:
for i in start .. len(n) + theEnd:
if (lsub(g, n.sons[i]) > MaxLineLen):
result = true
break
@@ -659,7 +663,7 @@ proc gif(g: var TSrcGen, n: PNode) =
incl(c.flags, rfLongMode)
gcoms(g) # a good place for comments
gstmts(g, n.sons[0].sons[1], c)
var length = sonsLen(n)
var length = len(n)
for i in 1 ..< length:
optNL(g)
gsub(g, n.sons[i], c)
@@ -708,7 +712,7 @@ proc gtry(g: var TSrcGen, n: PNode) =
proc gfor(g: var TSrcGen, n: PNode) =
var c: TContext
var length = sonsLen(n)
var length = len(n)
putWithSpace(g, tkFor, "for")
initContext(c)
if longMode(g, n) or
@@ -726,7 +730,7 @@ proc gfor(g: var TSrcGen, n: PNode) =
proc gcase(g: var TSrcGen, n: PNode) =
var c: TContext
initContext(c)
var length = sonsLen(n)
var length = len(n)
if length == 0: return
var last = if n.sons[length-1].kind == nkElse: -2 else: -1
if longMode(g, n, 0, last): incl(c.flags, rfLongMode)
@@ -740,13 +744,18 @@ proc gcase(g: var TSrcGen, n: PNode) =
if longMode(g, n.sons[length - 1]): incl(c.flags, rfLongMode)
gsub(g, n.sons[length - 1], c)
proc genSymSuffix(result: var string, s: PSym) {.inline.} =
if sfGenSym in s.flags:
result.add '_'
result.addInt s.id
proc gproc(g: var TSrcGen, n: PNode) =
var c: TContext
if n.sons[namePos].kind == nkSym:
let s = n.sons[namePos].sym
put(g, tkSymbol, renderDefinitionName(s))
if sfGenSym in s.flags:
put(g, tkIntLit, $s.id)
var ret = renderDefinitionName(s)
ret.genSymSuffix(s)
put(g, tkSymbol, ret)
else:
gsub(g, n.sons[namePos])
@@ -840,12 +849,12 @@ proc gident(g: var TSrcGen, n: PNode) =
t = tkSymbol
else:
t = tkOpr
put(g, t, s, if n.kind == nkSym and renderSyms in g.flags: n.sym else: nil)
if n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags or n.sym.kind == skTemp):
s.genSymSuffix(n.sym)
when defined(debugMagics):
put(g, tkIntLit, $n.sym.id & $n.sym.magic)
else:
put(g, tkIntLit, $n.sym.id)
s.add '_'
s.add $n.sym.magic
put(g, t, s, if n.kind == nkSym and renderSyms in g.flags: n.sym else: nil)
proc doParamsAux(g: var TSrcGen, params: PNode) =
if params.len > 1:
@@ -957,7 +966,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkColon, ":")
gsub(g, n, n.len-1)
else:
if sonsLen(n) >= 1: accentedName(g, n[0])
if len(n) >= 1: accentedName(g, n[0])
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
@@ -1037,14 +1046,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gcomma(g, n)
put(g, tkParRi, ")")
of nkObjDownConv, nkObjUpConv:
if sonsLen(n) >= 1: gsub(g, n.sons[0])
if len(n) >= 1: gsub(g, n.sons[0])
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
of nkClosedSymChoice, nkOpenSymChoice:
if renderIds in g.flags:
put(g, tkParLe, "(")
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if i > 0: put(g, tkOpr, "|")
if n.sons[i].kind == nkSym:
let s = n[i].sym
@@ -1106,7 +1115,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n, bodyPos)
of nkConstDef, nkIdentDefs:
gcomma(g, n, 0, -3)
var L = sonsLen(n)
var L = len(n)
if L >= 2 and n.sons[L - 2].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
gsub(g, n, L - 2)
@@ -1191,19 +1200,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
if n.len > 0: gsub(g, n.sons[0])
put(g, tkParRi, ")")
of nkRefTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkRef, "ref")
gsub(g, n.sons[0])
else:
put(g, tkRef, "ref")
of nkPtrTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkPtr, "ptr")
gsub(g, n.sons[0])
else:
put(g, tkPtr, "ptr")
of nkVarTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkVar, "var")
gsub(g, n.sons[0])
else:
@@ -1234,7 +1243,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkEquals, "=")
gsub(g, n.sons[2])
of nkObjectTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkObject, "object")
gsub(g, n.sons[0])
gsub(g, n.sons[1])
@@ -1244,7 +1253,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkObject, "object")
of nkRecList:
indentNL(g)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
optNL(g)
gsub(g, n.sons[i], c)
gcoms(g)
@@ -1254,14 +1263,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkOf, "of")
gsub(g, n, 0)
of nkProcTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkProc, "proc")
gsub(g, n, 0)
gsub(g, n, 1)
else:
put(g, tkProc, "proc")
of nkIteratorTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkIterator, "iterator")
gsub(g, n, 0)
gsub(g, n, 1)
@@ -1274,7 +1283,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n.sons[0])
put(g, tkBracketRi, "]")
of nkEnumTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkEnum, "enum")
gsub(g, n.sons[0])
gcoms(g)
@@ -1332,7 +1341,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
incl(a.flags, rfInConstExpr)
gsection(g, n, a, tkConst, "const")
of nkVarSection, nkLetSection, nkUsingStmt:
var L = sonsLen(n)
var L = len(n)
if L == 0: return
if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
@@ -1543,7 +1552,7 @@ proc renderModule*(n: PNode, infile, outfile: string,
g: TSrcGen
initSrcGen(g, renderFlags, conf)
g.fid = fid
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
gsub(g, n.sons[i])
optNL(g)
case n.sons[i].kind
@@ -1576,3 +1585,15 @@ proc getTokSym*(r: TSrcGen): PSym =
result = r.tokens[r.idx-1].sym
else:
result = nil
proc quoteExpr*(a: string): string {.inline.} =
## can be used for quoting expressions in error msgs.
"'" & a & "'"
proc genFieldError*(field: PSym, disc: PSym): string =
## this needs to be in a module accessible by jsgen, ccgexprs, and vm to
## provide this error msg FieldError; msgs would be better but it does not
## import ast
result = field.name.s.quoteExpr & " is not accessible using discriminant " &
disc.name.s.quoteExpr & " of type " &
disc.owner.name.s.quoteExpr

View File

@@ -156,7 +156,7 @@ proc encodeNode(g: ModuleGraph; fInfo: TLineInfo, n: PNode,
encodeVInt(n.sym.id, result)
pushSym(w, n.sym)
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
encodeNode(g, n.info, n.sons[i], result)
add(result, ')')
@@ -223,6 +223,9 @@ proc encodeType(g: ModuleGraph, t: PType, result: var string) =
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
add(result, '\14')
encodeVInt(t.lockLevel.int16, result)
if t.paddingAtEnd != 0:
add(result, '\15')
encodeVInt(t.paddingAtEnd, result)
for a in t.attachedOps:
add(result, '\16')
if a == nil:
@@ -241,7 +244,7 @@ proc encodeType(g: ModuleGraph, t: PType, result: var string) =
add(result, '\21')
encodeVInt(t.typeInst.uniqueId, result)
pushType(w, t.typeInst)
for i in 0 ..< sonsLen(t):
for i in 0 ..< len(t):
if t.sons[i] == nil:
add(result, "^()")
else:
@@ -422,9 +425,7 @@ proc storeRemaining*(g: ModuleGraph; module: PSym) =
transitiveClosure(g)
var nimid = 0
for x in items(g.config.m.fileInfos):
# don't store the "command line" entry:
if nimid != 0:
storeFilename(g, x.fullPath, FileIndex(nimid))
storeFilename(g, x.fullPath, FileIndex(nimid))
inc nimid
# ---------------- decoder -----------------------------------
@@ -633,6 +634,10 @@ proc loadType(g; id: int; info: TLineInfo): PType =
else:
result.lockLevel = UnspecifiedLockLevel
if b.s[b.pos] == '\15':
inc(b.pos)
result.paddingAtEnd = decodeVInt(b.s, b.pos).int16
for a in low(result.attachedOps)..high(result.attachedOps):
if b.s[b.pos] == '\16':
inc(b.pos)

View File

@@ -62,9 +62,15 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
cbos listDirs:
listDirs(a, {pcDir})
cbos removeDir:
os.removeDir getString(a, 0)
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
os.removeDir getString(a, 0)
cbos removeFile:
os.removeFile getString(a, 0)
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
os.removeFile getString(a, 0)
cbos createDir:
os.createDir getString(a, 0)
@@ -76,20 +82,35 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
cbos getCurrentDir:
setResult(a, os.getCurrentDir())
cbos moveFile:
os.moveFile(getString(a, 0), getString(a, 1))
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
os.moveFile(getString(a, 0), getString(a, 1))
cbos moveDir:
os.moveDir(getString(a, 0), getString(a, 1))
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
os.moveDir(getString(a, 0), getString(a, 1))
cbos copyFile:
os.copyFile(getString(a, 0), getString(a, 1))
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
os.copyFile(getString(a, 0), getString(a, 1))
cbos copyDir:
os.copyDir(getString(a, 0), getString(a, 1))
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
os.copyDir(getString(a, 0), getString(a, 1))
cbos getLastModificationTime:
setResult(a, getLastModificationTime(getString(a, 0)).toUnix)
cbos findExe:
setResult(a, os.findExe(getString(a, 0)))
cbos rawExec:
setResult(a, osproc.execCmd getString(a, 0))
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
setResult(a, osproc.execCmd getString(a, 0))
cbconf getEnv:
setResult(a, os.getEnv(a.getString 0, a.getString 1))
@@ -97,6 +118,8 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
setResult(a, os.existsEnv(a.getString 0))
cbconf putEnv:
os.putEnv(a.getString 0, a.getString 1)
cbconf delEnv:
os.delEnv(a.getString 0)
cbconf dirExists:
setResult(a, os.dirExists(a.getString 0))
cbconf fileExists:
@@ -162,11 +185,17 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
cbconf cppDefine:
options.cppDefine(conf, a.getString(0))
cbexc stdinReadLine, EOFError:
setResult(a, "")
setResult(a, stdin.readLine())
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
setResult(a, "")
setResult(a, stdin.readLine())
cbexc stdinReadAll, EOFError:
setResult(a, "")
setResult(a, stdin.readAll())
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
discard
else:
setResult(a, "")
setResult(a, stdin.readAll())
proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
freshDefines=true; conf: ConfigRef) =
@@ -185,6 +214,12 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
conf.searchPaths.add(conf.libpath)
let oldGlobalOptions = conf.globalOptions
let oldSelectedGC = conf.selectedGC
undefSymbol(conf.symbols, "nimv2")
conf.globalOptions.excl {optTinyRtti, optOwnedRefs, optSeqDestructors}
conf.selectedGC = gcUnselected
var m = graph.makeModule(scriptName)
incl(m.flags, sfMainModule)
graph.vm = setupVM(m, cache, scriptName.string, graph)
@@ -192,6 +227,14 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
graph.compileSystemModule() # TODO: see why this unsets hintConf in conf.notes
discard graph.processModule(m, llStreamOpen(scriptName, fmRead))
# watch out, "newruntime" can be set within NimScript itself and then we need
# to remember this:
if optOwnedRefs in oldGlobalOptions:
conf.globalOptions.incl {optTinyRtti, optOwnedRefs, optSeqDestructors}
defineSymbol(conf.symbols, "nimv2")
if conf.selectedGC == gcUnselected:
conf.selectedGC = oldSelectedGC
# ensure we load 'system.nim' again for the real non-config stuff!
resetSystemArtifacts(graph)
# do not remove the defined symbols

View File

@@ -77,14 +77,12 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
discard safeSemExpr(c, n)
proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
result = arg
let x = result.skipConv
let x = arg.skipConv
if x.kind in {nkPar, nkTupleConstr, nkCurly} and formal.kind != tyUntyped:
changeType(c, x, formal, check=true)
else:
result = skipHiddenSubConv(result)
#result.typ = takeType(formal, arg.typ)
#echo arg.info, " picked ", result.typ.typeToString
result = arg
result = skipHiddenSubConv(result)
proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
if arg.typ.isNil:
@@ -405,7 +403,13 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
if s.typ.sons[0] == nil:
result = semStmt(c, result, flags)
else:
case s.typ.sons[0].kind
var retType = s.typ.sons[0]
if retType.kind == tyTypeDesc and tfUnresolved in retType.flags and
retType.len == 1:
# bug #11941: template fails(T: type X, v: auto): T
# does not mean we expect a tyTypeDesc.
retType = retType[0]
case retType.kind
of tyUntyped:
# Not expecting a type here allows templates like in ``tmodulealias.in``.
result = semExpr(c, result, flags)
@@ -423,7 +427,6 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
result.typ = makeTypeDesc(c, typ)
#result = symNodeFromType(c, typ, n.info)
else:
var retType = s.typ.sons[0]
if s.ast[genericParamsPos] != nil and retType.isMetaType:
# The return type may depend on the Macro arguments
# e.g. template foo(T: typedesc): seq[T]
@@ -444,13 +447,14 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
const
errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"
errFloatToString = "cannot convert '$1' to '$2'"
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode =
pushInfoContext(c.config, nOrig.info, sym.detailedInfo)
let info = getCallLineInfo(n)
markUsed(c.config, info, sym, c.graph.usageSym)
markUsed(c, info, sym)
onUse(info, sym)
if sym == c.p.owner:
globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s)
@@ -571,7 +575,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
if c.lastGenericIdx < c.generics.len:
var a = newNodeI(nkStmtList, n.info)
addCodeForGenerics(c, a)
if sonsLen(a) > 0:
if len(a) > 0:
# a generic has been added to `a`:
if result.kind != nkEmpty: addSon(a, result)
result = a
@@ -612,12 +616,18 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
#if c.config.cmd == cmdIdeTools: findSuggest(c, n)
rod.storeNode(c.graph, c.module, result)
proc reportUnusedModules(c: PContext) =
for i in 0..high(c.unusedImports):
if sfUsed notin c.unusedImports[i][0].flags:
message(c.config, c.unusedImports[i][1], warnUnusedImportX, c.unusedImports[i][0].name.s)
proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
var c = PContext(context)
if c.config.cmd == cmdIdeTools and not c.suggestionsMade:
suggestSentinel(c)
closeScope(c) # close module's scope
rawCloseScope(c) # imported symbols; don't check for unused ones!
reportUnusedModules(c)
result = newNode(nkStmtList)
if n != nil:
internalError(c.config, n.info, "n is not nil") #result := n;

View File

@@ -176,6 +176,8 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
filterOnlyFirst = true
break
var maybeWrongSpace = false
var candidates = ""
var skipped = 0
for err in errors:
@@ -196,6 +198,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
case err.firstMismatch.kind
of kUnknownNamedParam: candidates.add("\n unknown named parameter: " & $nArg[0])
of kAlreadyGiven: candidates.add("\n named param already provided: " & $nArg[0])
of kPositionalAlreadyGiven: candidates.add("\n positional param was already given as named param")
of kExtraArg: candidates.add("\n extra argument given")
of kMissingParam: candidates.add("\n missing parameter: " & nameParam)
of kTypeMismatch, kVarNeeded:
@@ -215,13 +218,19 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
candidates.add typeToString(got)
doAssert wanted != nil
if got != nil: effectProblem(wanted, got, candidates)
of kUnknown: internalAssert(c.config, false)
of kUnknown: discard "do not break 'nim check'"
candidates.add "\n"
if err.firstMismatch.arg == 1 and nArg.kind == nkTupleConstr and
n.kind == nkCommand:
maybeWrongSpace = true
for diag in err.diagnostics:
candidates.add(diag & "\n")
if skipped > 0:
candidates.add($skipped & " other mismatching symbols have been " &
"suppressed; compile with --showAllMismatches:on to see them\n")
if maybeWrongSpace:
candidates.add("maybe misplaced space between " & renderTree(n[0]) & " and '(' \n")
result = (prefer, candidates)
const
@@ -284,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:
@@ -295,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)
@@ -396,7 +405,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
elif c.config.errorCounter == 0:
# don't cascade errors
var args = "("
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if i > 1: add(args, ", ")
add(args, typeToString(n.sons[i].typ))
add(args, ")")
@@ -474,7 +483,7 @@ proc semResolvedCall(c: PContext, x: TCandidate,
assert x.state == csMatch
var finalCallee = x.calleeSym
let info = getCallLineInfo(n)
markUsed(c.config, info, finalCallee, c.graph.usageSym)
markUsed(c, info, finalCallee)
onUse(info, finalCallee)
assert finalCallee.ast != nil
if x.hasFauxMatch:
@@ -568,7 +577,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
# binding has to stay 'nil' for this to work!
initCandidate(c, m, s, nil)
for i in 1..sonsLen(n)-1:
for i in 1..len(n)-1:
let formal = s.ast.sons[genericParamsPos].sons[i-1].typ
var arg = n[i].typ
# try transforming the argument into a static one before feeding it into
@@ -584,16 +593,16 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
var newInst = generateInstance(c, s, m.bindings, n.info)
newInst.typ.flags.excl tfUnresolved
let info = getCallLineInfo(n)
markUsed(c.config, info, s, c.graph.usageSym)
markUsed(c, info, s)
onUse(info, s)
result = newSymNode(newInst, info)
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
for i in 1..sonsLen(n)-1:
for i in 1..len(n)-1:
let e = semExpr(c, n.sons[i])
if e.typ == nil:
localError(c.config, e.info, "expression has no type")
n.sons[i].typ = errorType(c)
else:
n.sons[i].typ = e.typ.skipTypes({tyTypeDesc})
var s = s
@@ -631,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

@@ -11,7 +11,7 @@
import
intsets, options, ast, astalgo, msgs, idents, renderer,
magicsys, vmdef, modulegraphs, lineinfos
magicsys, vmdef, modulegraphs, lineinfos, sets
type
TOptionEntry* = object # entries to put on a stack for pragma parsing
@@ -71,7 +71,8 @@ type
TExprFlags* = set[TExprFlag]
PContext* = ref TContext
TContext* = object of TPassContext # a context represents a module
TContext* = object of TPassContext # a context represents the module
# that is currently being compiled
enforceVoidContext*: PType
module*: PSym # the module sym belonging to the context
currentScope*: PScope # current scope
@@ -136,6 +137,8 @@ type
# the generic type has been constructed completely. See
# tests/destructor/topttree.nim for an example that
# would otherwise fail.
unusedImports*: seq[(PSym, TLineInfo)]
exportIndirections*: HashSet[(int, int)]
template config*(c: PContext): ConfigRef = c.graph.config
@@ -209,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 = @[]
@@ -365,7 +383,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
if n.typ != nil and n.typ.n == nil:
result.flags.incl tfUnresolved
result.n = newNode(nkRange, n.info, @[
newIntTypeNode(nkIntLit, 0, intType),
newIntTypeNode(0, intType),
makeStaticExpr(c, nMinusOne(c, n))])
template rangeHasUnresolvedStatic*(t: PType): bool =
@@ -389,8 +407,8 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
info: TLineInfo; intType: PType = nil): PType =
let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt)
var n = newNodeI(nkRange, info)
addSon(n, newIntTypeNode(nkIntLit, first, intType))
addSon(n, newIntTypeNode(nkIntLit, last, intType))
addSon(n, newIntTypeNode(first, intType))
addSon(n, newIntTypeNode(last, intType))
result = newTypeS(tyRange, c)
result.n = n
addSonSkipIntLit(result, intType) # basetype of range
@@ -407,10 +425,10 @@ proc illFormedAstLocal*(n: PNode; conf: ConfigRef) =
localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) =
if sonsLen(n) != length: illFormedAst(n, conf)
if len(n) != length: illFormedAst(n, conf)
proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) =
if sonsLen(n) < length: illFormedAst(n, conf)
if len(n) < length: illFormedAst(n, conf)
proc isTopLevel*(c: PContext): bool {.inline.} =
result = c.currentScope.depthLevel <= 2

View File

@@ -25,12 +25,12 @@ const
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode =
let info = getCallLineInfo(n)
markUsed(c.config, info, s, c.graph.usageSym)
markUsed(c, info, s)
onUse(info, s)
# Note: This is n.info on purpose. It prevents template from creating an info
# context when called from an another template
pushInfoContext(c.config, n.info, s.detailedInfo)
result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in flags)
result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, efFromHlo in flags)
if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
popInfoContext(c.config)
@@ -149,7 +149,7 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
(srcBaseTyp.kind in IntegralTypes):
if targetTyp.isOrdinalType:
if src.kind in nkCharLit..nkUInt64Lit and
src.intVal notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp):
src.getInt notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp):
result = convNotInRange
elif src.kind in nkFloatLit..nkFloat64Lit and
(classify(src.floatVal) in {fcNan, fcNegInf, fcInf} or
@@ -225,7 +225,7 @@ proc isOwnedSym(c: PContext; n: PNode): bool =
result = s != nil and sfSystemModule in s.owner.flags and s.name.s == "owned"
proc semConv(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2:
if len(n) != 2:
localError(c.config, n.info, "a type conversion takes exactly one argument")
return n
@@ -301,11 +301,11 @@ proc semConv(c: PContext, n: PNode): PNode =
localError(c.config, n.info, errGenerated, value & " can't be converted to " &
result.typ.typeToString)
else:
for i in 0 ..< sonsLen(op):
for i in 0 ..< len(op):
let it = op.sons[i]
let status = checkConvertible(c, result.typ, it)
if status in {convOK, convNotNeedeed}:
markUsed(c.config, n.info, it.sym, c.graph.usageSym)
markUsed(c, n.info, it.sym)
onUse(n.info, it.sym)
markIndirect(c, it.sym)
return it
@@ -331,7 +331,7 @@ proc semCast(c: PContext, n: PNode): PNode =
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
const
opToStr: array[mLow..mHigh, string] = ["low", "high"]
if sonsLen(n) != 2:
if len(n) != 2:
localError(c.config, n.info, errXExpectsTypeOrValue % opToStr[m])
else:
n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
@@ -341,7 +341,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
n.typ = getSysType(c.graph, n.info, tyInt)
of tyArray:
n.typ = typ.sons[0] # indextype
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32, tyFloat..tyFloat64:
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt..tyUInt64, tyFloat..tyFloat64:
n.typ = n.sons[1].typ.skipTypes({tyTypeDesc})
of tyGenericParam:
# prepare this for resolving in semtypinst:
@@ -369,7 +369,7 @@ proc fixupStaticType(c: PContext, n: PNode) =
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
internalAssert c.config,
n.sonsLen == 3 and
n.len == 3 and
n[1].typ != nil and
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
@@ -408,7 +408,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
result.typ = n.typ
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
if sonsLen(n) != 3:
if len(n) != 3:
localError(c.config, n.info, "'is' operator takes 2 arguments")
let boolType = getSysType(c.graph, n.info, tyBool)
@@ -452,9 +452,9 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
proc semOpAux(c: PContext, n: PNode) =
const flags = {efDetermineType}
for i in 1 ..< n.sonsLen:
for i in 1 ..< n.len:
var a = n.sons[i]
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
if a.kind == nkExprEqExpr and len(a) == 2:
let info = a.sons[0].info
a.sons[0] = newIdentNode(considerQuotedIdent(c, a.sons[0], a), info)
a.sons[1] = semExprWithType(c, a.sons[1], flags)
@@ -470,22 +470,22 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
else:
result = newNodeI(nkCall, n.info)
addSon(result, newIdentNode(par, n.info))
for i in 0 ..< sonsLen(n): addSon(result, n.sons[i])
for i in 0 ..< len(n): addSon(result, n.sons[i])
result = semExpr(c, result)
proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
case n.kind
of nkCurly, nkBracket:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
changeType(c, n.sons[i], elemType(newType), check)
of nkPar, nkTupleConstr:
let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
if tup.kind != tyTuple:
if tup.kind == tyObject: return
globalError(c.config, n.info, "no tuple type for constructor")
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
elif len(n) > 0 and n.sons[0].kind == nkExprColonExpr:
# named tuple?
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var m = n.sons[i].sons[0]
if m.kind != nkSym:
globalError(c.config, m.info, "invalid tuple constructor")
@@ -499,7 +499,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
else:
changeType(c, n.sons[i].sons[1], tup.sons[i], check)
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
changeType(c, n.sons[i], tup.sons[i], check)
when false:
var m = n.sons[i]
@@ -513,43 +513,61 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
localError(c.config, n.info, "cannot convert " & $value &
" to " & typeToString(newType))
of nkFloatLit..nkFloat64Lit:
if check and not floatRangeCheck(n.floatVal, newType):
localError(c.config, n.info, errFloatToString % [$n.floatVal, typeToString(newType)])
else: discard
n.typ = newType
proc arrayConstrType(c: PContext, n: PNode): PType =
var typ = newTypeS(tyArray, c)
rawAddSon(typ, nil) # index type
if sonsLen(n) == 0:
if len(n) == 0:
rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
else:
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
addSonSkipIntLit(typ, t)
typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
typ.sons[0] = makeRangeType(c, 0, len(n) - 1, n.info)
result = typ
proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newNodeI(nkBracket, n.info)
result.typ = newTypeS(tyArray, c)
rawAddSon(result.typ, nil) # index type
if sonsLen(n) == 0:
var
firstIndex, lastIndex: Int128
indexType = getSysType(c.graph, n.info, tyInt)
lastValidIndex = lastOrd(c.config, indexType)
if len(n) == 0:
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
lastIndex = toInt128(-1)
else:
var x = n.sons[0]
var lastIndex: BiggestInt = 0
var indexType = getSysType(c.graph, n.info, tyInt)
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
if x.kind == nkExprColonExpr and len(x) == 2:
var idx = semConstExpr(c, x.sons[0])
lastIndex = getOrdValue(idx)
indexType = idx.typ
x = x.sons[1]
if not isOrdinalType(idx.typ):
localError(c.config, idx.info, "expected ordinal value for array " &
"index, got '$1'" % renderTree(idx))
else:
firstIndex = getOrdValue(idx)
lastIndex = firstIndex
indexType = idx.typ
lastValidIndex = lastOrd(c.config, indexType)
x = x.sons[1]
let yy = semExprWithType(c, x)
var typ = yy.typ
addSon(result, yy)
#var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal})
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if lastIndex == lastValidIndex:
let validIndex = makeRangeType(c, toInt64(firstIndex), toInt64(lastValidIndex), n.info,
indexType)
localError(c.config, n.info, "size of array exceeds range of index " &
"type '$1' by $2 elements" % [typeToString(validIndex), $(n.len-i)])
x = n.sons[i]
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
if x.kind == nkExprColonExpr and len(x) == 2:
var idx = semConstExpr(c, x.sons[0])
idx = fitNode(c, indexType, idx, x.info)
if lastIndex+1 != getOrdValue(idx):
@@ -565,7 +583,8 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
addSonSkipIntLit(result.typ, typ)
for i in 0 ..< result.len:
result.sons[i] = fitNode(c, typ, result.sons[i], result.sons[i].info)
result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
result.typ.sons[0] = makeRangeType(c, toInt64(firstIndex), toInt64(lastIndex), n.info,
indexType)
proc fixAbstractType(c: PContext, n: PNode) =
for i in 1 ..< n.len:
@@ -664,8 +683,8 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
# BUGFIX: check for L-Value still needs to be done for the arguments!
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
for i in 1 ..< sonsLen(n):
if i < sonsLen(t) and t.sons[i] != nil and
for i in 1 ..< len(n):
if i < len(t) and t.sons[i] != nil and
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
let it = n[i]
if isAssignable(c, it) notin {arLValue, arLocalLValue}:
@@ -680,13 +699,13 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
localError(c.config, n.info, errXStackEscape % renderTree(n[1], {renderNoComments}))
return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
let n = if n.kind == nkHiddenDeref: n[0] else: n
if n.sons[i].kind == nkHiddenCallConv:
# we need to recurse explicitly here as converters can create nested
# calls and then they wouldn't be analysed otherwise
analyseIfAddressTakenInCall(c, n.sons[i])
if i < sonsLen(t) and
if i < len(t) and
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
if n.sons[i].kind != nkHiddenAddr:
n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
@@ -868,7 +887,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = n0
result.kind = nkCall
result.flags.incl nfExplicitCall
for i in 1 ..< sonsLen(n): addSon(result, n.sons[i])
for i in 1 ..< len(n): addSon(result, n.sons[i])
return semExpr(c, result, flags)
else:
n.sons[0] = n0
@@ -899,7 +918,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
else:
var hasErrorType = false
var msg = "type mismatch: got <"
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if i > 1: add(msg, ", ")
let nt = n.sons[i].typ
add(msg, typeToString(nt))
@@ -987,7 +1006,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
result = nil
case r.kind
of nkRecList:
for i in 0 ..< sonsLen(r):
for i in 0 ..< len(r):
result = lookupInRecordAndBuildCheck(c, n, r.sons[i], field, check)
if result != nil: return
of nkRecCase:
@@ -997,19 +1016,19 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
if result != nil: return
let setType = createSetType(c, r.sons[0].typ)
var s = newNodeIT(nkCurly, r.info, setType)
for i in 1 ..< sonsLen(r):
for i in 1 ..< len(r):
var it = r.sons[i]
case it.kind
of nkOfBranch:
result = lookupInRecordAndBuildCheck(c, n, lastSon(it), field, check)
if result == nil:
for j in 0..sonsLen(it)-2: addSon(s, copyTree(it.sons[j]))
for j in 0..len(it)-2: addSon(s, copyTree(it.sons[j]))
else:
if check == nil:
check = newNodeI(nkCheckedFieldExpr, n.info)
addSon(check, c.graph.emptyNode) # make space for access node
s = newNodeIT(nkCurly, n.info, setType)
for j in 0 .. sonsLen(it) - 2: addSon(s, copyTree(it.sons[j]))
for j in 0 .. len(it) - 2: addSon(s, copyTree(it.sons[j]))
var inExpr = newNodeIT(nkCall, n.info, getSysType(c.graph, n.info, tyBool))
addSon(inExpr, newSymNode(c.graph.opContains, n.info))
addSon(inExpr, s)
@@ -1090,7 +1109,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
let s = getGenSym(c, sym)
case s.kind
of skConst:
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
onUse(n.info, s)
let typ = skipTypes(s.typ, abstractInst-{tyTypeDesc})
case typ.kind
@@ -1122,7 +1141,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
of skMacro:
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
(n.kind notin nkCallKinds and s.requiredParams > 0):
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
onUse(n.info, s)
result = symChoice(c, n, s, scClosed)
else:
@@ -1132,13 +1151,13 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
(n.kind notin nkCallKinds and s.requiredParams > 0) or
sfCustomPragma in sym.flags:
let info = getCallLineInfo(n)
markUsed(c.config, info, s, c.graph.usageSym)
markUsed(c, info, s)
onUse(info, s)
result = symChoice(c, n, s, scClosed)
else:
result = semTemplateExpr(c, n, s, flags)
of skParam:
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
onUse(n.info, s)
if s.typ != nil and s.typ.kind == tyStatic and s.typ.n != nil:
# XXX see the hack in sigmatch.nim ...
@@ -1162,7 +1181,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
if s.magic == mNimvm:
localError(c.config, n.info, "illegal context for 'nimvm' magic")
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
onUse(n.info, s)
result = newSymNode(s, n.info)
# We cannot check for access to outer vars for example because it's still
@@ -1180,7 +1199,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
n.typ = s.typ
return n
of skType:
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
onUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
return s.typ.n
@@ -1202,7 +1221,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
if f != nil and fieldVisible(c, f):
# is the access to a public field or in the same module or in a friend?
doAssert f == s
markUsed(c.config, n.info, f, c.graph.usageSym)
markUsed(c, n.info, f)
onUse(n.info, f)
result = newNodeIT(nkDotExpr, n.info, f.typ)
result.add makeDeref(newSymNode(p.selfSym))
@@ -1215,12 +1234,13 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
if ty.sons[0] == nil: break
ty = skipTypes(ty.sons[0], skipPtrs)
# old code, not sure if it's live code:
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
onUse(n.info, s)
result = newSymNode(s, n.info)
else:
let info = getCallLineInfo(n)
markUsed(c.config, info, s, c.graph.usageSym)
#if efInCall notin flags:
markUsed(c, info, s)
onUse(info, s)
result = newSymNode(s, info)
@@ -1242,7 +1262,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = symChoice(c, n, s, scClosed)
if result.kind == nkSym: result = semSym(c, n, s, flags)
else:
markUsed(c.config, n.sons[1].info, s, c.graph.usageSym)
markUsed(c, n.sons[1].info, s)
result = semSym(c, n, s, flags)
onUse(n.sons[1].info, s)
return
@@ -1306,7 +1326,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newSymNode(f)
result.info = n.info
result.typ = ty
markUsed(c.config, n.info, f, c.graph.usageSym)
markUsed(c, n.info, f)
onUse(n.info, f)
return
of tyObject, tyTuple:
@@ -1341,7 +1361,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
else: true
if not visibilityCheckNeeded or fieldVisible(c, f):
# is the access to a public field or in the same module or in a friend?
markUsed(c.config, n.sons[1].info, f, c.graph.usageSym)
markUsed(c, n.sons[1].info, f)
onUse(n.sons[1].info, f)
n.sons[0] = makeDeref(n.sons[0])
n.sons[1] = newSymNode(f) # we now have the correct field
@@ -1355,7 +1375,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
elif ty.kind == tyTuple and ty.n != nil:
f = getSymFromList(ty.n, i)
if f != nil:
markUsed(c.config, n.sons[1].info, f, c.graph.usageSym)
markUsed(c, n.sons[1].info, f)
onUse(n.sons[1].info, f)
n.sons[0] = makeDeref(n.sons[0])
n.sons[1] = newSymNode(f)
@@ -1404,7 +1424,7 @@ proc semDeref(c: PContext, n: PNode): PNode =
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
## returns nil if not a built-in subscript operator; also called for the
## checking of assignments
if sonsLen(n) == 1:
if len(n) == 1:
let x = semDeref(c, n)
if x == nil: return nil
result = newNodeIT(nkDerefExpr, x.info, x.typ)
@@ -1431,7 +1451,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
tyUncheckedArray:
if n.len != 2: return nil
n.sons[0] = makeDeref(n.sons[0])
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
n.sons[i] = semExprWithType(c, n.sons[i],
flags*{efInTypeof, efDetermineType})
# Arrays index type is dictated by the range's type
@@ -1462,7 +1482,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias, tySink}).kind in
{tyInt..tyInt64}:
let idx = getOrdValue(n.sons[1])
if idx >= 0 and idx < len(arr): n.typ = arr.sons[int(idx)]
if idx >= 0 and idx < len(arr): n.typ = arr.sons[toInt(idx)]
else: localError(c.config, n.info, "invalid index value for tuple subscript")
result = n
else:
@@ -1541,11 +1561,11 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
of nkBracketExpr:
if len(n) == 1: return n.sons[0]
else: discard
let valid = isAssignable(c, n)
let valid = isAssignable(c, n, isLent)
if valid != arLValue:
if valid == arLocalLValue:
localError(c.config, n.info, errXStackEscape % renderTree(n, {renderNoComments}))
elif not isLent:
else:
localError(c.config, n.info, errExprHasNoAddress)
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
result.add(n)
@@ -1761,21 +1781,21 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
var t = skipTypes(restype, {tyGenericInst, tyAlias, tySink})
case t.kind
of tyVar, tyLent:
if t.kind == tyVar: t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
if n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
n.sons[0] = n.sons[0].sons[1]
n.sons[0] = takeImplicitAddr(c, n.sons[0], t.kind == tyLent)
of tyTuple:
for i in 0..<t.sonsLen:
var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
for i in 0..<t.len:
let e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
if e.kind in {tyVar, tyLent}:
if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
if n.sons[0].kind in {nkPar, nkTupleConstr}:
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i], e.kind == tyLent)
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
n.sons[0].sons[1].kind in {nkPar, nkTupleConstr}:
var a = n.sons[0].sons[1]
a.sons[i] = takeImplicitAddr(c, a.sons[i], false)
a.sons[i] = takeImplicitAddr(c, a.sons[i], e.kind == tyLent)
else:
localError(c.config, n.sons[0].info, errXExpected, "tuple constructor")
else: discard
@@ -1876,7 +1896,6 @@ proc expectString(c: PContext, n: PNode): string =
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info)
result.flags = {sfGenSym}
proc semExpandToAst(c: PContext, n: PNode): PNode =
let macroCall = n[1]
@@ -1886,7 +1905,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
if expandedSym.kind == skError: return n
macroCall.sons[0] = newSymNode(expandedSym, macroCall.info)
markUsed(c.config, n.info, expandedSym, c.graph.usageSym)
markUsed(c, n.info, expandedSym)
onUse(n.info, expandedSym)
if isCallExpr(macroCall):
@@ -1911,7 +1930,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
else:
let info = macroCall.sons[0].info
macroCall.sons[0] = newSymNode(cand, info)
markUsed(c.config, info, cand, c.graph.usageSym)
markUsed(c, info, cand)
onUse(info, cand)
# we just perform overloading resolution here:
@@ -1927,7 +1946,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
flags: TExprFlags = {}): PNode =
if sonsLen(n) == 2:
if len(n) == 2:
n.sons[0] = newSymNode(magicSym, n.info)
result = semExpandToAst(c, n)
else:
@@ -2000,7 +2019,14 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
var tmpl = semTemplateDef(c, dummyTemplate)
quotes[0] = tmpl[namePos]
# This adds a call to newIdentNode("result") as the first argument to the template call
quotes[1] = newNode(nkCall, n.info, @[newIdentNode(getIdent(c.cache, "newIdentNode"), n.info), newStrNode(nkStrLit, "result")])
let identNodeSym = getCompilerProc(c.graph, "newIdentNode")
# so that new Nim compilers can compile old macros.nim versions, we check for 'nil'
# here and provide the old fallback solution:
let identNode = if identNodeSym == nil:
newIdentNode(getIdent(c.cache, "newIdentNode"), n.info)
else:
identNodeSym.newSymNode
quotes[1] = newNode(nkCall, n.info, @[identNode, newStrNode(nkStrLit, "result")])
result = newNode(nkCall, n.info, @[
createMagic(c.graph, "getAst", mExpandToAst).newSymNode,
newNode(nkCall, n.info, quotes)])
@@ -2012,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
@@ -2057,14 +2083,14 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
# we replace this node by a 'true' or 'false' node:
if sonsLen(n) != 2: return semDirectOp(c, n, flags)
if len(n) != 2: return semDirectOp(c, n, flags)
result = newIntNode(nkIntLit, ord(tryExpr(c, n[1], flags) != nil))
result.info = n.info
result.typ = getSysType(c.graph, n.info, tyBool)
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
if sonsLen(n) == 3:
if len(n) == 3:
# XXX ugh this is really a hack: shallowCopy() can be overloaded only
# with procs that take not 2 parameters:
result = newNodeI(nkFastAsgn, n.info)
@@ -2101,7 +2127,7 @@ proc setMs(n: PNode, s: PSym): PNode =
n.sons[0].info = n.info
proc semSizeof(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2:
if len(n) != 2:
localError(c.config, n.info, errXExpectsTypeOrValue % "sizeof")
else:
n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
@@ -2114,30 +2140,42 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = n
case s.magic # magics that need special treatment
of mAddr:
markUsed(c, n.info, s)
checkSonsLen(n, 2, c.config)
result[0] = newSymNode(s, n[0].info)
result[1] = semAddrArg(c, n.sons[1], s.name.s == "unsafeAddr")
result.typ = makePtrType(c, result[1].typ)
of mTypeOf:
markUsed(c, n.info, s)
result = semTypeOf(c, n)
#of mArrGet: result = semArrGet(c, n, flags)
#of mArrPut: result = semArrPut(c, n, flags)
#of mAsgn: result = semAsgnOpr(c, n)
of mDefined: result = semDefined(c, setMs(n, s), false)
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
of mIs: result = semIs(c, setMs(n, s), flags)
#of mOf: result = semOf(c, setMs(n, s))
of mShallowCopy: result = semShallowCopy(c, n, flags)
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
of mQuoteAst: result = semQuoteAst(c, n)
of mDefined:
markUsed(c, n.info, s)
result = semDefined(c, setMs(n, s), false)
of mDefinedInScope:
markUsed(c, n.info, s)
result = semDefined(c, setMs(n, s), true)
of mCompiles:
markUsed(c, n.info, s)
result = semCompiles(c, setMs(n, s), flags)
of mIs:
markUsed(c, n.info, s)
result = semIs(c, setMs(n, s), flags)
of mShallowCopy:
markUsed(c, n.info, s)
result = semShallowCopy(c, n, flags)
of mExpandToAst:
markUsed(c, n.info, s)
result = semExpandToAst(c, n, s, flags)
of mQuoteAst:
markUsed(c, n.info, s)
result = semQuoteAst(c, n)
of mAstToStr:
markUsed(c, n.info, s)
checkSonsLen(n, 2, c.config)
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
result.typ = getSysType(c.graph, n.info, tyString)
of mParallel:
markUsed(c, n.info, s)
if parallel notin c.features:
localError(c.config, n.info, "use the {.experimental.} pragma to enable 'parallel'")
result = setMs(n, s)
@@ -2147,6 +2185,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result.sons[1] = semStmt(c, x, {})
dec c.inParallelStmt
of mSpawn:
markUsed(c, n.info, s)
when defined(leanCompiler):
localError(c.config, n.info, "compiler was built without 'spawn' support")
result = n
@@ -2164,10 +2203,12 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
else:
result.add c.graph.emptyNode
of mProcCall:
markUsed(c, n.info, s)
result = setMs(n, s)
result.sons[1] = semExpr(c, n.sons[1])
result.typ = n[1].typ
of mPlugin:
markUsed(c, n.info, s)
# semDirectOp with conditional 'afterCallActions':
let nOrig = n.copyTree
#semLazyOpAux(c, n)
@@ -2184,6 +2225,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
if callee.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
of mRunnableExamples:
markUsed(c, n.info, s)
if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList:
when false:
# some of this dead code was moved to `prepareExamples`
@@ -2200,8 +2242,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = setMs(n, s)
else:
result = c.graph.emptyNode
of mSizeOf: result =
semSizeof(c, setMs(n, s))
of mSizeOf:
markUsed(c, n.info, s)
result = semSizeof(c, setMs(n, s))
else:
result = semDirectOp(c, n, flags)
@@ -2230,7 +2273,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
whenNimvm = exprNode.sym.magic == mNimvm
if whenNimvm: n.flags.incl nfLL
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
case it.kind
of nkElifBranch, nkElifExpr:
@@ -2268,12 +2311,12 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
proc semSetConstr(c: PContext, n: PNode): PNode =
result = newNodeI(nkCurly, n.info)
result.typ = newTypeS(tySet, c)
if sonsLen(n) == 0:
if len(n) == 0:
rawAddSon(result.typ, newTypeS(tyEmpty, c))
else:
# only semantic checking for all elements, later type checking:
var typ: PType = nil
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if isRange(n.sons[i]):
checkSonsLen(n.sons[i], 3, c.config)
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
@@ -2297,7 +2340,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
elif lengthOrd(c.config, typ) > MaxSetElements:
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
addSonSkipIntLit(result.typ, typ)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var m: PNode
let info = n.sons[i].info
if isRange(n.sons[i]):
@@ -2316,7 +2359,7 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
var lastKey = 0
for i in 0..n.len-1:
var x = n.sons[i]
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
if x.kind == nkExprColonExpr and len(x) == 2:
for j in lastKey ..< i:
var pair = newNodeI(nkTupleConstr, x.info)
pair.add(n.sons[j])
@@ -2338,7 +2381,7 @@ type
paNone, paSingle, paTupleFields, paTuplePositions
proc checkPar(c: PContext; n: PNode): TParKind =
var length = sonsLen(n)
var length = len(n)
if length == 0:
result = paTuplePositions # ()
elif length == 1:
@@ -2364,12 +2407,10 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
var typ = newTypeS(tyTuple, c)
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
var ids = initIntSet()
for i in 0 ..< sonsLen(n):
if n[i].kind != nkExprColonExpr or n[i][0].kind notin {nkSym, nkIdent}:
for i in 0 ..< len(n):
if n[i].kind != nkExprColonExpr:
illFormedAst(n.sons[i], c.config)
var id: PIdent
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
else: id = n.sons[i].sons[0].sym.name
let id = considerQuotedIdent(c, n[i][0])
if containsOrIncl(ids, id.id):
localError(c.config, n.sons[i].info, errFieldInitTwice % id.s)
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
@@ -2392,7 +2433,7 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = n # we don't modify n, but compute the type:
result.kind = nkTupleConstr
var typ = newTypeS(tyTuple, c) # leave typ.n nil!
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor})
addSonSkipIntLit(typ, n.sons[i].typ)
result.typ = typ
@@ -2434,11 +2475,11 @@ proc semExportExcept(c: PContext, n: PNode): PNode =
var s = initTabIter(i, exported.tab)
while s != nil:
if s.kind in ExportableSymKinds+{skModule} and
s.name.id notin exceptSet:
s.name.id notin exceptSet and sfError notin s.flags:
strTableAdd(c.module.tab, s)
result.add newSymNode(s, n.info)
s = nextIter(i, exported.tab)
markUsed(c.config, n.info, exported, c.graph.usageSym)
markUsed(c, n.info, exported)
proc semExport(c: PContext, n: PNode): PNode =
result = newNodeI(nkExportStmt, n.info)
@@ -2458,14 +2499,16 @@ proc semExport(c: PContext, n: PNode): PNode =
strTableAdd(c.module.tab, it)
result.add newSymNode(it, a.info)
it = nextIter(ti, s.tab)
markUsed(c, n.info, s)
else:
while s != nil:
if s.kind == skEnumField:
localError(c.config, a.info, errGenerated, "cannot export: " & renderTree(a) &
"; enum field cannot be exported individually")
if s.kind in ExportableSymKinds+{skModule}:
if s.kind in ExportableSymKinds+{skModule} and sfError notin s.flags:
result.add(newSymNode(s, a.info))
strTableAdd(c.module.tab, s)
markUsed(c, n.info, s)
s = nextOverloadIter(o, c, a)
proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
@@ -2520,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)
@@ -2712,7 +2755,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkUsingStmt: result = semUsing(c, n)
of nkAsmStmt: result = semAsm(c, n)
of nkYieldStmt: result = semYield(c, n)
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas, true)
of nkIteratorDef: result = semIterator(c, n)
of nkProcDef: result = semProc(c, n)
of nkFuncDef: result = semFunc(c, n)

View File

@@ -27,7 +27,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
of nkIdent, nkSym:
result = n
let ident = considerQuotedIdent(c.c, n)
var L = sonsLen(forLoop)
var L = len(forLoop)
if c.replaceByFieldName:
if ident.id == considerQuotedIdent(c.c, forLoop[0]).id:
let fieldName = if c.tupleType.isNil: c.field.name.s
@@ -54,8 +54,8 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
localError(c.c.config, n.info,
"'continue' not supported in a 'fields' loop")
result = copyNode(n)
newSons(result, sonsLen(n))
for i in 0 ..< sonsLen(n):
newSons(result, len(n))
for i in 0 ..< len(n):
result.sons[i] = instFieldLoopBody(c, n.sons[i], forLoop)
type
@@ -120,9 +120,9 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
var stmts = newNodeI(nkStmtList, n.info)
result.sons[1] = stmts
var length = sonsLen(n)
var length = len(n)
var call = n.sons[length-2]
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
if length-2 != len(call)-1 + ord(m==mFieldPairs):
localError(c.config, n.info, errWrongNumberOfVariables)
return result
@@ -139,7 +139,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
inc(c.p.nestedLoopCounter)
if tupleTypeA.kind == tyTuple:
var loopBody = n.sons[length-1]
for i in 0..sonsLen(tupleTypeA)-1:
for i in 0..len(tupleTypeA)-1:
openScope(c)
var fc: TFieldInstCtx
fc.tupleType = tupleTypeA

View File

@@ -15,7 +15,12 @@ import
platform, math, msgs, idents, renderer, types,
commands, magicsys, modulegraphs, strtabs, lineinfos
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
proc errorType*(g: ModuleGraph): PType =
## creates a type representing an error state
result = newType(tyError, g.owners[^1])
result.flags.incl tfCheckedForDestructor
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode {.deprecated: "intVal should be Int128".} =
case skipTypes(n.typ, abstractVarRange).kind
of tyInt:
result = newIntNode(nkIntLit, intVal)
@@ -35,8 +40,20 @@ proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
result.typ = n.typ
result.info = n.info
proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode =
result = newIntTypeNode(intVal, n.typ)
# See bug #6989. 'pred' et al only produce an int literal type if the
# original type was 'int', not a distinct int etc.
if n.typ.kind == tyInt:
# access cache for the int lit type
result.typ = getIntLitType(g, result)
result.info = n.info
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
result = newFloatNode(nkFloatLit, floatVal)
if n.typ.skipTypes(abstractInst).kind == tyFloat32:
result = newFloatNode(nkFloat32Lit, floatVal)
else:
result = newFloatNode(nkFloatLit, floatVal)
result.typ = n.typ
result.info = n.info
@@ -50,65 +67,30 @@ proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode
# expression
proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode
proc checkInRange(conf: ConfigRef; n: PNode, res: BiggestInt): bool =
if res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ):
result = true
proc checkInRange(conf: ConfigRef; n: PNode, res: Int128): bool =
res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ)
proc foldAdd(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
let res = a +% b
if ((res xor a) >= 0'i64 or (res xor b) >= 0'i64) and
checkInRange(g.config, n, res):
proc foldAdd(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
let res = a + b
if checkInRange(g.config, n, res):
result = newIntNodeT(res, n, g)
proc foldSub*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
let res = a -% b
if ((res xor a) >= 0'i64 or (res xor not b) >= 0'i64) and
checkInRange(g.config, n, res):
proc foldSub(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
let res = a - b
if checkInRange(g.config, n, res):
result = newIntNodeT(res, n, g)
proc foldUnarySub(a: BiggestInt, n: PNode, g: ModuleGraph): PNode =
proc foldUnarySub(a: Int128, n: PNode, g: ModuleGraph): PNode =
if a != firstOrd(g.config, n.typ):
result = newIntNodeT(-a, n, g)
proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
proc foldAbs(a: Int128, n: PNode; g: ModuleGraph): PNode =
if a != firstOrd(g.config, n.typ):
result = newIntNodeT(abs(a), n, g)
proc foldMod*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
if b != 0'i64:
result = newIntNodeT(a mod b, n, g)
proc foldModU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
if b != 0'i64:
result = newIntNodeT(a %% b, n, g)
proc foldDiv*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
if b != 0'i64 and (a != firstOrd(g.config, n.typ) or b != -1'i64):
result = newIntNodeT(a div b, n, g)
proc foldDivU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
if b != 0'i64:
result = newIntNodeT(a /% b, n, g)
proc foldMul*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
let res = a *% b
let floatProd = toBiggestFloat(a) * toBiggestFloat(b)
let resAsFloat = toBiggestFloat(res)
# Fast path for normal case: small multiplicands, and no info
# is lost in either method.
if resAsFloat == floatProd and checkInRange(g.config, n, res):
return newIntNodeT(res, n, g)
# Somebody somewhere lost info. Close enough, or way off? Note
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
# The difference either is or isn't significant compared to the
# true value (of which floatProd is a good approximation).
# abs(diff)/abs(prod) <= 1/32 iff
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd) and
checkInRange(g.config, n, res):
proc foldMul(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
let res = a * b
if checkInRange(g.config, n, res):
return newIntNodeT(res, n, g)
proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
@@ -119,10 +101,10 @@ proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
var t = skipTypes(a.typ, abstractRange)
case t.kind
of tyChar:
result = $chr(int(x) and 0xff)
result = $chr(toInt64(x) and 0xff)
of tyEnum:
var n = t.n
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if n.sons[i].kind != nkSym: internalError(g.config, a.info, "ordinalValToString")
var field = n.sons[i].sym
if field.position == x:
@@ -176,7 +158,7 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
result.n = n
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
proc fitLiteral(c: ConfigRef, n: PNode): PNode =
proc fitLiteral(c: ConfigRef, n: PNode): PNode {.deprecated: "no substitute".} =
# Trim the literal value in order to make it fit in the destination type
if n == nil:
# `n` may be nil if the overflow check kicks in
@@ -188,58 +170,68 @@ proc fitLiteral(c: ConfigRef, n: PNode): PNode =
let typ = n.typ.skipTypes(abstractRange)
if typ.kind in tyUInt..tyUInt32:
result.intVal = result.intVal and lastOrd(c, typ, fixedUnsigned=true)
result.intVal = result.intVal and castToInt64(lastOrd(c, typ))
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
template doAndFit(op: untyped): untyped =
# Implements wrap-around behaviour for unsigned types
fitLiteral(g.config, op)
# b and c may be nil
result = nil
case m
of mOrd: result = newIntNodeT(getOrdValue(a), n, g)
of mChr: result = newIntNodeT(getInt(a), n, g)
of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, g)
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
of mUnaryMinusF64: result = newFloatNodeT(-getFloat(a), n, g)
of mNot: result = newIntNodeT(One - getInt(a), n, g)
of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
of mBitnotI: result = doAndFit(newIntNodeT(not getInt(a), n, g))
of mBitnotI:
if n.typ.isUnsigned:
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, g)
else:
result = newIntNodeT(bitnot(getInt(a)), n, g)
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
if a.kind == nkNilLit:
result = newIntNodeT(0, n, g)
result = newIntNodeT(Zero, n, g)
elif a.kind in {nkStrLit..nkTripleStrLit}:
result = newIntNodeT(len a.strVal, n, g)
result = newIntNodeT(toInt128(a.strVal.len), n, g)
else:
result = newIntNodeT(sonsLen(a), n, g)
result = newIntNodeT(toInt128(len(a)), n, g)
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
of mToFloat, mToBiggestFloat:
result = newFloatNodeT(toFloat(int(getInt(a))), n, g)
# XXX: Hides overflow/underflow
of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n, g)
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n, g)
of mAbsI: result = foldAbs(getInt(a), n, g)
of mUnaryLt: result = doAndFit(foldSub(getOrdValue(a), 1, n, g))
of mSucc: result = doAndFit(foldAdd(getOrdValue(a), getInt(b), n, g))
of mPred: result = doAndFit(foldSub(getOrdValue(a), getInt(b), n, g))
of mUnaryLt: result = foldSub(getOrdValue(a), One, n, g)
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g)
of mPred: result = foldSub(getOrdValue(a), getInt(b), n, g)
of mAddI: result = foldAdd(getInt(a), getInt(b), n, g)
of mSubI: result = foldSub(getInt(a), getInt(b), n, g)
of mMulI: result = foldMul(getInt(a), getInt(b), n, g)
of mMinI:
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n, g)
else: result = newIntNodeT(getInt(a), n, g)
let argA = getInt(a)
let argB = getInt(b)
result = newIntNodeT(if argA < argB: argA else: argB, n, g)
of mMaxI:
if getInt(a) > getInt(b): result = newIntNodeT(getInt(a), n, g)
else: result = newIntNodeT(getInt(b), n, g)
let argA = getInt(a)
let argB = getInt(b)
result = newIntNodeT(if argA > argB: argA else: argB, n, g)
of mShlI:
case skipTypes(n.typ, abstractRange).kind
of tyInt8: result = newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n, g)
of tyInt16: result = newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n, g)
of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n, g)
of tyInt64, tyInt:
result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)
of tyUInt..tyUInt64:
result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g))
of tyInt8: result = newIntNodeT(toInt8(getInt(a)) shl getInt64(b), n, g)
of tyInt16: result = newIntNodeT(toInt16(getInt(a)) shl getInt64(b), n, g)
of tyInt32: result = newIntNodeT(toInt32(getInt(a)) shl getInt64(b), n, g)
of tyInt64: result = newIntNodeT(toInt64(getInt(a)) shl getInt64(b), n, g)
of tyInt:
if g.config.target.intSize == 4:
result = newIntNodeT(toInt128(toInt32(getInt(a)) shl getInt64(b)), n, g)
else:
result = newIntNodeT(toInt128(toInt64(getInt(a)) shl getInt64(b)), n, g)
of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl getInt64(b)), n, g)
of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl getInt64(b)), n, g)
of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl getInt64(b)), n, g)
of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl getInt64(b)), n, g)
of tyUInt:
if g.config.target.intSize == 4:
result = newIntNodeT(BiggestInt(toUInt32(getInt(a)) shl getInt64(b)), n, g)
else:
result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl getInt64(b)), n, g)
else: internalError(g.config, n.info, "constant folding for shl")
of mShrI:
var a = cast[uint64](getInt(a))
@@ -263,25 +255,27 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
result = newIntNodeT(c, n, g)
of mAshrI:
case skipTypes(n.typ, abstractRange).kind
of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g)
of tyInt16: result = newIntNodeT(ashr(int16(getInt(a)), int16(getInt(b))), n, g)
of tyInt32: result = newIntNodeT(ashr(int32(getInt(a)), int32(getInt(b))), n, g)
of tyInt8: result = newIntNodeT(ashr(int8(getInt64(a)), int8(getInt64(b))), n, g)
of tyInt16: result = newIntNodeT(ashr(int16(getInt64(a)), int16(getInt64(b))), n, g)
of tyInt32: result = newIntNodeT(ashr(int32(getInt64(a)), int32(getInt64(b))), n, g)
of tyInt64, tyInt:
result = newIntNodeT(ashr(getInt(a), getInt(b)), n, g)
result = newIntNodeT(ashr(getInt64(a), getInt64(b)), n, g)
else: internalError(g.config, n.info, "constant folding for ashr")
of mDivI: result = foldDiv(getInt(a), getInt(b), n, g)
of mModI: result = foldMod(getInt(a), getInt(b), n, g)
of mDivI:
let argA = getInt(a)
let argB = getInt(b)
if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
result = newIntNodeT(argA div argB, n, g)
of mModI:
let argA = getInt(a)
let argB = getInt(b)
if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
result = newIntNodeT(argA mod argB, n, g)
of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g)
of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
of mDivF64:
result = newFloatNodeT(getFloat(a) / getFloat(b), n, g)
of mMaxF64:
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(a), n, g)
else: result = newFloatNodeT(getFloat(b), n, g)
of mMinF64:
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n, g)
else: result = newFloatNodeT(getFloat(a), n, g)
of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n, g)
of mLtI, mLtB, mLtEnum, mLtCh:
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n, g)
@@ -296,17 +290,32 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n, g)
of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n, g)
of mLtU, mLtU64:
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n, g)
result = newIntNodeT(ord(`<%`(getOrdValue64(a), getOrdValue64(b))), n, g)
of mLeU, mLeU64:
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n, g)
of mBitandI, mAnd: result = doAndFit(newIntNodeT(a.getInt and b.getInt, n, g))
of mBitorI, mOr: result = doAndFit(newIntNodeT(getInt(a) or getInt(b), n, g))
of mBitxorI, mXor: result = doAndFit(newIntNodeT(a.getInt xor b.getInt, n, g))
of mAddU: result = doAndFit(newIntNodeT(`+%`(getInt(a), getInt(b)), n, g))
of mSubU: result = doAndFit(newIntNodeT(`-%`(getInt(a), getInt(b)), n, g))
of mMulU: result = doAndFit(newIntNodeT(`*%`(getInt(a), getInt(b)), n, g))
of mModU: result = doAndFit(foldModU(getInt(a), getInt(b), n, g))
of mDivU: result = doAndFit(foldDivU(getInt(a), getInt(b), n, g))
result = newIntNodeT(ord(`<=%`(getOrdValue64(a), getOrdValue64(b))), n, g)
of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, g)
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g)
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g)
of mAddU:
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
result = newIntNodeT(val, n, g)
of mSubU:
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
result = newIntNodeT(val, n, g)
# echo "subU: ", val, " n: ", n, " result: ", val
of mMulU:
let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size))
result = newIntNodeT(val, n, g)
of mModU:
let argA = maskBytes(getInt(a), int(a.typ.size))
let argB = maskBytes(getInt(b), int(a.typ.size))
if argB != Zero:
result = newIntNodeT(argA mod argB, n, g)
of mDivU:
let argA = maskBytes(getInt(a), int(a.typ.size))
let argB = maskBytes(getInt(b), int(a.typ.size))
if argB != Zero:
result = newIntNodeT(argA div argB, n, g)
of mLeSet: result = newIntNodeT(ord(containsSets(g.config, a, b)), n, g)
of mEqSet: result = newIntNodeT(ord(equalSets(g.config, a, b)), n, g)
of mLtSet:
@@ -332,10 +341,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mBoolToStr:
if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
else: result = newStrNodeT("true", n, g)
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n, g)
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(toInt64(getOrdValue(b)))), n, g)
of mCopyStrLast:
result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
int(getOrdValue(c))), n, g)
result = newStrNodeT(substr(getStr(a), toInt(getOrdValue(b)),
toInt(getOrdValue(c))), n, g)
of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
of mCStrToStr, mCharToStr:
if a.kind == nkBracket:
@@ -362,7 +371,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode =
result = nil
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it.len == 2:
var e = getConstExpr(c, it.sons[0], g)
@@ -380,27 +389,27 @@ proc leValueConv*(a, b: PNode): bool =
case a.kind
of nkCharLit..nkUInt64Lit:
case b.kind
of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
of nkCharLit..nkUInt64Lit: result = a.getInt <= b.getInt
of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int
else: result = false #internalError(a.info, "leValueConv")
of nkFloatLit..nkFloat128Lit:
case b.kind
of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat64(b.getInt)
else: result = false # internalError(a.info, "leValueConv")
else: result = false # internalError(a.info, "leValueConv")
proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode =
if sonsLen(n) <= 1: return
if len(n) <= 1: return
var s = n.sons[0].sym
var a = getConstExpr(m, n.sons[1], g)
var b, c: PNode
if a == nil: return
if sonsLen(n) > 2:
if len(n) > 2:
b = getConstExpr(m, n.sons[2], g)
if b == nil: return
if sonsLen(n) > 3:
if len(n) > 3:
c = getConstExpr(m, n.sons[3], g)
if c == nil: return
result = evalOp(s.magic, n, a, b, c, g)
@@ -415,57 +424,42 @@ proc getAppType(n: PNode; g: ModuleGraph): PNode =
else:
result = newStrNodeT("console", n, g)
proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) =
var err = false
if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}:
err = value <% firstOrd(g.config, n.typ) or value >% lastOrd(g.config, n.typ, fixedUnsigned=true)
else:
err = value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ)
if err:
proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) =
if value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ):
localError(g.config, n.info, "cannot convert " & $value &
" to " & typeToString(n.typ))
proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
let dstTyp = skipTypes(n.typ, abstractRange)
let srcTyp = skipTypes(a.typ, abstractRange)
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
# XXX range checks?
# 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()
case dstTyp.kind
of tyInt..tyInt64, tyUInt..tyUInt64:
case srcTyp.kind
of tyFloat..tyFloat64:
result = newIntNodeT(int(getFloat(a)), n, g)
of tyChar:
result = newIntNodeT(getOrdValue(a), n, g)
of tyUInt..tyUInt64, tyInt..tyInt64:
let toSigned = dstTyp.kind in tyInt..tyInt64
result = newIntNodeT(BiggestInt(getFloat(a)), n, g)
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
var val = a.getOrdValue
if dstTyp.kind in {tyInt, tyInt64, tyUInt, tyUInt64}:
# No narrowing needed
discard
elif dstTyp.kind in {tyInt..tyInt64}:
# Signed type: Overflow check (if requested) and conversion
if check: rangeCheck(n, val, g)
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
let valSign = val < 0
val = abs(val) and mask
if valSign: val = -val
else:
# Unsigned type: Conversion
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
val = val and mask
if check: rangeCheck(n, val, g)
result = newIntNodeT(val, n, g)
if dstTyp.kind in {tyUInt..tyUInt64}:
result.kind = nkUIntLit
else:
result = a
result.typ = n.typ
if check and result.kind in {nkCharLit..nkUInt64Lit}:
rangeCheck(n, result.intVal, g)
rangeCheck(n, getInt(result), g)
of tyFloat..tyFloat64:
case srcTyp.kind
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g)
result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
else:
result = a
result.typ = n.typ
@@ -490,16 +484,16 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
var y = getConstExpr(m, n.sons[1], g)
if y == nil: return
var idx = getOrdValue(y)
var idx = toInt64(getOrdValue(y))
case x.kind
of nkPar, nkTupleConstr:
if idx >= 0 and idx < sonsLen(x):
result = x.sons[int(idx)]
if idx >= 0 and idx < len(x):
result = x.sons[idx]
if result.kind == nkExprColonExpr: result = result.sons[1]
else:
localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)-1) & $n)
localError(g.config, n.info, formatErrorIndexBound(idx, len(x)-1) & $n)
of nkBracket:
idx = idx - firstOrd(g.config, x.typ)
idx = idx - toInt64(firstOrd(g.config, x.typ))
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
of nkStrLit..nkTripleStrLit:
@@ -518,7 +512,7 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
var field = n.sons[1].sym
for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
for i in ord(x.kind == nkObjConstr) ..< len(x):
var it = x.sons[i]
if it.kind != nkExprColonExpr:
# lookup per index:
@@ -533,7 +527,7 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
proc foldConStrStr(m: PSym, n: PNode; g: ModuleGraph): PNode =
result = newNodeIT(nkStrLit, n.info, n.typ)
result.strVal = ""
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
let a = getConstExpr(m, n.sons[i], g)
if a == nil: return nil
result.strVal.add(getStrOrChar(a))
@@ -635,12 +629,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
var a = getArrayConstr(m, n.sons[1], g)
if a.kind == nkBracket:
# we can optimize it away:
result = newIntNodeT(sonsLen(a)-1, n, g)
result = newIntNodeT(len(a)-1, n, g)
of mLengthOpenArray:
var a = getArrayConstr(m, n.sons[1], g)
if a.kind == nkBracket:
# we can optimize it away! This fixes the bug ``len(134)``.
result = newIntNodeT(sonsLen(a), n, g)
result = newIntNodeT(len(a), n, g)
else:
result = magicCall(m, n, g)
of mLengthArray:
@@ -689,7 +683,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
addSon(result, b)
#of nkObjConstr:
# result = copyTree(n)
# for i in 1 ..< sonsLen(n):
# for i in 1 ..< len(n):
# var a = getConstExpr(m, n.sons[i].sons[1])
# if a == nil: return nil
# result.sons[i].sons[1] = a
@@ -697,7 +691,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
of nkPar, nkTupleConstr:
# tuple constructor
result = copyNode(n)
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
if (len(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
for i, expr in n.pairs:
let exprNew = copyNode(expr) # nkExprColonExpr
exprNew.add expr[0]
@@ -729,8 +723,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var a = getConstExpr(m, n.sons[1], g)
if a == nil: return
# XXX: we should enable `check` for other conversion types too
result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv)
result = foldConv(n, a, g, check=true)
of nkCast:
var a = getConstExpr(m, n.sons[1], g)
if a == nil: return

View File

@@ -282,7 +282,7 @@ proc semGenericStmt(c: PContext, n: PNode,
# in threads.nim: the subtle preprocessing here binds 'globalsSlot' which
# is not exported and yet the generic 'threadProcWrapper' works correctly.
let flags = if mixinContext: flags+{withinMixin} else: flags
for i in first ..< sonsLen(result):
for i in first ..< safeLen(result):
result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
of nkCurlyExpr:
result = newNodeI(nkCall, n.info)
@@ -316,13 +316,13 @@ proc semGenericStmt(c: PContext, n: PNode,
withBracketExpr ctx, a.sons[0]:
result = semGenericStmt(c, result, flags, ctx)
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
of nkIfStmt:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
of nkWhenStmt:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
# bug #8603: conditions of 'when' statements are not
# in a 'mixin' context:
let it = n[i]
@@ -333,22 +333,22 @@ proc semGenericStmt(c: PContext, n: PNode,
n.sons[i] = semGenericStmt(c, it, flags+{withinMixin}, ctx)
of nkWhileStmt:
openScope(c)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
closeScope(c)
of nkCaseStmt:
openScope(c)
n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var a = n.sons[i]
checkMinSonsLen(a, 1, c.config)
var L = sonsLen(a)
var L = len(a)
for j in 0 .. L-2:
a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx)
a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
closeScope(c)
of nkForStmt, nkParForStmt:
var L = sonsLen(n)
var L = len(n)
openScope(c)
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
for i in 0 .. L - 3:
@@ -372,10 +372,10 @@ proc semGenericStmt(c: PContext, n: PNode,
of nkTryStmt, nkHiddenTryStmt:
checkMinSonsLen(n, 2, c.config)
n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx)
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var a = n.sons[i]
checkMinSonsLen(a, 1, c.config)
var L = sonsLen(a)
var L = len(a)
openScope(c)
for j in 0 .. L-2:
if a.sons[j].isInfixAs():
@@ -387,28 +387,28 @@ proc semGenericStmt(c: PContext, n: PNode,
closeScope(c)
of nkVarSection, nkLetSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var L = sonsLen(a)
var L = len(a)
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
for j in 0 .. L-3:
addTempDecl(c, getIdentNode(c, a.sons[j]), skVar)
of nkGenericParams:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var L = sonsLen(a)
var L = len(a)
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
# do not perform symbol lookup for default expressions
for j in 0 .. L-3:
addTempDecl(c, getIdentNode(c, a.sons[j]), skType)
of nkConstSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): illFormedAst(a, c.config)
@@ -417,13 +417,13 @@ proc semGenericStmt(c: PContext, n: PNode,
a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx)
a.sons[2] = semGenericStmt(c, a.sons[2], flags, ctx)
of nkTypeSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a, c.config)
checkSonsLen(a, 3, c.config)
addTempDecl(c, getIdentNode(c, a.sons[0]), skType)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a, c.config)
@@ -436,10 +436,10 @@ proc semGenericStmt(c: PContext, n: PNode,
else:
a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
of nkEnumTy:
if n.sonsLen > 0:
if n.len > 0:
if n.sons[0].kind != nkEmpty:
n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var a: PNode
case n.sons[i].kind
of nkEnumFieldDef: a = n.sons[i].sons[0]
@@ -452,11 +452,11 @@ proc semGenericStmt(c: PContext, n: PNode,
checkMinSonsLen(n, 1, c.config)
if n.sons[0].kind != nkEmpty:
n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var a = n.sons[i]
if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var L = sonsLen(a)
var L = len(a)
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
for j in 0 .. L-3:
@@ -489,7 +489,7 @@ proc semGenericStmt(c: PContext, n: PNode,
checkMinSonsLen(n, 2, c.config)
result.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
when defined(nimsuggest):

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)
@@ -387,7 +387,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
if c.inGenericContext == 0:
instantiateBody(c, n, fn.typ.n, result, fn)
sideEffectsCheck(c, result)
if result.magic != mSlice:
if result.magic notin {mSlice, mTypeOf}:
# 'toOpenArray' is special and it is allowed to return 'openArray':
paramsTypeCheck(c, result.typ)
else:

View File

@@ -16,14 +16,14 @@ proc ithField(n: PNode, field: var int): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result = ithField(n.sons[i], field)
if result != nil: return
of nkRecCase:
if n.sons[0].kind != nkSym: return
result = ithField(n.sons[0], field)
if result != nil: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
result = ithField(lastSon(n.sons[i]), field)

View File

@@ -141,6 +141,14 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
return typeWithSonsResult(tyAnd, @[operand, operand2])
of "not":
return typeWithSonsResult(tyNot, @[operand])
of "typeToString":
var prefer = preferTypeName
if traitCall.sons.len >= 2:
let preferStr = traitCall.sons[2].strVal
prefer = parseEnum[TPreferedDesc](preferStr)
result = newStrNode(nkStrLit, operand.typeToString(prefer))
result.typ = newType(tyString, context)
result.info = traitCall.info
of "name", "$":
result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
result.typ = newType(tyString, context)
@@ -172,7 +180,7 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
checkMinSonsLen(n, 2, c.config)
let t = n.sons[1].typ
internalAssert c.config, t != nil and t.kind == tyTypeDesc
if t.sonsLen > 0:
if t.len > 0:
# This is either a type known to sem or a typedesc
# param to a regular proc (again, known at instantiation)
result = evalTypeTrait(c, n, t, getCurrOwner(c))
@@ -186,7 +194,9 @@ proc semOrd(c: PContext, n: PNode): PNode =
if isOrdinalType(parType, allowEnumWithHoles=true):
discard
elif parType.kind == tySet:
result.typ = makeRangeType(c, firstOrd(c.config, parType), lastOrd(c.config, parType), n.info)
let a = toInt64(firstOrd(c.config, parType))
let b = toInt64(lastOrd(c.config, parType))
result.typ = makeRangeType(c, a, b, n.info)
else:
localError(c.config, n.info, errOrdinalTypeExpected)
result.typ = errorType(c)
@@ -269,11 +279,11 @@ 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
idxNode = newIntTypeNode(nkIntLit, idx, c.graph.getSysType(TLineInfo(), tyInt))
idxNode = newIntTypeNode(idx, c.graph.getSysType(TLineInfo(), tyInt))
result = copyNode(n)
for x in n: result.add x
@@ -283,7 +293,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semOf(c: PContext, n: PNode): PNode =
if sonsLen(n) == 3:
if len(n) == 3:
n.sons[1] = semExprWithType(c, n.sons[1])
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
#restoreOldStyleType(n.sons[1])

View File

@@ -100,7 +100,7 @@ proc allPossibleValues(c: PContext, t: PType): IntSet =
for field in t.n.sons:
result.incl(field.sym.position)
else:
for i in firstOrd(c.config, t) .. lastOrd(c.config, t):
for i in toInt64(firstOrd(c.config, t)) .. toInt64(lastOrd(c.config, t)):
result.incl(i.int)
proc branchVals(c: PContext, caseNode: PNode, caseIdx: int,
@@ -113,6 +113,13 @@ proc branchVals(c: PContext, caseNode: PNode, caseIdx: int,
for i in 1 .. caseNode.len-2:
processBranchVals(caseNode[i], excl)
proc rangeTypVals(rangeTyp: PType): IntSet =
assert rangeTyp.kind == tyRange
let (a, b) = (rangeTyp.n.sons[0].intVal, rangeTyp.n.sons[1].intVal)
result = initIntSet()
for it in a .. b:
result.incl(it.int)
proc formatUnsafeBranchVals(t: PType, diffVals: IntSet): string =
if diffVals.len <= 32:
var strs: seq[string]
@@ -228,9 +235,9 @@ proc semConstructFields(c: PContext, recNode: PNode,
template badDiscriminatorError =
let fields = fieldsPresentInBranch(selectedBranch)
localError(c.config, initExpr.info,
("you must provide a compile-time value for the discriminator '$1' " &
"in order to prove that it's safe to initialize $2.") %
[discriminator.sym.name.s, fields])
("cannot prove that it's safe to initialize $1 with " &
"the runtime value for the discriminator '$2' ") %
[fields, discriminator.sym.name.s])
mergeInitStatus(result, initNone)
template wrongBranchError(i) =
@@ -241,30 +248,45 @@ proc semConstructFields(c: PContext, recNode: PNode,
"are in conflict with this value.",
[discriminator.sym.name.s, discriminatorVal.renderTree, fields])
template valuesInConflictError(valsDiff) =
localError(c.config, discriminatorVal.info, ("possible values " &
"$2are in conflict with discriminator values for " &
"selected object branch $1.") % [$selectedBranch,
formatUnsafeBranchVals(recNode.sons[0].typ, valsDiff)])
let branchNode = recNode[selectedBranch]
let flags = flags*{efAllowDestructor} + {efPreferStatic,
efPreferNilResult}
var discriminatorVal = semConstrField(c, flags,
discriminator.sym, initExpr)
if discriminatorVal != nil:
discriminatorVal = discriminatorVal.skipHidden
if discriminatorVal.kind notin nkLiterals and (
not isOrdinalType(discriminatorVal.typ, true) or
lengthOrd(c.config, discriminatorVal.typ) > MaxSetElements or
lengthOrd(c.config, recNode.sons[0].typ) > MaxSetElements):
localError(c.config, discriminatorVal.info,
"branch initialization with a runtime discriminator only " &
"supports ordinal types with 2^16 elements or less.")
if discriminatorVal == nil:
badDiscriminatorError()
elif discriminatorVal.kind == nkSym:
let (ctorCase, ctorIdx) = findUsefulCaseContext(c, discriminatorVal)
if ctorCase == nil:
badDiscriminatorError()
if discriminatorVal.typ.kind == tyRange:
let rangeVals = rangeTypVals(discriminatorVal.typ)
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
let diff = rangeVals - recBranchVals
if diff.len != 0:
valuesInConflictError(diff)
else:
badDiscriminatorError()
elif discriminatorVal.sym.kind notin {skLet, skParam} or
discriminatorVal.sym.typ.kind == tyVar:
localError(c.config, discriminatorVal.info,
"runtime discriminator must be immutable if branch fields are " &
"initialized, a 'let' binding is required.")
elif not isOrdinalType(discriminatorVal.sym.typ, true) or
lengthOrd(c.config, discriminatorVal.sym.typ) > MaxSetElements:
localError(c.config, discriminatorVal.info,
"branch initialization with a runtime discriminator only " &
"supports ordinal types with 2^16 elements or less.")
elif ctorCase[ctorIdx].kind == nkElifBranch:
localError(c.config, discriminatorVal.info, "branch initialization " &
"with a runtime discriminator is not supported inside of an " &
@@ -275,20 +297,27 @@ proc semConstructFields(c: PContext, recNode: PNode,
recBranchVals = branchVals(c, recNode, selectedBranch, false)
branchValsDiff = ctorBranchVals - recBranchVals
if branchValsDiff.len != 0:
localError(c.config, discriminatorVal.info, ("possible values " &
"$2are in conflict with discriminator values for " &
"selected object branch $1.") % [$selectedBranch,
formatUnsafeBranchVals(recNode.sons[0].typ, branchValsDiff)])
valuesInConflictError(branchValsDiff)
else:
var failedBranch = -1
if branchNode.kind != nkElse:
if not branchNode.caseBranchMatchesExpr(discriminatorVal):
wrongBranchError(selectedBranch)
failedBranch = selectedBranch
else:
# With an else clause, check that all other branches don't match:
for i in 1 .. (recNode.len - 2):
if recNode[i].caseBranchMatchesExpr(discriminatorVal):
wrongBranchError(i)
failedBranch = i
break
if failedBranch != -1:
if discriminatorVal.typ.kind == tyRange:
let rangeVals = rangeTypVals(discriminatorVal.typ)
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
let diff = rangeVals - recBranchVals
if diff.len != 0:
valuesInConflictError(diff)
else:
wrongBranchError(failedBranch)
# When a branch is selected with a partial match, some of the fields
# that were not initialized may be mandatory. We must check for this:
@@ -310,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:
@@ -351,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

@@ -380,7 +380,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
# Collect the exceptions caught by the except branches
for i in 1 ..< n.len:
let b = n.sons[i]
let blen = sonsLen(b)
let blen = len(b)
if b.kind == nkExceptBranch:
inc branches
if blen == 1:
@@ -398,7 +398,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
# Add any other exception raised in the except bodies
for i in 1 ..< n.len:
let b = n.sons[i]
let blen = sonsLen(b)
let blen = len(b)
if b.kind == nkExceptBranch:
setLen(tracked.init, oldState)
track(tracked, b.sons[blen-1])
@@ -430,7 +430,7 @@ proc isForwardedProc(n: PNode): bool =
result = n.kind == nkSym and sfForward in n.sym.flags
proc trackPragmaStmt(tracked: PEffects, n: PNode) =
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if whichPragma(it) == wEffects:
# list the computed effects up to here:
@@ -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,6 +751,9 @@ proc track(tracked: PEffects, n: PNode) =
discard
else:
message(tracked.config, arg.info, warnProveInit, $arg)
# 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

@@ -157,7 +157,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
var typ = commonTypeBegin
var hasElse = false
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it.len == 2:
openScope(c)
@@ -208,7 +208,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
n[0] = semExprBranchScope(c, n[0])
typ = commonType(typ, n[0].typ)
var last = sonsLen(n) - 1
var last = len(n) - 1
var catchAllExcepts = 0
for i in 1 .. last:
@@ -292,6 +292,8 @@ proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal)
result.info = n.info
result.typ = typ
if not floatRangeCheck(result.floatVal, typ):
localError(c.config, n.info, errFloatToString % [$result.floatVal, typeToString(typ)])
else:
changeType(c, r1, typ, check=true)
result = r1
@@ -361,13 +363,13 @@ proc isDiscardUnderscore(v: PSym): bool =
proc semUsing(c: PContext; n: PNode): PNode =
result = c.graph.emptyNode
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "using")
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a)
var length = len(a)
if a.sons[length-2].kind != nkEmpty:
let typ = semTypeNode(c, a.sons[length-2], nil)
for j in 0 .. length-3:
@@ -414,7 +416,7 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
if obj.kind == tyObject and tfPartial in obj.flags:
let field = newSym(skField, getIdent(c.cache, y.s), obj.sym, n[1].info)
field.typ = skipIntLit(typ)
field.position = sonsLen(obj.n)
field.position = len(obj.n)
addSon(obj.n, newSymNode(field))
n.sons[0] = makeDeref x
n.sons[1] = newSymNode(field)
@@ -435,13 +437,13 @@ proc setVarType(c: PContext; v: PSym, typ: PType) =
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode
result = copyNode(n)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a)
var length = len(a)
var typ: PType = nil
if a.sons[length-2].kind != nkEmpty:
@@ -500,7 +502,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if a.kind == nkVarTuple:
if tup.kind != tyTuple:
localError(c.config, a.info, errXExpected, "tuple")
elif length-2 != sonsLen(tup):
elif length-2 != len(tup):
localError(c.config, a.info, errWrongNumberOfVariables)
b = newNodeI(nkVarTuple, a.info)
newSons(b, length)
@@ -581,13 +583,13 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
proc semConst(c: PContext, n: PNode): PNode =
result = copyNode(n)
inc c.inStaticContext
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue
if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a)
var length = len(a)
var typ: PType = nil
if a.sons[length-2].kind != nkEmpty:
@@ -630,7 +632,7 @@ proc semConst(c: PContext, n: PNode): PNode =
if a.kind == nkVarTuple:
if typ.kind != tyTuple:
localError(c.config, a.info, errXExpected, "tuple")
elif length-2 != sonsLen(typ):
elif length-2 != len(typ):
localError(c.config, a.info, errWrongNumberOfVariables)
b = newNodeI(nkVarTuple, a.info)
newSons(b, length)
@@ -673,28 +675,33 @@ proc symForVar(c: PContext, n: PNode): PSym =
proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
var length = sonsLen(n)
var length = len(n)
let iterBase = n.sons[length-2].typ
var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink})
var iterAfterVarLent = iter.skipTypes({tyLent, tyVar})
# length == 3 means that there is one for loop variable
# and thus no tuple unpacking:
if iter.kind != tyTuple or length == 3:
if iterAfterVarLent.kind != tyTuple or length == 3:
if length == 3:
if n.sons[0].kind == nkVarTuple:
var mutable = false
if iter.kind == tyVar:
iter = iter.skipTypes({tyVar})
mutable = true
if sonsLen(n[0])-1 != sonsLen(iter):
if len(n[0])-1 != len(iterAfterVarLent):
localError(c.config, n[0].info, errWrongNumberOfVariables)
for i in 0 ..< sonsLen(n[0])-1:
for i in 0 ..< len(n[0])-1:
var v = symForVar(c, n[0][i])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
if mutable:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iter[i]
else:
v.typ = iter.sons[i]
case iter.kind
of tyVar:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
of tyLent:
v.typ = newTypeS(tyLent, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
else:
v.typ = iter.sons[i]
n.sons[0][i] = newSymNode(v)
if sfGenSym notin v.flags: addDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
@@ -710,23 +717,33 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
elif v.owner == nil: v.owner = getCurrOwner(c)
else:
localError(c.config, n.info, errWrongNumberOfVariables)
elif length-2 != sonsLen(iter):
elif length-2 != len(iterAfterVarLent):
localError(c.config, n.info, errWrongNumberOfVariables)
else:
for i in 0 .. length - 3:
if n.sons[i].kind == nkVarTuple:
var mutable = false
if iter[i].kind == tyVar:
iter[i] = iter[i].skipTypes({tyVar})
mutable = true
if sonsLen(n[i])-1 != sonsLen(iter[i]):
var isLent = false
iter[i] = case iter[i].kind
of tyVar:
mutable = true
iter[i].skipTypes({tyVar})
of tyLent:
isLent = true
iter[i].skipTypes({tyLent})
else: iter[i]
if len(n[i])-1 != len(iter[i]):
localError(c.config, n[i].info, errWrongNumberOfVariables)
for j in 0 ..< sonsLen(n[i])-1:
for j in 0 ..< len(n[i])-1:
var v = symForVar(c, n[i][j])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
if mutable:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iter[i][j]
elif isLent:
v.typ = newTypeS(tyLent, c)
v.typ.sons.add iter[i][j]
else:
v.typ = iter[i][j]
n.sons[i][j] = newSymNode(v)
@@ -735,7 +752,19 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
else:
var v = symForVar(c, n.sons[i])
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
v.typ = iter.sons[i]
case iter.kind
of tyVar:
v.typ = newTypeS(tyVar, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
of tyLent:
v.typ = newTypeS(tyLent, c)
v.typ.sons.add iterAfterVarLent[i]
if tfVarIsPtr in iter.flags:
v.typ.flags.incl tfVarIsPtr
else:
v.typ = iter.sons[i]
n.sons[i] = newSymNode(v)
if sfGenSym notin v.flags:
if not isDiscardUnderscore(v): addDecl(c, v)
@@ -763,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
@@ -792,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.
@@ -812,15 +842,15 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
errors, false)
if r.state == csMatch:
var match = r.calleeSym
markUsed(c.config, n[0].info, match, c.graph.usageSym)
markUsed(c, n[0].info, match)
onUse(n[0].info, match)
# but pass 'n' to the 'match' macro, not 'n[0]':
r.call.sons[1] = n
let toExpand = semResolvedCall(c, r, r.call, {})
case match.kind
of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, {})
of skTemplate: result = semTemplateExpr(c, toExpand, match, {})
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
@@ -830,9 +860,9 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
checkMinSonsLen(n, 3, c.config)
var length = sonsLen(n)
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
@@ -895,12 +925,12 @@ 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)
return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
setCaseContextIdx(c, i)
var x = n.sons[i]
when defined(nimsuggest):
@@ -910,7 +940,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
of nkOfBranch:
checkMinSonsLen(x, 2, c.config)
semCaseBranch(c, n, x, i, covered)
var last = sonsLen(x)-1
var last = len(x)-1
x.sons[last] = semExprBranchScope(c, x.sons[last])
typ = commonType(typ, x.sons[last])
of nkElifBranch:
@@ -971,7 +1001,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
proc addGenericParamListToScope(c: PContext, n: PNode) =
if n.kind != nkGenericParams: illFormedAst(n, c.config)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkSym: addDecl(c, a.sym)
else: illFormedAst(a, c.config)
@@ -988,7 +1018,7 @@ proc typeSectionTypeName(c: PContext; n: PNode): PNode =
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
# process the symbols on the left side for the whole type section, before
# we even look at the type definitions on the right
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
when defined(nimsuggest):
if c.config.cmd == cmdIdeTools:
@@ -1120,7 +1150,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
discard traverseSubTypes(c, body)
proc typeSectionRightSidePass(c: PContext, n: PNode) =
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if a.kind != nkTypeDef: illFormedAst(a, c.config)
@@ -1157,7 +1187,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
if body != nil:
body.sym = s
body.size = -1 # could not be computed properly
s.typ.sons[sonsLen(s.typ) - 1] = body
s.typ.sons[len(s.typ) - 1] = body
if tfCovariant in s.typ.flags:
checkCovariantParamsUsages(c, s.typ)
# XXX: This is a temporary limitation:
@@ -1247,7 +1277,7 @@ proc checkForMetaFields(c: PContext; n: PNode) =
internalAssert c.config, false
proc typeSectionFinalPass(c: PContext, n: PNode) =
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
let name = typeSectionTypeName(c, a.sons[0])
@@ -1345,7 +1375,7 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
s.typ = semProcTypeNode(c, n, genericParams, nil, s.kind)
proc addParams(c: PContext, n: PNode, kind: TSymKind) =
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
else: illFormedAst(n, c.config)
@@ -1420,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
@@ -1469,7 +1504,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[paramsPos], gp, s)
# paramsTypeCheck(c, s.typ)
if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
if len(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
# we have a list of implicit type parameters:
n.sons[genericParamsPos] = gp
else:
@@ -1497,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 =
@@ -1534,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
@@ -1593,7 +1628,9 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
else: break
if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
obj = canonType(c, obj)
if obj.destructor.isNil:
if obj.attachedOps[attachedDestructor] == s:
discard "forward declared destructor"
elif obj.destructor.isNil and tfCheckedForDestructor notin obj.flags:
obj.attachedOps[attachedDestructor] = s
else:
prevDestructor(c, obj.destructor, obj, n.info)
@@ -1658,7 +1695,9 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
obj = canonType(c, obj)
#echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj)
let k = if name == "=": attachedAsgn else: attachedSink
if obj.attachedOps[k].isNil:
if obj.attachedOps[k] == s:
discard "forward declared op"
elif obj.attachedOps[k].isNil and tfCheckedForDestructor notin obj.flags:
obj.attachedOps[k] = s
else:
prevDestructor(c, obj.attachedOps[k], obj, n.info)
@@ -1691,7 +1730,7 @@ type
proc hasObjParam(s: PSym): bool =
var t = s.typ
for col in 1 ..< sonsLen(t):
for col in 1 ..< len(t):
if skipTypes(t.sons[col], skipPtrs).kind == tyObject:
return true
@@ -1705,7 +1744,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
var foundObj = false
# we start at 1 for now so that tparsecombnum continues to compile.
# XXX Revisit this problem later.
for col in 1 ..< sonsLen(tt):
for col in 1 ..< len(tt):
let t = tt.sons[col]
if t != nil and t.kind == tyGenericInvocation:
var x = skipTypes(t.sons[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
@@ -1778,7 +1817,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# process parameters:
if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[paramsPos], gp, s)
if sonsLen(gp) > 0:
if len(gp) > 0:
if n.sons[genericParamsPos].kind == nkEmpty:
# we have a list of implicit type parameters:
n.sons[genericParamsPos] = gp
@@ -1878,7 +1917,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else:
pushProcCon(c, s)
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
if not usePseudoGenerics and s.magic == mNone: paramsTypeCheck(c, s.typ)
c.p.wasForwarded = proto != nil
maybeAddResult(c, s, n)
@@ -1904,6 +1943,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
discard
popProcCon(c)
else:
if s.kind in {skProc, skFunc} and s.typ[0] != nil and s.typ[0].kind == tyUntyped:
# `auto` is represented as `tyUntyped` at this point in compilation.
localError(c.config, n[paramsPos][0].info, "return type 'auto' cannot be used in forward declarations")
if s.kind == skMethod: semMethodPrototype(c, s, n)
if proto != nil: localError(c.config, n.info, errImplOfXexpected % proto.name.s)
if {sfImportc, sfBorrow, sfError} * s.flags == {} and s.magic == mNone:
@@ -1918,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:
@@ -1998,7 +2041,7 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
var s = result.sons[namePos].sym
var t = s.typ
if t.sons[0] == nil: localError(c.config, n.info, errXNeedsReturnType % "converter")
if sonsLen(t) != 2: localError(c.config, n.info, "a converter takes exactly one argument")
if len(t) != 2: localError(c.config, n.info, "a converter takes exactly one argument")
addConverter(c, s)
proc semMacroDef(c: PContext, n: PNode): PNode =
@@ -2032,9 +2075,11 @@ proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info)
addSon(result, n)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var imp: PNode
let it = n.sons[i]
if it.kind == nkInfix and it.len == 3 and it[0].ident.s != "/":
localError(c.config, it.info, "Cannot use '" & it[0].ident.s & "' in 'include'.")
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
let sep = it[0]
let dir = it[1]
@@ -2111,7 +2156,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
result = n
result.kind = nkStmtList
var length = sonsLen(n)
var length = len(n)
var voidContext = false
var last = length-1
# by not allowing for nkCommentStmt etc. we ensure nkStmtListExpr actually

View File

@@ -34,7 +34,7 @@ type
spNone, spGenSym, spInject
proc symBinding(n: PNode): TSymBinding =
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
if key.kind == nkIdent:
@@ -47,7 +47,8 @@ type
TSymChoiceRule = enum
scClosed, scOpen, scForceOpen
proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
isField = false): PNode =
var
a: PSym
o: TOverloadIter
@@ -63,9 +64,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
# XXX this makes more sense but breaks bootstrapping for now:
# (s.kind notin routineKinds or s.magic != mNone):
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
result = newSymNode(s, info)
markUsed(c.config, info, s, c.graph.usageSym)
onUse(info, s)
if not isField or sfGenSym notin s.flags:
result = newSymNode(s, info)
markUsed(c, info, s)
onUse(info, s)
else:
result = n
else:
# semantic checking requires a type; ``fitNode`` deals with it
# appropriately
@@ -74,8 +78,9 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
result = newNodeIT(kind, info, newTypeS(tyNone, c))
a = initOverloadIter(o, c, n)
while a != nil:
if a.kind != skModule:
if a.kind != skModule and (not isField or sfGenSym notin s.flags):
incl(a.flags, sfUsed)
markOwnerModuleAsUsed(c, a)
addSon(result, newSymNode(a, info))
onUse(info, a)
a = nextOverloadIter(o, c, n)
@@ -119,6 +124,8 @@ type
owner: PSym
cursorInBody: bool # only for nimsuggest
scopeN: int
noGenSym: int
inTemplateHeader: int
template withBracketExpr(ctx, x, body: untyped) =
body
@@ -138,9 +145,12 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
illFormedAst(n, c.c.config)
result = n
template oldCheck(cx: TemplCtx; cond: bool): bool =
(optNimV019 notin cx.c.config.globalOptions or cond)
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
result = n.kind == nkSym and n.sym.kind == skParam and
n.sym.owner == c.owner and sfGenSym notin n.sym.flags
n.sym.owner == c.owner and sfTemplateParam in n.sym.flags
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
@@ -197,7 +207,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
else:
replaceIdentBySym(c.c, n, ident)
else:
if (n.kind == nkPragmaExpr and sonsLen(n) >= 2 and n.sons[1].kind == nkPragma):
if (n.kind == nkPragmaExpr and len(n) >= 2 and n.sons[1].kind == nkPragma):
let pragmaNode = n.sons[1]
for i in 0..<pragmaNode.sons.len:
openScope(c)
@@ -225,11 +235,17 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
styleCheckDef(c.c.config, n.info, local)
onDef(n.info, local)
replaceIdentBySym(c.c, n, newSymNode(local, n.info))
if k == skParam and c.inTemplateHeader > 0:
local.flags.incl sfTemplateParam
else:
replaceIdentBySym(c.c, n, ident)
proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
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
@@ -237,15 +253,23 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
# Introduced in this pass! Leave it as an identifier.
result = n
of OverloadableSyms:
result = symChoice(c, n, s, scOpen)
result = symChoice(c, n, s, scOpen, isField)
of skGenericParam:
result = newSymNodeTypeDesc(s, n.info)
if isField and sfGenSym in s.flags: result = n
else: result = newSymNodeTypeDesc(s, n.info)
of skParam:
result = n
of skType:
result = newSymNodeTypeDesc(s, n.info)
if isField and sfGenSym in s.flags: result = n
else: result = newSymNodeTypeDesc(s, n.info)
else:
result = newSymNode(s, n.info)
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
@@ -279,7 +303,14 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
n.sons[namePos] = semRoutineInTemplName(c, n.sons[namePos])
# open scope for parameters
openScope(c)
for i in patternPos..miscPos:
for i in patternPos..paramsPos-1:
n.sons[i] = semTemplBody(c, n.sons[i])
if k == skTemplate: inc(c.inTemplateHeader)
n.sons[paramsPos] = semTemplBody(c, n.sons[paramsPos])
if k == skTemplate: dec(c.inTemplateHeader)
for i in paramsPos+1..miscPos:
n.sons[i] = semTemplBody(c, n.sons[i])
# open scope for locals
inc c.scopeN
@@ -292,12 +323,12 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
closeScope(c)
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) =
for i in start ..< sonsLen(n):
for i in start ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a, c.c.config)
checkMinSonsLen(a, 3, c.c.config)
var L = sonsLen(a)
var L = len(a)
when defined(nimsuggest):
inc c.c.inTypeContext
a.sons[L-2] = semTemplBody(c, a.sons[L-2])
@@ -322,22 +353,23 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
if n.ident.id in c.toInject: return n
let s = qualifiedLookUp(c.c, n, {})
if s != nil:
if s.owner == c.owner and s.kind == skParam:
if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
# oldCheck(c, sfGenSym notin s.flags or c.noGenSym == 0):
incl(s.flags, sfUsed)
result = newSymNode(s, n.info)
onUse(n.info, s)
elif contains(c.toBind, s.id):
result = symChoice(c.c, n, s, scClosed)
result = symChoice(c.c, n, s, scClosed, c.noGenSym > 0)
elif contains(c.toMixin, s.name.id):
result = symChoice(c.c, n, s, scForceOpen)
elif s.owner == c.owner and sfGenSym in s.flags:
result = symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
elif s.owner == c.owner and sfGenSym in s.flags and c.noGenSym == 0:
# template tmp[T](x: var seq[T]) =
# var yz: T
incl(s.flags, sfUsed)
result = newSymNode(s, n.info)
onUse(n.info, s)
else:
result = semTemplSymbol(c.c, n, s)
result = semTemplSymbol(c.c, n, s, c.noGenSym > 0)
of nkBind:
result = semTemplBody(c, n.sons[0])
of nkBindStmt:
@@ -348,7 +380,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
of nkEmpty, nkSym..nkNilLit, nkComesFrom:
discard
of nkIfStmt:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it.len == 2:
openScope(c)
@@ -359,27 +391,27 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
n.sons[i] = semTemplBodyScope(c, it)
of nkWhileStmt:
openScope(c)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
n.sons[i] = semTemplBody(c, n.sons[i])
closeScope(c)
of nkCaseStmt:
openScope(c)
n.sons[0] = semTemplBody(c, n.sons[0])
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var a = n.sons[i]
checkMinSonsLen(a, 1, c.c.config)
var L = sonsLen(a)
var L = len(a)
for j in 0 .. L-2:
a.sons[j] = semTemplBody(c, a.sons[j])
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
closeScope(c)
of nkForStmt, nkParForStmt:
var L = sonsLen(n)
var L = len(n)
openScope(c)
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
for i in 0 .. L - 3:
if n[i].kind == nkVarTuple:
for j in 0 ..< sonsLen(n[i])-1:
for j in 0 ..< len(n[i])-1:
addLocalDecl(c, n[i][j], skForVar)
else:
addLocalDecl(c, n.sons[i], skForVar)
@@ -404,10 +436,10 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
of nkTryStmt, nkHiddenTryStmt:
checkMinSonsLen(n, 2, c.c.config)
n.sons[0] = semTemplBodyScope(c, n.sons[0])
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var a = n.sons[i]
checkMinSonsLen(a, 1, c.c.config)
var L = sonsLen(a)
var L = len(a)
openScope(c)
for j in 0 .. L-2:
if a.sons[j].isInfixAs():
@@ -424,7 +456,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
n.sons[0] = semTemplBody(c, n.sons[0])
semTemplSomeDecl(c, n, skParam, 1)
of nkConstSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): illFormedAst(a, c.c.config)
@@ -433,13 +465,13 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
a.sons[1] = semTemplBody(c, a.sons[1])
a.sons[2] = semTemplBody(c, a.sons[2])
of nkTypeSection:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
checkSonsLen(a, 3, c.c.config)
addLocalDecl(c, a.sons[0], skType)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
@@ -524,12 +556,27 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
onUse(n.info, s)
return newSymNode(s, n.info)
elif contains(c.toBind, s.id):
return symChoice(c.c, n, s, scClosed)
return symChoice(c.c, n, s, scClosed, c.noGenSym > 0)
elif contains(c.toMixin, s.name.id):
return symChoice(c.c, n, s, scForceOpen)
return symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
else:
return symChoice(c.c, n, s, scOpen)
result = semTemplBodySons(c, n)
return symChoice(c.c, n, s, scOpen, c.noGenSym > 0)
if n.kind == nkDotExpr:
result = n
result.sons[0] = semTemplBody(c, n.sons[0])
if optNimV019 notin c.c.config.globalOptions: inc c.noGenSym
result.sons[1] = semTemplBody(c, n.sons[1])
if optNimV019 notin c.c.config.globalOptions: dec c.noGenSym
else:
result = semTemplBodySons(c, n)
of nkExprColonExpr, nkExprEqExpr:
if n.len == 2:
if optNimV019 notin c.c.config.globalOptions: inc c.noGenSym
result.sons[0] = semTemplBody(c, n.sons[0])
if optNimV019 notin c.c.config.globalOptions: dec c.noGenSym
result.sons[1] = semTemplBody(c, n.sons[1])
else:
result = semTemplBodySons(c, n)
else:
result = semTemplBodySons(c, n)
@@ -558,7 +605,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
if s != nil and contains(c.toBind, s.id):
return symChoice(c.c, n, s, scClosed)
result = n
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
proc semTemplateDef(c: PContext, n: PNode): PNode =
@@ -600,9 +647,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
# body by the absence of the sfGenSym flag:
for i in 1 .. s.typ.n.len-1:
let param = s.typ.n.sons[i].sym
param.flags.incl sfTemplateParam
param.flags.excl sfGenSym
if param.typ.kind != tyUntyped: allUntyped = false
if sonsLen(gp) > 0:
if len(gp) > 0:
if n.sons[genericParamsPos].kind == nkEmpty:
# we have a list of implicit type parameters:
n.sons[genericParamsPos] = gp
@@ -715,7 +763,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
if stupidStmtListExpr(n):
result = semPatternBody(c, n.lastSon)
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result.sons[i] = semPatternBody(c, n.sons[i])
of nkCallKinds:
let s = qualifiedLookUp(c.c, n.sons[0], {})
@@ -748,7 +796,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
result.sons[1] = semPatternBody(c, n.sons[1])
return
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result.sons[i] = semPatternBody(c, n.sons[i])
else:
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
@@ -764,7 +812,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
of nkPar:
if n.len == 1: return semPatternBody(c, n.sons[0])
else: discard
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result.sons[i] = semPatternBody(c, n.sons[i])
proc semPattern(c: PContext, n: PNode): PNode =

View File

@@ -10,6 +10,8 @@
# this module does the semantic checking of type declarations
# included from sem.nim
import math
const
errStringOrIdentNodeExpected = "string or ident node expected"
errStringLiteralExpected = "string literal expected"
@@ -52,8 +54,8 @@ proc newConstraint(c: PContext, k: TTypeKind): PType =
result.addSonSkipIntLit(newTypeS(k, c))
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if n.sonsLen == 0: return newConstraint(c, tyEnum)
elif n.sonsLen == 1:
if n.len == 0: return newConstraint(c, tyEnum)
elif n.len == 1:
# don't create an empty tyEnum; fixes #3052
return errorType(c)
var
@@ -69,13 +71,13 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
base = semTypeNode(c, n.sons[0].sons[0], nil)
if base.kind != tyEnum:
localError(c.config, n.sons[0].info, "inheritance only works with an enum")
counter = lastOrd(c.config, base) + 1
counter = toInt64(lastOrd(c.config, base)) + 1
rawAddSon(result, base)
let isPure = result.sym != nil and sfPure in result.sym.flags
var symbols: TStrTable
if isPure: initStrTable(symbols)
var hasNull = false
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if n.sons[i].kind == nkEmpty: continue
case n.sons[i].kind
of nkEnumFieldDef:
@@ -88,12 +90,12 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
var strVal: PNode = nil
case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind
of tyTuple:
if sonsLen(v) == 2:
if len(v) == 2:
strVal = v.sons[1] # second tuple part is the string value
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
if not isOrdinalType(v.sons[0].typ, allowEnumWithHoles=true):
localError(c.config, v.sons[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v.sons[0].typ, preferDesc))
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
x = toInt64(getOrdValue(v.sons[0])) # first tuple part is the ordinal
else:
localError(c.config, strVal.info, errStringLiteralExpected)
else:
@@ -104,7 +106,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
else:
if not isOrdinalType(v.typ, allowEnumWithHoles=true):
localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
x = getOrdValue(v)
x = toInt64(getOrdValue(v))
if i != 1:
if x != counter: incl(result.flags, tfEnumHasHoles)
if x < counter:
@@ -141,7 +143,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
proc semSet(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tySet, prev, c)
if sonsLen(n) == 2 and n.sons[1].kind != nkEmpty:
if len(n) == 2 and n.sons[1].kind != nkEmpty:
var base = semTypeNode(c, n.sons[1], nil)
addSonSkipIntLit(result, base)
if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
@@ -155,7 +157,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
addSonSkipIntLit(result, errorType(c))
proc semContainerArg(c: PContext; n: PNode, kindStr: string; result: PType) =
if sonsLen(n) == 2:
if len(n) == 2:
var base = semTypeNode(c, n.sons[1], nil)
if base.kind == tyVoid:
localError(c.config, n.info, errTIsNotAConcreteType % typeToString(base))
@@ -171,17 +173,17 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVarargs, prev, c)
if sonsLen(n) == 2 or sonsLen(n) == 3:
if len(n) == 2 or len(n) == 3:
var base = semTypeNode(c, n.sons[1], nil)
addSonSkipIntLit(result, base)
if sonsLen(n) == 3:
if len(n) == 3:
result.n = newIdentNode(considerQuotedIdent(c, n.sons[2]), n.sons[2].info)
else:
localError(c.config, n.info, errXExpectsOneTypeParam % "varargs")
addSonSkipIntLit(result, errorType(c))
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
if sonsLen(n) == 1:
if len(n) == 1:
result = newOrPrevType(tyVar, prev, c)
var base = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
if base.kind == tyVar:
@@ -223,7 +225,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
if not hasUnknownTypes:
if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})):
localError(c.config, n.info, "type mismatch")
elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128 or
elif not isOrdinalType(rangeT[0]) and rangeT[0].kind notin tyFloat..tyFloat128 or
rangeT[0].kind == tyBool:
localError(c.config, n.info, "ordinal or float type expected")
elif enumHasHoles(rangeT[0]):
@@ -236,6 +238,10 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
else:
result.n.addSon semConstExpr(c, range[i])
if (result.n[0].kind in {nkFloatLit..nkFloat64Lit} and classify(result.n[0].floatVal) == fcNan) or
(result.n[1].kind in {nkFloatLit..nkFloat64Lit} and classify(result.n[1].floatVal) == fcNan):
localError(c.config, n.info, "NaN is not a valid start or end for a range")
if weakLeValue(result.n[0], result.n[1]) == impNo:
localError(c.config, n.info, "range is empty")
@@ -243,7 +249,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
proc semRange(c: PContext, n: PNode, prev: PType): PType =
result = nil
if sonsLen(n) == 2:
if len(n) == 2:
if isRange(n[1]):
result = semRangeAux(c, n[1], prev)
let n = result.n
@@ -309,7 +315,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
proc semArray(c: PContext, n: PNode, prev: PType): PType =
var base: PType
if sonsLen(n) == 3:
if len(n) == 3:
# 3 = length(array indx base)
let indx = semArrayIndex(c, n[1])
var indxB = indx
@@ -335,7 +341,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyOrdinal, prev, c)
if sonsLen(n) == 2:
if len(n) == 2:
var base = semTypeNode(c, n.sons[1], nil)
if base.kind != tyGenericParam:
if not isOrdinalType(base):
@@ -353,7 +359,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
if result.isNil:
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
if result != nil:
markUsed(c.config, n.info, result, c.graph.usageSym)
markUsed(c, n.info, result)
onUse(n.info, result)
if result.kind == skParam and result.typ.kind == tyTypeDesc:
@@ -408,7 +414,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
result = errorSym(c, n)
proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
if sonsLen(n) == 0:
if len(n) == 0:
localError(c.config, n.info, errTypeExpected)
result = newOrPrevType(tyTuple, prev, c)
for it in n:
@@ -420,11 +426,11 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
result.n = newNodeI(nkRecList, n.info)
var check = initIntSet()
var counter = 0
for i in ord(n.kind == nkBracketExpr) ..< sonsLen(n):
for i in ord(n.kind == nkBracketExpr) ..< len(n):
var a = n.sons[i]
if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a)
var length = len(a)
if a.sons[length - 2].kind != nkEmpty:
typ = semTypeNode(c, a.sons[length - 2], nil)
else:
@@ -454,7 +460,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
allowed: TSymFlags): PSym =
# identifier with visibility
if n.kind == nkPostfix:
if sonsLen(n) == 2:
if len(n) == 2:
# for gensym'ed identifiers the identifier may already have been
# transformed to a symbol and we need to use that here:
result = newSymG(kind, n.sons[1], c)
@@ -491,7 +497,7 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
let ex = t[branchIndex][currentEx].skipConv
for i in 1 .. branchIndex:
for j in 0 .. sonsLen(t.sons[i]) - 2:
for j in 0 .. len(t.sons[i]) - 2:
if i == branchIndex and j == currentEx: break
if overlap(t.sons[i].sons[j].skipConv, ex):
localError(c.config, ex.info, errDuplicateCaseLabel)
@@ -507,7 +513,7 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var Int128): PNode =
result.add(at)
result.add(bt)
if emptyRange(ac, bc): localError(c.config, b.info, "range is empty")
else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
else: covered = covered + getOrdValue(bc) + 1 - getOrdValue(ac)
proc semCaseBranchRange(c: PContext, t, b: PNode,
covered: var Int128): PNode =
@@ -528,7 +534,7 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
covered: var Int128) =
let lastIndex = sonsLen(branch) - 2
let lastIndex = len(branch) - 2
for i in 0..lastIndex:
var b = branch.sons[i]
if b.kind == nkRange:
@@ -538,7 +544,7 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
else:
# constant sets and arrays are allowed:
var r = semConstExpr(c, b)
if r.kind in {nkCurly, nkBracket} and len(r) == 0 and sonsLen(branch)==2:
if r.kind in {nkCurly, nkBracket} and len(r) == 0 and len(branch)==2:
# discarding ``{}`` and ``[]`` branches silently
delSon(branch, 0)
return
@@ -564,13 +570,13 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
checkForOverlap(c, t, i, branchIndex)
# Elements added above needs to be checked for overlaps.
for i in lastIndex.succ..(sonsLen(branch) - 2):
for i in lastIndex.succ..(len(branch) - 2):
checkForOverlap(c, t, i, branchIndex)
proc toCover(c: PContext, t: PType): Int128 =
let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
if t2.kind == tyEnum and enumHasHoles(t2):
result = toInt128(sonsLen(t2.n))
result = toInt128(len(t2.n))
else:
# <----
let t = skipTypes(t, abstractVar-{tyTypeDesc})
@@ -582,7 +588,7 @@ proc toCover(c: PContext, t: PType): Int128 =
elif t.kind in {tyInt, tyUInt}:
result = toInt128(1) shl (c.config.target.intSize * 8)
else:
result = toInt128(lengthOrd(c.config, t))
result = lengthOrd(c.config, t)
proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
father: PNode, rectype: PType, hasCaseFields = false)
@@ -629,7 +635,13 @@ 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")
for i in 1 ..< sonsLen(n):
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)
case n.sons[i].kind
@@ -642,7 +654,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
localError(c.config, b.info, "invalid else, all cases are already covered")
chckCovered = false
else: illFormedAst(n, c.config)
delSon(b, sonsLen(b) - 1)
delSon(b, len(b) - 1)
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype, hasCaseFields = true)
if chckCovered and covered != toCover(c, a.sons[0].typ):
if a.sons[0].typ.kind == tyEnum:
@@ -658,7 +670,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
case n.kind
of nkRecWhen:
var branch: PNode = nil # the branch to take
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it == nil: illFormedAst(n, c.config)
var idx = 1
@@ -695,12 +707,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
of nkRecList:
# attempt to keep the nesting at a sane level:
var a = if father.kind == nkRecList: father else: copyNode(n)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
if a != father: addSon(father, a)
of nkIdentDefs:
checkMinSonsLen(n, 3, c.config)
var length = sonsLen(n)
var length = len(n)
var a: PNode
if father.kind != nkRecList and length>=4: a = newNodeI(nkRecList, n.info)
else: a = newNodeI(nkEmpty, n.info)
@@ -715,7 +727,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
propagateToOwner(rectype, typ)
var fieldOwner = if c.inGenericContext > 0: c.getCurrOwner
else: rectype.sym
for i in 0 .. sonsLen(n)-3:
for i in 0 .. len(n)-3:
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
suggestSym(c.config, n.sons[i].info, f, c.graph.usageSym)
f.typ = typ
@@ -750,13 +762,13 @@ proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
of nkRecCase:
if (n.sons[0].kind != nkSym): internalError(c.config, n.info, "addInheritedFieldsAux")
addInheritedFieldsAux(c, check, pos, n.sons[0])
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
addInheritedFieldsAux(c, check, pos, lastSon(n.sons[i]))
else: internalError(c.config, n.info, "addInheritedFieldsAux(record case branch)")
of nkRecList, nkRecWhen, nkElifBranch, nkElse:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
addInheritedFieldsAux(c, check, pos, n.sons[i])
of nkSym:
incl(check, n.sym.name.id)
@@ -773,12 +785,12 @@ proc skipGenericInvocation(t: PType): PType {.inline.} =
proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
obj: PType) =
assert obj.kind == tyObject
if (sonsLen(obj) > 0) and (obj.sons[0] != nil):
if (len(obj) > 0) and (obj.sons[0] != nil):
addInheritedFields(c, check, pos, obj.sons[0].skipGenericInvocation)
addInheritedFieldsAux(c, check, pos, obj.n)
proc semObjectNode(c: PContext, n: PNode, prev: PType; isInheritable: bool): PType =
if n.sonsLen == 0:
if n.len == 0:
return newConstraint(c, tyObject)
var check = initIntSet()
var pos = 0
@@ -844,6 +856,7 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
localError(c.config, n.info, "type '$1 void' is not allowed" % kindToStr[kind])
result = newOrPrevType(kind, prev, c)
var isNilable = false
var isOwned = false
# check every except the last is an object:
for i in isCall .. n.len-2:
let ni = n[i]
@@ -851,16 +864,24 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
isNilable = true
else:
let region = semTypeNode(c, ni, nil)
if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
if region.kind == tyOwned:
isOwned = true
elif region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
tyError, tyObject}:
message c.config, n[i].info, errGenerated, "region needs to be an object type"
addSonSkipIntLit(result, region)
else:
message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated")
addSonSkipIntLit(result, region)
addSonSkipIntLit(result, region)
addSonSkipIntLit(result, t)
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 optOwnedRefs in c.config.globalOptions:
let t = newTypeS(tyOwned, c)
t.flags.incl tfHasOwned
t.rawAddSonNoPropagationOfTypeFlags result
result = t
proc findEnforcedStaticType(t: PType): PType =
# This handles types such as `static[T] and Foo`,
@@ -899,63 +920,59 @@ template shouldHaveMeta(t) =
internalAssert c.config, tfHasMeta in t.flags
# result.lastSon.flags.incl tfHasMeta
proc addImplicitGeneric(c: PContext; typeClass: PType, typId: PIdent;
info: TLineInfo; genericParams: PNode;
paramName: string): PType =
if genericParams == nil:
# This happens with anonymous proc types appearing in signatures
# XXX: we need to lift these earlier
return
let finalTypId = if typId != nil: typId
else: getIdent(c.cache, paramName & ":type")
# is this a bindOnce type class already present in the param list?
for i in 0 ..< genericParams.len:
if genericParams.sons[i].sym.name.id == finalTypId.id:
return genericParams.sons[i].typ
let owner = if typeClass.sym != nil: typeClass.sym
else: getCurrOwner(c)
var s = newSym(skType, finalTypId, owner, info)
if sfExplain in owner.flags: s.flags.incl sfExplain
if typId == nil: s.flags.incl(sfAnon)
s.linkTo(typeClass)
typeClass.flags.incl tfImplicitTypeParam
s.position = genericParams.len
genericParams.addSon(newSymNode(s))
result = typeClass
addDecl(c, s)
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
paramType: PType, paramName: string,
info: TLineInfo, anon = false): PType =
if paramType == nil: return # (e.g. proc return type)
proc addImplicitGenericImpl(c: PContext; typeClass: PType, typId: PIdent): PType =
if genericParams == nil:
# This happens with anonymous proc types appearing in signatures
# XXX: we need to lift these earlier
return
let finalTypId = if typId != nil: typId
else: getIdent(c.cache, paramName & ":type")
# is this a bindOnce type class already present in the param list?
for i in 0 ..< genericParams.len:
if genericParams.sons[i].sym.name.id == finalTypId.id:
return genericParams.sons[i].typ
let owner = if typeClass.sym != nil: typeClass.sym
else: getCurrOwner(c)
var s = newSym(skType, finalTypId, owner, info)
if sfExplain in owner.flags: s.flags.incl sfExplain
if typId == nil: s.flags.incl(sfAnon)
s.linkTo(typeClass)
typeClass.flags.incl tfImplicitTypeParam
s.position = genericParams.len
genericParams.addSon(newSymNode(s))
result = typeClass
addDecl(c, s)
# XXX: There are codegen errors if this is turned into a nested proc
template liftingWalk(typ: PType, anonFlag = false): untyped =
template recurse(typ: PType, anonFlag = false): untyped =
liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
#proc liftingWalk(paramType: PType, anon = false): PType =
var paramTypId = if not anon and paramType.sym != nil: paramType.sym.name
else: nil
template maybeLift(typ: PType): untyped =
let lifted = liftingWalk(typ)
(if lifted != nil: lifted else: typ)
template addImplicitGeneric(e): untyped =
addImplicitGenericImpl(c, e, paramTypId)
case paramType.kind:
of tyAnything:
result = addImplicitGenericImpl(c, newTypeS(tyGenericParam, c), nil)
result = addImplicitGeneric(c, newTypeS(tyGenericParam, c), nil, info, genericParams, paramName)
of tyStatic:
if paramType.base.kind != tyNone and paramType.n != nil:
# this is a concrete static value
return
if tfUnresolved in paramType.flags: return # already lifted
let base = paramType.base.maybeLift
let lifted = recurse(paramType.base)
let base = (if lifted != nil: lifted else: paramType.base)
if base.isMetaType and procKind == skMacro:
localError(c.config, info, errMacroBodyDependsOnGenericTypes % paramName)
result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
result = addImplicitGeneric(c, c.newTypeWithSons(tyStatic, @[base]),
paramTypId, info, genericParams, paramName)
if result != nil: result.flags.incl({tfHasStatic, tfUnresolved})
of tyTypeDesc:
@@ -968,15 +985,15 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
paramTypId = nil
let t = c.newTypeWithSons(tyTypeDesc, @[paramType.base])
incl t.flags, tfCheckedForDestructor
result = addImplicitGeneric(t)
result = addImplicitGeneric(c, t, paramTypId, info, genericParams, paramName)
of tyDistinct:
if paramType.sonsLen == 1:
if paramType.len == 1:
# disable the bindOnce behavior for the type class
result = liftingWalk(paramType.base, true)
result = recurse(paramType.base, true)
of tyAlias, tyOwned:
result = liftingWalk(paramType.base)
result = recurse(paramType.base)
of tySequence, tySet, tyArray, tyOpenArray,
tyVar, tyLent, tyPtr, tyRef, tyProc:
@@ -989,12 +1006,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
let typ = c.newTypeWithSons(tyBuiltInTypeClass,
@[newTypeS(paramType.kind, c)])
result = addImplicitGeneric(typ)
result = addImplicitGeneric(c, typ, paramTypId, info, genericParams, paramName)
else:
for i in 0 ..< paramType.len:
if paramType.sons[i] == paramType:
globalError(c.config, info, errIllegalRecursionInTypeX % typeToString(paramType))
var lifted = liftingWalk(paramType.sons[i])
var lifted = recurse(paramType.sons[i])
if lifted != nil:
paramType.sons[i] = lifted
result = paramType
@@ -1003,7 +1020,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = newTypeS(tyGenericInvocation, c)
result.rawAddSon(paramType)
for i in 0 .. paramType.sonsLen - 2:
for i in 0 .. paramType.len - 2:
if paramType.sons[i].kind == tyStatic:
var staticCopy = paramType.sons[i].exactReplica
staticCopy.flags.incl tfInferrableStatic
@@ -1014,29 +1031,29 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if paramType.lastSon.kind == tyUserTypeClass:
result.kind = tyUserTypeClassInst
result.rawAddSon paramType.lastSon
return addImplicitGeneric(result)
return addImplicitGeneric(c, result, paramTypId, info, genericParams, paramName)
let x = instGenericContainer(c, paramType.sym.info, result,
allowMetaTypes = true)
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, x])
#result = newTypeS(tyCompositeTypeClass, c)
#for i in 0..<x.len: result.rawAddSon(x.sons[i])
result = addImplicitGeneric(result)
result = addImplicitGeneric(c, result, paramTypId, info, genericParams, paramName)
of tyGenericInst:
if paramType.lastSon.kind == tyUserTypeClass:
var cp = copyType(paramType, getCurrOwner(c), false)
cp.kind = tyUserTypeClassInst
return addImplicitGeneric(cp)
return addImplicitGeneric(c, cp, paramTypId, info, genericParams, paramName)
for i in 1 .. paramType.len-2:
var lifted = liftingWalk(paramType.sons[i])
var lifted = recurse(paramType.sons[i])
if lifted != nil:
paramType.sons[i] = lifted
result = paramType
result.lastSon.shouldHaveMeta
let liftBody = liftingWalk(paramType.lastSon, true)
let liftBody = recurse(paramType.lastSon, true)
if liftBody != nil:
result = liftBody
result.flags.incl tfHasMeta
@@ -1044,7 +1061,8 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyGenericInvocation:
for i in 1 ..< paramType.len:
let lifted = liftingWalk(paramType.sons[i])
#if paramType[i].kind != tyTypeDesc:
let lifted = recurse(paramType.sons[i])
if lifted != nil: paramType.sons[i] = lifted
let body = paramType.base
@@ -1056,14 +1074,16 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if body.lastSon.kind == tyUserTypeClass:
let expanded = instGenericContainer(c, info, paramType,
allowMetaTypes = true)
result = liftingWalk(expanded, true)
result = recurse(expanded, true)
of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass,
tyAnd, tyOr, tyNot:
result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), false))
result = addImplicitGeneric(c,
copyType(paramType, getCurrOwner(c), false), paramTypId,
info, genericParams, paramName)
of tyGenericParam:
markUsed(c.config, paramType.sym.info, paramType.sym, c.graph.usageSym)
markUsed(c, paramType.sym.info, paramType.sym)
onUse(paramType.sym.info, paramType.sym)
if tfWildcard in paramType.flags:
paramType.flags.excl tfWildcard
@@ -1071,8 +1091,6 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
else: discard
# result = liftingWalk(paramType)
proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
if n.kind == nkCurlyExpr:
result = semTypeNode(c, n.sons[0], nil)
@@ -1119,7 +1137,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
typ: PType = nil
def: PNode = nil
constraint: PNode = nil
length = sonsLen(a)
length = len(a)
hasType = a.sons[length-2].kind != nkEmpty
hasDefault = a.sons[length-1].kind != nkEmpty
@@ -1230,6 +1248,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
# 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
# compiler is hardly aware of 'auto':
r = newTypeS(tyUntyped, c)
elif r.kind == tyStatic:
# type allowed should forbid this type
discard
else:
if r.sym == nil or sfAnon notin r.sym.flags:
let lifted = liftParamType(c, kind, genericParams, r, "result",
@@ -1266,7 +1287,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
checkMinSonsLen(n, 1, c.config)
var length = sonsLen(n)
var length = len(n)
for i in 0 .. length - 2:
n.sons[i] = semStmt(c, n.sons[i], {})
if length > 0:
@@ -1331,7 +1352,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
else: addSonSkipIntLit(result, typ)
if t.kind == tyForward:
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
var elem = semGenericParamInInvocation(c, n.sons[i])
addToResult(elem)
return
@@ -1356,7 +1377,10 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
for i in 1 ..< m.call.len:
var typ = m.call[i].typ
if typ.kind == tyTypeDesc and typ.sons[0].kind == tyNone:
# is this a 'typedesc' *parameter*? If so, use the typedesc type,
# unstripped.
if m.call[i].kind == nkSym and m.call[i].sym.kind == skParam and
typ.kind == tyTypeDesc and containsGenericType(typ):
isConcrete = false
addToResult(typ)
else:
@@ -1440,7 +1464,7 @@ template modifierTypeKindOfNode(n: PNode): TTypeKind =
else: tyNone
proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
# if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
# if n.len == 0: return newConstraint(c, tyTypeClass)
let
pragmas = n[1]
inherited = n[2]
@@ -1551,7 +1575,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semTypeof(c, n.sons[0], prev)
if result.kind == tyTypeDesc: result.flags.incl tfExplicit
of nkPar:
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
if len(n) == 1: result = semTypeNode(c, n.sons[0], prev)
else:
result = semAnonTuple(c, n, prev)
of nkTupleConstr: result = semAnonTuple(c, n, prev)
@@ -1620,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:
@@ -1644,7 +1668,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mSet: result = semSet(c, n, prev)
of mOrdinal: result = semOrdinal(c, n, prev)
of mSeq:
if c.config.selectedGC == gcDestructors and optNimV2 notin c.config.globalOptions:
if false: # c.config.selectedGC == gcDestructors and optNimV2 notin c.config.globalOptions:
let s = c.graph.sysTypes[tySequence]
assert s != nil
assert prev == nil
@@ -1751,7 +1775,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else:
assignType(prev, t)
result = prev
markUsed(c.config, n.info, n.sym, c.graph.usageSym)
markUsed(c, n.info, n.sym)
onUse(n.info, n.sym)
else:
if s.kind != skError:
@@ -1768,7 +1792,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkDistinctTy: result = semDistinct(c, n, prev)
of nkStaticTy: result = semStaticType(c, n[0], prev)
of nkIteratorTy:
if n.sonsLen == 0:
if n.len == 0:
result = newTypeS(tyBuiltInTypeClass, c)
let child = newTypeS(tyProc, c)
child.flags.incl tfIterator
@@ -1781,7 +1805,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else:
result.callConv = ccClosure
of nkProcTy:
if n.sonsLen == 0:
if n.len == 0:
result = newConstraint(c, tyProc)
else:
result = semProcTypeWithScope(c, n, prev, skProc)
@@ -1790,7 +1814,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkStmtListType: result = semStmtListType(c, n, prev)
of nkBlockType: result = semBlockType(c, n, prev)
else:
localError(c.config, n.info, errTypeExpected)
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
result = newOrPrevType(tyError, prev, c)
n.typ = result
dec c.inTypeContext
@@ -1810,13 +1834,8 @@ proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
# FIXME: proper support for clongdouble should be added.
# long double size can be 8, 10, 12, 16 bytes depending on platform & compiler
if conf.target.targetCPU == cpuI386 and size == 8:
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
if conf.target.targetOS != osWindows:
if kind in {tyFloat64, tyFloat, tyInt, tyUInt, tyInt64, tyUInt64}:
# on i386 for all known POSIX systems, 64bits ints are aligned
# to 4bytes (except with -malign-double)
m.typ.align = 4
if kind in {tyFloat64, tyFloat, tyInt, tyUInt, tyInt64, tyUInt64} and size == 8:
m.typ.align = int16(conf.floatInt64Align)
proc setMagicIntegral(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
setMagicType(conf, m, kind, size)
@@ -1915,7 +1934,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
if n.kind != nkGenericParams:
illFormedAst(n, c.config)
return
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var a = n.sons[i]
if a.kind != nkIdentDefs: illFormedAst(n, c.config)
let L = a.len

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
@@ -169,7 +169,7 @@ proc replaceObjBranches(cl: TReplTypeVars, n: PNode): PNode =
discard
of nkRecWhen:
var branch: PNode = nil # the branch to take
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it == nil: illFormedAst(n, cl.c.config)
case it.kind
@@ -189,7 +189,7 @@ proc replaceObjBranches(cl: TReplTypeVars, n: PNode): PNode =
else:
result = newNodeI(nkRecList, n.info)
else:
for i in 0..<n.sonsLen:
for i in 0..<n.len:
n.sons[i] = replaceObjBranches(cl, n.sons[i])
proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
@@ -209,7 +209,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
result = newNode(nkRecList, n.info)
of nkRecWhen:
var branch: PNode = nil # the branch to take
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var it = n.sons[i]
if it == nil: illFormedAst(n, cl.c.config)
case it.kind
@@ -234,7 +234,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
result = if cl.allowMetaTypes: n
else: cl.c.semExpr(cl.c, n)
else:
var length = sonsLen(n)
var length = len(n)
if length > 0:
newSons(result, length)
if start > 0:
@@ -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).
@@ -260,12 +260,32 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
#result = PSym(idTableGet(cl.symMap, s))
#if result == nil:
#[
We cannot naively check for symbol recursions, because otherwise
object types A, B whould share their fields!
import tables
type
Table[S, T] = object
x: S
y: T
G[T] = object
inodes: Table[int, T] # A
rnodes: Table[T, int] # B
var g: G[string]
]#
result = copySym(s)
incl(result.flags, sfFromGeneric)
#idTablePut(cl.symMap, s, result)
result.owner = s.owner
result.typ = replaceTypeVarsT(cl, s.typ)
result.ast = replaceTypeVarsN(cl, s.ast)
if result.kind != skType:
result.ast = replaceTypeVarsN(cl, s.ast)
proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
result = cl.typeMap.lookup(t)
@@ -311,7 +331,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
when defined(reportCacheHits):
echo "Generic instantiation cached ", typeToString(result), " for ", typeToString(t)
return
for i in 1 ..< sonsLen(t):
for i in 1 ..< len(t):
var x = t.sons[i]
if x.kind in {tyGenericParam}:
x = lookupTypeVar(cl, x)
@@ -351,14 +371,14 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
var typeMapLayer = newTypeMapLayer(cl)
cl.typeMap = addr(typeMapLayer)
for i in 1 ..< sonsLen(t):
for i in 1 ..< len(t):
var x = replaceTypeVarsT(cl, t.sons[i])
assert x.kind != tyGenericInvocation
header.sons[i] = x
propagateToOwner(header, x)
cl.typeMap.put(body.sons[i-1], x)
for i in 1 ..< sonsLen(t):
for i in 1 ..< len(t):
# if one of the params is not concrete, we cannot do anything
# but we already raised an error!
rawAddSon(result, header.sons[i])
@@ -426,11 +446,11 @@ proc eraseVoidParams*(t: PType) =
if t.sons[0] != nil and t.sons[0].kind == tyVoid:
t.sons[0] = nil
for i in 1 ..< t.sonsLen:
for i in 1 ..< t.len:
# don't touch any memory unless necessary
if t.sons[i].kind == tyVoid:
var pos = i
for j in i+1 ..< t.sonsLen:
for j in i+1 ..< t.len:
if t.sons[j].kind != tyVoid:
t.sons[pos] = t.sons[j]
t.n.sons[pos] = t.n.sons[j]
@@ -440,7 +460,7 @@ proc eraseVoidParams*(t: PType) =
break
proc skipIntLiteralParams*(t: PType) =
for i in 0 ..< t.sonsLen:
for i in 0 ..< t.len:
let p = t.sons[i]
if p == nil: continue
let skipped = p.skipIntLit
@@ -553,7 +573,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
bailout()
result = instCopyType(cl, t)
idTablePut(cl.localCache, t, result)
for i in 1 ..< result.sonsLen:
for i in 1 ..< result.len:
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
propagateToOwner(result, result.lastSon)
@@ -566,10 +586,10 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
#if not cl.allowMetaTypes:
idTablePut(cl.localCache, t, result)
for i in 0 ..< sonsLen(result):
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: '" &
@@ -597,20 +617,6 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
eraseVoidParams(result)
skipIntLiteralParams(result)
of tySequence:
if cl.isReturnType and cl.c.config.selectedGC == gcDestructors and
result.attachedOps[attachedDestructor].isNil and
result[0].kind != tyEmpty and optNimV2 notin cl.c.config.globalOptions:
let s = cl.c.graph.sysTypes[tySequence]
var old = copyType(s, s.owner, keepId=false)
# Remove the 'T' parameter from tySequence:
old.sons.setLen 0
old.n = nil
old.flags = {tfHasAsgn}
old.addSonSkipIntLit result[0]
result.attachedOps = old.attachedOps
cl.c.typesWithOps.add((result, old))
else: discard
else:
# If this type doesn't refer to a generic type we may still want to run it
@@ -673,10 +679,10 @@ proc recomputeFieldPositions*(t: PType; obj: PNode; currPosition: var int) =
recomputeFieldPositions(b, b.n, currPosition)
case obj.kind
of nkRecList:
for i in 0 ..< sonsLen(obj): recomputeFieldPositions(nil, obj.sons[i], currPosition)
for i in 0 ..< len(obj): recomputeFieldPositions(nil, obj.sons[i], currPosition)
of nkRecCase:
recomputeFieldPositions(nil, obj.sons[0], currPosition)
for i in 1 ..< sonsLen(obj):
for i in 1 ..< len(obj):
recomputeFieldPositions(nil, lastSon(obj.sons[i]), currPosition)
of nkSym:
obj.sym.position = currPosition
@@ -685,6 +691,10 @@ proc recomputeFieldPositions*(t: PType; obj: PNode; currPosition: var int) =
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType =
# Given `t` like Foo[T]
# pt: Table with type mappings: T -> int
# Desired result: Foo[int]
# proc (x: T = 0); T -> int ----> proc (x: int = 0)
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), info, nil)
pushInfoContext(p.config, info)

View File

@@ -93,7 +93,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
case t.kind
of tyGenericInvocation:
for i in 0 ..< sonsLen(t):
for i in 0 ..< len(t):
c.hashType t.sons[i], flags
of tyDistinct:
if CoDistinct in flags:
@@ -180,15 +180,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
of tyTuple:
c &= char(t.kind)
if t.n != nil and CoType notin flags:
assert(sonsLen(t.n) == sonsLen(t))
for i in 0 ..< sonsLen(t.n):
assert(len(t.n) == len(t))
for i in 0 ..< len(t.n):
assert(t.n.sons[i].kind == nkSym)
c &= t.n.sons[i].sym.name.s
c &= ':'
c.hashType(t.sons[i], flags+{CoIgnoreRange})
c &= ','
else:
for i in 0 ..< sonsLen(t): c.hashType t.sons[i], flags+{CoIgnoreRange}
for i in 0 ..< len(t): c.hashType t.sons[i], flags+{CoIgnoreRange}
of tyRange:
if CoIgnoreRange notin flags:
c &= char(t.kind)

View File

@@ -21,7 +21,7 @@ when (defined(booting) or defined(nimsuggest)) and not defined(leanCompiler):
type
MismatchKind* = enum
kUnknown, kAlreadyGiven, kUnknownNamedParam, kTypeMismatch, kVarNeeded,
kMissingParam, kExtraArg
kMissingParam, kExtraArg, kPositionalAlreadyGiven
MismatchInfo* = object
kind*: MismatchKind # reason for mismatch
@@ -107,7 +107,8 @@ type
const
isNilConversion = isConvertible # maybe 'isIntConv' fits better?
proc markUsed*(conf: ConfigRef; info: TLineInfo, s: PSym; usageSym: var PSym)
proc markUsed*(c: PContext; info: TLineInfo, s: PSym)
proc markOwnerModuleAsUsed*(c: PContext; s: PSym)
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
@@ -133,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
@@ -166,7 +170,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
initIdTable(c.bindings)
if binding != nil and callee.kind in routineKinds:
var typeParams = callee.ast[genericParamsPos]
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
for i in 1..min(len(typeParams), len(binding)-1):
var formalTypeParam = typeParams.sons[i-1].typ
var bound = binding[i].typ
if bound != nil:
@@ -333,7 +337,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
n.sons[i] = arg
if arg.typ != nil and arg.typ.kind == tyError: return
add(result, argTypeToString(arg, prefer))
if i != sonsLen(n) - 1: add(result, ", ")
if i != len(n) - 1: add(result, ", ")
proc typeRel*(c: var TCandidate, f, aOrig: PType,
flags: TTypeRelFlags = {}): TTypeRelation
@@ -377,10 +381,10 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
if k == f.kind: result = isSubrange
elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
tyUInt..tyUInt64} and
isIntLit(ab) and ab.n.intVal >= firstOrd(nil, f) and
ab.n.intVal <= lastOrd(nil, f):
isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
getInt(ab.n) <= lastOrd(nil, f):
# passing 'nil' to firstOrd/lastOrd here as type checking rules should
# not depent on the target integer size configurations!
# not depend on the target integer size configurations!
# integer literal in the proper range; we want ``i16 + 4`` to stay an
# ``int16`` operation so we declare the ``4`` pseudo-equal to int16
result = isFromIntLit
@@ -396,27 +400,30 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
f.kind in {tyUInt8..tyUInt32} and a[0].kind in {tyUInt8..tyInt32}) and
a.n[0].intVal >= firstOrd(nil, f) and a.n[1].intVal <= lastOrd(nil, f):
# passing 'nil' to firstOrd/lastOrd here as type checking rules should
# not depent on the target integer size configurations!
# not depend on the target integer size configurations!
result = isConvertible
else: result = isNone
proc isConvertibleToRange(f, a: PType): bool =
# be less picky for tyRange, as that it is used for array indexing:
if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
case f.kind
of tyInt, tyInt64: result = true
of tyInt8: result = a.kind in {tyInt8, tyInt}
of tyInt16: result = a.kind in {tyInt8, tyInt16, tyInt}
of tyInt32: result = a.kind in {tyInt8, tyInt16, tyInt32, tyInt}
of tyUInt, tyUInt64: result = true
of tyUInt8: result = a.kind in {tyUInt8, tyUInt}
of tyUInt16: result = a.kind in {tyUInt8, tyUInt16, tyUInt}
of tyUInt32: result = a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
of tyInt8: result = isIntLit(a) or a.kind in {tyInt8}
of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
# This is wrong, but seems like there's a lot of code that relies on it :(
of tyInt, tyUInt, tyUInt64: result = true
of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
#of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
#of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64}
else: result = false
elif f.kind in {tyFloat..tyFloat128} and
a.kind in {tyFloat..tyFloat128}:
result = true
elif f.kind in {tyFloat..tyFloat128}:
# `isIntLit` is correct and should be used above as well, see PR:
# https://github.com/nim-lang/Nim/pull/11197
result = isIntLit(a) or a.kind in {tyFloat..tyFloat128}
proc handleFloatRange(f, a: PType): TTypeRelation =
if a.kind == f.kind:
@@ -436,7 +443,7 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
if fGenericOrigin != nil and last.kind == tyGenericInst and
last.len-1 == fGenericOrigin.len:
for i in 1 ..< sonsLen(fGenericOrigin):
for i in 1 ..< len(fGenericOrigin):
let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
if x == nil:
put(c, fGenericOrigin.sons[i], last.sons[i])
@@ -514,16 +521,16 @@ proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
result = isNone
if sameType(f, a):
result = isEqual
elif sonsLen(a) == sonsLen(f):
elif len(a) == len(f):
result = isEqual
let firstField = if f.kind == tyTuple: 0
else: 1
for i in firstField ..< sonsLen(f):
for i in firstField ..< len(f):
var m = typeRel(c, f.sons[i], a.sons[i])
if m < isSubtype: return isNone
result = minRel(result, m)
if f.n != nil and a.n != nil:
for i in 0 ..< sonsLen(f.n):
for i in 0 ..< len(f.n):
# check field names:
if f.n.sons[i].kind != nkSym: return isNone
elif a.n.sons[i].kind != nkSym: return isNone
@@ -603,7 +610,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
case a.kind
of tyProc:
if sonsLen(f) != sonsLen(a): return
if len(f) != len(a): return
result = isEqual # start with maximum; also correct for no
# params at all
@@ -613,7 +620,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
# Note: We have to do unification for the parameters before the
# return type!
for i in 1 ..< f.sonsLen:
for i in 1 ..< f.len:
checkParam(f.sons[i], a.sons[i])
if f.sons[0] != nil:
@@ -873,7 +880,7 @@ proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool =
of mUnaryMinusI:
return inferStaticParam(c, lhs[1], -rhs)
of mUnaryPlusI, mToInt, mToBiggestInt:
of mUnaryPlusI:
return inferStaticParam(c, lhs[1], rhs)
else: discard
@@ -902,10 +909,10 @@ proc inferStaticsInRange(c: var TCandidate,
allowUnresolved = true)
let upperBound = tryResolvingStaticExpr(c, inferred.n[1],
allowUnresolved = true)
template doInferStatic(e: PNode, r: BiggestInt) =
template doInferStatic(e: PNode, r: Int128) =
var exp = e
var rhs = r
if inferStaticParam(c, exp, rhs):
if inferStaticParam(c, exp, toInt64(rhs)):
return isGeneric
else:
failureToInferStaticParam(c.c.config, exp)
@@ -918,7 +925,7 @@ proc inferStaticsInRange(c: var TCandidate,
return isNone
doInferStatic(upperBound, lengthOrd(c.c.config, concrete) + lowerBound.intVal - 1)
elif upperBound.kind == nkIntLit:
doInferStatic(lowerBound, upperBound.intVal + 1 - lengthOrd(c.c.config, concrete))
doInferStatic(lowerBound, getInt(upperBound) + 1 - lengthOrd(c.c.config, concrete))
template subtypeCheck() =
if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in {
@@ -939,7 +946,7 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
of tyGenericInst:
let body = f.base
return body == a.base and
a.sonsLen == 3 and
a.len == 3 and
tfWeakCovariant notin body.sons[0].flags and
baseTypesCheck(f.sons[1], a.sons[1])
else:
@@ -1412,7 +1419,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# YYYY
result = isEqual
for i in 1 .. rootf.sonsLen-2:
for i in 1 .. rootf.len-2:
let ff = rootf.sons[i]
let aa = roota.sons[i]
let res = typeRel(c, ff, aa, nextFlags)
@@ -1493,8 +1500,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# simply no match for now:
discard
elif x.kind == tyGenericInst and f.sons[0] == x.sons[0] and
sonsLen(x) - 1 == sonsLen(f):
for i in 1 ..< sonsLen(f):
len(x) - 1 == len(f):
for i in 1 ..< len(f):
if x.sons[i].kind == tyGenericParam:
internalError(c.c.graph.config, "wrong instantiated type!")
elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype:
@@ -1502,7 +1509,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if f.sons[i].kind != tyTypeDesc: return
result = isGeneric
elif x.kind == tyGenericInst and isGenericSubtype(c, x, f, depth, f) and
(sonsLen(x) - 1 == sonsLen(f)):
(len(x) - 1 == len(f)):
# do not recurse here in order to not K bind twice for this code:
#
# type
@@ -1534,7 +1541,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# var it1 = internalFind(root, 312) # cannot instantiate: 'D'
#
# we steal the generic parameters from the tyGenericBody:
for i in 1 ..< sonsLen(f):
for i in 1 ..< len(f):
let x = PType(idTableGet(c.bindings, genericBody.sons[i-1]))
if x == nil:
discard "maybe fine (for eg. a==tyNil)"
@@ -1639,7 +1646,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let roota = a.skipGenericAlias
let rootf = f.lastSon.skipGenericAlias
if a.kind == tyGenericInst and roota.base == rootf.base:
for i in 1 .. rootf.sonsLen-2:
for i in 1 .. rootf.len-2:
let ff = rootf.sons[i]
let aa = roota.sons[i]
result = typeRel(c, ff, aa)
@@ -1654,8 +1661,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyGenericParam:
var x = PType(idTableGet(c.bindings, f))
if x == nil:
if c.callee.kind == tyGenericBody and
f.kind == tyGenericParam and not c.typedescMatched:
if c.callee.kind == tyGenericBody and not c.typedescMatched:
# XXX: The fact that generic types currently use tyGenericParam for
# their parameters is really a misnomer. tyGenericParam means "match
# any value" and what we need is "match any type", which can be encoded
@@ -1664,7 +1670,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if tfWildcard in a.flags:
result = isGeneric
elif a.kind == tyTypeDesc:
if f.sonsLen == 0:
if f.len == 0:
result = isGeneric
else:
internalAssert c.c.graph.config, a.len > 0
@@ -1686,7 +1692,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = isNone
else:
# check if 'T' has a constraint as in 'proc p[T: Constraint](x: T)'
if f.sonsLen > 0 and f.sons[0].kind != tyNone:
if f.len > 0 and f.sons[0].kind != tyNone:
let oldInheritancePenalty = c.inheritancePenalty
result = typeRel(c, f.sons[0], a, flags + {trDontBind})
if doBind and result notin {isNone, isGeneric}:
@@ -1700,6 +1706,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
c.inheritancePenalty = oldInheritancePenalty - c.inheritancePenalty -
100 * ord(result == isEqual)
result = isGeneric
elif a.kind == tyTypeDesc:
# somewhat special typing rule, the following is illegal:
# proc p[T](x: T)
# p(int)
result = isNone
else:
result = isGeneric
@@ -1889,7 +1900,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
dest = generateTypeInstance(c, m.bindings, arg, dest)
let fdest = typeRel(m, f, dest)
if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind == tyVar):
markUsed(c.config, arg.info, c.converters[i], c.graph.usageSym)
markUsed(c, arg.info, c.converters[i])
var s = newSymNode(c.converters[i])
s.typ = c.converters[i].typ
s.info = arg.info
@@ -2218,7 +2229,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
else: result = nil
else:
# only one valid interpretation found:
markUsed(m.c.config, arg.info, arg.sons[best].sym, m.c.graph.usageSym)
markUsed(m.c, arg.info, arg.sons[best].sym)
onUse(arg.info, arg.sons[best].sym)
result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
argOrig)
@@ -2294,7 +2305,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
arg: PNode # current prepared argument
formal: PSym # current routine parameter
defer:
template noMatch() =
m.state = csNoMatch
m.firstMismatch.arg = a
m.firstMismatch.formal = formal
@@ -2304,19 +2316,19 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
# better match over other routines with no such restriction:
inc(m.genericMatches, 100)
else:
m.state = csNoMatch
noMatch()
return
if formal.typ.kind == tyVar:
let argConverter = if arg.kind == nkHiddenDeref: arg[0] else: arg
if argConverter.kind == nkHiddenCallConv:
if argConverter.typ.kind != tyVar:
m.state = csNoMatch
m.firstMismatch.kind = kVarNeeded
noMatch()
return
elif not n.isLValue:
m.state = csNoMatch
m.firstMismatch.kind = kVarNeeded
noMatch()
return
m.state = csMatch # until proven otherwise
@@ -2352,12 +2364,12 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
prepareNamedParam(n.sons[a], c)
if n.sons[a].sons[0].kind != nkIdent:
localError(c.config, n.sons[a].info, "named parameter has to be an identifier")
m.state = csNoMatch
noMatch()
return
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
formal = getNamedParamFromList(m.callee.n, n.sons[a].sons[0].ident)
if formal == nil:
# no error message!
m.state = csNoMatch
noMatch()
return
if containsOrIncl(marker, formal.position):
m.firstMismatch.kind = kAlreadyGiven
@@ -2366,7 +2378,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
# bug #3836 of why that is not sound (other overload with
# different parameter names could match later on):
when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch
noMatch()
return
m.baseTypeMatch = false
m.typedescMatched = false
@@ -2376,7 +2388,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
n.sons[a].sons[1], n.sons[a].sons[1])
m.firstMismatch.kind = kTypeMismatch
if arg == nil:
m.state = csNoMatch
noMatch()
return
checkConstraint(n.sons[a].sons[1])
if m.baseTypeMatch:
@@ -2417,23 +2429,24 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
incrIndexType(container.typ)
checkConstraint(n.sons[a])
else:
m.state = csNoMatch
noMatch()
return
else:
m.firstMismatch.kind = kExtraArg
m.state = csNoMatch
noMatch()
return
else:
if m.callee.n.sons[f].kind != nkSym:
internalError(c.config, n.sons[a].info, "matches")
noMatch()
return
formal = m.callee.n.sons[f].sym
m.firstMismatch.kind = kTypeMismatch
if containsOrIncl(marker, formal.position) and container.isNil:
m.firstMismatch.kind = kAlreadyGiven
# already in namedParams: (see above remark)
m.firstMismatch.kind = kPositionalAlreadyGiven
# positional param already in namedParams: (see above remark)
when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch
noMatch()
return
if formal.typ.isVarargsUntyped:
@@ -2450,7 +2463,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
n.sons[a], nOrig.sons[a])
if arg == nil:
m.state = csNoMatch
noMatch()
return
if m.baseTypeMatch:
assert formal.typ.kind == tyVarargs
@@ -2479,10 +2492,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
# this assertion can be off
localError(c.config, n.sons[a].info, "cannot convert $1 to $2" % [
typeToString(n.sons[a].typ), typeToString(formal.typ) ])
m.state = csNoMatch
noMatch()
return
checkConstraint(n.sons[a])
inc(a)
# for some edge cases (see tdont_return_unowned_from_owned test case)
m.firstMismatch.arg = a
m.firstMismatch.formal = formal
proc semFinishOperands*(c: PContext, n: PNode) =
# this needs to be called to ensure that after overloading resolution every
@@ -2510,7 +2526,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
if m.state == csNoMatch: return
# check that every formal parameter got a value:
var f = 1
while f < sonsLen(m.callee.n):
while f < len(m.callee.n):
var formal = m.callee.n.sons[f].sym
if not containsOrIncl(marker, formal.position):
if formal.ast == nil:
@@ -2538,18 +2554,23 @@ 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:
for t in m.inferredTypes:
if t.sonsLen > 1: t.sons.setLen 1
if t.len > 1: t.sons.setLen 1
proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
var m: TCandidate

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