Compare commits

...

1603 Commits

Author SHA1 Message Date
narimiran
dde13f38c9 revert adding a test, should have been part of 00cd7b8ca backport 2020-10-26 11:22:09 +01:00
Jason Beetham
fabbb7ea3e Fixed iteration limit hit from execproc (#15723) [backport:1.2] [backport:1.4]
When calling procs from Nim in Nimscript you could hit the VM iteration limit even though the code is functioning properly. This resolves that by making the iteration limit reset eachtime you call a proc.

(cherry picked from commit a87617956f)
2020-10-26 11:14:55 +01:00
Danil Yarantsev
76971596ad Add support to the latest LibreSSL version (#15715) [backport:1.2] [backport:1.4]
(cherry picked from commit b2740f5c63)
2020-10-26 11:14:49 +01:00
Timothee Cour
d777a8f86c fix #15704 #15597 wrong VM register was freed (#15705)
(cherry picked from commit d4c2e2c53f)
2020-10-26 10:29:54 +01:00
Clyybber
00cd7b8ca4 Revert "fixes #15280 [backport:1.2] (#15281)" (#15700)
This reverts commit 3f00a738db.

(cherry picked from commit d4022ebe53)
2020-10-24 17:18:44 +02:00
narimiran
714fd81199 remove tests that shouldn't have been backported in previous commit 2020-10-15 14:00:15 +02:00
Andreas Rumpf
59b5bdc2c6 renamed '=' to '=copy' [backport:1.2] (#15585)
(cherry picked from commit da4aa2e1fb)
2020-10-15 13:32:25 +02:00
Igor Ribeiro de Assis
4642a3485c Fix crash in parsexml (#15582) (#15583)
Co-authored-by: Igor Ribeiro de Assis <igor.ribeiro_de_assis@zeiss.com>
(cherry picked from commit 42c180c665)
2020-10-15 13:27:46 +02:00
genotrance
58d711ec57 Bump nimble (#15573)
(cherry picked from commit a4c28394be)
2020-10-15 13:27:29 +02:00
narimiran
8f3f264160 bump NimVersion to 1.2.8 2020-10-14 11:01:02 +02:00
Andreas Rumpf
2ce9352285 sigmatch: hotfix [backport] (#15565)
(cherry picked from commit c664fb2843)
2020-10-14 11:00:47 +02:00
alaviss
825f358c8b terminal: fix fgColor/bgColor commands [backport] (#15554)
Since #8296, fgSetColor is no longer a global. These commands were
probably left out from the change as an oversight, so some tests have
been added to make sure this won't happen again.

(cherry picked from commit d1af9587b8)
2020-10-13 21:21:52 +02:00
Christopher Dunn
17bed3c966 Fix doc for CountTable (#15561) [backport]
(cherry picked from commit f1d81dc6e6)
2020-10-13 08:43:46 +02:00
Christian Ulrich
eb51fa5ead close socket in getPrimaryIPAddr (#15538) [backport]
(cherry picked from commit c7ccbfac39)
2020-10-13 08:43:27 +02:00
alaviss
dc1c251a2c tslow_tables: wait for an additional 2 seconds (#14266)
This test runtime tends to hover around the 5s mark depending on how
loaded the system currently is. This causes the test to fail a lot
during CI, per analytics:
https://dev.azure.com/nim-lang/Nim/_test/analytics?definitionId=1&contextType=build

Give the test an extra 2 seconds to account for unrelated overhead.

(cherry picked from commit 83435fe696)
2020-10-09 15:09:48 +02:00
narimiran
d6c8a91b72 fix wrong word-wrap in tunknown_named_parameter 2020-10-09 14:55:20 +02:00
Araq
991902e286 fixes a renderer regression
(cherry picked from commit 0ac74ddd74)
2020-10-09 12:06:05 +02:00
narimiran
5534c56d05 manually backport #15506 2020-10-09 12:03:07 +02:00
cooldome
777c28cf45 fix #15516 (#15518)
(cherry picked from commit fe187719ab)
2020-10-09 10:04:24 +02:00
alaviss
3f0432bf8d koch: unify nimble building scripts [backport:1.4] (#15443)
This commit gets rid of buildNimble in favor of the simpler
bundleNimbleExe, which does pretty much the same thing.

(cherry picked from commit 3919f0aa54)
2020-10-07 20:11:18 +02:00
alaviss
bc42ec515e tools/deps: fix git dir check (#15470)
On Windows, a successful call will have a trailing newline appended, so
strip that away before doing any checks.

(cherry picked from commit e3eae3f7c7)
2020-10-07 19:44:35 +02:00
alaviss
60783ccc11 koch, compiler: bundle fusion as part of the source archive (#15409)
This allows distributions to build Nim from the downloaded source
archive without an Internet connection.

(cherry picked from commit d4892e9388)
2020-10-07 19:44:00 +02:00
Andreas Rumpf
9599d95caa fixes https://github.com/nim-lang/RFCs/issues/257 [backport:1.2] (#15479)
(cherry picked from commit 2288188fe9)
2020-10-06 09:50:36 +02:00
Andreas Rumpf
e3c85f5885 remove nim.cfg file change lefover [backport:1.2] (#15469)
(cherry picked from commit ff70ff529d)
2020-10-06 08:49:06 +02:00
Andreas Rumpf
da03b5ca8b closureiters: fixes #15243 (#15454) [backport:1.2]
* fixes #15243 [backport:1.2]

(cherry picked from commit aa1d7fe1e9)
2020-10-06 08:48:44 +02:00
Miran
736e1dd0a0 various documentation fixes [backport] (#15422)
(cherry picked from commit eb2a4961c7)
2020-10-06 08:46:54 +02:00
Yuriy Glukhov
c6d51805be Dont assert on setstacksize result in iOS (#15427) [backport:1.2]
(cherry picked from commit 22d0a39932)
2020-10-06 08:46:41 +02:00
Andreas Rumpf
c53c6458b0 finish the stacktraces.nim implementation [backport:1.2] (#15393)
(cherry picked from commit e2d80b15a6)
2020-10-06 08:46:25 +02:00
Andreas Rumpf
eefb13d638 better nativestacktrace support; refs #15284; backport [1.2] (#15384)
* nimStackTraceOverride: enable stack traces in exceptions

This is a two-step stack trace collection scheme, because re-raised
exceptions will collect multiple stack traces but use them rarely, when
printing info about an uncaught exception, so it makes sense to only do
the cheap stack unwinding all the time and the relatively expensive
debugging information collection on-demand.

`asyncfutures` implements its own `$` proc for printing
`seq[StackTraceEntry]`, so we have to add the debugging info there, just
like we do for the private `$` proc in `system/excpt`.

* cleaned up PR #15284

Co-authored-by: Ștefan Talpalaru <stefantalpalaru@yahoo.com>
(cherry picked from commit 1fae66e4df)
2020-10-06 08:45:13 +02:00
Andreas Rumpf
7ef706fef9 fixes #15360 [backport:1.2] (#15378)
(cherry picked from commit c2434d939e)
2020-09-21 18:19:13 +02:00
Andreas Rumpf
4827bf5e88 base64: fixes the error message for an invalid base64 input character [backport:1.2]
(cherry picked from commit cbdda631db)
2020-09-21 18:19:04 +02:00
Andreas Rumpf
2624de0588 fixes #9754 [backport] (#15342)
(cherry picked from commit 8b66412a8b)
2020-09-21 18:18:44 +02:00
flywind
183f876bd1 remove annoying messages when creating orderedTables (#15309)
* nativesockets docs minor [backport: 1.2]

* remove annoying messages

(cherry picked from commit a41b243fea)
2020-09-21 18:15:54 +02:00
alaviss
6eb656a75b Small optimization for the CI pipeline. (#15088)
* azure-pipelines: cache csources to speed up build

Building csources takes about 2-4 mins, and since it hasn't changed for
a long time, employ some caching to cut the time spent.

* azure-pipelines: remove ppa avoidance configs

Testing shows that there aren't any difference between having this and
not having it, so removing this to simplify the code.

(cherry picked from commit c292c57e48)
2020-09-14 09:07:03 +02:00
narimiran
0e457ae92c disable package 'ws' 2020-09-12 08:47:17 +02:00
narimiran
5254e0693e fix failing tests 2020-09-11 15:54:17 +02:00
slangmgh
abe72ba1b3 fix #14203 (#14204)
(cherry picked from commit b56432bd8a)
2020-09-11 14:49:21 +02:00
narimiran
e980256794 fix RangeDefect to RangeError 2020-09-11 14:39:51 +02:00
Andreas Rumpf
7bba0deb1d fixes #15280 [backport:1.2] (#15281)
* fixes #15280 [backport:1.2]

* make tests green again

* adapt tests

(cherry picked from commit 3f00a738db)
2020-09-11 13:58:04 +02:00
flywind
0845e88110 nativesockets docs minor [backport: 1.2] (#15285)
(cherry picked from commit a81610230d)
2020-09-11 13:58:04 +02:00
flywind
040ac6cd2b more Protocol supports in windows (#15274) [backport:1.2]
(cherry picked from commit e08b802d79)
2020-09-11 13:58:04 +02:00
shirleyquirk
1c8ed1de0e Fix c_malloc inside syslocks.nim to take size_t (#15268) [backport]
* update c_malloc's to csize_t

(cherry picked from commit 57f98dae9a)
2020-09-11 13:58:04 +02:00
Miran
b5c90a3431 fix #15257, toHex couldn't handle large uint64 (#15261) [backport:1.2]
(cherry picked from commit 4fb17bc03b)
2020-09-11 13:58:04 +02:00
PMunch
53f3bd9376 Fix sets for architectures with default integers smaller than 32 bits (#15258) [backport]
(cherry picked from commit 244760197c)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
ae688aa7f5 fixes #15210 [backport:1.2] (#15237)
* fixes #15210 [backport:1.2]

* use patched version of bigints library

(cherry picked from commit ff13f8cc3c)
2020-09-11 13:58:04 +02:00
Araq
4e428c5a18 fixes #15207 [backport:1.2]
(cherry picked from commit 40969296e9)
2020-09-11 13:58:04 +02:00
Miran
dc3f74f1c2 [backport] fix #15064, strscans.scanf edge case for '$+' (#15223)
(cherry picked from commit 15ff89cec1)
2020-09-11 13:58:04 +02:00
alaviss
98e73512d1 asyncnet: don't try to close the socket again [backport] (#15174)
The closed flag isn't a good design by any means, but let's have this
working first before I get rid of the flag and potentially create a
non-backportable commit.

(cherry picked from commit 957bf15a08)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
a41ece8d86 fixes #15101 [backport] (#15171)
(cherry picked from commit 2a8bf470af)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
67d729aa2e fixes a collect() bug reported on the forum (#15156) [backport:1.2]
(cherry picked from commit 64aec6eb85)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
0ddf7153b8 fixes #15129 [backport:1.2] (#15144)
(cherry picked from commit d6161e7e9e)
2020-09-11 13:58:04 +02:00
Andreas Rumpf
0aec43e850 fixes #15071 [backport] (#15131)
(cherry picked from commit d23ae49535)
2020-09-11 13:58:04 +02:00
narimiran
f94a3fa671 bump Nim version to 1.2.7 2020-09-11 13:58:04 +02:00
c-blake
bf320ed172 Attempt to explain better why delImplIdx is the way it is. Maybe this can (#15108)
avoid future implementation mischief.  (Maybe not.  Sometimes, general
distrust of theory leads people to distrust simple reasoning over times
from CPUs trying as hard as possible to mask DRAM latency via pre-fetch.)

(cherry picked from commit 196e747df1)
2020-07-29 11:59:40 +02:00
Andreas Rumpf
e9d6d2b961 fixes #14616 [backport:1.2] (#15109)
(cherry picked from commit a3a87cdb29)
2020-07-29 11:59:20 +02:00
Bung
9d11fc026b fixes #14189 (#15080) [backport]
(cherry picked from commit 191c388792)
2020-07-29 10:43:48 +02:00
Jjp137
896c3c41d3 parsecsv: fix '\0' being displayed as '0' in docs (#15086) [backport]
(cherry picked from commit a62bc55955)
2020-07-29 10:43:36 +02:00
Andreas Rumpf
f2844ba2d3 fixes #15038 [backport:1.2]
(cherry picked from commit aae998feff)
2020-07-29 10:43:20 +02:00
Bung
a3f00b87e1 fix #14534 (#15060) [backport]
(cherry picked from commit 9746868832)
2020-07-29 10:39:39 +02:00
Araq
df490bd59f fixes #15056 [backport]
(cherry picked from commit 12a9fe017e)
2020-07-29 10:39:29 +02:00
Andreas Rumpf
b4ccdf870b fixes #15044 [backport:1.2]
(cherry picked from commit c90c53e8bb)
2020-07-29 10:39:11 +02:00
narimiran
c0e1ee965a bump NimVersion to 1.2.6 2020-07-29 09:54:54 +02:00
c-blake
c804e559ad Fulfill https://github.com/nim-lang/Nim/pull/14995#issuecomment-664914391 (#15104)
request.  This can be conceived as an alternate, more capable resolution of
  https://github.com/nim-lang/Nim/issues/12200
than
  https://github.com/nim-lang/Nim/pull/12208

The code re-org idea here is to upgrade tablimpl.nim:`delImpl`/`delImplIdx`
to abstract client code conventions for cell emptiness & cell hashing via
three new template arguments - `makeEmpty`, `cellEmpty`, `cellHash` which
all take a single integer argument and clear a cell, test if clear or
produce the hash of the key stored at that index in `.data[]`.

Then we update the 3 call sites (`Table`, `CountTable`, `SharedTable`) of
`delImpl`/`delImplIdx` by defining define those arguments just before the
first invocation as non-exported templates.

Because `CountTable` does not save hash() outputs as `.hcode`, it needs a
new tableimpl.nim:`delImplNoHCode` which simply in-lines the hash search
when no `.hcode` field is available for "prefix compare" acceleration.
It is conceivable this new template could be used by future variants, such
as one optimized for integer keys where `hash()` and `==` are fast and
`.hcode` is both wasted space & time (though a small change to interfaces
there for a sentinel key meaning "empty" is needed for maximum efficiency).

We also eliminate the old O(n) `proc remove(CountTable...)` in favor of
simply invoking the new `delImpl*` templates and take care to correctly
handle the case where `val` is either zero for non-existent keys in `inc`
or evolves to zero over time in `[]=` or `inc`.

The only user-visible changes from the +-42 delta here are speed, iteration
order post deletes, and relaxing the `Positive` constraint on `val` in
`proc inc` again, as indicated in the `changelog.md` entry.

(cherry picked from commit b2a1944587)
2020-07-29 09:54:39 +02:00
narimiran
378dc7c9fb bump NimVersion to 1.2.5 2020-07-23 20:24:00 +02:00
Andreas Rumpf
d0a2857675 enforce browsers.nim only handles URLs [backport] (#15045)
(cherry picked from commit 925dd92e07)
2020-07-23 11:52:15 +02:00
Miran
170f5b6229 asyncftpclient.nim - don't assume a sufficiend line length (#14973)
(cherry picked from commit f4f21c89e5)
2020-07-22 15:52:18 +02:00
Miran
e71395f571 fix several newline problems (#15028) [backend]
* prevent newlines where they shouldn't be
* 'contentLength' shouldn't be negative

(cherry picked from commit 5fafa2fd5c)
2020-07-22 15:47:58 +02:00
Dominik Picheta
ddcbc1a58f [Backport] Fixes callbacks being dropped on Linux/macOS/BSD. (#15012)
Fixes #15003.

This is a serious bug which occurs when data cannot be read/sent
immediately and there are a bunch of other read/write events
pending. What happens is that the new events are dropped which
results in the case of the reported bug resulted in some data not
being sent (!).

(cherry picked from commit 1e3a0ef1e1)
2020-07-21 15:46:41 +02:00
cooldome
28bc815d3e fix odbc regressions (#15009) [backport]
* fix odbc regressions

* make only necessary changes

(cherry picked from commit edbbbdf1a8)
2020-07-21 15:46:23 +02:00
Bung
e854d385f5 fix #9771 (#14357)
* fix #9771
* map SQLLEN SQLULEN
* fix proc params take TSqlLen

Co-authored-by: bung87 <crc32@qq.com>
(cherry picked from commit ce0552c100)
2020-07-21 15:46:11 +02:00
Miran
27acb43e69 fix #14082, don't crash on incorrectly formatted input (#14977) [backport]
(cherry picked from commit c62513049c)
2020-07-21 15:42:58 +02:00
Clyybber
1b093d7ec7 Fix #14911 (#14922) [backport]
* Fix #14911

* Add testcase

* Fix test

(cherry picked from commit 5bd2da3f64)
2020-07-21 15:40:24 +02:00
aguspiza
4d6cb1ff21 SSL_CTX_load_verify_locations parameters are reversed (#14815) [backport]
(cherry picked from commit d968163cd1)
2020-07-21 15:40:18 +02:00
narimiran
ba808ba7ee bump NimVersion to 1.2.4 2020-06-26 10:46:56 +02:00
narimiran
a5667218a9 update test command for 'norm' package 2020-06-25 13:03:12 +02:00
Miran
7c27cdc719 [backport] fix #14748, move gdb files to other section of installer.ini (#14772)
(cherry picked from commit 6bf2990f66)
2020-06-24 06:56:37 +02:00
Andreas Rumpf
f864c351f0 fixes #14240 [backport:1.2] (#14757)
(cherry picked from commit 451129de42)
2020-06-24 06:56:14 +02:00
Andreas Rumpf
ac00504928 fixes #14458 [backport:1.2] (#14756)
(cherry picked from commit 8df20276c9)
2020-06-24 06:56:05 +02:00
alaviss
bcb6d9a763 posix_other: add define to force time_t to 64 bit [backport] (#14753)
This is a temporary remedy for time_t transition to 64 bit on newer
Linux libc (musl >= 1.2.0, glibc >= 2.32).

In the future we might want to move away from libc, or figure out a way
to reliably detect the real size of C types at compile time, both of
which are difficult.

(cherry picked from commit c8554ebc0c)
2020-06-24 06:55:56 +02:00
ee7
90546716dc [backport] Docs: Fix broken code-block (#14749)
This commit indents the contents of a `code-block` in `httpclient.nim`
so that it displays correctly. The bug was introduced by 42a64245f8.

I did a quick search for other `code-block`s that are broken in the same
way, but the only other one I found (in `pegs.nim`) is not included in
the generated documentation.

(cherry picked from commit 1e484ed62b)
2020-06-24 06:55:34 +02:00
alaviss
8083a1fd2f encodings: use only one iconv definition [backport:1.2] (#14741)
Fix an issue reported on IRC: using encodings with --dynlibOverrideAll
result in duplicated iconv definitions, causing compile errors.

This commit remove the `var` wrapper of iconv and go all out on
pointers, as it should due to how the API accepts nil. Also corrected
the API to resemble iconv(3p).

(cherry picked from commit c7dee55b87)
2020-06-24 06:54:15 +02:00
Araq
49f2b7eac6 fixes #14718 [backport]
(cherry picked from commit 65c7884a3c)
2020-06-24 06:54:05 +02:00
narimiran
25c21711b7 bump NimVersion to 1.2.3 2020-06-24 06:53:25 +02:00
narimiran
be34b5abe2 bump Nim version to 1.2.2 2020-06-09 11:50:15 +02:00
Andreas Rumpf
5297bbe1cb optimized wrapWords; fixes #14579 (#14606) [backport:1.2]
(cherry picked from commit c308c2e60b)
2020-06-09 11:40:15 +02:00
Andreas Rumpf
10fb986fb6 more precise analysis about 'observable stores' [backport:1.2] (#14582)
(cherry picked from commit 32083c7ff8)
2020-06-08 13:26:33 +02:00
Andreas Rumpf
33bf7839ba fixes #14514 [backport:1.2] (#14533)
(cherry picked from commit 8710395a0f)
2020-06-08 13:26:28 +02:00
Zed
56b1e52e17 Fix asynchttpserver newline breaking content-length (#14565) [backport]
(cherry picked from commit ea761419ad)
2020-06-08 13:22:20 +02:00
Danil Yarantsev
5702a60793 Change severity of template instantiation message [backport] (#14526)
* Change severity of template instatiation msg

* Add a test

* Trailing newline argh

(cherry picked from commit 3698f197f1)
2020-06-01 17:41:04 +02:00
genotrance
4f689d4960 Fix #14057 - moveFile should overwrite on Windows (#14433)
(cherry picked from commit b012205b2e)
2020-06-01 17:40:11 +02:00
narimiran
4c0c82ae42 disable 'nimx' package, see PR #14293 2020-06-01 17:39:30 +02:00
Andreas Rumpf
2c64868764 warn about observerable stores but don't prevent them for 1.2.2 [backport:1.2]; refs https://github.com/nim-lang/RFCs/issues/230 (#14510)
(cherry picked from commit 52c3633223)
2020-06-01 13:39:16 +02:00
narimiran
957e74e99e correctly backport #14496 2020-06-01 13:38:04 +02:00
Andreas Rumpf
97c68d9446 fixes #14498 [backport:1.2] (#14503)
(cherry picked from commit 7ccc7d7e93)
2020-06-01 12:15:28 +02:00
Andreas Rumpf
aec0d583d1 fixes #14495 [backport:1.2] (#14496)
(cherry picked from commit 3105909f88)
2020-06-01 12:15:15 +02:00
Andreas Rumpf
051f4ffad9 manual.rst: updates [backport] (#14445)
(cherry picked from commit 79e85cb0b5)
2020-06-01 12:13:18 +02:00
Mamy Ratsimbazafy
ed966b77c3 The whole options module should be inline (#14417) [backport:1.2]
* The whole options module should be inline

* Use inline per proc and tag `lent` where appropriate

* Remove lent annotation (failing at compiletime)

(cherry picked from commit f71f8b0239)
2020-06-01 12:11:15 +02:00
Andreas Rumpf
7800fa394f specialize genericReset (#14398)
* progress
* make tests green
* maybe we also want to reset pointers, dunno
* progress
* cleanup; fixes #13879 [backport:1.2]

(cherry picked from commit b35d370d88)
2020-05-20 15:30:20 +02:00
Danil Yarantsev
bcfbaea833 Fix some typos in the manual [backport] (#14399)
(cherry picked from commit 1450924b1e)
2020-05-20 15:29:12 +02:00
Andreas Rumpf
acc3879c54 fixes #14126 [backport:1.2] (#14390)
* fixes #14126 [backport:1.2]

* used more logic to optimize it further; updated Nimble version

(cherry picked from commit 16003bffe1)
2020-05-20 09:04:49 +02:00
Ștefan Talpalaru
c0b749da38 fix #14364 (#14372) [backport:1.2]
Turn on the TLS emulation when using Boehm, since it doesn't scan the
real TLS.

(cherry picked from commit 27741d6a5c)
2020-05-19 12:15:59 +02:00
Clyybber
87992a3a18 Fix #14269 (#14286)
(cherry picked from commit 8e93105606)
2020-05-19 12:12:45 +02:00
Clyybber
c3ecd38da1 New "ping-pong" DFA (#14322)
* New ping-pong analysis

* Add testcase for #13456

* Remove debugging leftover

* Unquote "unstructured controlflow"

* Fix typo

* Fix exponential complexity in edge cases

* Add sanity testcase

* Fix

(cherry picked from commit 9f78f116b2)
2020-05-19 12:12:45 +02:00
cooldome
a7ebbad8cf fix #14219 (#14225)
Co-authored-by: cooldome <ariabushenko@bk.ru>
(cherry picked from commit a39123c93c)
2020-05-19 12:12:45 +02:00
Antonis
e9d2b8971a better error message
(cherry picked from commit 517dd800f8)
2020-05-18 22:22:27 +02:00
Antonis
287dff200d fix closure env check
(cherry picked from commit 3616b0698b)
2020-05-18 22:22:08 +02:00
Clyybber
d60a01e513 Fix the DFA for "unstructured controlflow" (#14263)
* Fix the DFA for "unstructured controlflow"

* Add testcase from #14233

(cherry picked from commit 42db75c970)
2020-05-18 22:21:56 +02:00
cooldome
8cb8cb7861 Implements RFCs #209 (#13995)
* add test
* add changelod entry
Co-authored-by: cooldome <ariabushenko@bk.ru>

(cherry picked from commit 9295251e68)
2020-05-18 22:16:07 +02:00
narimiran
9b510643fa install gtk3 on osx for package testing 2020-05-18 16:46:40 +02:00
narimiran
d2d401c657 disable the new fragile test in 'tosproc.nim' 2020-05-14 09:58:15 +02:00
Kaushal Modi
7826356f36 Fail quickly if re or nre module is attempted to be compiled with js [backport] (#14341)
Fixes https://github.com/nim-lang/Nim/issues/14338 .

(cherry picked from commit a2a3fa1039)
2020-05-14 07:32:38 +02:00
Andreas Rumpf
32d56fa913 fixes #13998 [backport:1.2]
(cherry picked from commit 82870e0737)
2020-05-14 07:32:29 +02:00
Andreas Rumpf
59a97a0e06 fixes #13104 [backport]
(cherry picked from commit f3e17e7c77)
2020-05-14 07:32:23 +02:00
slangmgh
de867bea3c Fix #14289 (#14304) [backport]
(cherry picked from commit 76f7e95814)
2020-05-14 07:31:03 +02:00
Timothee Cour
8e5e92f679 fix https://github.com/nim-lang/Nim/issues/14275 querySetting(nimcacheDir) works even if implicitly set (#14277)
(cherry picked from commit 363b7ff3b8)
2020-05-13 08:15:50 +02:00
Timothee Cour
01f42a5933 fix a critical bug in windows.osproc leading to resource leaks and blocking IO [backport] (#14296)
(cherry picked from commit d11cb9d495)
2020-05-13 08:15:24 +02:00
alaviss
8e5c389bef net: remove more erroneous set constructions (#14252) [backport]
Refs #13764

(cherry picked from commit 1a1e9986a3)
2020-05-13 08:15:17 +02:00
Andreas Rumpf
75abd4dc68 fixes #14209 [backport:1.2] (#14213)
* fixes #14209 [backport:1.2]
* improve stability

(cherry picked from commit 64e839d5fd)
2020-05-06 17:22:16 +02:00
Andreas Rumpf
2977a31654 destructors: don't produce stupid code for 'cast' (#14208) [backport:1.2]
* destructors: don't produce stupid code for 'cast'

* fixes #14207

(cherry picked from commit b6fb609e0d)
2020-05-06 17:20:07 +02:00
slangmgh
05151d7f62 Fix #14151 (#14205) [backport]
(cherry picked from commit d5c014e59b)
2020-05-06 17:13:52 +02:00
Araq
a5d0950eb0 fixes #14159 [backport:1.2]
(cherry picked from commit 87ac28d19a)
2020-05-06 17:13:34 +02:00
Kaushal Modi
9ff2ec7ec5 Document that proc named fooTask is created for every foo task [backport] (#14187)
Ref: https://irclogs.nim-lang.org/01-05-2020.html#15:18:03
(cherry picked from commit 0880f118d3)
2020-05-06 17:09:59 +02:00
Andreas Rumpf
9caa1a5aa8 arc: do not unload globals when building a library [backport:1.2] (#14180)
(cherry picked from commit d5fc35c968)
2020-05-06 17:09:35 +02:00
Andreas Rumpf
62b9dcb8db fixes #13698 [backport:1.2] (#14175)
(cherry picked from commit 89be5be03e)
2020-05-06 17:09:21 +02:00
Andreas Rumpf
b997e32129 fixes #13986 [backport:1.2] (#14173)
(cherry picked from commit cf3e0008b9)
2020-05-06 17:09:12 +02:00
Andreas Rumpf
ff90206332 fixes #14054 [backport:1.2] (#14061)
* fixes #14054

* make tests green again

* more tests are green

* maybe now

(cherry picked from commit cc60caedb3)
2020-05-06 17:09:07 +02:00
Araq
b09f7275b2 fixes another silly arc/orc bug [backport:1.2]
(cherry picked from commit bd57f0cd32)
2020-05-06 17:08:43 +02:00
Andreas Rumpf
49decbf4b4 fixes #14079 [backport:1.2] (#14163)
(cherry picked from commit d9e907c0e2)
2020-05-06 17:08:32 +02:00
narimiran
dc3919bb1a use the same Azure Pipelines workflow as current devel 2020-04-28 14:27:07 +02:00
genotrance
d3cd0cc843 Improve #12920 fix (#13958)
(cherry picked from commit 35b046373a)
2020-04-28 08:00:08 +02:00
Timothee Cour
0136fc3e53 fix #14132 dsymutil should not be called on static libraries (#14133) [backport:1.2]
(cherry picked from commit b8d7a98265)
2020-04-28 07:59:11 +02:00
hlaaftana
14ce3e45e0 small docs fix in typetraits (#14108)
(cherry picked from commit 31ba27590c)
2020-04-26 07:25:07 +02:00
Jae Yang
4513cb0680 Fixes #14110 (#14111)
Fixes jsffi usage example in doc

(cherry picked from commit 362c8964bf)
2020-04-26 07:25:01 +02:00
Timothee Cour
b8573064e0 fix nim CI; fix local testament (#14102)
(cherry picked from commit d5b7e9902c)
2020-04-25 15:17:57 +02:00
alaviss
b306c1a449 testament: don't try to test nimgrep if it's not there [backport:1.2] (#14085)
One more compiler source-specific tackled

(cherry picked from commit dd5ccc3e5a)
2020-04-25 15:15:35 +02:00
Timothee Cour
a5b74b99ad [ci skip] changelog conflicts are a thing of the past (#14098)
(cherry picked from commit f07f07eef9)
2020-04-25 15:15:22 +02:00
alaviss
abbf94127d testament: don't rely on Nim source structure [backport:1.2] (#14077)
It's also just faster to get the current file name instead of scanning
the PATH.

(cherry picked from commit 4b43d42b98)
2020-04-23 18:45:38 +02:00
alaviss
bd12e7fb17 tools/finish: don't quote path with space (#14058) [backport]
Path with spaces should be added as is, quoting them makes utilities
treat the quotes as part of the path. This makes `nim` unable to be used
from the command line even if it appears to be added to user's Path
environment variable.

Even more confusing, Windows 10's PATH editor shows the path without any
quotes, you only see them when you use "Edit text". Took me a good 15
minutes to figure out why couldn't I run `nim` despite it being in Path.

(cherry picked from commit 22418ce8fb)
2020-04-23 18:45:28 +02:00
Andreas Rumpf
6e625246ce fixes #14052 [backport:1.2] (#14055)
(cherry picked from commit 1b6c4ed2ba)
2020-04-23 18:44:38 +02:00
alaviss
57f41d6b6c asyncdispatch: export Callback (#14042) [backport]
This let us see the definition of `Callback` in docs, which is required
to even make use of asyncdispatch.

Ref #13539.

(cherry picked from commit 7beed44fc9)
2020-04-23 18:44:24 +02:00
Timothee Cour
dbf35e2ac3 fix https://github.com/nim-lang/RFCs/issues/211: var a: DateTime compiles and is usable (#14002) [backport:1.2]
* fix https://github.com/nim-lang/RFCs/issues/211: `var a: DateTime` works
* assertValidDate checks for sentinel month

(cherry picked from commit e3919b658f)
2020-04-23 18:44:03 +02:00
cooldome
9d667306df fix #14007 (#14012) [backport]
Co-authored-by: cooldome <ariabushenko@bk.ru>
(cherry picked from commit d839eb9352)
2020-04-23 18:43:50 +02:00
cooldome
605d395ace fixes #14003 (#14006) [backport:1.2]
Co-authored-by: cooldome <ariabushenko@bk.ru>
(cherry picked from commit f10689d3d4)
2020-04-23 18:43:35 +02:00
Miran
a1610420c5 make fuzzy search a bit less fuzzy (#13996) [backport:1.2]
(cherry picked from commit 06e0c75ba9)
2020-04-23 18:43:25 +02:00
narimiran
dd0e823a0c package 'inim' now has dependencies 2020-04-20 18:55:57 +02:00
Timothee Cour
341141529f backport nimExe from #13876 (#14024) 2020-04-20 13:39:17 +02:00
narimiran
1e3bdf04d8 bump Nim version to 1.2.1 2020-04-14 09:30:20 +02:00
Dominik Picheta
f1bf28d5de Fixes issues with dynamic loading OpenSSL. Fixes #13903. (#13919) [backport]
This fixes at least a couple of issues:

* Procs loaded from the DLL being used even when the pointer is nil.
* The actual issue (#13903) which appeared to cause stack corruption on
  Android 7.1.1 with OpenSSL 1.1.1f. The change that fixed this was the
  move to loading the procs in `sslSym`.

(cherry picked from commit 350ee0308a)
2020-04-14 07:30:29 +02:00
cooldome
9ef1acac64 fix #13909 (#13914) [backport:1.2]
Co-authored-by: cooldome <ariabushenko@bk.ru>
(cherry picked from commit f86fc5316a)
2020-04-14 07:30:24 +02:00
Timothee Cour
f34779c289 fix #13902 distinct uint64 type corruption on 32-bit with borrow (#13907) [backport:1.2]
* fix #13902 distinct uint64 type corruption on 32-bit with borrow

Co-authored-by: Timothee Cour <timothee.cour2+lightsail@gmail.com>
(cherry picked from commit 95fd8ae93c)
2020-04-14 07:30:14 +02:00
Clyybber
078df45e99 Fix #13889 with testcase (#13896) [backport]
* Fix https://github.com/nim-lang/Nim/issues/13889

* Add testcase

* Reduce test time

Co-authored-by: Elie Zedeck RANDRIAMIANDRIRAY <elie.zedeck@gmail.com>
(cherry picked from commit 92c4aad205)
2020-04-14 07:30:06 +02:00
Timothee Cour
adf644d6a4 openDefaultBrowser now works on OSX (#13892) [backport]
(cherry picked from commit e6d870896b)
2020-04-14 07:29:59 +02:00
Timothee Cour
0d59ec9b54 fix https://github.com/timotheecour/Nim/issues/88 (#13865) [backport:1.2]
(cherry picked from commit f1fd3ef7f4)
2020-04-14 07:29:37 +02:00
supakeen
c4dfdb71f4 Add isNil check to custom Content-Length. (#13867) [backport:1.2]
Related to #13866.

(cherry picked from commit 09ca19208f)
2020-04-14 07:29:26 +02:00
narimiran
7e83adff84 bump Nim version to 1.2.0 2020-04-03 14:17:15 +02:00
Alexander Ivanov
920add5880 sourcemaps for the JS codegen (#7508) 2020-04-03 12:06:23 +02:00
Andreas Rumpf
2b3b24a804 make bootstrapping more robust for people who have Nim inside /usr/bin (#13855) 2020-04-03 10:25:15 +02:00
itsumura-h
87e6b88f3b fix #7241 (#13779)
finalize() should run in insert()
2020-04-03 09:38:05 +02:00
Timothee Cour
93cd98dd14 move tinyc to a separate repo and allow installing external dependencency (eg tinyc) from koch / library code (#13850)
* remove tinyc
* installDeps
* update tinyc paths
2020-04-03 09:10:45 +02:00
flywind
6b9ffc7fad fix asynchttpserver content-length header (#13846) 2020-04-03 09:05:43 +02:00
Timothee Cour
d23371fdd7 std/byaddr => std/decls (#13847) 2020-04-03 09:03:13 +02:00
narimiran
7d17cd34b8 create a changelog for v1.2.0 2020-04-02 16:28:01 +02:00
Araq
8ee0771b5a return types must not be Natural for reasons I won't outline here 2020-04-02 15:01:14 +02:00
Araq
d01fca974d added an .assert pragma and mentioned the pragmas in the changelog 2020-04-02 12:57:32 +02:00
Dean Eigenmann
df8e0e7f0c feature/count (#13837) 2020-04-02 12:09:29 +02:00
Andreas Rumpf
d01245e501 renamed new std/pragmas.nim to std/byaddr.nim (#13844)
* renamed new std/pragmas.nim to std/byaddr.nim

* minor code cleanup
2020-04-02 11:52:31 +02:00
Timothee Cour
68539a2926 fix last remaining warning when building nim (intVal should be Int128) + minor cleanups (#13841) 2020-04-02 08:53:52 +02:00
Juan Carlos
c167261735 Deprecate PHP (#13838) 2020-04-02 08:48:09 +02:00
Juan Carlos
160d5fe589 Jsconsole update (#12448)
* Improve jsconsole adding the rest of the stable api as documented on the standard at https://developer.mozilla.org/docs/Web/API/Console

* Improve jsconsole, add runnableexamples
* Simplify jsconsole
2020-04-02 08:47:45 +02:00
Juan Carlos
46ca19ff18 Deprecate DCE:on (#13839) 2020-04-02 02:58:43 +02:00
Juan Carlos
afd0afe0a3 Deprecate when declared(echo):echo (#13840) 2020-04-02 02:56:18 +02:00
Juan Carlos
9102ac8c7d Documentation and Code Style inotify (#13836) 2020-04-02 01:05:55 +02:00
Juan Carlos
9599757068 Add browsers.openDefaultBrowser without URL, implements IETF RFC-6694 Section-3 (#13835) 2020-04-01 15:46:47 -04:00
Andreas Rumpf
bc37668c5a fixes #13782 (#13834) 2020-04-01 20:30:28 +02:00
Juan Carlos
4816984726 Documentation, add more examples (#13825) 2020-04-01 19:39:58 +02:00
Andreas Rumpf
484548c784 revert stdlib changes which are not required anymore 2020-04-01 19:38:44 +02:00
Zahary Karadjov
66f18037b3 Fix tests/types/tparameterizedparent0 2020-04-01 19:38:44 +02:00
Zahary Karadjov
08afa03075 The raises list can now use expressions referencing the generic params 2020-04-01 19:38:44 +02:00
Zahary Karadjov
be95f8fdfa Turn some of the errors back into warnings 2020-04-01 19:38:44 +02:00
Zahary Karadjov
ce9a4ed124 Replace tfHasRequiresInit with a more accurate mechanism
The new mechanism can deal with more complex scenarios such as
not nil field appearing in a non-default case object branch or
a field within a generic object that may depend on a when branch.

The commit also plugs another hole: the user is no longer able
to create illegal default values through seq.setLen(N).
2020-04-01 19:38:44 +02:00
Zahary Karadjov
d374c6373b Fix tests/parallel/tguard2.nim 2020-04-01 19:38:44 +02:00
Zahary Karadjov
2b66d66567 Fix a CI failure during koch doc 2020-04-01 19:38:44 +02:00
Zahary Karadjov
e63b673ce2 Fix https://github.com/nim-lang/Nim/issues/4907 2020-04-01 19:38:44 +02:00
Zahary Karadjov
06438ed143 Close https://github.com/nim-lang/Nim/issues/11428 2020-04-01 19:38:44 +02:00
Zahary Karadjov
4f3d309fb0 Perform nil checks during object construction and within compiles()
Close https://github.com/nim-lang/Nim/issues/6494
2020-04-01 19:38:44 +02:00
Zahary Karadjov
7b7e42be54 More precise error messages for uninitialized fields in the presence of inheritance 2020-04-01 19:38:44 +02:00
Zahary Karadjov
0521f98486 Hrm, the new errors highlighted some code that seems to be broken
New issue: since `Table[A, B]` allocates its backing storage with
`newSeq[KeyValuePair[A, B]]`, it's no longer legal to create a table
with `not nil` types used as either keys or values.
2020-04-01 19:38:44 +02:00
Zahary Karadjov
f3be5a716f not nil types are illegal to construct through default(T) 2020-04-01 19:38:44 +02:00
Zahary Karadjov
1b570f2b18 Turn the warning for uninitialized (result) variables into errors 2020-04-01 19:38:44 +02:00
Zahary Karadjov
e0bb78553a Fix tests/notnil/tnotnil_in_objconstr.nim 2020-04-01 19:38:44 +02:00
Zahary Karadjov
54f06427c8 Enable the requiresInit checks only for objects 2020-04-01 19:38:44 +02:00
Zahary Karadjov
8ae48292ff Plug another hole: default(T) forbidden for objects requiring initialization 2020-04-01 19:38:44 +02:00
Zahary Karadjov
05a0ec4adb Don't allow 'var x: T' for objects that require initialization 2020-04-01 19:38:44 +02:00
Zahary Karadjov
7652aede41 More sophistication; Allow requiresInit to be specified per-field 2020-04-01 19:38:44 +02:00
Zahary Karadjov
a8b6222c86 First steps, the compiler can boot with enforced requiresInit 2020-04-01 19:38:44 +02:00
Timothee Cour
216fd59c44 make usage of foo is a user-defined error more informative (#13833) 2020-04-01 17:49:29 +02:00
Timothee Cour
d3020af44d fix open file leak when running --debugger:native (#13832) 2020-04-01 17:48:17 +02:00
Araq
c2d29eb3e0 updated the changelog 2020-04-01 14:10:47 +02:00
Araq
48213c7428 encodeMIME should be encodeMime by our coding guidelines 2020-04-01 14:10:27 +02:00
Timothee Cour
fd202136b4 fix #13829 (#13831) 2020-04-01 12:46:59 +01:00
Clyybber
515b6d661e Small typo (#13824) 2020-03-31 22:59:43 +02:00
lbartoletti
567af54baf Add arm/arm64 for FreeBSD (#13822)
* Add arm and arm64 for FreeBSD

* Add arm64 with aarch64 and reorder to avoid conflict with arm
2020-03-31 22:55:25 +02:00
Andreas Rumpf
9ffec79300 DrNim (Nim compiler with Z3 integration) (#13743)
* code cleanups and feature additions
* added basic test and koch/CI integration
* make it build on Unix
* DrNim: now buildable on Unix, only takes 10 minutes, enjoy
* added basic documentation for DrNim which can also be seen as the RFC we're following
* drnim: change the build setup so that drnim.exe ends up in bin/
* makes simple floating point ranges work
* added basic float range check
* drnim: teach Z3 about Nim's range types plus code refactoring
* drnim: make unsigned numbers work
* added and fixed index checking under setLen
* first implementation of .ensures, .invariant and .assume (.requires still missing and so is proc type compatibility checking
* drnim: .requires checking implemented
* drnim: implemented .ensures properly
* more impressive test involving min()
* drnim: check for proc type compatibility and base method compatibility wrt .requires and .ensures
* testament: support for 'pattern <directory>
* koch: uses new <directory> feature of testament
* drnim: added tiny musings about 'old'
* Make testament work with old SSL versions
* koch: add support for 'koch drnim -d:release'
* drnim: preparations for the param.old notation
2020-03-31 22:54:48 +02:00
Juan Carlos
dd44701728 Tiny fix on browsers.openDefaultBrowser (#13818) 2020-03-31 21:22:24 +02:00
Juan Carlos
c6586322ba Fix a 'See XXX' on documentation, clean out (#13820) 2020-03-31 21:21:49 +02:00
cooldome
c70b3952ff fixes #13810 (#13821)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-31 21:15:06 +02:00
Andreas Rumpf
9134bb9cfb macros for proc types, macros for types (#13778)
* new minor feature: macros for proc types, to be documented

* Finished the implementation and added tests

* [skip ci] Describe the new custom pragmas in the manual and the changelog

Co-authored-by: Zahary Karadjov <zahary@gmail.com>
2020-03-31 21:14:05 +02:00
alaviss
40898871a9 workflows/ci_docs: fix documentation deployment (#13819)
* workflows/ci_docs: fix docs publishing

It turns out that github.ref is the full ref name, so we have to be a
bit more specific.

See https://developer.github.com/v3/activity/events/types/#pushevent

Also fixed a silly typo :)

* workflows/ci_docs: run CI when there are changes to the workflow
2020-03-31 19:36:37 +02:00
c-blake
b1aa3b1eea Unwind just the "pseudorandom probing" part of recent sets,tables changes (#13816)
* Unwind just the "pseudorandom probing" (whole hash-code-keyed variable
stride double hashing) part of recent sets & tables changes (which has
still been causing bugs over a month later (e.g., two days ago
https://github.com/nim-lang/Nim/issues/13794) as well as still having
several "figure this out" implementation question comments in them (see
just diffs of this PR).

This topic has been discussed in many places:
  https://github.com/nim-lang/Nim/issues/13393
  https://github.com/nim-lang/Nim/pull/13418
  https://github.com/nim-lang/Nim/pull/13440
  https://github.com/nim-lang/Nim/issues/13794

Alternative/non-mandatory stronger integer hashes (or vice-versa opt-in
identity hashes) are a better solution that is more general (no illusion
of one hard-coded sequence solving all problems) while retaining the
virtues of linear probing such as cache obliviousness and age-less tables
under delete-heavy workloads (still untested after a month of this change).

The only real solution for truly adversarial keys is a hash keyed off of
data unobservable to attackers.  That all fits better with a few families
of user-pluggable/define-switchable hashes which can be provided in a
separate PR more about `hashes.nim`.

This PR carefully preserves the better (but still hard coded!) probing
of the  `intsets` and other recent fixes like `move` annotations, hash
order invariant tests, `intsets.missingOrExcl` fixing, and the move of
`rightSize` into `hashcommon.nim`.

* Fix `data.len` -> `dataLen` problem.
2020-03-31 19:18:45 +02:00
Euan
7abeba6aeb #13806 - getApplFreebsd might lose data (#13807)
* #13806 - first call sysctl with a null buffer to get the length, then alloc buffer and call again

* Use csize_t rather than csize

* Suggestions from @Clyybber

Co-authored-by: Euan Torano <euan.torano@bluesky-wireless.co.uk>
2020-03-31 15:50:24 +02:00
alaviss
5621ff6d09 workflows/ci_docs: lots of goodies (#13809)
* workflows/ci_docs: publish documentation to Github Pages

This should be a complete replacement for our current Travis CI setup.

* workflows/ci_docs: run docgen upon modification to the css on push

So that any changes regarding the stylesheets would be reflected on the
published docs.

* workflows/ci_docs: build the compiler in release mode

* workflows/ci_docs: set branch name for the generated docs

This makes the "Source" links work correctly.

* workflows/ci_docs: run docgen on windows and osx too

Only deploy the Linux-generated version.

* workflows/ci_docs: cache csources compiler

This should cut the time spent building csources, which is about 1-2mins
depending on OS.
2020-03-31 15:48:56 +02:00
Juan Carlos
42d2c3088e Add Documentation (#13811)
* Add more Docs and runnableExamples
2020-03-31 15:47:57 +02:00
Timothee Cour
1e4093d949 refs #13797 (#13812) 2020-03-31 15:43:35 +02:00
Huy Doan
119b0ce66f Fix telebot test failed, closes ba0f3/telebot.nim#49 [ref #13812] (#13814)
I was update telebot to version 1.0.0, update folder structure follow `nimble` guideline
2020-03-31 11:25:12 +02:00
Timothee Cour
19cab9fa51 stacktraces can now show custom runtime msgs per frame (#13351)
* stacktraces can now show custom runtime msgs
* improve tests/stdlib/tstackframes.nim
* fix test for --gc:arc
* test --stacktraceMsgs:on and --stacktraceMsgs:off
* --stacktracemsgs:off by default
2020-03-30 13:45:32 +02:00
Miran
8088633250 faster CIs (#13803)
* ttables: smaller table, 5x speedup

* thavlak: less iterations, less loops; 30% speedup

* tasyncclosestall: shorter timeout; 35% speedup

* gcleak4: less iterations, 2x speedup

* ttimes: remove deprecated stuff

* tdangerisrelease: remove cpp backend, 3x speedup

* tfrexp1: smaller range, 2x speedup

* trtree: fix warnings, less iterations, 6x speedup

* tasyncawait_cyclebreaker: smaller swarm size; 2x speedup

* trealloc: smaller number of iterations; 10x speedup

* towned_binary_tree: less iterations, 4x speedup

* tclosure: remove unused code, less iterations; 2x speedup

* twaitany: less durations; 1.4x speedup

* tasync_misc: less iterations, 2x speedup

* t8535: smaller sleep, 1.5x speedup

* tmanyjoin: smaller sleep, 2x speedup

* t12221: shorter sleeps, removed two slower tests; 1.6x speedup

* tfuturestream: smaller sleep; 1.5x speedup

* growobjcrash: less iterations; 2x speedup

* ttryrecv: smaller sleep; 1.5x speedup

* treusetvar: less threads; 2x speedup

* delete tthreadanalysis2, basically a duplicate of tthreadanalysis

* t7758: less iterations, 1.5x speedup

* tasyncawait: smaller swarm, less messages; 1.5x speedup

* tjsandnativeasync: smaller sleep, 1.5x speedup

* tpendingcheck: smaller sleep, 1.5x speedup

* remove rodfiles test category

* move tseq from its own category to 'collections' category

* remove unneeded tests and helpers from 'assert' category

* stdlib: merge tbitops2 into tbitops

* remove 'trepr2' from 'stdlib' cat

* merge 'tstreams' into one file

* remove 'tinefficient_const_table' from 'ccbugs' cat

* merge 'tcollections_to_string' into 'tcollections'

* tblocking_channel: smaller sleep, small speedup

* tconvexhull: less iterartions; 1.2x speedup

* merge 'tdeepcopy2' into 'tdeepcopy'

* merge 'tdisjoint_slice2' into 'tdisjoint_slice1'

* tmissing_deepcopy: smaller sequence

* tsendtwice: smaller arrays; 5x speedup

* remove 'tindexerrorformatbounds'

* disable multimethod tests

* remove 'gc:none' and 'refc' without 'd:useRealtimeGC' from gc tests

* koch.nim: bootstrap just with '-d:release', no need for 'csource'

* add github workflow for documentation

* testament: no need for 8 sub-second decimals
2020-03-30 13:18:12 +02:00
Andreas Rumpf
2a278f6eba '.push raises: []' now also affects proc types (#13776)
* '.push raises: []' now also affects proc types

* fixes the regression

* less disruptive bugfix

* another attempt
2020-03-29 22:00:18 +02:00
Timothee Cour
06f8c5cb6f fix #13794 HashSet leak (#13800) 2020-03-29 18:08:50 +02:00
Juan Carlos
8c719fce54 Fix #13631 (#13789) 2020-03-29 14:39:58 +02:00
Timothee Cour
cfa1a827dc fix #13730 (#13787) 2020-03-28 08:51:16 +01:00
Timothee Cour
95ab9ab75d [CI] fix recent freebsd systematic failure (#13788) 2020-03-28 01:45:22 -04:00
Andreas Rumpf
0a49fe5fad fixes #13763 (#13777) 2020-03-27 12:14:57 +01:00
alaviss
0eaacbc2c4 More fixes for Haiku (#13774)
* osproc: move fork-based code path under the when conditional

* osproc: avoid using the environ global on Haiku

* osenv: import environ from stdlib.h on Haiku

Haiku's environ is declared in `<stdlib.h>` by default, differing from
POSIX and/or Linux. Import it from there to avoid collision with anyone
importing `<stdlib.h>` from Nim.
2020-03-27 09:08:13 +01:00
Arne Döring
142c59fc37 fix typos and deprecation warnings for tconvariancerules.nim (#13772) 2020-03-27 08:36:21 +01:00
cooldome
289b31ee75 make nim_temp compile with --gc:arc --sinkInference:off (#13769)
* make nim_temp compiler with --gc:arc

* trigger build

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-26 20:15:38 +01:00
Clyybber
2925a47ae6 Fix vm.nim for --gc:arc (#13741)
* koch boot --gc:arc now passes the nim stage

... but generates invalid C code

* Move it closer to where its used

* Try something else

* Poor mans var

* Use UncheckedArray instead
2020-03-26 15:18:45 +00:00
alaviss
6162da812a ssl_certs: add Haiku support (#13761) 2020-03-26 14:47:15 +01:00
alaviss
2da438c33b asyncdispatch: fix erroneous set construction (#13765)
These constants were defined as `cint`. They can be huge on certain
systems, such as Haiku, and trigger out-of-bounds errors in
asyncdispatch.

Ref #13764.
2020-03-26 09:26:56 +01:00
zah
e50441ab33 Fix typeSym.getImpl for ref types (#13752)
* Fix typeSym.getImpl for ref types

* Fix a codegen issue affecting the test suite of nim-beacon-chain

* Fix tests/stdlib/tjsonmacro

To understand the fix better it may help to take a look
at the history of the replaced code.

The nil check that is removed in this commit was introduced
in another fix that failed to identify the root cause of the
issue - namely that we allow an object type to exist for which
no ast is present:

https://github.com/nim-lang/Nim/pull/9601/files

The original intention of the code is more obvious here:

https://github.com/nim-lang/Nim/pull/9538/files
2020-03-26 09:26:19 +01:00
Euan
1b31e08917 import macros rather than import std/macros. (#13762) 2020-03-26 09:11:32 +01:00
Timothee Cour
98753da331 distinctBase overload for values (#13746) 2020-03-25 21:47:03 +01:00
cooldome
764a81ca25 Continue bool conversion fixing (#13751)
* continue fixing #13744

* improve style

* improve test

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-25 21:36:22 +01:00
Miran
e1e062197e bump copyright year to 2020 (#13753) 2020-03-25 21:28:16 +01:00
Rory O’Kane
a8a464810e [ci skip] docs: make the syntax for generics easy to look up (#13754) 2020-03-25 21:09:23 +01:00
Rory O’Kane
febd48f343 [skip ci] docs: reword Part 3 link to communicate that it exists (#13755) 2020-03-25 21:08:24 +01:00
Rory O’Kane
84b378b94f docs: say that nil can be used as a value (#13756)
and improve wording in other ways

Showing that `nil` can be assigned helps to warn readers that variables can be `nil` even after being assigned a value.
2020-03-25 19:42:34 +01:00
Miran
5b55aa52d0 fix deprecations and other warnings (#13748) 2020-03-25 19:15:34 +01:00
cooldome
182d3c16e3 fixes #13744 (#13749)
* fixes #13744

* improve style

Co-authored-by: cooldome <ariabushenko@gmail.ru>
2020-03-25 13:44:52 +00:00
Timothee Cour
46c827be6a fix #13737 (#13738) 2020-03-24 10:14:49 +01:00
Araq
5300baae06 use nimEmulateOverflowChecks for ARM/ARM64 2020-03-24 09:46:54 +01:00
Euan
c0dbcffca6 __stderrp and friends are only on FreeBSD & DragonFlyBSD. (#13735) 2020-03-23 21:39:40 +01:00
Miran
4fb7f076d8 fix #13731, ambiguous repr of pointers (#13732) 2020-03-23 20:03:07 +01:00
Andreas Rumpf
fc5dd11b3d fixes #13722 (#13729)
* fixes #13722

* better fix
2020-03-23 15:47:10 +01:00
Araq
e05fd1d00f hotfix: make 'nim doc nimhcr' work on all platforms 2020-03-23 13:05:29 +01:00
Araq
bcccb74429 trees.nim: compare floating points by their bitpatterns because NaN comparisions are always false (WORST design in the history of computing!) 2020-03-23 12:06:33 +01:00
Araq
ee440df02d disable even more of scope based destruction handling; fixes #13709 2020-03-23 12:05:59 +01:00
Araq
28a755dc80 trees.nim: compare floating points by their bitpatterns because NaN comparisions are always false (WORST design in the history of computing!) 2020-03-23 12:05:59 +01:00
Timothee Cour
913bc95964 new syntax for lvalue references: var b {.byaddr.} = expr (#13508)
* new syntax for lvalue references: `var b {.byaddr.} = expr`
* on type mismatch, `???(0, 0)` not shown anymore
* * compiler now lowers `var a: {.foo.}: MyType = expr` to foo(a, MyType, expr)
* new pragmas.byaddr defined in pure library code exploiting this lowering
* skip `template foo() {.pragma.}`
2020-03-23 11:15:45 +01:00
Andy Davidoff
fa06203e90 add error for missing commandLineParams (#13719)
* add error for missing commandLineParams

* fixup

* rewrite
2020-03-23 11:08:37 +01:00
Andreas Rumpf
7ee08b8cf6 Revert "fix #13417 (#13712)" (#13728)
This reverts commit a5f02cac85.
2020-03-23 09:57:17 +01:00
Christian Ulrich
0ac9c7bb64 introduce getPeerCertificates, fixes #13299 (#13650)
* make i2d_X509 and d2i_X509 always available

i2d_X509 and d2i_X509 have been available in all versions of OpenSSL, so
make them available even if nimDisableCertificateValidation is set.

* introduce getPeerCertificates, fixes #13299

getPeerCertificates retrieves the verified certificate chain of the peer
we are connected to through an SSL-wrapped Socket/AsyncSocket. This
introduces the new type Certificate which stores a DER-encoded X509 certificate.
2020-03-22 21:00:37 +01:00
Araq
ef2566218e better error messages for Nim's effect system 2020-03-22 20:45:03 +01:00
Araq
4c1fdc2e8f Windows API callbacks cannot raise exceptions 2020-03-22 20:45:03 +01:00
Arne Döring
a5f02cac85 fix #13417 (#13712)
* fix #13417

* add test
2020-03-22 20:03:51 +01:00
Arne Döring
64ffa17f0f fixes #13715 (#13716)
* fixes #13715

* fix test
2020-03-22 20:01:01 +01:00
Araq
474dd98125 typo 2020-03-22 19:45:02 +01:00
Arne Döring
047d3af6da fix #13720 (#13721) 2020-03-22 19:35:55 +01:00
Hiroki Noda
86b9435138 Add EPOLLEXCLUSIVE (#13718) 2020-03-21 22:52:44 +01:00
cooldome
586ebb090b fixes #13708 (#13711)
* fixes #13708
* differentiate between arc and rest of GC

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-21 07:12:10 +01:00
narimiran
b6e04eafce [ci skip] add back unintentionally removed line 2020-03-20 17:15:48 +01:00
Federico Ceratto
5b85444244 SSL certificate verify GitHub action (#13697)
* Implement SSL/TLS certificate checking #782

* SSL: Add nimDisableCertificateValidation

Remove NIM_SSL_CERT_VALIDATION env var
tests/untestable/thttpclient_ssl.nim ran successfully on Linux with libssl 1.1.1d

* SSL: update integ test to skip flapping tests

* Revert .travis.yml change

* nimDisableCertificateValidation disable imports

Prevent loading symbols that are not defined on older SSL libs

* SSL: disable verification in net.nim

..when nimDisableCertificateValidation is set

* Update changelog

* Fix peername type

* Add define check for windows

* Disable test on windows

* Add exprimental GitHub action CI for SSL

* Test nimDisableCertificateValidation
2020-03-20 17:11:39 +01:00
Timothee Cour
1d665adecd [RFC] 'walkDir' now has a new 'checkDir' flag, to mimic behaviour of other languages (#13642)
Co-authored-by: narimiran
2020-03-20 16:39:55 +01:00
Araq
8215c57666 threadpool.nim: allow control over MaxThreadPoolSize and MaxDistinguishedThread; refs #10584 2020-03-20 15:07:11 +01:00
Joey
0f2377ebef Revert –#13658 for nim-gdb.bat. Fixes #13705 (#13707) 2020-03-20 14:38:33 +01:00
Andreas Rumpf
253e1b9e96 fixes #13698 (#13706) 2020-03-20 14:35:45 +01:00
Hayden
f4dbdd311f Detect Ubuntu by checking release() and uname() (#13704)
This will improve detection of Ubuntu when running on Ubuntu on WSL. #13703
2020-03-20 10:59:05 +01:00
Araq
dae9865b14 fight the code bloat in base64.nim 2020-03-20 10:46:58 +01:00
Araq
12ab5059a0 make 'nim check' more robust for illdefined constants 2020-03-20 10:46:40 +01:00
Juan Carlos
70d93636cb Add Base64 safe (#13672)
* Implement RFC-4648 Section-7
* https://github.com/nim-lang/Nim/pull/13672#issuecomment-600993466
2020-03-20 10:21:42 +01:00
Timothee Cour
dd362ab4c0 fix #13538 sigmatch errors are now sorted (#13701)
* fix #13538 sigmatch now sorted and has reliable order

* re-enable tests that were disabled because of that bug

* fix remaining tests and un-disable 2 other tests that were affected by this bug
2020-03-20 09:28:03 +01:00
Juan Carlos
55d3780b7b Remove 2 old deprecated files (#13702) 2020-03-20 09:24:35 +01:00
Jasper Jenkins
1037318e68 fix nimsuggest warning (#13699) 2020-03-20 09:24:04 +01:00
Jasper Jenkins
28b6b1c3fb fix nimpretty warning (#13700) 2020-03-20 09:22:40 +01:00
Andreas Rumpf
35fb38629f cycle breaker (#13593)
* cycle breaking as an alternative to cycle detection
2020-03-19 22:58:16 +01:00
Juan Carlos
705e283fef Clean 1 old deprecated empty file (#13696) 2020-03-19 20:40:52 +01:00
cooldome
b3176b8817 Attempt to finish off araq cpp exceptions (#13695)
* config update
* disable a questionable test
* remove c++ exception handling IDs, new impl doesn't require it anymore
* C++ based exceptions finally work
* fixes bootstrapping problem in C++ mode
* teach GCC it's 2020 now
* more bugfixes for C++ based exception handling
* apply cooldome's patch
* another attempt to enable C++11
* bug fix

Co-authored-by: Araq <rumpf_a@web.de>
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-19 20:38:25 +01:00
Andreas Rumpf
034dad8e32 fixes #13691 (#13694) 2020-03-19 12:57:45 +01:00
Timothee Cour
1f2042411a fix #13412 nim now recompiles for stdin input; SuccessX now configurable; can show whether it recompiled (#13506)
* fix #13412 nim now recompiles for stdin input; SuccessX now indicates whether it recompiled
2020-03-19 10:39:18 +01:00
Timothee Cour
a17e87b516 fix #11458 oswalkdir (#13689)
* fix #11458 oswalkdir

* changelog
2020-03-19 10:23:05 +01:00
Andreas Rumpf
ba6e7c6365 added a switch -d:nimEmulateOverflowChecks for broken or old GCC versions (#13692) 2020-03-19 09:56:30 +01:00
Miran
b5c9881a30 add move to tables to prevent warnings when compiled with --gc:arc (#13684) 2020-03-19 09:09:01 +01:00
alaviss
b33335d7fd httpcore: deprecate ==(string, HttpCode) (#13682)
According to [RFC7230], the reason phrase attached to the status line is
optional and clients should not rely on it. This in turn causes the proc
to be practically useless, as clients should only inspect the return
code.

Ref #13680.

[RFC7230]: https://tools.ietf.org/html/rfc7230#section-3.1.2
2020-03-19 09:07:44 +01:00
Andreas Rumpf
c74cee4e6a gc.rst that doesn't lie (#13686) 2020-03-19 06:41:54 +01:00
Andreas Rumpf
15ba765ebd enable --tlsEmulation:on for --gc:arc (#13685)
* enable --tlsEmulation:on for --gc:arc
* make -d:useMalloc work with --gc:arc --threads:on
2020-03-18 23:52:49 +01:00
Juan Carlos
a0ccfd16a7 Documentation GC (#13109)
* Update Documentation about GC, add ARC based on code observations and https://forum.nim-lang.org/t/5734#35562

* Rephrase 'Garbage Collector' on documentation, see #13331

* Peer Review Feedbacks

* When the body of a documentation section is all for garbage collector details then add 'for garbage collectors' to the title to identify they may not apply for ARC

* Change 'GC' for 'garbage collector'.

* Move 'Memory Management Strategies' at the top, without changes

* Move the info for RefC GC from 'Introduction' to 'RefC' section without changes, make 'Introduction' about Nims 'Multi-paradigm Memory Management Strategies'.
2020-03-18 22:55:39 +01:00
Arne Döring
88566cc651 allow category nimble-packages to test a single package (#13576) 2020-03-18 21:36:48 +01:00
Andreas Rumpf
fb641483f0 arc optimizations (#13325)
* scope based destructors
* handle 'or' and 'and' expressions properly, see the new test arc/tcontrolflow.nim
* make this branch mergable, logic is disabled for now
2020-03-18 16:57:34 +01:00
Araq
a96842aaeb removed .gitattributes as it only causes trouble for me 2020-03-18 14:43:39 +01:00
Andreas Rumpf
3f29911a94 new feature: --staticBoundChecks:on to enforce static array index checking (#10965) 2020-03-18 14:25:10 +01:00
Timothee Cour
ed263e174e fix #13524 astToStr now works inside generics (#13681) 2020-03-18 13:43:32 +01:00
Andreas Rumpf
a87062393a fixes #13622 (#13679) 2020-03-18 13:42:33 +01:00
Araq
3f1a85b7f0 fixes hash(HashSet) which was wrong as it didn't respect tombstones; refs #13649 2020-03-18 10:47:58 +01:00
Andreas Rumpf
5f6997794e fixes #13671 [backport] (#13678) 2020-03-18 10:37:36 +01:00
Jasper Jenkins
51bd442b88 fix when statements in inheritable generic objects (#13667) [backport] 2020-03-17 23:44:32 +01:00
Jasper Jenkins
122751aa52 add nnkMacroDef to RoutineNodes (#13676) 2020-03-17 23:41:07 +01:00
Andreas Rumpf
fe7b1dfb2a rewritten goto based exception handling; much cleaner implementation;… (#13677)
* rewritten goto based exception handling; much cleaner implementation; fixes #13668
2020-03-17 23:18:43 +01:00
Araq
b737bb4be0 fixes a bug for 'dup' and 'with'; they can now handle nested statement lists that can result from macros 2020-03-17 18:00:11 +01:00
cooldome
35d14095ed Fixes #13659 (#13674)
* fixes #13659

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-17 16:36:38 +01:00
Timothee Cour
af9c852701 fix nim doc subdir/foo which was generating broken css; + other fixes (#13647)
* docgen: minor refactoring via docOutDir
* fix css for `nim doc subdir/foo` without --outdir nor -o
* tcompilesetting.nim: keep `git status` clean
* re-enable pkg nimgame2 that got fixed upstream
2020-03-17 13:44:37 +01:00
Jasper Jenkins
6a23452bf4 fix sets of scoped imported enums (#13666) 2020-03-17 10:47:27 +01:00
Andreas Rumpf
bec0522fca updated builds.sr.ht script according to their email (#13669) 2020-03-17 08:49:26 +01:00
Leorize
e5adaeed20 workflows/ci: disable
Since we got Azure Pipelines running, this will be a fallback pipeline.

Activate by removing the `.disabled` suffix
2020-03-17 08:48:42 +01:00
Leorize
5017320e7b gitattributes: fix tests for windows
Nim-generated files used in tests all end in LF, so we tell git to not
touch them. Should allow a Windows user to clone and run tests without
having to tweak their git settings
2020-03-17 08:48:42 +01:00
alaviss
6e4cd3e5bf .github/workflows: new CI pipeline (#13656)
* .github/workflows: new CI pipeline

As Azure Pipelines went offline, this will be our (temporary?)
replacement. This pipeline covers everything that Azure Pipelines does.

* workflows/ci: disable pipeline

* workflows/ci: properly disable the pipeline

* gitattributes: .txt used in tests should be LF-terminated

This avoids test failures when the compiler was cloned on an OS where
git attempts to convert LF->CRLF.

We target only .txt in tests/ as the minimum required to keep tests
running correctly.

* workflows/ci: re-enable for testing
2020-03-16 23:02:50 +01:00
Andreas Rumpf
955b31a7d9 fixes #13654 2020-03-16 23:00:43 +01:00
Araq
d375120c42 rename sfAlwaysReturn to sfNeverRaises 2020-03-16 19:05:33 +01:00
Andreas Rumpf
5ba5b5202a fixes #13661 (#13664) [backport] 2020-03-16 18:40:17 +01:00
Araq
b9b53b6ca1 fixes #13645 2020-03-16 16:24:50 +01:00
Andy Davidoff
0f672378ab fix .deprecated. object typedef crash (#13643)
* fix .deprecated. object typedef crash
* fixup a test that i don't understand
* disable the test rather than debug ci
2020-03-16 15:08:38 +01:00
Araq
a102eb5ef6 fixes #13646 2020-03-16 14:55:58 +01:00
Araq
3a6b470412 minor code style change 2020-03-16 14:55:58 +01:00
Araq
7205c3ebe2 minor code style changes 2020-03-16 14:55:58 +01:00
cooldome
613ea6e85e fixes #12747 [backport] (#13651)
* fixes #12747
* fix tests
* improve code style

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-16 13:40:40 +01:00
Kartik Saranathan
fe53f6ef4f fix typo (#13660) [ci skip] 2020-03-16 09:07:10 +01:00
Joey
fd3583803e Fix gdb scripts (#13658)
* Fix nim-gdb and rename to nim-gdb.bash
* Add symlink to nim-gdb.bash
* Fix windows debug script
* Add PR suggestions
* Make readlink check easier to maintain/understand
* Swap symlinks
2020-03-16 08:59:16 +01:00
alaviss
ae5094e143 azure-pipelines: walkaround issues with triggers (#13657)
See https://status.dev.azure.com/_event/179641421
2020-03-15 23:44:07 +01:00
Timothee Cour
6e0c06f50e fix #13218: avoid some irrelevant warnings for nim doc,rst2html,--app:lib, + other fixes (#13550)
* fix #13218: avoid some irrelevant warnings for nim doc,rst2html
* suppress warnRedefinitionOfLabel for nim doc
* lots of fixes for UnusedImport warnings
2020-03-13 20:42:41 +01:00
Timothee Cour
380a505507 azure-pipelines: use OSX 10.15 (was just enabled upstream) (#13546) 2020-03-13 14:02:47 +01:00
Araq
9eeb514dda disable nimgame2 for now 2020-03-13 11:50:39 +01:00
Andreas Rumpf
a6682de004 catchable defects (#13626)
* allow defects to be caught even for --exceptions:goto (WIP)
* implemented the new --panics:on|off switch; refs https://github.com/nim-lang/RFCs/issues/180
* new implementation for integer overflow checking
* produce a warning if a user-defined exception type inherits from Exception directly
* applied Timothee's suggestions; improved the documentation and replace the term 'checked runtime check' by 'panic'
* fixes #13627
* don't inherit from Exception directly
2020-03-12 23:44:33 +01:00
Miran
14b2354b7d rename lenTuple and lenVarargs (#13639)
* rename 'lenTuple' to 'tupleLen'

Rationale:
`lenTuple` is a tuple consisting of lengths (e.g. `(1, 5, 0)`),
`tupleLen` is a length of a tuple (e.g. `tupleLen((1, 5, 0) == 3`)

* rename 'lenVarargs' to 'varargsLen'

The same rationale as a previous commit. Consistency.
2020-03-12 20:07:02 +01:00
Clyybber
f0cd50f9c4 Change order of forwarded koch boot command line options, so as to be able to overwrite the nimcache location (#13637) 2020-03-12 16:15:46 +01:00
Timothee Cour
60a3e036f6 fix #13633 fix koch boot crashing regression (#13635) 2020-03-12 11:39:10 +01:00
Clyybber
2bb0ada797 Amend fix for #13633 (#13636) 2020-03-12 11:20:08 +01:00
Clyybber
d84c4bba9b Fix #13633 2020-03-12 11:01:03 +01:00
genotrance
bbc231f8e0 Fix #12676 (#13634) 2020-03-12 08:53:11 +01:00
Kaushal Modi
64995db4fd unicode.split: Fix the splitting when a Rune separator is used [backport] (#13629)
* unicode.split: Fix the splitting when a Rune separator is used [backport]

- Fixes https://github.com/nim-lang/Nim/issues/13628
- Ref https://irclogs.nim-lang.org/11-03-2020.html#20:01:34

* unicode.split: Remove the sepLen based logic.. resulted in wrong jumps
2020-03-12 00:41:45 +01:00
treeform
f2c7152770 Add more JS stuff to dom.nim (#13483)
* Add more JS stuff to dom.nim

* Make all links to docs doc comments.

* Fix minor textContent * space.

* Remove Selection object.

* More work on docs.

* Fixing links.

* Made the links be "see <docs>".
2020-03-11 23:24:56 +00:00
Clyybber
6b3098c378 Make listCmd honor hint:cc:off (#13606)
* Make listCmd honor hint:cc:off

* Tiny cleanup

* Tiny tiny cleanup

* VERY IMPORTANT: --hint:cc:on will overwrite --verbosity:0 :p

* Tiny cleanup

* Stupid

* Move displayProgressCC to where its required

* Tiny cleanup
2020-03-11 23:04:33 +01:00
Miran
70bd41dae0 fix #13310, Deque misbehaves on VM (#13625)
* fix #13310, Deque misbehaves on VM
* use 'when nimVM'
2020-03-11 17:30:36 +01:00
Timothee Cour
281e02fc79 fixes #13558: toDateTime buggy on 29th, 30th and 31th of each month; breaking change: do not use now to compute result, was undocumented and non-sensical (#13565) 2020-03-11 09:47:34 +01:00
Araq
f5f9243cc0 disable chronos testing for now 2020-03-11 09:28:10 +01:00
Araq
3aed8ff432 fixes async regression 2020-03-11 09:26:57 +01:00
Araq
60f8fdcdab fixes #13240 2020-03-11 09:26:57 +01:00
Araq
861a5340fe fixes #13519 2020-03-11 09:26:57 +01:00
Araq
b0684ec425 fixes #12757 2020-03-11 09:26:57 +01:00
Arne Döring
f95eef99a9 add expectIdent to macros (#12778)
* add expectIdent to macros

* apply feedback

* Update lib/core/macros.nim

Co-Authored-By: Clyybber <darkmine956@gmail.com>

* Update texpectIdent2.nim

* Update texpectIdent1.nim

Co-authored-by: Clyybber <darkmine956@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-03-11 08:27:31 +01:00
めぐみ発動機 (isVowel / GreenWing)
8e3a349561 fixed to jsonArrayEnd comment. (#13624)
typo: start → end
2020-03-11 08:26:10 +01:00
Arne Döring
2f557652d4 fix operators containing percent for VM usage (#13536)
* fixes #13513
* merge tarithmetics in tarithm
2020-03-11 01:01:25 +01:00
Timothee Cour
e64f1c7ee4 koch --nim:pathto/nim boot and koch boot --hint:cc:off now work (#13516)
* `koch boot --hint:cc:off` now works

* `koch --nim:pathto/nim boot` now works; code cleanup
2020-03-11 00:31:34 +01:00
Araq
3b7b017798 fixes #13607 2020-03-10 16:01:13 +01:00
Araq
9e2bce2a8c hotfix: make --useVersion:1.0 work 2020-03-10 16:01:13 +01:00
genotrance
ab5d962b50 Revert "Support cross compiling from host to host (#12859)" (#13591)
This reverts commit e4f7656772.
2020-03-10 15:58:27 +01:00
Andreas Rumpf
090ba1e3a3 fixes #13436 (#13615) 2020-03-10 00:52:46 +01:00
narimiran
7d07897a99 travis now only builds devel docs 2020-03-09 21:16:56 +01:00
Andreas Rumpf
ec5cef13cf fixes #13599 (#13614) 2020-03-09 18:12:52 +01:00
Andreas Rumpf
63af8ae53c fixes #13596 (#13612) 2020-03-09 15:32:38 +01:00
Miran
4aecc6b346 fix #12508, unaligned access on sparc64 (#13594) 2020-03-09 14:08:50 +01:00
Andreas Rumpf
dc94c81cb0 fixes #13605 (#13611) 2020-03-09 13:13:54 +01:00
Andy Davidoff
a693ce7765 surgical fix for #13319 (#13604) 2020-03-08 10:55:19 +01:00
Clyybber
eae31a7f8d Only print the link command when listCmd is active; fix docs (#13603) 2020-03-07 23:53:43 +01:00
Juan Carlos
6a5b3811e7 Add isValidFilename (#13561)
* Add os.isValidFilename

* Add os.isValidFilename

* Peer Review Feedbacks https://github.com/nim-lang/Nim/pull/13561#discussion_r388013139

* Peer Review Feedbacks https://github.com/nim-lang/Nim/pull/13561#issuecomment-595259568

* Add since to const

* Update the documentation comment

* Update the changelog

* Update lib/pure/os.nim

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>

* Update lib/pure/os.nim

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>

* Peer Review Feedbacks, Add more Tests

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
2020-03-07 14:10:22 +00:00
Zed
e056298ceb Implement file streaming for httpclient's MultipartData (#12982)
* Add `uploadFile` to POST files by streaming them

* Use constant for \c\L

* Formatting

* Remove uploadFile

* Implement MultipartData file streaming

* Remove unnecessary var annotations

* Call string on TaintedStrings

Fixes #12789

* Move cl constant to httpcore

* Fix `request` inconsistencies

* Update documentaion

* Clean up

* Skip multipart formatting when there's 0 entries

* Remove extraneous `cl` from multipart formatting

* Update MultipartData `$` to match old behaviour

* Update comment

* Address comments
2020-03-06 18:55:45 +00:00
Andrea Ferretti
7ae0811818 Fix #13573 and #13574 (#13575)
* Fix https://github.com/nim-lang/Nim/issues/13573 and https://github.com/nim-lang/Nim/issues/13574

* Restored asynchttpserver
2020-03-06 18:38:56 +00:00
alaviss
4bd388ad58 Revert "nimsuggest: don't add CRLF to replies (#13545)" (#13597)
This reverts commit a974684b14.

The CRLF was to separate between each response, and removing them causes
the responses to not be splitted correctly.

I didn't notice that it was in a loop when I made the #13545.
2020-03-06 19:29:28 +01:00
Dominik Picheta
ec8a17cc86 Revert broken asynchttpserver FutureStream additions.
As discussed in #13394, these changes cannot work. Reverted via

```
git revert --no-commit 5bf571f061
git revert --no-commit abd660c407
git revert --no-commit 955465e5f4
git commit
```
2020-03-06 11:52:30 +01:00
Timothee Cour
b80d293a3f close #12704 by adding a test (tuple codegen error) (#13592)
* close #12704 by adding a test

* move test to tests/metatype/ttypedesc2.nim
2020-03-06 08:55:53 +01:00
Andreas Rumpf
cb0f7c5d9e Removed simpleGetOrDefault (#13590) 2020-03-05 21:03:39 +01:00
Andreas Rumpf
83e715c5b6 fixes #5170 (#13589)
* fixes #5170

* make tests green
2020-03-05 16:02:34 +01:00
Andreas Rumpf
62c113ebc7 fix #13579 joinPath("/foo/", "../a") is now /a (#13586) 2020-03-05 15:31:22 +01:00
Varriount
357edd86b4 fix nightlies builds on Windows (#13587)
Before the files that should have been ignored weren't ignored
because of different dir separator ('\' vs '/') on Windows.
2020-03-04 14:44:42 -05:00
alaviss
a974684b14 nimsuggest: don't add CRLF to replies (#13545)
This is already sent by replTcp after the message is sent.
2020-03-04 15:56:40 +01:00
Andreas Rumpf
a0eca75182 sink parameter inference for types that have destructors (#13544)
* ensure capitalize doesn't take an inferred sink parameter

* sink parameter inference: first version, for now disabled. Changed that sink parameters can be consumed multiple times in order to adhere to our spec.

* sink inference can now be disabled with .nosinks; sometimes for proc type interop this is required

* fixes yet another critical DFA bug

* better implementation that also understands if expressions etc

* document sink parameter inference and allow for global disabling
2020-03-04 14:28:53 +01:00
Andreas Rumpf
614fb7567c std/compilesettings implementation (#13584)
* Implement compileSetting() and compileSettingSeq()
* Change from magic to vmop
* better design for querySetting

Co-authored-by: genotrance <dev@genotrance.com>
2020-03-04 13:46:42 +01:00
Juan Carlos
0809098971 Nimpretty Fix negative indent breaks code (#13580) 2020-03-04 10:27:52 +01:00
Timothee Cour
9fa070b1dc fix hintSuccess: out was wrong for nim doc without -o flag (#13569) 2020-03-04 10:26:56 +01:00
Miran
9961d1f67d fix #13531 by adding a test (#13581) 2020-03-04 10:25:59 +01:00
hlaaftana
34c16f5eca fix #13409: Document as infix operator (#13570) 2020-03-04 07:50:36 +01:00
narimiran
3ca8f0bde6 [ci skip] important_packages: change the order in commented out packages too 2020-03-04 07:15:34 +01:00
Araq
8705ee7015 ARC hotfix; proper destruction of seqs and strings after a move 2020-03-03 23:03:33 +01:00
genotrance
f8175688a3 Fix docgen snippet numbering (#13507) 2020-03-03 20:52:16 +01:00
Miran
e8c057fb27 important_packages: change the order of arguments in the template (#13577)
Leads to a cleaner and less confusing code - an empty command
doesn't mean 'nimble test' anymore.
2020-03-03 16:25:59 +01:00
Arne Döring
eb42f38088 Remove dead magics (#13551) 2020-03-03 12:42:43 +01:00
Timothee Cour
31332bca45 workaround refs #13563 freebsd CI (#13564) 2020-03-02 22:30:41 -05:00
Timothee Cour
451b724c40 make genericParams support static[T] generic params (#13433)
* make genericParams support static[T] generic params

* WrapStatic => StaticParam
2020-03-02 18:05:14 +01:00
Timothee Cour
27241fda23 fix #13528 nimgrep --word now works better with operators (#13537) 2020-03-02 17:55:17 +01:00
PMunch
05e9473f80 Add signatures object to jsondoc for routine types (#13530)
jsondoc is meant to be read by computers, but yet the signatures of
procedures where simply a string of the whole thing. This adds a
signature object that unpacks this information into an object so it's
easier to analyse the documented signatures.
2020-03-02 17:52:42 +01:00
Timothee Cour
653de5f27a fix broken nim CI, disable blscurve (#13555) 2020-03-02 10:26:10 +01:00
Timothee Cour
22d1ba4be7 fixes #13543 and added times.isLeapDay (#13547) 2020-03-01 21:56:20 +01:00
hlaaftana
525ab5a497 Document import/include outside of top level semantics (#13548) 2020-03-01 21:52:29 +01:00
cooldome
0f1a4ac96c make it possible to pass linker options for vcc (#13535) [backport] 2020-02-29 18:57:00 +01:00
cooldome
c79df2fb6a EndsInNoReturn in expressions extension, fixes #13490 (#13520)
* fix #13490
2020-02-28 09:55:06 +00:00
cooldome
25dc5f76e0 fixes #12627 (#13521)
* fixes #12627
2020-02-28 09:54:17 +00:00
Timothee Cour
1056f9ecff properly handle note override logic/verbosity/config/cmdline using modifiedyNotes, cmdlineNotes 2020-02-27 13:22:18 +01:00
Timothee Cour
c1cbf94e2d remove isCmdLine; use passCmd1 2020-02-27 13:22:18 +01:00
Timothee Cour
ce36fdc897 correctly honor cmdline --hint:conf:on/off ; correctly show Conf hints in order 2020-02-27 13:22:18 +01:00
Ganesh Viswanathan
96bffadf60 Fix #9405 - cfg and nims run in sync 2020-02-27 13:22:18 +01:00
Timothee Cour
73f5f1e80c save another 33s of CI for tests/gc/gcleak.nim 2020-02-27 13:19:31 +01:00
Timothee Cour
fdc5925cbd CI tests run faster: save 120s in azure machines, 335s on local OSX 2020-02-27 13:19:31 +01:00
Timothee Cour
9b8c9abead revert changes to tests/gc/gcleak2.nim 2020-02-27 13:19:31 +01:00
Timothee Cour
81b0718a8f make CI tests faster + more precise 2020-02-27 13:19:31 +01:00
solo989
e84e01cb8c Update pegs.nim to work at compiletime. No range errors. (#13459) 2020-02-27 11:08:57 +01:00
Timothee Cour
6a0e87eb38 cleanup Ordinal (#13501) 2020-02-27 10:43:13 +01:00
Timothee Cour
42dad3a836 tables/sharedtables/intsets/etc: fix #13496, #13504, #13505; add lots of tests (#13498) [backport]
* fix #13496 handle tombstones
* add test
* more tests
* fix #13504; add SharedTable tests
* fix #https://github.com/nim-lang/Nim/issues/13505 intsets.missingOrExcl silently gave wrong results sometimes
* add test for tintsets
2020-02-26 22:07:09 +01:00
Miran
9a93f73983 docgen: don't create compiler's docs + cleanup (#13509) 2020-02-26 20:37:27 +01:00
Andreas Rumpf
d55bbefdcc added operateOn to sugar.nim to give Nim the chaining mechanism it de… (#13092)
* implemented the with stdlib module as specified in https://github.com/nim-lang/RFCs/issues/193
* change sugar.outplace to sugar.dup according to https://github.com/nim-lang/RFCs/issues/193
* changelog update
2020-02-26 20:36:06 +01:00
Kaushal Modi
f091b5a0ee xmltree: Make indentation consistent with any num of children nodes (#13482)
Ref: https://forum.nim-lang.org/t/5972
2020-02-26 11:41:44 +01:00
Timothee Cour
0c312ad898 fix #13455 ; joinPath(a,b) now honors trailing slashes in b (or a if b = "") (#13467)
* fix #13455 ; joinPath(a,b) now honors trailing slashes in b (or a if b = "")
* fix test windows
2020-02-26 11:25:27 +01:00
Timothee Cour
11db28bc61 runCI: logs now show CPU/OS/etc info to be self contained (#13486) 2020-02-26 10:44:23 +01:00
Timothee Cour
bd90199a2f fix #8312 --hints:off and --warnings:off now honored everywhere (#13489) 2020-02-26 10:26:47 +01:00
Juan Carlos
94b0d6bb63 Documentation staticRead maximum file size limits (#13485) 2020-02-26 10:01:23 +01:00
Arne Döring
5d2483fb64 fix #13479 (#13503) 2020-02-26 09:51:07 +01:00
Kaushal Modi
e4ed19c12f [backport] tut1: Update the proc overloading examples (#13497) [skip ci] 2020-02-25 21:19:51 +01:00
Timothee Cour
db540a0223 fix #13449 texitcode flaky on windows (#13487) 2020-02-25 17:49:16 +01:00
narimiran
c444ab9a54 make devel green again: tnetdial still doesn't work on Travis 2020-02-25 08:46:08 +01:00
Timothee Cour
1cf5c280e3 only enable linenoise for -d:nimUseLinenoise (#13478)
* only enable linenoise for -d:nimUseLinenoise

* fixup
2020-02-24 11:06:39 +01:00
hlaaftana
84e78b4ffc Minor doc change in macros, future -> sugar (#13475) [ci skip] 2020-02-24 09:57:15 +01:00
Miran
3e8858d694 add more files to the ignore list, hopefully fixes nightlies on windows (#13474) 2020-02-24 09:41:28 +01:00
Andrey Makarov
3dad130034 fix 3 minor bugs in joinPath (see #13455) (#13462) [backport] 2020-02-23 20:22:46 +01:00
hlaaftana
13d292786e Remove genToArray in jsgen, a PHP remnant (#13466) 2020-02-22 20:04:46 +01:00
Lee Matos
c11b91d52d Update advopt.txt to include link to nim cache docs (#13464) 2020-02-22 09:09:04 +01:00
Timothee Cour
a43583f9c8 relativePath("foo", "foo") is now ".", not "" (#13452) 2020-02-22 09:07:53 +01:00
hlaaftana
1276e386fe Consider proc as a pointer type in options (#13460)
* Consider proc as a pointer type in options

* Add version annotation for SomePointer having proc in options

* Log procs as pointers for options in changelog
2020-02-21 23:14:55 +01:00
Andreas Rumpf
0d219d2c67 fixes #13457 (#13458) 2020-02-21 21:06:41 +01:00
Timothee Cour
e05aca8734 make unzip faster: seq[i]=val can be 7X faster than seq.add(elem) (#13448) 2020-02-21 17:26:52 +01:00
Araq
1d90d9816b fixes #13444 2020-02-21 16:58:30 +01:00
Joey
3667fd9f42 Make gdb script work on mac and linux; add windows gdb script (#13453) 2020-02-21 08:53:05 +01:00
genotrance
7a2b623d2a Fix #8648 - use parent streams to avoid hang (#13445) 2020-02-20 23:04:48 +01:00
Kaushal Modi
bb777fef76 Add sequtils.unzip to complement sequtils.zip (#13429) 2020-02-20 19:15:34 +01:00
Manav
479f4ca6a3 Fixed non-working examples in Manual: Exception Handling (#13424) 2020-02-20 15:16:19 +01:00
Clyybber
87dd19453b Remove testutils (#13435) [backport] 2020-02-19 23:02:08 +01:00
Timothee Cour
8c22518d67 [backport] pseudorandom probing for hash collision (#13418) 2020-02-19 17:19:55 +01:00
Timothee Cour
273a93581f fix incorrect lenTuple implementation (#13423) 2020-02-19 11:07:17 +01:00
alaviss
d1f9f11245 manual: documents changes regarding dynlib (#13425)
* manual: documents changes regarding dynlib

Closes #13416

* manual: clean up sentence phrasing
2020-02-18 19:44:54 +01:00
cooldome
046bb0b881 stdlib/system: add sink and move (#13283) 2020-02-18 19:43:26 +01:00
Nな人(N na hito)
8f73753a2d Update LICENSE (#13421) 2020-02-17 18:40:39 +01:00
Ico Doornekamp
73553621a1 Improved assertion error messages on usage of JsonNode iterators on wrong kinds (#13389) 2020-02-17 09:00:25 +01:00
Khronos
006fe4cfc4 Fix vertical tab in JSON. (#13399)
'\v' is not injected in JSON anymore
2020-02-17 00:39:19 +01:00
Juan Carlos
ba25f849a6 Add browsers.osOpen (#12901)
* Add osOpen alias for the operating system specific open command

* Add `--git.devel` option to the documentation
remove unused import (#12900)

fix json regression D20191212T144944 (#12902) [backport]

Peer Review Feedback https://github.com/nim-lang/Nim/pull/12901#issuecomment-565851680

Merge branch 'devel' of https://github.com/nim-lang/Nim into osopen

Peer Review Feedback https://github.com/nim-lang/Nim/pull/12901#issuecomment-565851680

Update lib/pure/browsers.nim

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>
Peer Review Feedback https://github.com/nim-lang/Nim/pull/12901#discussion_r358492316

allow typed/untyped in magic procs (#12911)

NaN floatFormat with clang_cl  (#12910)

* clang_cl nan floatFormat

* format

add $nimeq for gdb (#12909)

ARC: cycle detector (#12823)

* first implementation of the =trace and =dispose hooks for the cycle collector
* a cycle collector for ARC: progress
* manual: the .acyclic pragma is a thing once again
* gcbench: adaptations for --gc:arc
* enable valgrind tests for the strutils tests
* testament: better valgrind support
* ARC refactoring: growable jumpstacks
* ARC cycle detector: non-recursive algorithm
* moved and renamed core/ files back to system/
* refactoring: --gc:arc vs --gc:orc since 'orc' is even more experimental and we want to ship --gc:arc soonish

Cleanup leftovers of #12911(#12916)

Fix single match output (#12920)

fixes #12899 (#12921)

* fixes #12899

* fixes regression: destroy global variables in reverse declaration order, closureleak test relies on it

Implement NixOS distro check (#12914)

Better case coverage error message for alias and range enum (#12913)

fix error in assertions document (#12925) [backport]

fix cmdline bugs affecting nimBetterRun correctness (#12933) [backport]

fix #12919 tasyncclosestall flaky: Address already in use (#12934)

system.reset is no longer magic (#12937)

It has now means setting x to default for new and old runtime alike
Fix #12785 (#12943)

* Fix #12785 and add test

* better variable name

update documentation for `closureScope` and `capture` (#12886)

fixes #12735 on osx, call dsymutil for debug builds (#12931)

* fix #12735 osx: dsymutil needs to be called for debug builds
* also write dsymutil command to extraCmds in json build file

Auto-initialize deques (#12879)

case coverage error message for `char` (#12948)

lenVarargs: number of varargs elements (#12907)

docs: tiny style improvements

added guidelines for evolving Nim's stdlib

fixes a bug that kept sugar.collect from working with for loop macros [backport]

fixes #12826

fixes a regression

a better bugfix

fixes a test case

fixes a silly regression

fixes the distros.nim regression

ported channels to ARC

ported osproc.nim to ARC

ported re.nim to ARC

ARC: default to a shared heap with --threads:on

osproc: fixes regression

fixes another regression

fixes #12945 (#12959)

minor refactorings

Fixes stackoverflow links in readme (#12963) [backport]

Allow customize Host header
[ci skip] docfix .. < => ..< (#12981) [backport]

parsecfg: retain CRLF line breaks, fixes #12970 (#12971)

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.}

Added fix for handling TaintedStrings in streams and httpclient (#12969)

* Added fix for taint mode in streams and httpclient

* Removed taintMode export from system.nim

Check pqntuples > 0 in getValue. Fixes #12973 (#12974)

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.
fixes #12989

Revert "fixes #12989"

This reverts commit 928c2fee06.

fixes #12965 (#12991)

fixes #12989 (#12992)

* fixes #12989
* Revert "remove unwanted changes"

This reverts commit 501829732a.

fixes disruptek/nimph#102 multi-level nim.cfg use (#13001) [backport]

--exception:goto switch for deterministic exception handling (#12977)

This implements "deterministic" exception handling for Nim based on goto instead of setjmp. This means raising an exception is much cheaper than in C++'s table based implementations. Supports hard realtime systems. Default for --gc:arc and the C target because it's generally a good idea and arc is all about deterministic behavior.

Note: This implies that fatal runtime traps are not catchable anymore! This needs to be documented.
fix #12985 {.push.} now does not apply to generic instantiations (#12986)

Sink to MemMove optimization in injectdestructors (#13002)

remove default argument for readLines (#12807) [backport]

fixes #12978 (#13012)

Fix typo (#13015) [backport]

fixes #12961 (#13019)

fixes #12956 (#13020)

fix #12988 (#13022)

fix #12988
Fixes #13026 (#13028)

fixes #12964 (#13027)

fixes #13032

VM: support importc var, ptr/pointer types, cast int <=> ptr/pointer (#12877)

* VM: allow certain hardcoded special var variables at CT
* VM: allow all importc var, cast[int](ptr)
* fix tests tests/vm/tstaticprintseq.nim, tests/cpp/t8241.nim
* VM: == works for ptr/pointer nodes
* bugfix: ==, cast now also works for pointer, not just ptr
* VM supports cast PtrLikeKinds <=> PtrLikeKinds / int
* improve cname handling
* fixup + bug fix
* VM: support cast from ref to int
* address comment: opcLdGlobalDeref => opcLdGlobalDerefFFI
* defensive check against typ == nil

fix enumtostr crash for enum-range (#13035)

fixes #13013, reverts previous changes to readLines() (#13036) [backport]

* Revert "remove default argument for readLines (#12807) [backport]"

This reverts commit c949b81efd.

reprjs: style changes

fixes #12996

Rst parser respect `:start-after:` and `:end-before:` in `include` directive (#12972)

* [FEATURE] rst parser respect :start-after: in include

Rst parser now respects `:start-after:` and `:end-before:` attributes
for `include` directive.

* [DOC] include directive parsing proc update

* [TEST] Added unit tests for include rst directive in `rst` module

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.
[cleanup] remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits (#13041)

* remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits

* D20200105T085828 fix super strange bug that causes CI to fail: builds.sr.ht with: `Error: Settle timed out after 120 attempts`

Continue #13002 (#13021)

testament/important_packages dont run hts (#13052)

Modify the test command for nimly (nimble-package) (#13053)

clean up deprecated stuff and unused imports in tests (#13059)

--styleCheck:hint now works (#13055)

[easy] --hint🔗on now shows link cmd instead of nothing (#13056)

* --hint🔗on now shows link cmd instead of nothing

* update doc for --listCmd

add pqserverVersion,pqconnectionNeedsPassword,pqconnectionUsedPassword (#13060)

basename supports pragmaexpr (#13045)

* basename supports pragmaexpr

* update changelog

distinctBase type trait for distinct types (#13031)

make SuccessX show project file + output file (#13043)

* make SuccessX show project file + output file
* address comments
* fix test and add `result.err = reNimcCrash` otherwise hard to see where reNimcCrash used
* address comments

move entries from the wrong changelog file [ci skip]

fix crash due to errant symbols in nim.cfg (#13073) [backport]

Deleted misplaced separator (#13085) [backport]

Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.
take the one good idea from --os:standalone and enable it via -d:StandaloneHeapSize (#13077)

remove all remaining warnings when build nim (with -d:nimHasLibFFI) (#13084)

* cleanup deprecations in evalffi + elsewhere

* remove dead code getOrdValue64

Use '__noinline' instead of 'noinline' for N_NOINLINE gcc attribute, this prevents clashes with systems where 'noinline' might be already defined (#13089)

Fix error check code in osproc (#13090) [backport]

fixes #13072; no test case because it will be added later with more exception handling related bugfixes

fixes #13070

typetraits: fixes #6454; genericParams; added lenTuple; added tuple type get (#13064)

[backport] system/io.nim fix wrong documentation comment [ci skip]

fixes an asyncftpclient bug; refs #13096 [backport]

System cleanup, part 1 (#13069)

* system.nim: mark what every .pop does

* system.nim: un-nest when statements

[backport] fix #12813, fix #13079 (#13099)

Correctly remove a key from CountTable when it is set to zero.
more arc features (#13098)

* config update
* ARC now supports 'repr' and 'new' with finalizers is supported

Remove some unused/disabled OpenSSL functions (#13106)

Add link to posix_utils.html in posix.nim (#13111)

VM FFI: write(stderr, msg) and fprintf(cstderr, msg) now work at CT (#13083)

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

fix rtti sizeof for varargs in global scope (#13125) [backport]

fixes #13122 (#13126)

* fixes #13122

* moved tests to where they belong

fixes #13112 (#13127)

* improve line error information

* fixes #13112

Expose more openSSL methods. (#13131)

fixes #13100 nim doc now treats `export localSymbol` correctly (#13123) [backport]

* fix #13100 nim doc now treats `export localSymbol` correctly
* use owner instead

fixes #13119 (#13128)

* fixes #13119
* fixes a regression

fixes #13105 (#13138)

fixes #10665 (#13141) [backport]

pass platform argument only if vccexe is used (#13078)

* pass platform only if vccexe is used
* fixes #12297

fixes #13104 [backport] (#13142)

fixes #9674 [backport] (#13143)

Fix typo in doc/destructors.rst (#13148)

Added 'ansic' os support for minimal (embedded) targets (#13088)

* os:any implementation
* os:asny: omit flock/funlock calls in echoBinSafe
* Disabled default "unhandled expection" reporting for `--os:any` to reduce
code size. Added unhandledExceptionHook instead which can be used to get
a notification from Nim and handle it from the application.

System cleanup, part 2 (#13155)

* create basic_types, arithmetics, exceptions, comparisons
* create setops.nim
* create memalloc.nim
* create gc_interface.nim
* create iterators_1.nim

export normalizePathEnd (#13152)

successX now correctly shows html output for `nim doc`, `nim jsondoc`; fix #13121 (#13116)

* successX now correctly shows html output for nim doc
* fixes #13121
* fixup hintSuccessX to be less weird

ARC: misc bugfixes (#13156)

* fixes #13102
* closes #13149
* ARC: fixes a move optimizer bug (there are more left regarding array and tuple indexing)
* proper fix; fixes #12957
* fixes yet another case object '=' code generation problem

CI fix timeout error (#13134)

Remove obsolete code from osalloc (#13158)

style fix: change 'JS' to 'js' to make it consistent (#13168)

Working towards arc codegen (#13153)

fixes #13029
fixes #12998 nim doc regression (#13117)

fix tsizeof3 for aarch64 (#13169)

Cleanup DFA (#13173)

Fix docs (#13176)

fixes #13095 (#13181)

* fixes #13095

* fix typo

make case-object transitions explicit, make unknownLineInfo a const, replace a few magic numbers with consts (#13170)

ARC works for async on Windows (#13179)

make sink operator optional (#13068)

* make sink operator optional

* bug fix, add changelog entry

* Trigger build

* fix one regression

* fix test

* Trigger build

* fix typos

Fix docs for subdirs too (#13180)

* Fix doc subdirs
* Extract to helper proc, and fix on windows

followup on #10435 : should be diff, not show (#13162)

fixes #13157

refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.}  (#13136)

* refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.}
* put back NIM_EXTERNC for N_LIB_EXPORT; causes issues with compilerproc

fixes #13144 (#13145)

* fixup: genscript now does not copy nimbase.h but uses -I$nim/lib

times: toUnixFloat, fromUnixFloat (#13044)

maybe: allows optional chaining of field access and indexing when LHS i snil (#13023)

* maybe: allows optional chaining
* fix tools/kochdocs.nim
* improve semantics to distinguish valid from invalid values
* for now, wrapnil, isValid, unwrap are not exported

fix docs + API for fieldPairs, fields (#13189)

more on arc codegen (#13178)

* arc codegen for union type

* add more tests

* fix offsetof

* fix tsizeof test

* fix style

Add link to packaging.html (#13194)

Fixes #13186 (#13188)

fixes #13195

revert last commit

Merge branch 'devel' of https://github.com/nim-lang/Nim into devel

Revert "fixes #13195"

This reverts commit cd7904f2b2.

fixes #13110 (#13197)

fixes #13195 (#13198)

* fixes #13195

* extra fix

* fix typo

compiler/ccgtypes: hide exportc proc unless it has dynlib (#13199)

This hides most of stdlib's internal functions from resulting
binaries/libraries, where they aren't needed on *nix. Static libraries
are not affected by this change (visibility doesn't apply to them).
fix range[enum] type conversion (#13204) [backport]

Idxmin & idxmax, continuation (#13208)

* Add idxmin() which returns the index of the minimum value

* Add idxmax() which returns the index of the maximum value

* Add tests for idxmin()

* Add tests for idxmax()

* Remove initialization of result = 0

* Adds overloading for arrays (no enums indexed arrays yet)

* Add support for enum index arrays

* Fix tests with enum

* Fix tests for idxmax

* Change names of the procedures to minIndex and maxIndex

* address Araq's comments:

- remove 'array' versions
- add .since pragma
- return 'int' instead of 'Natural'
- add changelog entry

Co-authored-by: Federico A. Corazza <20555025+Imperator26@users.noreply.github.com>

fix #13211 relativePath("foo", ".") (#13213)

fixes a critical times.nim bug reported on IRC [backport] (#13216)

httpclient, maxredirects to Natural, newHttpClient/newAsyncHttpClient add headers argument instead of hardcoded empty (#13207)

added note to re constructor regarding performance (#13224)

Since I was new to regex I did not know that there is a compilation going on with ``re"[abc]"`` constructor and so I followed the other examples in the docs blindly, that is I just put the constructor directly in the arguments of match, find, etc., which was inside a loop and then wondered why my performance was so bad. Of course putting it outside the loop made it vastly more performant. People like me would benefit from the small note I added I would think :)
[backport] Documentation Fix #12251 (#13226) [ci skip]

[backport] times/getClockStr(): fix mistake in doc (#13229) [ci skip]

new os.isRelativeTo (#13212)

[backport] Fix typo and improve in code-block of 'lib/pure/parseutils.nim' (#13231) [ci skip]

[backport] fix #11440, add docs to isNil for seq types needing nilseq (#13234) [ci skip]

VM: allow overriding MaxLoopIterations without rebuilding nim (#13233)

kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes (#13221)

* kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes
* fixup after #13212 isRelativeTo got merged

fix lots of bugs with parentDir, refs #8734 (#13236)

Unexport even more symbols (#13214)

* system/gc: don't export markStackAndRegisters

* compiler/cgen: unexport internal symbols

As these functions are Nim-specific walkaround against C's optimization
schemes, they don't serve any purpose being exported.

* compiler/cgen: don't export global var unless marked

* compiler/ccgthreadvars: don't export threadvar unless marked

* tests/dll/visibility: also check for exports

This ensure that these changes don't break manual exports.

* compiler/cgen: hide all variables created for constants

* compiler/ccgtypes: don't export RTTI variables

* compiler/ccgexprs: make all complex const static

* nimbase.h: fix export for windows

* compiler/cgen, ccgthreadvars: export variables correctly

For C/C++ variables, `extern` means that the variable is defined in an
another unit. Added a new N_LIB_EXPORT_VAR to correctly export
variables.

Removed lib/system/allocators.nim. seqs_v2 and strs_v2 now uses allocShared0. (#13190)

* Cleanup, remove lib/system/allocators.nim. seqs_v2 and strs_v2 now use
allocShared0 by default.

* Fixed -d:useMalloc allocShared / reallocShared / deallocShared. These now use the alloc/dealloc/realloc implementation that also takes care of zeroing memory at realloc.

* Removed debug printfs

* Removed unpairedEnvAllocs() from tests/destructor/tnewruntime_misc

* More mmdisp cleanups. The shared allocators do not need to zero memory or throw since the regular ones already do that

* Introduced realloc0 and reallocShared0, these procs are now used by
strs_v2 and seqs_v2. This also allowed the -d:useMalloc allocator to
drop the extra header with allocation length.

* Moved strs_v2/seqs_v2 'allocated' flag into 'cap' field

* Added 'getAllocStats()' to get low level alloc/dealloc counters. Enable with -d:allocStats

* *allocShared implementations for boehm and go allocators now depend on the proper *allocImpl procs

[backport] documentation: Add channels examples (#13202) [ci skip]

[backport] Make all parseutils examples auto-checking (#13238)

- Also fix one example's output (ikString -> ikStr, ikVar instead of ikExpr)
Updated 'nim for embedded systems' section to use --os:any and --gc:arc (#13237)

* Updated 'nim for embedded systems' section to use --os:any and --gc:arc

* Added section about size optimization to embedded systems

Remove name attribute from docutils.nimble (#13239)

Fixes asyncftpclient multiline reading, fixes #4684 (#13242)

Previously, the 4th character of `result` was checked for `'-'` every time, instead of each new line.

Also made it work for taint mode.
Fix typo for literal `[` (#13243)

The literal value for the `tkBracketLe` token was incorrectly set to `]` rather than `[`. I've had a quick glance at the code and it doesn't look like this change will affect anything at all, but I haven't tested yet - let's see if the CI explodes...
Add "origin" to window.location (#13251)

Add "origin" to window location: https://www.w3schools.com/jsref/prop_loc_origin.asp
nim dump: add libpath (#13249)

contributing docs: symbols need package prefix; changed allocStats to nimAllocStats (#13247)

testament/azure: major rewrite (#13246)

This commit features a major rewrite of Azure Pipelines integration,
turning the spaghetti it originally was into something maintainable.

Key changes:
- No longer requires a ton of hooks into testament.
- Results are now cached then bulk-uploaded to prevent throttling from
  Azure Pipelines, avoiding costly timeouts.
- A low timeout is also employed to avoid inflated test time.
- The integration is now documented.
Cleaned up mmdisp.nim, moved implementations into lib/system/mm/ (#13254)

make goto based exceptions available for 'nim cpp' (#13244)

* make goto based exceptions available for 'nim cpp'
* optimize seq.add to be comparable to C++'s emplace_back

ARC: remove unnecessary code

ARC: optimize complete object constructors to use nimNewObjUninit

make nre compile with --gc:arc

Rename isNilOrWhitespace to isEmptyOrWhitespace and make it use allCharsInSet (#13258)

* Rename isNilOrWhitespace to isEmptyOrWhitespace

* Make isEmptyOrWhitespace use allCharsInSet(Whitespace)

Clearer final objects error; fixes #13256 (#13257)

scrollTop must be settable (#13263)

* scrollTop must be assignable

Make scrollTop settable

* add missing export

fixes #13219 (#13272)

fixes #13281 (#13282)

* fixes ##13281

* add comment to test

unittest add resetOutputFormatters proc (#13267)

* add resetOutputFormatters

* remove space

* resolve comments

TlSF Alloctor: use less memory for --gc:arc (#13280)

Tiny since cleanup (#13286)

nimv2 widestring indexing (#13279)

Repr v2 progress (#13268)

* progress on repr_v2

* repr progress

* add ref objects with distrinct

* fix failing tests

refactor htmldocs; gitignore it

removed unused import

fix stdout(etc) for emscripten

csize => csize_t for sysctl

Thread attributes should be destroyed using the pthread_attr_destroy() (#13293)

On some OSes (such as FreeBSD or Solaris), pthread_attr_init allocate
memory. So it is necessary to deallocate that memory by using
pthread_attr_destroy.
fix critical bug discovered by #11591 (#13290) [backport]

miscellaneous bug fixes (#13291)

* fix for emscripten etc

* add testcase for #13290

* replace deprecated isNilOrWhitespace

CT FFI: fix for windows; fix case transition; error msg shows more useful context (#13292)

* evalffi: fix case transition
* evalffi: fix for windows
* evallffi: `cannot import` errmsg now also shows which library it tried to import symbol from

refs #8391 std/os now shows runtime context for raiseOSError exceptions (#13294)

* refs #8391: fix errmsg for setCurrentDir

* raiseOSError calls for copyFile

* refs #8391 std/os now shows runtime context for raiseOSError exceptions

build_all.sh: building csources 5X faster thanks to make -j (#13300)

* build_all.sh: building csources 5X faster thanks to make -j
* fix for freebsd
* use OS-dependent formula to get number of logical cores
* make is an optional dependency

Fix capture for object types (#13315)

* Fix capture for object|tuple|... types

* Add test case

Quote nim executable before executing. (#13316) [backport]

In case nim executable is located in PATH containing spaces.

fixes #13311
ReSync with devel

Make build_all.sh more portable and a bit simpler (#13308)

koch: enable checks in the compiler when running CI (#13323)

fix #13132 tnetdial (#13318)

enable testing -d:nimHasLibFFI mode (#13091)

Fix #10717, fix #13284 (#13307)

Fixed codegen for constant cstring with --gc:arc (#13326)

* Fixed codegen for constant cstring with --gc:arc, fixes  #13321

* Added test for #13321

Option to allow the request body to be processed outside the asynchttpserver library. (#13147)

Allow the request body to be processed outside the asynchttpserver library to break big files into chunks of data. This change does not break anything.

build_all.sh update (#13320)

* Don't overload the system, don't crash when you can't determine the CPU count and don't rely on bash

* Extract to variable

* Limit number of spawned jobs for systems with weak IO

* Use proper arithmetic braces

contributing.rst: Add a special rule for 'outplace'-like features

[backport] -d:danger should imply -d:release (#13336)

nim secret: support linenoise when available (#13328)

fix #13150 `nim doc --project` now works reliably (#13223)

* fix #13150 `nim doc --project` works with duplicate names and with imports below main project file

* add to help; fixup after #13212 isRelativeTo got merged
* fix test tests/compilerapi/tcompilerapi.nim
* remove nimblePkg field; compute on the fly instead
* kochdocs: compiler docs now under compiler/
* --docRoot now has smart default: best among @pkg, @path

make monotimes have zero overhead if you don't use it (#13338) [backport]

fix #13349 regression: isNamedTuple now works with generic tuples (#13350)

fixes #13269 (#13344)

adding sqlite3 backup functions (#13346)

* adding sqlite3 backup functions

* changing sleep to sqlite3_sleep to prevent clashes

Added a basic example how to handle a Post request. (#13339)

* Added a basic example how to handle a Post request.

They were also made minor cosmetic changes.

* Minor fixes suggested by Yardanico

* Fixed a wrong value in chunkSize constant.

* Re-added the request.body for compatibility!

replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple in dollars.nim (#13347)

* replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple

* fix for bootstrap

fix #13182: `proc fun(a: varargs[Foo, conv])` now can be overloaded (#13345) [backport]

miscellaneous bug fixes (part 3) (#13304)

* fix deprecation; fix indentation

* git clone: use -q

* fix Warning: pragma before generic parameter list is deprecated; fix typo

* bugfix: sysTypeFromName("float64") was never cached

testament: introduce 'matrix' for testing multiple options (#13343)

printing float values will have one more digit. (#13276) [backport]

* printing float values will have one more digit. Fixes #13196

[backport] fix #13352

[backport] remove 'CountTable.mget' (#13355)

It didn't work, and it was an oversight to be included in v1.0.
fix #6736: templates in unittest now show actual value (#13354)

Revert "printing float values will have one more digit. (#13276) [backport]" (#13363)

This reverts commit b2c6db97f9.
Add sideEffect pragma to importC procs in posix, winlean and time module (#13370)

* Add sideEffect pragma to procs in winlean
* Add sideEffect pragma to procs in posix
* Add test for #13306
* Add sideEffect pragma to procs in times
* Fixes #13306
fixes #3339 by documenting the limitations of case-statement (#13366)

fixes #13314 (#13372)

testament: this now works: "testament r /abspath/to/test.nim" (#13358)

fix `is` with generic types; fix `genericHead(Foo[T])` (#13303)

* fix #9855, fix #9855, fix genericHead
* render TTypeKind via toHumanStr

fix #13255 (#13275) [backport]

remove outplace version of 'merge' for CountTables (#13377)

* remove outplace version of 'merge' for CountTables

* remove 'merge' tests

fix #13374 `nim c -r -` now generates $nimcache/stdinfile (#13380) [backport]

fix #9634 don't crash on execCmdEx/readLine when inside gdb/lldb (#13232)

* fix #9634 debugging a program using execCmdEx now works

* only apply EINTR to c_gets for now

This reverts commit c0f5305b5a0b46983dfd27e3d77ecbf4f8744dcc.

lib.rst: add a link for jsconsole [backport] (#13383)

Make vccexe parse response files (#13329)

expectLen now shows the length that we got (#13387)

fix several bugs with `repr`  (#13386)

fixes #13378 [backport] (#13392)

remove dead code test_nimhcr_integration.(bat,sh) (#13388)

* enable test for osx: import tests/dll/nimhcr_integration

* re-disable osx test

fix linenoise regression (#13395)

* fix nightlies linenoise regression

* fix other installers

Revert "remove dead code test_nimhcr_integration.(bat,sh) (#13388)" (#13396)

This reverts commit 90491ea0a9.
fixes #13368 (#13397)

fix bug in int128 (#13403)

isolate the build process from external config files (#13411)

add ggplotnim to important_packages (#13206)

Fix to asynchttpserver form data/body broken with #13147 (#13394)

* Fix to asynchttpserver form data/body broken with #13147
* New implementation that use a interator instance of future streams
* asynchttpserver now can handle chunks of data.

Merge branch 'devel' of https://github.com/nim-lang/Nim into osopen

Squash Commits; Peer review feedbacks https://github.com/nim-lang/Nim/pull/12901#discussion_r379694384
2020-02-15 22:31:00 +00:00
Clyybber
f3eb0a5970 capture macro now accepts variables of different types (#13356)
* Capture macro can now accept variables of different types

* Add test

* Update examples

* Use let instead of var
2020-02-15 19:53:40 +01:00
Henrique Dias
5bf571f061 Fix to asynchttpserver form data/body broken with #13147 (#13394)
* Fix to asynchttpserver form data/body broken with #13147
* New implementation that use a interator instance of future streams
* asynchttpserver now can handle chunks of data.
2020-02-14 21:59:37 +01:00
Miran
3300e317a4 add ggplotnim to important_packages (#13206) 2020-02-14 21:28:50 +01:00
Ștefan Talpalaru
3d7d06571c isolate the build process from external config files (#13411) 2020-02-14 21:15:52 +01:00
Arne Döring
ccd2e044cb fix bug in int128 (#13403) 2020-02-14 12:33:36 +01:00
cooldome
7dd787b8a3 fixes #13368 (#13397) 2020-02-14 10:13:55 +01:00
Andreas Rumpf
1e303100f8 Revert "remove dead code test_nimhcr_integration.(bat,sh) (#13388)" (#13396)
This reverts commit 90491ea0a9.
2020-02-12 13:22:26 +01:00
Timothee Cour
2b368bcdd7 fix linenoise regression (#13395)
* fix nightlies linenoise regression

* fix other installers
2020-02-12 10:35:00 +01:00
Timothee Cour
90491ea0a9 remove dead code test_nimhcr_integration.(bat,sh) (#13388)
* enable test for osx: import tests/dll/nimhcr_integration

* re-disable osx test
2020-02-12 10:21:32 +01:00
Andreas Rumpf
c446c0f57a fixes #13378 [backport] (#13392) 2020-02-11 23:48:41 +01:00
Timothee Cour
eec07b4e84 fix several bugs with repr (#13386) 2020-02-11 21:33:06 +01:00
Clyybber
f6d45b40a5 expectLen now shows the length that we got (#13387) 2020-02-11 12:31:52 +01:00
Fredrik Høisæther Rasch
8100e2e9cd Make vccexe parse response files (#13329) 2020-02-11 12:05:47 +01:00
Jjp137
84a71dad87 lib.rst: add a link for jsconsole [backport] (#13383) 2020-02-11 10:22:49 +01:00
Timothee Cour
39ba502f87 fix #9634 don't crash on execCmdEx/readLine when inside gdb/lldb (#13232)
* fix #9634 debugging a program using execCmdEx now works

* only apply EINTR to c_gets for now

This reverts commit c0f5305b5a0b46983dfd27e3d77ecbf4f8744dcc.
2020-02-11 10:16:30 +01:00
Timothee Cour
1f7c907e7d fix #13374 nim c -r - now generates $nimcache/stdinfile (#13380) [backport] 2020-02-11 00:37:40 +01:00
Miran
ceb3d5ad68 remove outplace version of 'merge' for CountTables (#13377)
* remove outplace version of 'merge' for CountTables

* remove 'merge' tests
2020-02-10 20:50:55 +01:00
Arne Döring
2fee89f7db fix #13255 (#13275) [backport] 2020-02-09 13:51:36 +01:00
Timothee Cour
7939319379 fix is with generic types; fix genericHead(Foo[T]) (#13303)
* fix #9855, fix #9855, fix genericHead
* render TTypeKind via toHumanStr
2020-02-09 13:48:55 +01:00
Timothee Cour
debe7fffd8 testament: this now works: "testament r /abspath/to/test.nim" (#13358) 2020-02-09 13:44:16 +01:00
Andreas Rumpf
240174dd81 fixes #13314 (#13372) 2020-02-09 00:22:34 +01:00
Miran
038f47e7b9 fixes #3339 by documenting the limitations of case-statement (#13366) 2020-02-08 20:11:20 +01:00
Tomohiro
2a4aa24620 Add sideEffect pragma to importC procs in posix, winlean and time module (#13370)
* Add sideEffect pragma to procs in winlean
* Add sideEffect pragma to procs in posix
* Add test for #13306
* Add sideEffect pragma to procs in times
* Fixes #13306
2020-02-08 20:09:49 +01:00
Timothee Cour
e4415422fe Revert "printing float values will have one more digit. (#13276) [backport]" (#13363)
This reverts commit b2c6db97f9.
2020-02-08 09:30:24 +01:00
Miran
f3117d350e fix #6736: templates in unittest now show actual value (#13354) 2020-02-07 22:04:08 +01:00
Miran
78b15de304 [backport] remove 'CountTable.mget' (#13355)
It didn't work, and it was an oversight to be included in v1.0.
2020-02-07 20:50:44 +01:00
narimiran
36d1ad39d0 [backport] fix #13352 2020-02-07 18:26:08 +01:00
Arne Döring
b2c6db97f9 printing float values will have one more digit. (#13276) [backport]
* printing float values will have one more digit. Fixes #13196
2020-02-07 17:10:25 +01:00
Miran
cdedb86348 testament: introduce 'matrix' for testing multiple options (#13343) 2020-02-07 16:45:49 +01:00
Timothee Cour
1f725f1d7e miscellaneous bug fixes (part 3) (#13304)
* fix deprecation; fix indentation

* git clone: use -q

* fix Warning: pragma before generic parameter list is deprecated; fix typo

* bugfix: sysTypeFromName("float64") was never cached
2020-02-07 16:37:40 +01:00
Timothee Cour
79ec8c2571 fix #13182: proc fun(a: varargs[Foo, conv]) now can be overloaded (#13345) [backport] 2020-02-07 13:29:18 +01:00
Timothee Cour
c0a2e2ed92 replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple in dollars.nim (#13347)
* replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple

* fix for bootstrap
2020-02-07 13:27:28 +01:00
Henrique Dias
abd660c407 Added a basic example how to handle a Post request. (#13339)
* Added a basic example how to handle a Post request.

They were also made minor cosmetic changes.

* Minor fixes suggested by Yardanico

* Fixed a wrong value in chunkSize constant.

* Re-added the request.body for compatibility!
2020-02-07 03:59:28 -05:00
pyloor
bf3f1c3762 adding sqlite3 backup functions (#13346)
* adding sqlite3 backup functions

* changing sleep to sqlite3_sleep to prevent clashes
2020-02-07 01:11:05 -05:00
Andreas Rumpf
c87796180e fixes #13269 (#13344) 2020-02-07 06:58:57 +01:00
Timothee Cour
7481f43753 fix #13349 regression: isNamedTuple now works with generic tuples (#13350) 2020-02-07 06:58:04 +01:00
Andreas Rumpf
e24443f1bc make monotimes have zero overhead if you don't use it (#13338) [backport] 2020-02-06 16:12:54 +01:00
Timothee Cour
7ec7731f82 fix #13150 nim doc --project now works reliably (#13223)
* fix #13150 `nim doc --project` works with duplicate names and with imports below main project file

* add to help; fixup after #13212 isRelativeTo got merged
* fix test tests/compilerapi/tcompilerapi.nim
* remove nimblePkg field; compute on the fly instead
* kochdocs: compiler docs now under compiler/
* --docRoot now has smart default: best among @pkg, @path
2020-02-06 11:17:00 +01:00
Timothee Cour
574f61315d nim secret: support linenoise when available (#13328) 2020-02-05 16:44:19 +01:00
Miran
c6d5f0df8d [backport] -d:danger should imply -d:release (#13336) 2020-02-05 13:41:16 +01:00
Araq
8279da5219 contributing.rst: Add a special rule for 'outplace'-like features 2020-02-05 13:39:08 +01:00
Clyybber
ab525cc48a build_all.sh update (#13320)
* Don't overload the system, don't crash when you can't determine the CPU count and don't rely on bash

* Extract to variable

* Limit number of spawned jobs for systems with weak IO

* Use proper arithmetic braces
2020-02-04 21:26:38 +01:00
Henrique Dias
955465e5f4 Option to allow the request body to be processed outside the asynchttpserver library. (#13147)
Allow the request body to be processed outside the asynchttpserver library to break big files into chunks of data. This change does not break anything.
2020-02-04 21:13:25 +01:00
Ico Doornekamp
bfe96e069b Fixed codegen for constant cstring with --gc:arc (#13326)
* Fixed codegen for constant cstring with --gc:arc, fixes  #13321

* Added test for #13321
2020-02-04 17:39:27 +01:00
genotrance
7cc03b43f8 Fix #10717, fix #13284 (#13307) 2020-02-04 17:38:24 +01:00
Timothee Cour
e70294dff2 enable testing -d:nimHasLibFFI mode (#13091) 2020-02-04 14:08:56 +01:00
Timothee Cour
b20d7e2110 fix #13132 tnetdial (#13318) 2020-02-04 10:31:44 +01:00
alaviss
7e5c070244 koch: enable checks in the compiler when running CI (#13323) 2020-02-04 09:27:54 +01:00
Clyybber
1ab37ccfc6 Make build_all.sh more portable and a bit simpler (#13308) 2020-02-03 02:02:44 +01:00
Fredrik Høisæther Rasch
dfecc3489b Quote nim executable before executing. (#13316) [backport]
In case nim executable is located in PATH containing spaces.

fixes #13311
2020-02-02 13:54:48 +01:00
Clyybber
d43e5bef39 Fix capture for object types (#13315)
* Fix capture for object|tuple|... types

* Add test case
2020-02-02 13:52:21 +01:00
Timothee Cour
45a5c64c9a build_all.sh: building csources 5X faster thanks to make -j (#13300)
* build_all.sh: building csources 5X faster thanks to make -j
* fix for freebsd
* use OS-dependent formula to get number of logical cores
* make is an optional dependency
2020-01-31 20:00:05 +01:00
Timothee Cour
adc52b0039 refs #8391 std/os now shows runtime context for raiseOSError exceptions (#13294)
* refs #8391: fix errmsg for setCurrentDir

* raiseOSError calls for copyFile

* refs #8391 std/os now shows runtime context for raiseOSError exceptions
2020-01-30 11:06:04 +01:00
Timothee Cour
4a747f0250 CT FFI: fix for windows; fix case transition; error msg shows more useful context (#13292)
* evalffi: fix case transition
* evalffi: fix for windows
* evallffi: `cannot import` errmsg now also shows which library it tried to import symbol from
2020-01-30 11:04:06 +01:00
Timothee Cour
bf22b44b1f miscellaneous bug fixes (#13291)
* fix for emscripten etc

* add testcase for #13290

* replace deprecated isNilOrWhitespace
2020-01-30 10:54:50 +01:00
Timothee Cour
81a43791f9 fix critical bug discovered by #11591 (#13290) [backport] 2020-01-29 17:40:03 +01:00
Hiroki Noda
3ab1274231 Thread attributes should be destroyed using the pthread_attr_destroy() (#13293)
On some OSes (such as FreeBSD or Solaris), pthread_attr_init allocate
memory. So it is necessary to deallocate that memory by using
pthread_attr_destroy.
2020-01-29 17:33:21 +01:00
Timothee Cour
2ecef8f779 csize => csize_t for sysctl 2020-01-28 23:36:24 +00:00
Timothee Cour
2e20f5648b fix stdout(etc) for emscripten 2020-01-28 23:36:24 +00:00
Timothee Cour
9657a83698 removed unused import 2020-01-28 23:36:24 +00:00
Timothee Cour
5676912209 refactor htmldocs; gitignore it 2020-01-28 23:36:24 +00:00
cooldome
76ede7c198 Repr v2 progress (#13268)
* progress on repr_v2

* repr progress

* add ref objects with distrinct

* fix failing tests
2020-01-28 20:05:57 +01:00
cooldome
92010becbe nimv2 widestring indexing (#13279) 2020-01-28 20:02:39 +01:00
Clyybber
fb94836bc7 Tiny since cleanup (#13286) 2020-01-28 20:02:07 +01:00
Andreas Rumpf
be795bbf1a TlSF Alloctor: use less memory for --gc:arc (#13280) 2020-01-28 17:09:48 +01:00
cooldome
84e8477b90 unittest add resetOutputFormatters proc (#13267)
* add resetOutputFormatters

* remove space

* resolve comments
2020-01-28 14:16:03 +00:00
cooldome
46bfb590c8 fixes #13281 (#13282)
* fixes ##13281

* add comment to test
2020-01-28 14:55:54 +01:00
Andreas Rumpf
c8418651b1 fixes #13219 (#13272) 2020-01-27 22:50:10 +01:00
Jairo
32f0910f11 scrollTop must be settable (#13263)
* scrollTop must be assignable

Make scrollTop settable

* add missing export
2020-01-27 09:14:56 +01:00
hlaaftana
a71654323d Clearer final objects error; fixes #13256 (#13257) 2020-01-26 18:56:04 +01:00
hlaaftana
e7744b0909 Rename isNilOrWhitespace to isEmptyOrWhitespace and make it use allCharsInSet (#13258)
* Rename isNilOrWhitespace to isEmptyOrWhitespace

* Make isEmptyOrWhitespace use allCharsInSet(Whitespace)
2020-01-26 14:02:07 +01:00
Araq
6900da314c make nre compile with --gc:arc 2020-01-26 13:43:02 +01:00
Araq
a10cc18247 ARC: optimize complete object constructors to use nimNewObjUninit 2020-01-26 13:43:02 +01:00
Araq
ab35f07e77 ARC: remove unnecessary code 2020-01-26 13:43:02 +01:00
Andreas Rumpf
6efac70181 make goto based exceptions available for 'nim cpp' (#13244)
* make goto based exceptions available for 'nim cpp'
* optimize seq.add to be comparable to C++'s emplace_back
2020-01-25 20:00:13 +01:00
Ico Doornekamp
4f3dd33509 Cleaned up mmdisp.nim, moved implementations into lib/system/mm/ (#13254) 2020-01-25 17:14:31 +01:00
alaviss
5124b2e575 testament/azure: major rewrite (#13246)
This commit features a major rewrite of Azure Pipelines integration,
turning the spaghetti it originally was into something maintainable.

Key changes:
- No longer requires a ton of hooks into testament.
- Results are now cached then bulk-uploaded to prevent throttling from
  Azure Pipelines, avoiding costly timeouts.
- A low timeout is also employed to avoid inflated test time.
- The integration is now documented.
2020-01-25 09:32:27 +01:00
Timothee Cour
981ffc912e contributing docs: symbols need package prefix; changed allocStats to nimAllocStats (#13247) 2020-01-25 09:27:29 +01:00
Timothee Cour
4cbeddddcc nim dump: add libpath (#13249) 2020-01-24 20:06:54 +01:00
Jairo
fb74497c99 Add "origin" to window.location (#13251)
Add "origin" to window location: https://www.w3schools.com/jsref/prop_loc_origin.asp
2020-01-24 20:06:17 +01:00
Euan
ccb728a7b0 Fix typo for literal [ (#13243)
The literal value for the `tkBracketLe` token was incorrectly set to `]` rather than `[`. I've had a quick glance at the code and it doesn't look like this change will affect anything at all, but I haven't tested yet - let's see if the CI explodes...
2020-01-24 08:42:03 +00:00
hlaaftana
4656580b54 Fixes asyncftpclient multiline reading, fixes #4684 (#13242)
Previously, the 4th character of `result` was checked for `'-'` every time, instead of each new line.

Also made it work for taint mode.
2020-01-24 00:18:16 +01:00
hlaaftana
caaa8f285f Remove name attribute from docutils.nimble (#13239) 2020-01-23 18:51:25 +01:00
Ico Doornekamp
5dd2fa3e0c Updated 'nim for embedded systems' section to use --os:any and --gc:arc (#13237)
* Updated 'nim for embedded systems' section to use --os:any and --gc:arc

* Added section about size optimization to embedded systems
2020-01-23 17:17:48 +01:00
Kaushal Modi
c4ff4e553e [backport] Make all parseutils examples auto-checking (#13238)
- Also fix one example's output (ikString -> ikStr, ikVar instead of ikExpr)
2020-01-23 17:14:22 +01:00
chr v1.x
aebcbfe5ea [backport] documentation: Add channels examples (#13202) [ci skip] 2020-01-23 14:47:00 +01:00
Ico Doornekamp
b68eb1cad0 Removed lib/system/allocators.nim. seqs_v2 and strs_v2 now uses allocShared0. (#13190)
* Cleanup, remove lib/system/allocators.nim. seqs_v2 and strs_v2 now use
allocShared0 by default.

* Fixed -d:useMalloc allocShared / reallocShared / deallocShared. These now use the alloc/dealloc/realloc implementation that also takes care of zeroing memory at realloc.

* Removed debug printfs

* Removed unpairedEnvAllocs() from tests/destructor/tnewruntime_misc

* More mmdisp cleanups. The shared allocators do not need to zero memory or throw since the regular ones already do that

* Introduced realloc0 and reallocShared0, these procs are now used by
strs_v2 and seqs_v2. This also allowed the -d:useMalloc allocator to
drop the extra header with allocation length.

* Moved strs_v2/seqs_v2 'allocated' flag into 'cap' field

* Added 'getAllocStats()' to get low level alloc/dealloc counters. Enable with -d:allocStats

* *allocShared implementations for boehm and go allocators now depend on the proper *allocImpl procs
2020-01-23 14:25:22 +01:00
alaviss
f500895efe Unexport even more symbols (#13214)
* system/gc: don't export markStackAndRegisters

* compiler/cgen: unexport internal symbols

As these functions are Nim-specific walkaround against C's optimization
schemes, they don't serve any purpose being exported.

* compiler/cgen: don't export global var unless marked

* compiler/ccgthreadvars: don't export threadvar unless marked

* tests/dll/visibility: also check for exports

This ensure that these changes don't break manual exports.

* compiler/cgen: hide all variables created for constants

* compiler/ccgtypes: don't export RTTI variables

* compiler/ccgexprs: make all complex const static

* nimbase.h: fix export for windows

* compiler/cgen, ccgthreadvars: export variables correctly

For C/C++ variables, `extern` means that the variable is defined in an
another unit. Added a new N_LIB_EXPORT_VAR to correctly export
variables.
2020-01-23 13:45:31 +01:00
Timothee Cour
3a5056dc70 fix lots of bugs with parentDir, refs #8734 (#13236) 2020-01-23 13:39:41 +01:00
Timothee Cour
b8a436af93 kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes (#13221)
* kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes
* fixup after #13212 isRelativeTo got merged
2020-01-23 11:06:28 +01:00
Timothee Cour
b462baed65 VM: allow overriding MaxLoopIterations without rebuilding nim (#13233) 2020-01-23 10:53:30 +01:00
D-Nice
f12bea16ad [backport] fix #11440, add docs to isNil for seq types needing nilseq (#13234) [ci skip] 2020-01-23 07:51:53 +01:00
Mera
4a754ff392 [backport] Fix typo and improve in code-block of 'lib/pure/parseutils.nim' (#13231) [ci skip] 2020-01-23 06:49:27 +01:00
Timothee Cour
7356bc29b7 new os.isRelativeTo (#13212) 2020-01-23 00:45:16 +01:00
Milan
3e843ab335 [backport] times/getClockStr(): fix mistake in doc (#13229) [ci skip] 2020-01-22 18:22:14 +01:00
Juan Carlos
fbd7fe118c [backport] Documentation Fix #12251 (#13226) [ci skip] 2020-01-22 17:56:44 +01:00
whiterock
ef9fb39cdf added note to re constructor regarding performance (#13224)
Since I was new to regex I did not know that there is a compilation going on with ``re"[abc]"`` constructor and so I followed the other examples in the docs blindly, that is I just put the constructor directly in the arguments of match, find, etc., which was inside a loop and then wondered why my performance was so bad. Of course putting it outside the loop made it vastly more performant. People like me would benefit from the small note I added I would think :)
2020-01-22 16:02:16 +01:00
Juan Carlos
2fad7f134f httpclient, maxredirects to Natural, newHttpClient/newAsyncHttpClient add headers argument instead of hardcoded empty (#13207) 2020-01-21 19:34:47 +01:00
Andreas Rumpf
bdb7c82c6a fixes a critical times.nim bug reported on IRC [backport] (#13216) 2020-01-21 16:49:59 +01:00
Timothee Cour
b355ef2a72 fix #13211 relativePath("foo", ".") (#13213) 2020-01-21 15:48:19 +01:00
Miran
bf96d6d316 Idxmin & idxmax, continuation (#13208)
* Add idxmin() which returns the index of the minimum value

* Add idxmax() which returns the index of the maximum value

* Add tests for idxmin()

* Add tests for idxmax()

* Remove initialization of result = 0

* Adds overloading for arrays (no enums indexed arrays yet)

* Add support for enum index arrays

* Fix tests with enum

* Fix tests for idxmax

* Change names of the procedures to minIndex and maxIndex

* address Araq's comments:

- remove 'array' versions
- add .since pragma
- return 'int' instead of 'Natural'
- add changelog entry

Co-authored-by: Federico A. Corazza <20555025+Imperator26@users.noreply.github.com>
2020-01-20 16:57:34 +01:00
Jasper Jenkins
0606b6a44e fix range[enum] type conversion (#13204) [backport] 2020-01-20 16:56:59 +01:00
alaviss
470faa97c6 compiler/ccgtypes: hide exportc proc unless it has dynlib (#13199)
This hides most of stdlib's internal functions from resulting
binaries/libraries, where they aren't needed on *nix. Static libraries
are not affected by this change (visibility doesn't apply to them).
2020-01-20 10:51:21 +01:00
cooldome
da1bddb084 fixes #13195 (#13198)
* fixes #13195

* extra fix

* fix typo
2020-01-20 10:41:12 +01:00
Andreas Rumpf
41555ca86f fixes #13110 (#13197) 2020-01-19 23:30:45 +01:00
Andrii Riabushenko
6f3476d39c Revert "fixes #13195"
This reverts commit cd7904f2b2.
2020-01-19 20:33:23 +00:00
Andrii Riabushenko
e349f7ad21 Merge branch 'devel' of https://github.com/nim-lang/Nim into devel 2020-01-19 20:22:06 +00:00
Andrii Riabushenko
7576387dfe revert last commit 2020-01-19 20:21:26 +00:00
Andrii Riabushenko
cd7904f2b2 fixes #13195 2020-01-19 20:18:04 +00:00
slangmgh
13ddbc46fc Fixes #13186 (#13188) 2020-01-19 14:16:50 +01:00
Federico Ceratto
8d64550b1e Add link to packaging.html (#13194) 2020-01-19 14:15:59 +01:00
cooldome
416b4c3612 more on arc codegen (#13178)
* arc codegen for union type

* add more tests

* fix offsetof

* fix tsizeof test

* fix style
2020-01-19 14:14:26 +01:00
Timothee Cour
bc14453f69 fix docs + API for fieldPairs, fields (#13189) 2020-01-18 13:33:30 +01:00
Timothee Cour
f6ba4e81b0 maybe: allows optional chaining of field access and indexing when LHS i snil (#13023)
* maybe: allows optional chaining
* fix tools/kochdocs.nim
* improve semantics to distinguish valid from invalid values
* for now, wrapnil, isValid, unwrap are not exported
2020-01-18 12:24:56 +01:00
Timothee Cour
e11ecc8266 times: toUnixFloat, fromUnixFloat (#13044) 2020-01-18 01:24:44 +01:00
Timothee Cour
5010bc1af5 fixes #13144 (#13145)
* fixup: genscript now does not copy nimbase.h but uses -I$nim/lib
2020-01-18 01:21:13 +01:00
Timothee Cour
c56612ff96 refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.} (#13136)
* refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.}
* put back NIM_EXTERNC for N_LIB_EXPORT; causes issues with compilerproc
2020-01-18 01:19:20 +01:00
Araq
107352f9d7 fixes #13157 2020-01-17 17:52:06 +01:00
Timothee Cour
6c2214b7de followup on #10435 : should be diff, not show (#13162) 2020-01-17 16:56:21 +01:00
Clyybber
451c47634c Fix docs for subdirs too (#13180)
* Fix doc subdirs
* Extract to helper proc, and fix on windows
2020-01-17 16:49:37 +01:00
cooldome
f51613e262 make sink operator optional (#13068)
* make sink operator optional

* bug fix, add changelog entry

* Trigger build

* fix one regression

* fix test

* Trigger build

* fix typos
2020-01-17 11:44:06 +00:00
Andreas Rumpf
7626907401 ARC works for async on Windows (#13179) 2020-01-17 11:14:17 +01:00
Jasper Jenkins
796aafe7e0 make case-object transitions explicit, make unknownLineInfo a const, replace a few magic numbers with consts (#13170) 2020-01-17 10:34:31 +01:00
cooldome
2bf337abae fixes #13095 (#13181)
* fixes #13095

* fix typo
2020-01-17 09:17:18 +01:00
Clyybber
41cf609fc7 Fix docs (#13176) 2020-01-16 22:22:17 +01:00
Clyybber
e3acb2d12c Cleanup DFA (#13173) 2020-01-16 20:15:50 +01:00
Jasper Jenkins
d245d4cf09 fix tsizeof3 for aarch64 (#13169) 2020-01-16 14:21:12 +01:00
Timothee Cour
1b54be7779 fixes #12998 nim doc regression (#13117) 2020-01-16 14:19:58 +01:00
cooldome
5ef0494677 Working towards arc codegen (#13153)
fixes #13029
2020-01-16 14:16:17 +01:00
Miran
352232e62d style fix: change 'JS' to 'js' to make it consistent (#13168) 2020-01-16 14:14:03 +01:00
Ico Doornekamp
54bfd69a27 Remove obsolete code from osalloc (#13158) 2020-01-16 09:11:05 +01:00
Timothee Cour
d5f011d9e6 CI fix timeout error (#13134) 2020-01-15 22:54:04 +01:00
Andreas Rumpf
a5e67071d2 ARC: misc bugfixes (#13156)
* fixes #13102
* closes #13149
* ARC: fixes a move optimizer bug (there are more left regarding array and tuple indexing)
* proper fix; fixes #12957
* fixes yet another case object '=' code generation problem
2020-01-15 22:13:31 +01:00
Timothee Cour
d88b52c0bc successX now correctly shows html output for nim doc, nim jsondoc; fix #13121 (#13116)
* successX now correctly shows html output for nim doc
* fixes #13121
* fixup hintSuccessX to be less weird
2020-01-15 15:18:37 +01:00
Timothee Cour
51c072bd37 export normalizePathEnd (#13152) 2020-01-15 15:03:06 +01:00
Miran
e708d5de75 System cleanup, part 2 (#13155)
* create basic_types, arithmetics, exceptions, comparisons
* create setops.nim
* create memalloc.nim
* create gc_interface.nim
* create iterators_1.nim
2020-01-15 14:42:49 +01:00
Ico Doornekamp
79a326759a Added 'ansic' os support for minimal (embedded) targets (#13088)
* os:any implementation
* os:asny: omit flock/funlock calls in echoBinSafe
* Disabled default "unhandled expection" reporting for `--os:any` to reduce
code size. Added unhandledExceptionHook instead which can be used to get
a notification from Nim and handle it from the application.
2020-01-15 11:06:41 +01:00
Tomohiro
d31e32743f Fix typo in doc/destructors.rst (#13148) 2020-01-14 19:51:58 +01:00
Andreas Rumpf
675ca997fb fixes #9674 [backport] (#13143) 2020-01-14 16:20:48 +01:00
Andreas Rumpf
8b00586488 fixes #13104 [backport] (#13142) 2020-01-14 15:16:36 +01:00
cooldome
b4545f03de pass platform argument only if vccexe is used (#13078)
* pass platform only if vccexe is used
* fixes #12297
2020-01-14 15:02:10 +01:00
Andreas Rumpf
fadbd8f70d fixes #10665 (#13141) [backport] 2020-01-14 13:51:28 +01:00
Andreas Rumpf
9fc04a555c fixes #13105 (#13138) 2020-01-14 12:57:20 +01:00
Andreas Rumpf
d56848878c fixes #13119 (#13128)
* fixes #13119
* fixes a regression
2020-01-14 09:56:08 +01:00
Timothee Cour
49d1822c8f fixes #13100 nim doc now treats export localSymbol correctly (#13123) [backport]
* fix #13100 nim doc now treats `export localSymbol` correctly
* use owner instead
2020-01-13 22:05:38 +01:00
treeform
d9640ed075 Expose more openSSL methods. (#13131) 2020-01-13 22:04:43 +01:00
Andreas Rumpf
eadd1ba9ed fixes #13112 (#13127)
* improve line error information

* fixes #13112
2020-01-13 15:47:17 +01:00
Andreas Rumpf
abea80376a fixes #13122 (#13126)
* fixes #13122

* moved tests to where they belong
2020-01-13 14:11:51 +01:00
Jasper Jenkins
bf2e052e6d fix rtti sizeof for varargs in global scope (#13125) [backport] 2020-01-13 10:17:21 +01:00
perter lee
1f27a2f8ab 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
2020-01-13 10:16:19 +01:00
Timothee Cour
ee1563ef33 VM FFI: write(stderr, msg) and fprintf(cstderr, msg) now work at CT (#13083) 2020-01-12 13:44:43 +01:00
Federico Ceratto
1c001fe583 Add link to posix_utils.html in posix.nim (#13111) 2020-01-12 13:36:37 +01:00
treeform
01a89cc473 Remove some unused/disabled OpenSSL functions (#13106) 2020-01-11 10:58:38 +01:00
Andreas Rumpf
767592a3c3 more arc features (#13098)
* config update
* ARC now supports 'repr' and 'new' with finalizers is supported
2020-01-10 23:17:33 +01:00
Miran
c0973d1b47 [backport] fix #12813, fix #13079 (#13099)
Correctly remove a key from CountTable when it is set to zero.
2020-01-10 15:24:33 +01:00
Miran
f7ce4e8705 System cleanup, part 1 (#13069)
* system.nim: mark what every .pop does

* system.nim: un-nest when statements
2020-01-10 10:14:02 +01:00
Andreas Rumpf
3a39ab83ac fixes an asyncftpclient bug; refs #13096 [backport] 2020-01-10 09:42:21 +01:00
narimiran
e9e114058c [backport] system/io.nim fix wrong documentation comment [ci skip] 2020-01-10 08:53:44 +01:00
Timothee Cour
4cd86c0842 typetraits: fixes #6454; genericParams; added lenTuple; added tuple type get (#13064) 2020-01-10 08:51:37 +01:00
Araq
fcd2f305ad fixes #13070 2020-01-10 08:32:30 +01:00
Araq
033da35de1 fixes #13072; no test case because it will be added later with more exception handling related bugfixes 2020-01-10 08:32:30 +01:00
Tomohiro
a33b72af49 Fix error check code in osproc (#13090) [backport] 2020-01-09 18:00:41 +01:00
Ico Doornekamp
bb7273bc47 Use '__noinline' instead of 'noinline' for N_NOINLINE gcc attribute, this prevents clashes with systems where 'noinline' might be already defined (#13089) 2020-01-09 17:27:42 +01:00
Timothee Cour
3f78873898 remove all remaining warnings when build nim (with -d:nimHasLibFFI) (#13084)
* cleanup deprecations in evalffi + elsewhere

* remove dead code getOrdValue64
2020-01-09 13:19:18 +01:00
Andreas Rumpf
852170cc78 take the one good idea from --os:standalone and enable it via -d:StandaloneHeapSize (#13077) 2020-01-09 11:48:37 +01:00
Teashrock
27fee4d8b4 Deleted misplaced separator (#13085) [backport]
Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.
2020-01-09 11:48:13 +01:00
Andy Davidoff
56fb909676 fix crash due to errant symbols in nim.cfg (#13073) [backport] 2020-01-08 22:25:25 +01:00
narimiran
5e9ebe9ec1 move entries from the wrong changelog file [ci skip] 2020-01-08 15:20:30 +01:00
Timothee Cour
15043d35b8 make SuccessX show project file + output file (#13043)
* make SuccessX show project file + output file
* address comments
* fix test and add `result.err = reNimcCrash` otherwise hard to see where reNimcCrash used
* address comments
2020-01-08 00:39:07 +01:00
cooldome
871d5e79b1 distinctBase type trait for distinct types (#13031) 2020-01-08 00:36:57 +01:00
b3liever
8bcc7e8b9e basename supports pragmaexpr (#13045)
* basename supports pragmaexpr

* update changelog
2020-01-07 11:25:51 +01:00
Bung
291608045c add pqserverVersion,pqconnectionNeedsPassword,pqconnectionUsedPassword (#13060) 2020-01-07 10:52:02 +01:00
Timothee Cour
e5ae7ceaa3 [easy] --hint🔗on now shows link cmd instead of nothing (#13056)
* --hint🔗on now shows link cmd instead of nothing

* update doc for --listCmd
2020-01-07 10:38:59 +01:00
Timothee Cour
569d4d18f8 --styleCheck:hint now works (#13055) 2020-01-07 09:53:11 +01:00
Miran
1551fff853 clean up deprecated stuff and unused imports in tests (#13059) 2020-01-07 09:49:08 +01:00
loloiccl
6a7a19eb15 Modify the test command for nimly (nimble-package) (#13053) 2020-01-07 06:47:40 +01:00
Brent Pedersen
a019cc52f6 testament/important_packages dont run hts (#13052) 2020-01-07 06:47:18 +01:00
Clyybber
ba4fbb6328 Continue #13002 (#13021) 2020-01-06 11:40:42 +00:00
Timothee Cour
72499a8d7c [cleanup] remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits (#13041)
* remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits

* D20200105T085828 fix super strange bug that causes CI to fail: builds.sr.ht with: `Error: Settle timed out after 120 attempts`
2020-01-05 19:33:33 +01:00
BinHong Lee
2cfa8d8385 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.
2020-01-05 19:24:29 +01:00
Kamanji
9a5aaadda8 Rst parser respect :start-after: and :end-before: in include directive (#12972)
* [FEATURE] rst parser respect :start-after: in include

Rst parser now respects `:start-after:` and `:end-before:` attributes
for `include` directive.

* [DOC] include directive parsing proc update

* [TEST] Added unit tests for include rst directive in `rst` module
2020-01-05 10:01:21 +01:00
Araq
ae68ff959b fixes #12996 2020-01-05 09:42:44 +01:00
Araq
fdcea66fd9 reprjs: style changes 2020-01-05 09:42:44 +01:00
cooldome
a3df1b55f3 fixes #13013, reverts previous changes to readLines() (#13036) [backport]
* Revert "remove default argument for readLines (#12807) [backport]"

This reverts commit c949b81efd.
2020-01-05 09:22:41 +01:00
Jasper Jenkins
9474a818af fix enumtostr crash for enum-range (#13035) 2020-01-05 09:18:14 +01:00
Timothee Cour
13c08f3ab4 VM: support importc var, ptr/pointer types, cast int <=> ptr/pointer (#12877)
* VM: allow certain hardcoded special var variables at CT
* VM: allow all importc var, cast[int](ptr)
* fix tests tests/vm/tstaticprintseq.nim, tests/cpp/t8241.nim
* VM: == works for ptr/pointer nodes
* bugfix: ==, cast now also works for pointer, not just ptr
* VM supports cast PtrLikeKinds <=> PtrLikeKinds / int
* improve cname handling
* fixup + bug fix
* VM: support cast from ref to int
* address comment: opcLdGlobalDeref => opcLdGlobalDerefFFI
* defensive check against typ == nil
2020-01-05 09:11:29 +01:00
Araq
a1beeb313f fixes #13032 2020-01-04 19:33:49 +01:00
Andreas Rumpf
0f6987a86e fixes #12964 (#13027) 2020-01-04 07:40:02 +01:00
cooldome
47e7b8771c Fixes #13026 (#13028) 2020-01-04 02:33:13 +01:00
rockcavera
89570aa44b fix #12988 (#13022)
fix #12988
2020-01-03 22:41:58 +01:00
Andreas Rumpf
fb1b51f1e3 fixes #12956 (#13020) 2020-01-03 17:36:09 +01:00
Andreas Rumpf
8aadba1a2a fixes #12961 (#13019) 2020-01-03 14:30:54 +01:00
Siegfried Ehret
a577a88c36 Fix typo (#13015) [backport] 2020-01-03 10:23:28 +01:00
Andreas Rumpf
0ecb709cbe fixes #12978 (#13012) 2020-01-03 01:21:45 +01:00
cooldome
c949b81efd remove default argument for readLines (#12807) [backport] 2020-01-02 23:27:37 +01:00
cooldome
002d50f1f0 Sink to MemMove optimization in injectdestructors (#13002) 2020-01-02 22:58:01 +01:00
Timothee Cour
0ff23e696c fix #12985 {.push.} now does not apply to generic instantiations (#12986) 2020-01-02 16:49:57 +01:00
Andreas Rumpf
c3344862b0 --exception:goto switch for deterministic exception handling (#12977)
This implements "deterministic" exception handling for Nim based on goto instead of setjmp. This means raising an exception is much cheaper than in C++'s table based implementations. Supports hard realtime systems. Default for --gc:arc and the C target because it's generally a good idea and arc is all about deterministic behavior.

Note: This implies that fatal runtime traps are not catchable anymore! This needs to be documented.
2020-01-01 10:01:49 +01:00
Andy Davidoff
8a63caca07 fixes disruptek/nimph#102 multi-level nim.cfg use (#13001) [backport] 2019-12-31 22:29:19 +01:00
cooldome
584e8c8283 fixes #12989 (#12992)
* fixes #12989
* Revert "remove unwanted changes"

This reverts commit 501829732a.
2019-12-31 21:13:26 +01:00
Andreas Rumpf
ce40ed18bb fixes #12965 (#12991) 2019-12-31 09:42:18 +01:00
Andrii Riabushenko
9eeff690d5 Revert "fixes #12989"
This reverts commit 928c2fee06.
2019-12-31 00:10:02 +00:00
Andrii Riabushenko
928c2fee06 fixes #12989 2019-12-31 00:07:49 +00:00
Ștefan Talpalaru
defaf3b5a5 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.
2019-12-30 02:13:41 +01:00
Chris Heller
8d1a7db6ea Check pqntuples > 0 in getValue. Fixes #12973 (#12974) 2019-12-29 17:41:18 +01:00
Sam Wang
441cacf70f Added fix for handling TaintedStrings in streams and httpclient (#12969)
* Added fix for taint mode in streams and httpclient

* Removed taintMode export from system.nim
2019-12-29 17:37:22 +01:00
Ștefan Talpalaru
ee9ee297d8 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.}
2019-12-29 15:46:01 +01:00
Simon Krauter
37e93eab66 parsecfg: retain CRLF line breaks, fixes #12970 (#12971) 2019-12-29 15:39:48 +01:00
Timothee Cour
8c19372690 [ci skip] docfix .. < => ..< (#12981) [backport] 2019-12-29 15:34:36 +01:00
Jack Tang
21ea1094ef Allow customize Host header 2019-12-28 17:26:02 +00:00
King Eca
b67dea7a33 Fixes stackoverflow links in readme (#12963) [backport] 2019-12-27 08:31:01 +00:00
Andreas Rumpf
1917ebf082 minor refactorings 2019-12-27 08:29:40 +01:00
cooldome
649bf326bf fixes #12945 (#12959) 2019-12-24 20:34:14 +01:00
Araq
30162908b0 fixes another regression 2019-12-24 17:33:27 +01:00
Araq
3516947642 osproc: fixes regression 2019-12-24 17:33:27 +01:00
Araq
5aa7b1a44b ARC: default to a shared heap with --threads:on 2019-12-24 17:33:27 +01:00
Araq
bafb4f119c ported re.nim to ARC 2019-12-24 17:33:27 +01:00
Araq
8f17a70fe1 ported osproc.nim to ARC 2019-12-24 17:33:27 +01:00
Araq
9faf00598f ported channels to ARC 2019-12-24 17:33:27 +01:00
Araq
fbb8052e3a fixes the distros.nim regression 2019-12-24 17:33:27 +01:00
Araq
7bcf7696f0 fixes a silly regression 2019-12-24 17:33:27 +01:00
Araq
942db8c5f3 fixes a test case 2019-12-24 17:33:27 +01:00
Araq
6152eb3be3 a better bugfix 2019-12-24 17:33:27 +01:00
Araq
767bd57289 fixes a regression 2019-12-24 17:33:27 +01:00
Araq
d1d017ae85 fixes #12826 2019-12-24 17:33:27 +01:00
Araq
a7b4b2ed54 fixes a bug that kept sugar.collect from working with for loop macros [backport] 2019-12-24 17:33:27 +01:00
Araq
fd5aa89304 added guidelines for evolving Nim's stdlib 2019-12-24 17:33:27 +01:00
Araq
2616a86d4b docs: tiny style improvements 2019-12-24 17:33:27 +01:00
Timothee Cour
a0980c88c9 lenVarargs: number of varargs elements (#12907) 2019-12-23 09:42:32 +01:00
Jasper Jenkins
2e7c9eb6a8 case coverage error message for char (#12948) 2019-12-22 10:10:46 +01:00
Ico Doornekamp
28466ce6fc Auto-initialize deques (#12879) 2019-12-21 21:01:34 +01:00
Timothee Cour
b081166685 fixes #12735 on osx, call dsymutil for debug builds (#12931)
* fix #12735 osx: dsymutil needs to be called for debug builds
* also write dsymutil command to extraCmds in json build file
2019-12-21 20:59:08 +01:00
Judd
e1d79d40f2 update documentation for closureScope and capture (#12886) 2019-12-21 08:06:32 +01:00
RSDuck
9b8afd1dbb Fix #12785 (#12943)
* Fix #12785 and add test

* better variable name
2019-12-21 07:51:19 +01:00
Clyybber
10bd7d8fa0 system.reset is no longer magic (#12937)
It has now means setting x to default for new and old runtime alike
2019-12-19 20:36:59 +01:00
Timothee Cour
e041c184d2 fix #12919 tasyncclosestall flaky: Address already in use (#12934) 2019-12-19 18:50:39 +01:00
Timothee Cour
206a4cee77 fix cmdline bugs affecting nimBetterRun correctness (#12933) [backport] 2019-12-19 14:53:01 +01:00
flywind
cb0a20b9b4 fix error in assertions document (#12925) [backport] 2019-12-18 14:29:45 +01:00
Jasper Jenkins
3c38edf563 Better case coverage error message for alias and range enum (#12913) 2019-12-18 10:29:01 +01:00
Emery Hemingway
148f6d9820 Implement NixOS distro check (#12914) 2019-12-18 08:01:58 +01:00
Andreas Rumpf
3f6df5cc34 fixes #12899 (#12921)
* fixes #12899

* fixes regression: destroy global variables in reverse declaration order, closureleak test relies on it
2019-12-18 07:54:20 +01:00
genotrance
f9f55a23bb Fix single match output (#12920) 2019-12-17 20:26:11 +01:00
Clyybber
18e2ea787e Cleanup leftovers of #12911(#12916) 2019-12-17 17:58:04 +01:00
Andreas Rumpf
83a736a34a ARC: cycle detector (#12823)
* first implementation of the =trace and =dispose hooks for the cycle collector
* a cycle collector for ARC: progress
* manual: the .acyclic pragma is a thing once again
* gcbench: adaptations for --gc:arc
* enable valgrind tests for the strutils tests
* testament: better valgrind support
* ARC refactoring: growable jumpstacks
* ARC cycle detector: non-recursive algorithm
* moved and renamed core/ files back to system/
* refactoring: --gc:arc vs --gc:orc since 'orc' is even more experimental and we want to ship --gc:arc soonish
2019-12-17 17:37:50 +01:00
Arne Döring
5848f0042c add $nimeq for gdb (#12909) 2019-12-17 11:30:01 +01:00
cooldome
7650617448 NaN floatFormat with clang_cl (#12910)
* clang_cl nan floatFormat

* format
2019-12-17 11:25:46 +01:00
Timothee Cour
e8f4586c68 allow typed/untyped in magic procs (#12911) 2019-12-17 11:07:32 +01:00
Timothee Cour
e5ed4c1b7d fix json regression D20191212T144944 (#12902) [backport] 2019-12-15 23:04:06 +01:00
Krzysztof Majk
e4e74a5565 remove unused import (#12900) 2019-12-15 22:59:08 +01:00
BinHong Lee
20a59da401 Add --git.devel option to the documentation 2019-12-15 12:45:57 +00:00
Andreas Rumpf
347a04606b fixes #12885 [backport] (#12895) 2019-12-13 19:20:29 +01:00
Andreas Rumpf
a0aa8fa857 fixes #12874 (#12890)
* fixes #12874

* fixes introduced regressions
2019-12-13 15:36:39 +01:00
cooldome
12d2b980e8 Fixes #12883 (#12894)
* fixes #12883

* fix comment

* add normalize

* fix
2019-12-13 13:30:27 +00:00
cooldome
777c9ad0ef Better clang_cl support (#12896) 2019-12-13 12:12:04 +00:00
cooldome
1e1fd73530 fixes #12882 (#12889)
* fixes #12882
2019-12-13 11:24:05 +00:00
Andreas Rumpf
22b2684608 fixes #12148 [backport] (#12888) 2019-12-12 11:05:18 +01:00
cooldome
94289161f9 invoke createTypeBoundOps for constructors (#12878) 2019-12-11 10:46:20 +00:00
Andreas Rumpf
3524944e21 ARC: fixes cycle detection and move the .cursor attribute into closures (#12872) 2019-12-11 06:57:00 +01:00
Ico Doornekamp
e61d702206 Increased TInstr field sizes: allow long jumps and 65535 VM registers (#12777)
* Increased regBx size from 16 to 24 bits to increase jump range in the VM
from 32K to 8M instructions. Fixes #12727

* Increased VM TInst register field sizes to 16 bits to allow up to 65535 VM registers per proc

* Added test case for >255 VM registers
2019-12-10 19:04:02 +01:00
Andreas Rumpf
b8152b29e8 ARC: yet another bugfix (#12871) 2019-12-10 16:44:54 +01:00
Judd
56cf3403b4 introduce capture macro (#12712)
capture works for more cases than `closureScope`.
2019-12-10 13:16:37 +01:00
PMunch
65fd95bf85 Fix AVR target to define ints properly (#12817)
* Fix AVR target to define ints properly

* Fix more than AVR target

* Test to see how robust not using stdint is

* Fix for namespaces using cstdint

* Fix for pre C++11 compilers when using namespaces
2019-12-10 12:10:33 +01:00
Andreas Rumpf
61d89aae11 completes #12799, fixes #12216 (#12870) 2019-12-10 12:09:48 +01:00
cooldome
13d232ec56 fixes #12827 (#12829) [backport] 2019-12-10 07:08:46 +01:00
Andreas Rumpf
c282cee4db feature dracula themed doc (#12816)
* Implement gorgeous Dracula themed Nim documentation

* Add color for escape sequences

* fixes the test cases

* the big CSS cleanup
2019-12-10 06:48:11 +01:00
cooldome
5929c3da21 fixes #12820 (#12828) 2019-12-09 20:03:23 +01:00
Neelesh Chandola
e4f7656772 Support cross compiling from host to host (#12859) 2019-12-09 13:39:25 +01:00
Neelesh Chandola
7ebb2baa6c Assigning template to var/let/const gives a proper error (#12851)
* Assigning template to var/let/const gives a proper error

* Fix style
2019-12-09 08:19:40 +00:00
Andy Davidoff
a3d45d0c1b add a StringTable.clear that requires no mode specification (#12853)
* add clear overload, test, changelog

* add since annotation
2019-12-09 06:58:36 +01:00
Kevin
a02d043b58 added cstrutils (#12858) [backport]
fixed for 'csuCmpIgnoreStyle' error on hotcodereloading
2019-12-09 06:58:06 +01:00
Neelesh Chandola
ff5ef95414 Fixes #12832 (#12842) [backport]
* Fix #12832
* nimVm -> nimvm in json.nim
* Use suggestSym() instead of markUsed(); Also use styleCheckUse() for finding style violations
2019-12-08 23:27:25 +01:00
Mark
73dd348ddd Manual update: custom exceptions (#12847) [backport]
Said that you can have custom exceptions and showed how to create and raise them.
2019-12-08 21:39:44 +00:00
Elliot Waite
50c1e50184 Add a 32x32 favicon (#12856) 2019-12-08 22:19:35 +01:00
KeepCoolWithCoolidge
ae7b53ec51 Fixes classify function to detect subnormal floating points (#12836)
* Fix classify to test for subnormality.
* Minor fix.
* Modified to maintain existing API.
* Minor change.
* Removed 32-bit case since float is always 64-bit.
2019-12-08 20:17:11 +01:00
Elliot Waite
5da27a891c Removing the mention of using discard for block comments (#12837) [backport]
* Remove mention of using `discard` for block comments

* Add a 32x32 alternate favicon
2019-12-08 20:16:17 +01:00
Mark
0ebc709037 deviated -> derived (#12846) [backport] 2019-12-08 20:15:19 +01:00
Mark
46144a31ab deviated -> derived (#12845) [backport] 2019-12-08 20:14:54 +01:00
Timothee Cour
23fc93fc2d VM: allow ptr setting ptr fields (#12825) 2019-12-06 22:38:53 +01:00
cooldome
7213969901 fixes #12821 (#12822) 2019-12-06 09:56:54 +01:00
Neelesh Chandola
1db21721ec Fixed objects being erroneously zeroed out before object construction (#12814) [backport] 2019-12-05 17:31:51 +01:00
Andreas Rumpf
3fbb3bfd3f ARC related bugfixes and refactorings (#12781) 2019-12-05 16:59:06 +01:00
cooldome
9b0e874687 fixes #12783 [backport] (#12810)
* fixes #12783

* Trigger build
2019-12-05 15:17:45 +01:00
Andrey Makarov
26074f594d nimgrep improvements (#12779)
* fix sticky colors in styledWrite

* nimgrep: context printing, colorthemes and other

* add context printing (lines after and before a match)
* nimgrep: add exclude/include options
* nimgrep: improve error printing & symlink handling
* nimgrep: rename dangerous `-r` argument
* add a `--newLine` style option for starting matching/context
  lines from a new line
* add color themes: 3 new themes besides default `simple`
* enable printing of multi-line matches with line numbers
* proper display of replace when there was another match replaced at
  the same line / context block
* improve cmdline arguments error reporting
2019-12-05 14:42:20 +01:00
Andreas Rumpf
0e7338d65c better support for PROGMEM like annotations for lets/vars; fixes #12216 (#12799) 2019-12-05 13:45:16 +01:00
Clyybber
267fed53ee Fix #12812 2019-12-05 13:22:40 +01:00
itsumura-h
208b018f6b fix db_mysql getRow() when column is null error raised (#12806) [backport]
* fix db_mysql getRow()
* added if y == nil [backport]
2019-12-05 10:28:47 +01:00
cooldome
0987872675 fixes #12804 (#12809) 2019-12-05 07:38:12 +01:00
Araq
de1a283383 fixes #12798 [backport] 2019-12-04 20:38:20 +01:00
Arne Döring
b0c06aa711 fix #12740 (#12774)
* fix #12740

* A different kind of a hack

* proper fix

* fix typo
2019-12-04 07:33:01 +00:00
Timothee Cour
3383985c44 osx: support nanosecond resolution for file stat (eg getLastModificationTime) (#12794) 2019-12-04 08:12:55 +01:00
cooldome
01c7409924 Fix external file recompilation (#12802) 2019-12-03 16:54:42 +01:00
Alex Mitchell
7b562dd43d Update events.nim (#12803)
Removing old username.
2019-12-03 16:54:23 +01:00
genotrance
eed328856f Path substitution for --out and --outdir (#12796)
* Enable pathSubs for --out and --outDir
* Cleanup
2019-12-03 09:26:18 +01:00
Timothee Cour
9e1fd9e46b [minor] fix doc for $(Time) (#12795) [backport] 2019-12-03 09:12:08 +01:00
Tomohiro
378289c6a8 Fixes #12734 (#12784) 2019-12-01 23:21:36 +01:00
Ico Doornekamp
6aade97fe8 Refactored VM registerlayout. The size and location of the registers in (#12775)
the instructions are now all derived from a single definition, allowing
the register layout to be changed.
2019-11-30 13:38:36 +01:00
Jasper Jenkins
0d022622e3 fix nimsuggest deprecation warnings (#12772) 2019-11-30 06:54:15 +01:00
Jasper Jenkins
b6b8d540e3 [backport] always set fileInfoIdx.isKnownFile (#12773) 2019-11-29 22:36:01 +01:00
Euan
c5c6bae2a4 #12103 - CI for FreeBSD (#12179)
* Ref #12103 - adds FreeBSD CI
* Fix getApplFreebsd - length of the string includes the null terminator byte, so minus 1 for result length
* Show last commit in setup task.
* Remove .git from repository URL
* Don't include noisy details showing last commit.
* Add FreeBSD build status badge
* Fix #12182 - disable tconsole on FreeBSD
* Disable tgetaddrinfo on FreebSD as getaddrinfo doesn't support the ICMP protocol.
* Install boehm-gc-threaded
* Use libgc-threaded.so on FreeBSD rather than libgc.so.
* Simplify build failure handling. Update alt text for CI badge.
* Disable test on FreeBSD
* Simplify build config

- use GNU make to build csources
- set PATH variable using the environment key
- remove modification of config to set CC as this is already set

* Install git which seems to be missing from current freebsd images
* Revert change to how path is set
* Add a comment explaining why the length is truncated
* Fix tconsole.
2019-11-29 21:00:54 +01:00
Araq
7e6e399d10 fixes #12669 2019-11-29 19:46:21 +01:00
Araq
b688250202 fixes #12766 2019-11-29 19:46:21 +01:00
Pierre-Jean Grenier
a114a40b57 fix httpclient.lastModified bad pattern in parsing (#12698) 2019-11-29 11:17:10 +01:00
Oscar Nihlgård
5456da3ca9 Fix sequtils.delete bug with out of bounds indexes (#12506) 2019-11-29 11:15:20 +01:00
genotrance
49db2a08ba Fixes #12767 (#12768) 2019-11-29 10:18:44 +01:00
Jasper Jenkins
9ea55eccbb make addQuoted work on nimscript (#12717) [backport] 2019-11-28 23:01:17 +01:00
Araq
0996eb174f fixes #11727 [backport] 2019-11-28 23:00:34 +01:00
Araq
87f0d534d6 fixes #12488 [backport] 2019-11-28 23:00:34 +01:00
Araq
2dea920379 ARC: implemented a simple cycle detector 2019-11-28 23:00:34 +01:00
Clyybber
7e747d11c6 Cosmetic compiler cleanup (#12718)
* Cleanup compiler code base

* Unify add calls

* Unify len invocations

* Unify range operators

* Fix oversight

* Remove {.procvar.} pragma

* initCandidate -> newCandidate where reasonable

* Unify safeLen calls
2019-11-28 17:13:04 +01:00
PMunch
b662842bd0 Fix for 16 bit platforms (#12760) [backend]
This fixes some tiny issues with using Nim on 16-bit platforms. Not
entirely sure why the AVR chip I was compiling for with "cpu = avr" was
detected as 16-bit, but that's probably another issue..
2019-11-28 17:11:56 +01:00
genotrance
010067f3cc Substitute $nimbleDir in --path flags (#12750) 2019-11-28 13:58:38 +01:00
Andreas Rumpf
abe07eb75d VM: improvements for var T/addr (#12667); fixes #12489 2019-11-28 09:56:02 +01:00
Araq
d4cae118dc fixes a flaky test for the realtime GC 2019-11-28 09:33:01 +01:00
3n-k1
0944b0f441 [backport] Fix style issues in lib/, tools/, and testament/. Fixes #12687. (#12754) 2019-11-28 08:32:11 +01:00
Brian Wignall
a7aeabb9d2 [backport] Fix spelling typos (#12755) 2019-11-28 08:30:55 +01:00
Andreas Rumpf
fd85a5ae05 more fixes for --cpu:avr [backport] (#12748) 2019-11-27 16:24:21 +01:00
Araq
80b508d337 test suite: rename tests containing 'fail' for easier search in logs 2019-11-26 16:04:28 +01:00
Araq
72237e2bcf ARC: ported the GC tests over to --gc:arc 2019-11-26 16:04:28 +01:00
Miran
879801c639 increase the timeout for 'tasyncclosestall' (#12744)
This test is very flaky, this change might help reducing the
number of failings (usually solved by restarting the test suite).

Refs https://github.com/nim-lang/Nim/pull/12694#issuecomment-557583790
2019-11-26 14:12:15 +01:00
Timothee Cour
dfe5d115fb fixes #12663 staticRead now creates a dependency for rebuilds (#12731) [backport]
* fix #12663 staticRead
* address comments
2019-11-25 14:44:13 +01:00
Arne Döring
04614a30bd fix in tests/js/tconsole (#12709) 2019-11-25 10:30:22 +01:00
Andy Davidoff
bd8f49cbd3 replace some runtime repr in stdlib for gc:arc (#12716) 2019-11-25 10:13:30 +01:00
tauplus
8debf79837 fix typo in the manual (#12723) 2019-11-25 10:08:22 +01:00
tauplus
bfad0056ab Fix wrong section hierarchy in the manual (#12724) [backport] 2019-11-25 10:06:54 +01:00
Mamy Ratsimbazafy
1f7871ea1c csize_t changes: pinToCpu didn't compile (#12725) 2019-11-25 08:42:19 +01:00
narimiran
015bec6254 Revert "ARC: another critical bugfix; temporary tuples we introduce for tuple unpackaging are not owning the data"
This reverts commit 8b2f8f5430.
2019-11-24 09:50:52 +01:00
Araq
8b2f8f5430 ARC: another critical bugfix; temporary tuples we introduce for tuple unpackaging are not owning the data 2019-11-22 21:41:45 +01:00
Arne Döring
2acf74d458 delete list comprehension (#12392)
The `lc` macro is now part of `graveyard` repository.
2019-11-22 19:57:43 +01:00
Araq
c85e266d1d ARC: yet another silly bugfix 2019-11-22 17:18:11 +01:00
Jack Tang
f0c5d99924 index out of bounds exception when data is empty (#12428) 2019-11-22 15:37:59 +01:00
b3liever
5bb6c67a45 add collect macro (#12708)
* add collect macro

* Add to changelog
2019-11-22 14:40:50 +01:00
Andreas Rumpf
e5478b32a8 fixes #11863 multipart data need $ (#12707)
* fixes #11863
* improved the code; refs #12412
2019-11-22 14:21:03 +01:00
Andreas Rumpf
64e8f050e1 implemented a new localPassc pragma (#12706) 2019-11-22 14:20:15 +01:00
Juan Carlos
c0eeea4f3c Improve head comment on JS (#12548)
* Improve comment on JSGen, replace 12+ concatenations by 1 multiline string

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12548#discussion_r340051147
2019-11-22 11:37:30 +01:00
Andreas Rumpf
f7ba7c711a added the --asm command line option for inspection of the produced assember code (#12699) 2019-11-21 22:53:51 +01:00
Araq
135774d92b thavlak.nim: more idiomatic code 2019-11-21 20:01:43 +01:00
Araq
d45a736cc8 more thavlak.nim improvements 2019-11-21 16:06:04 +01:00
Araq
f07774d064 more thavlak.nim improvements 2019-11-21 16:03:44 +01:00
Araq
48eed1f522 thavlak.nim test: improved the code style 2019-11-21 15:34:45 +01:00
Jjp137
1b2c1bc64a Remove a stray file (#12697) 2019-11-21 11:19:54 +01:00
Andreas Rumpf
78e02d174d fixes #12670 [backport] (#12693) 2019-11-20 19:08:16 +01:00
Andreas Rumpf
c98e0e22ad conversions to unsigned numbers are not checked anymore; implements /… (#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
2019-11-20 17:08:43 +01:00
Andreas Rumpf
85ffcd80c0 more arc improvements (#12690)
* ARC: bugfix for =destroy for inherited objects
* added code useful for debugging
2019-11-20 14:34:05 +01:00
c-blake
a88004114d Discussion both in (#12678)
https://github.com/nim-lang/Nim/pull/12600
and in
    https://forum.nim-lang.org/t/5499
indicates that everyone is happy/happier with ``pop``.

This just renames the brand new ``take``s to ``pop`` and installs inline
aliases/wrappers to preserve ``Table.take`` and ``TableRef.take``.

Update apis.rst to try to maintain consistency of remove-and-return procs.
2019-11-20 08:39:45 +01:00
Andreas Rumpf
56a00da34a fixes #12612 [backport] (#12681) 2019-11-19 12:09:36 +01:00
Arne Döring
03fa9a9041 fix regression in align (#12680)
* fix regression in align

* add test typesym without type
2019-11-19 09:58:47 +01:00
Andreas Rumpf
5278cf80eb ARC: closure bugfixes (#12677)
* ARC: closure bugfixes
* progress
* ARC closures: create =hooks for captured parameters
* ARC: always destroy constructions like tuples, arrays properly, even in edge cases
* fixes a regression
2019-11-18 12:33:44 +01:00
Dominik Picheta
bab5351d43 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: ()
```
2019-11-18 09:26:06 +01:00
Andreas Rumpf
223e65e529 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
2019-11-18 09:10:48 +01:00
Andreas Rumpf
58f3e07b1a fixes and changes the recently introduced 'alignas' to be 'align' (#12666)
* fixes and changes the recently introduced 'alignas' to be 'align'

* more improvements
2019-11-15 20:24:14 +01:00
Juan Carlos
9c46526cfa Fix htmlgen html lang (#12668) [backport]
* Fix HTMLGen enable lang on html tag
2019-11-15 20:23:03 +01:00
Gampol T
83b7656c0e fixes #12319 - change exception handling for finish.exe (#12413)
* documented behaviour of recv on bufferd socket

* fixes #12319- check exception using errorCode
2019-11-15 13:28:55 +01:00
Andreas Rumpf
76179cbec2 ARC: fixes leaking new() statement (#12665) 2019-11-15 12:38:11 +01:00
Miran
107b40f097 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.
2019-11-15 12:37:43 +01:00
David Krause
ffca3eefb5 fix documentation of $*(dt: DateTime) (#12660)
(cherry picked from commit 39122ecd93)
2019-11-15 08:06:26 +01:00
Andreas Rumpf
a14abc5708 ARC: solves phase ordering problems (#12654) 2019-11-14 23:19:18 +01:00
Araq
f22d3c75aa ARC: closure inside object constructor now works 2019-11-13 23:29:21 +01:00
Araq
bcab3ed06c ARC: handle closures like tuples consistently 2019-11-13 23:29:21 +01:00
Araq
3020e49b75 ARC: use the new .cursor annotation for 'up' pointers 2019-11-13 23:29:21 +01:00
Andreas Rumpf
6ad0238fd7 make tests green again 2019-11-13 23:29:21 +01:00
Araq
25c724d38b gc:arc: support GC_ref/unref for ref T 2019-11-13 23:29:21 +01:00
Araq
eea0cb07cf async: cleaner solution that avoids GC_ref on strings which doesn't exist for --gc:arc 2019-11-13 23:29:21 +01:00
narimiran
a1e7bf81b3 a better way to test Arraymancer 2019-11-13 16:25:43 +01:00
narimiran
8394c00300 remove long-deprecated 'mapIt' 2019-11-13 14:24:25 +01:00
Arne Döring
0496a666e2 implemented alignas pragma (#12643)
* implemented alignas pragma

* fix bootstrap

* generate c++ compatible syntax for alignas

* Make it work.

* Multiple alignof expressions. Implement top level alignof.
2019-11-13 08:22:41 +00:00
Andreas Rumpf
84861eb48a fixes #12644 2019-11-12 23:56:19 +01:00
Andreas Rumpf
dfb020b174 .cursor implementation (#12637)
* cursors: first implementation
* added currently failing test
* .cursor works for doubly linked lists
* make -d:useMalloc work again
* added code to nil out refs in a destructor
* it's now called --gc:arc
* renderer.nim: render nkBreakState properly
* make simple closure iterators work without leaking
2019-11-12 15:05:36 +01:00
Euan
7e689873e2 Fix #12135 and #12109 (#12137)
* Fix #12135 and fix #12109 - fix OpenBSD type defs

* Fix Mode definition as in #12132
2019-11-11 16:18:08 +01:00
b3liever
0c4d81241a Version of trimZeros without temp strings (#12633) 2019-11-11 12:54:17 +01:00
Araq
a4d43d7d0c --gc:destructors: bugfixes 2019-11-09 20:34:51 +01:00
Araq
e835377d3f inhibit silly warning about moving closure environments for performance 2019-11-09 20:33:23 +01:00
Andreas Rumpf
82e0765fc9 --gc:destructors improvements (#12626)
* do not cache the noDestructors transformation
* liftdestructor: improvements
* undo bugfix
2019-11-09 13:21:55 +01:00
Clyybber
144ad36974 Implemented outplace differently (#12599)
* implemented sugar.outplace; refs #12550
* Different approach, allows for chaining
2019-11-09 12:52:31 +01:00
Miran
6958248efe fix #12519: introduce OrderedTable.take, CountTable.del, CountTable.take (#12600)
* add OrderedTable.take

* add CountTable.del and CountTable.take

* add .since pragma to the introduced public procs

* add changelog entry [ci skip]
2019-11-08 16:35:27 +01:00
cooldome
1e71c13697 fix compilation warning (#12618)
* fix compilation warning

* comments incorporated
2019-11-08 09:16:44 +01:00
Volodymyr Lashko
4e841ab156 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
2019-11-07 22:00:34 +00:00
Andreas Rumpf
135e945ff0 make parsexml compatible with --gc:destructors/newruntime 2019-11-07 18:18:51 +01:00
Yanis Zafirópulos
76085e8a45 added support for openArray's for gcd and lcm (#12621) 2019-11-07 18:06:48 +01:00
Arne Döring
a2d6691af2 fix #12597 (#12604) 2019-11-07 17:16:34 +01:00
Judd
8b1ef8e07e allow random module to be used in standalone: (#12617)
proc randomized*() uses time releated function which is not available on
standalone, so disable this function for standalone.
2019-11-07 14:48:33 +01:00
cooldome
e1b1759439 fixes #5050; fixes #11826 (#12606) [backport] 2019-11-07 14:47:26 +01:00
Arne Döring
94675c2378 backtick and export marker handling in eqIdent (#12574) 2019-11-07 14:40:44 +01:00
Andreas Rumpf
372b01711e added 'since' template for further stdlib additions 2019-11-07 14:20:39 +01:00
Andreas Rumpf
f69ee294c8 bugfix that enables the 'since' template [backport] 2019-11-07 14:20:39 +01:00
Andreas Rumpf
14a0182ca6 pragmas.nim: tiny code formatting 2019-11-07 14:20:39 +01:00
narimiran
0d00bde4ea fix failing test 2019-11-07 11:04:41 +01:00
Andreas Rumpf
166048da5d osproc needs 'import linux' for -d:useClone 2019-11-07 09:51:15 +01:00
Andreas Rumpf
230c618eb9 error message: Nim calls it 'proc' 2019-11-07 09:41:04 +01:00
Dominik Picheta
675189c77f Merge pull request #12613 from nim-lang/miran-unused-imports
Remove unused imports
2019-11-06 22:08:43 +00:00
Andy Davidoff
5544a13236 restore --define🔑val in nim.cfg and fix #12367 (#12611) 2019-11-06 21:26:03 +01:00
Andy Davidoff
738c957e94 add --clearNimblePath; fixes #12601 (#12609) 2019-11-06 20:40:22 +01:00
narimiran
717da9f158 [backport] print more information for the previous commit 2019-11-06 16:14:28 +01:00
narimiran
5381c810a8 [backport] rewrite flaky runnable example 2019-11-06 15:54:21 +01:00
narimiran
c6a451c584 remove unused imports from tests 2019-11-06 14:35:45 +01:00
Tor Arvid Lund
5ccbf7e3cf [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`
2019-11-06 13:42:39 +01:00
narimiran
cc3e9ca164 remove unused imports 2019-11-06 12:01:00 +01:00
Andy Davidoff
61889c604a export nim.cfg parser (#12602) 2019-11-06 09:59:23 +01:00
Federico Ceratto
59c212607e [backport] Add links to packaging and distro pages (#12603) [ci skip] 2019-11-06 09:03:28 +01:00
Araq
d19206755b async: use $ and not repr in debug mode 2019-11-05 17:10:02 +01:00
Araq
1794cd477d expr -> untyped 2019-11-05 16:55:08 +01:00
jiro
0694bd47b9 Add or detectOs(Manjaro) (#12587) [backport]
Using `pacman` command in Manjaro Linux

(cherry picked from commit 1ff3494dab)
2019-11-05 16:21:28 +01:00
Andreas Rumpf
3ba3307d61 remove deprecated procs (#12535) 2019-11-05 11:05:46 +01:00
Miran
ffa9a7405f fix #8242, fix #12586: fix 'formatFloat' with 'precision = 0' (#12592)
* fix #8242, fix #12586: fix 'formatFloat' with 'precision = 0'

'formatFloat' with 'precision = 0' now gives the same result
(a number without a decimal point) in all backends.
This is compatible with Python's formatters, too.

* fix failing tests

* add changelog entry

* add version switch
2019-11-05 10:31:23 +01:00
Andreas Rumpf
46af8164c0 implement the --useVersion emulation feature 2019-11-04 21:58:26 +01:00
Kaushal Modi
b24560a140 Make sequtils.zip return seq of anonymous tuples (#12575)
* Make sequtils.zip return seq of anonymous tuples

Earlier the tuples had named fields "a" and "b" and that made it
difficult to assign the zip returned seqs to other vars which expected
seqs of tuples with field names other than "a" and "b".

* Make sequtils.zip backwards compatible with Nim 1.0.x
2019-11-04 21:11:43 +01:00
Clyybber
cf5c3f2400 Fixes #12379 (#12591) [backport] 2019-11-04 20:57:14 +01:00
alaviss
558ecd1ca6 compiler/suggest: add variable support to con (#12569)
This allows for the type of a variable to be retrieved.
2019-11-04 18:29:26 +01:00
Miran
ae32d637f7 [backport] fix #12395 (#12590)
'countBits32' is now fixed in the same way that
'countBits64' was already patched earlier (by adding 'u32
where needed).
2019-11-04 15:02:36 +01:00
Arne Döring
992f0a7756 fix conversions to uint in varints.nim (#12564) 2019-11-04 13:06:08 +01:00
Andreas Rumpf
62fc3db9d7 --os:ios needs to imply defined(macosx) [backport] (#12585) 2019-11-04 13:05:03 +01:00
narimiran
bdc2bcc36c NimPatch of devel version should be an odd number because of the earlier hacks 2019-11-03 16:04:21 +01:00
Andreas Rumpf
3f4b9971fc newruntime: only check for dangling refs when 'owned ref T' support is enabled 2019-11-03 09:46:49 +01:00
Juan Carlos
4c9a7e6f00 JS improve indent (#12581)
* JSgen make indent be all spaces, instead of mixed spaces and tabs, for generated JS
2019-11-03 08:03:03 +01:00
Andreas Rumpf
ceda586d88 fixes #12577 [backport] (#12584) 2019-11-03 07:55:55 +01:00
Tomohiro
4e0f12092e Fixes #12536 (#12568) [backport] 2019-11-02 08:21:49 +01:00
Andreas Rumpf
44a27ccfe1 --gc:destructors: simple closures work 2019-11-02 00:39:04 +01:00
Andreas Rumpf
7a4d066102 make renderIds work again 2019-11-01 21:02:44 +01:00
Andreas Rumpf
3761e62fde improve codegen quality for --gc:destructors 2019-11-01 09:59:18 +01:00
Kaushal Modi
d914e9a65f [backport] Add docs to better distinguish among getProjectPath, getCurrentDir and currentSourcePath (#12565)
Fixes https://github.com/nim-lang/Nim/issues/10477.
2019-10-31 21:00:18 +01:00
Arne Döring
99078d80d7 introduce csize_t instead of fixing csize (#12497) 2019-10-31 19:18:12 +01:00
genotrance
0c7b6c9c15 Switch mingw links (#12561) 2019-10-31 11:13:32 +01:00
Andreas Rumpf
79a262d6e9 better testing for nimcrypto; re-enable chronos testing (#12560) 2019-10-31 07:18:45 +01:00
Andreas Rumpf
1746da2d9e --gc:destructors now means Nim uses pure refcounting (#12557) 2019-10-30 16:15:17 +01:00
Juan Carlos
b5bb581642 Improve Math.Trunc code emit on JS, had weird whitespaces and indents (#12549) 2019-10-30 14:12:17 +01:00
Nindaleth
34dbc5699e fix several typos in documentation and comments (#12553) 2019-10-30 09:08:45 +01:00
Araq
1214960a1b fixes #12547 [backport] 2019-10-29 15:07:04 +01:00
zah
de5f6a07c2 Fix newLit for objects having string fields (#12542) [backport] 2019-10-28 22:45:55 +01:00
Araq
44b1ecc287 destructors.rst: added a missing 'var' to the motivating example 2019-10-28 18:15:17 +01:00
Andreas Rumpf
e58c2d261c [backport] fix #12528, fix #12525: incorrect generic type resolution for default values (#12538) 2019-10-28 16:56:38 +01:00
Andreas Rumpf
c52a2c3ab0 proof that refcounting can handle Nim's async (#12533) 2019-10-28 16:13:38 +01:00
Solitude
160c07be00 Fix code style errors (#12545) 2019-10-28 15:21:10 +01:00
Anthon van der Neut
c58aa7705d [backport] fix broken link to non-existing c2nim manual html, fixes #12537 [ci skip] (#12544) 2019-10-28 13:51:43 +01:00
Tomohiro
90376940bb Add a changelog entry related to PR #11748 [ci skip] (#12541) 2019-10-28 13:29:13 +01:00
Jjp137
ee119f7984 colors: fix 'mix' template and make most examples runnable (#12532) [backport]
* colors: fix the 'mix' template
* colors: make most examples runnable
2019-10-28 13:11:11 +01:00
Artem V L
580462c886 splitPath() behavior synchronized with splitFile() (#12481)
* splitPath() behavior synchronized with splitFile() having the expected behavior in all languages

splitPath() docstrings update, tests added for both splitPath() and splitFile()

* Path splitting refined and described
2019-10-28 12:58:02 +01:00
Tomohiro
a9d7796e1c [feature]strformat: add 2 'fmt' macros that use specified characters instead of '{}' (#11748)
* [feature]strformat: add 2 'fmt' macros that use specified chars instead of '{}'

* strformat: revert documentation comments of `&` and 'fmt'

* strformat: removed single open/close char variant of fmt
2019-10-28 12:33:44 +01:00
Arne Döring
5ed99f8d3f Extent json.to testing to VM, add workrounds for VM bugs. (#12493)
fixes #12479
2019-10-28 10:06:16 +01:00
Miran
a2ad7d4883 fix deprecation warnings related to Int128 (#12474)
* semfold: fix deprecation warnings related to Int128

* semmagic: fix deprecation warnings related to Int128

* system/io: remove unneeded conversion of TaintedString to itself
2019-10-28 09:58:39 +01:00
Arne Döring
91af075244 integer literal documentation [ci skip] (#12513)
* integer literal documentation [ci skip]

* apply feedback [ci skip]
2019-10-28 09:52:59 +01:00
Andreas Rumpf
7192b13609 some progress on bug #12443 2019-10-27 17:50:30 +01:00
Andreas Rumpf
cbbc2cc237 fixes #12502 2019-10-27 17:50:30 +01:00
Andreas Rumpf
120829155a development version should be 1.1.0 so that version checking can work properly 2019-10-27 17:50:30 +01:00
Andreas Rumpf
0631d2dccc minor improvements 2019-10-27 17:50:30 +01:00
Tomohiro
f3b56e7ac0 Add /nologo option when nim call cl.exe (#12524) 2019-10-27 11:36:38 +01:00
Arne Döring
3c567bcf20 fixes #12514 (#12520) [backport] 2019-10-27 11:34:33 +01:00
Jjp137
3a62cf29d8 Remove sentences referring to the graphics module (#12522) 2019-10-26 04:28:01 -04:00
Artem V L
60ff41a8da '#' value parcing is explained (disambiguated) (#12476) 2019-10-25 15:22:26 +02:00
Jjp137
1d42108fda sequtils: replace deprecated 'random' call within example (#12515) [backport] 2019-10-25 09:47:34 +02:00
alaviss
5b3571c9a4 compiler/semtypes: improve lineinfo for exported object fields (#12495)
The line info should now points to the `a`, not the `*`, like this:
    a*: string
    ^
Additionally this fixes nimsuggest's highlighting of exported object
fields.
2019-10-25 01:06:53 +02:00
Andreas Rumpf
e0d13abaff VM: fixes register leaks [backport] (#12510) 2019-10-25 00:45:06 +02:00
Tomohiro
8040c84615 Fix Nim specify wrong option to vccexe when vcc.options.always is set (#12490) [backport] 2019-10-24 23:43:59 +02:00
Andreas Rumpf
8a599fb571 fixes #12491 [backport] 2019-10-24 22:51:13 +02:00
alaviss
f827d75804 compiler/semcall: return the correct lineinfo for nkCallStrLit (#12484) 2019-10-24 18:21:37 +02:00
Andreas Rumpf
801a794039 VM: fixes most ran-out-registers problems [backport] (#12485) 2019-10-24 17:29:32 +02:00
Federico Ceratto
9ac062b746 [backport] Add link to posix_utils.html - related to #10723 (#12509) 2019-10-24 14:08:59 +02:00
UNIcodeX
d731646106 [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.
2019-10-24 14:08:27 +02:00
Miran
b03de8a4d9 Fix many broken links and prefer relative links within docs (#12463)
* 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.

* 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.

* koch.rst: remove link to nonexistent section

* 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.

* asyncstreams: replace unintended link with emphasis

* Fix word wrapping
2019-10-24 14:07:43 +02:00
Juan Carlos
8f8916413f [backport] Documentation Math module (#12460) 2019-10-24 14:07:21 +02:00
narimiran
2baa21d461 disable package 'chronos' for now 2019-10-24 13:46:59 +02:00
Araq
a03a8e80ea fixes a regression that caused that Nim devel cannot compile 1.0 anymore 2019-10-24 12:27:34 +02:00
Araq
e506c1e0ea fixes a regression that caused that Nim devel cannot compile 1.0 anymore 2019-10-24 12:27:34 +02:00
Araq
619b997c31 ast.nim: slightly better documentation 2019-10-24 12:27:34 +02:00
Oscar Nihlgård
3d0c756a3c Fix JS bug in std/monotimes (#12499) [backport] 2019-10-24 11:24:26 +02:00
Oscar Nihlgård
4ac100c912 Fix jsgen bug with uninitialized seq (#12500) [backport] 2019-10-24 11:17:01 +02:00
Oscar Nihlgård
9ccfcf5dd2 Fix compiler crash caused by top level return (#12501) 2019-10-24 11:04:04 +02:00
narimiran
822078ed12 add changelog for v1.0.2 2019-10-23 14:35:31 +02:00
Arne Döring
8d3d97aa9b no html comments in issue template [skip ci] (#12496) 2019-10-23 12:08:17 +02:00
narimiran
d5cd5b00b9 disable flaky test on OSX 2019-10-23 11:24:43 +02:00
narimiran
2120fb2777 [backport] package chronos now has dependencies 2019-10-23 11:20:12 +02:00
Arne Döring
fe4a59f12b fixes #12453 (#12475) 2019-10-23 10:29:12 +02:00
narimiran
c90b4ecddc Revert "[ci skip] disable two packages until #11764 is merged"
This reverts commit 48975bb3e7.
2019-10-23 07:09:08 +02:00
Jjp137
3ad48069d3 Fix word wrapping 2019-10-22 17:59:12 -07:00
Jjp137
e6d5379b3b asyncstreams: replace unintended link with emphasis 2019-10-22 17:59:12 -07:00
Jjp137
59c1f7c87f 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.
2019-10-22 17:59:12 -07:00
Jjp137
79aa58979c koch.rst: remove link to nonexistent section 2019-10-22 17:59:12 -07:00
Jjp137
72147c9ba4 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.
2019-10-22 17:59:12 -07:00
Jjp137
93461aee34 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.
2019-10-22 17:59:12 -07:00
Dominik Picheta
6bfa4eb6c5 Merge pull request #12371 from rayman22201/IOSelector_unregister_fix
Test + fix for epoll and kqueue selector modules to properly unregister event handles that have the key type "User"
2019-10-22 11:32:22 -07:00
Dominik Picheta
92fa7e0579 Merge branch 'devel' into IOSelector_unregister_fix 2019-10-22 11:31:38 -07:00
Artem V L
049032432c Docstring refined for the getSectionValue() (#12478) [backport] 2019-10-22 18:20:25 +02:00
Paul Tan
ad3c10022a guards.nim:sameTree(): handle uint literals correctly (#12483) [backport] 2019-10-22 18:18:33 +02:00
Andy Davidoff
2ccd1c3428 tweaked for clarity after editing to fix a typo (#12473) 2019-10-22 13:54:48 +02:00
Andreas Rumpf
38b3590e40 fixes #12310 [backport] (#12470) 2019-10-20 22:37:31 +02:00
Arne Döring
ec20fd3544 fix #12426 (#12462) 2019-10-20 11:52:50 +02:00
ducdetronquito
df4c339cfc Namespace unittest enums to avoid name conflicts (#12468) [backport]
* [backport] Fixes: #12465 - Unittest - Namespace the usage of TestStatus enum to avoid name conflicts.
2019-10-20 08:12:02 +02:00
Araq
0eae2217b6 first implementation of the new --seqsv2 switch 2019-10-20 08:11:07 +02:00
Araq
ed2fb36bc6 refactoring: use the new strings and seqs when optSeqDestructors is active 2019-10-20 08:11:07 +02:00
Araq
61ea85687c refactoring: --newruntime consists of 3 different switches 2019-10-20 08:11:07 +02:00
Ray Imber
91661c16a1 Update changelog.md based on feedback from Dom96 2019-10-19 14:30:10 -07:00
Andreas Rumpf
832b0a0232 fixes #12420 [backport] (#12456) 2019-10-18 22:13:24 +02:00
Tomohiro
6b157e5f73 Fix vcc linker option name (#12422) 2019-10-18 16:20:18 +02:00
Andreas Rumpf
889b745b2b Revert "Fixes #12187 (#12321)" (#12447)
This reverts commit 00c31e8766.
2019-10-18 15:59:22 +02:00
Juan Carlos
f5b4d9a2e5 Fixes #8802 (#12439)
* Fix #8802

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12439#discussion_r335905397
2019-10-18 14:27:23 +02:00
Juan Carlos
4a0debfe87 Add no-ident for GCC when -d:release (#12454) 2019-10-18 14:13:55 +02:00
Juan Carlos
0a6e0a3f38 Improve htmlgen (#12452) 2019-10-18 12:16:01 +02:00
Miran
a5ab502f08 [backport] fix type's case in random.nim (#12445) 2019-10-17 22:13:00 +02:00
Andreas Rumpf
81125e2029 [backport] add back a check that got accidentically removed; fixes #12379 (#12444) 2019-10-17 20:02:59 +02:00
Juan Carlos
4d1f69c7d2 Fixes #10824 (#12437) 2019-10-17 11:39:01 +02:00
Juan Carlos
2cfd58de48 Fix #10804 (#12438) 2019-10-17 11:37:55 +02:00
Juan Carlos
1ccf1b89c2 Improve jsconsole adding the rest of the stable api as documented on the standard at https://developer.mozilla.org/docs/Web/API/Console (#12440) 2019-10-17 11:37:08 +02:00
Arne Döring
21cbfd72ec Refactor json macro (#12391)
* closes #12316
* make tjsonmacro work at js target
* closes #12289
* closes #11988
* also fixed gdb related stuff
2019-10-17 09:55:41 +02:00
treeform
5ba932e43c About 50% faster base64 implemention. (#12436) 2019-10-17 09:50:00 +02:00
Ray Imber
bec8225448 Updated the changelog 2019-10-16 19:14:18 -07:00
Ray Imber
bef1c4437d fixes based on code review by @dom96
- For clarity: Changed the unregister if statement to use the in operator instead of
the set intersection operator in ioselectors_epoll.nim and
ioselectors_select.nim.

- Fixed unregister of Event.User case on the Android branch.
2019-10-16 14:13:09 -07:00
alaviss
37dfb7ecc6 compiler/options: only check the last folder for a candidate (#12421)
This prevents a nimble file from causing a different project to be
targeted instead of the desired one.
2019-10-16 13:03:11 +02:00
Miran
734da9e1df fixes #11764, faster hashing of (u)int (#12407) 2019-10-15 16:31:07 +02:00
Miran
5f5ac8ce16 [backport] fix #12418, fix random.randomize on JS backend (#12432) 2019-10-15 16:29:32 +02:00
Yuriy Glukhov
1aed455e7c Fixed yield in nkCheckedFieldExpr (#12429) [backport] 2019-10-15 09:16:06 +02:00
narimiran
48975bb3e7 [ci skip] disable two packages until #11764 is merged 2019-10-14 11:51:41 +02:00
Ray Imber
233455a685 Remove unnecessary change to ioselectors_kqueue.nim found by @cheatfate. 2019-10-11 12:24:29 -07:00
Alexander Ivanov
990aadc43c Fixes semCustomPragma when nkSym (#12414) [backport] 2019-10-11 18:05:23 +02:00
alaviss
94c1695be6 compiler/options: improve project file detection (#12404)
The compiler can now correctly find the project file of a nimble package.
The algorithm is based on what used by nim.nvim, which has yielded good
results.
2019-10-11 18:04:52 +02:00
alaviss
f957266574 nimsuggest: add a command that returns the project file (#12411)
This can be used to let nimsuggest users know which project is
nimsuggest being in charge of, so they can know when should a new
nimsuggest instance be spawned.

An additional feature is to debug the project file finding feature.
2019-10-11 18:00:38 +02:00
alaviss
eeffa0163f nimsuggest: add option to force finding the project file (#12409) 2019-10-11 09:55:15 +02:00
Arne Döring
7cf3395d85 refactor illegal iterator assignment detection (#12212)
* refactor illegal iterator assignment detection

* delete crappy test
2019-10-11 08:43:58 +02:00
Jasper Jenkins
245a954b25 ungeneric unsigned ops (#12230)
* ungenericise unsigned ops, remove nimNewShiftOps
* fix/remove tests
* update t6448
* fix line info
* disable on 32bit
* fix different line info
* add changelog entry
2019-10-11 08:38:08 +02:00
genotrance
9e62876647 Fixes #12286 - require explicit disabling of boehm interior pointer checking (#12406) [backport] 2019-10-11 07:39:18 +02:00
Ray Imber
4e6f2b5313 Fix drain to correctly take into account hasPendingOperations and the timeout value 2019-10-10 17:53:44 -07:00
Ray Imber
aa84d35d86 Fix io slector unregister for windows as well. 2019-10-10 16:50:36 -07:00
Euan
45030972b9 #12389: Check working directory for getAppFilename() (#12390)
* Check working directory for exe
* Expand symlinks
* Use expandFilename() to expand symlinks
* Move OpenBSD code to getApplOpenBsd()
2019-10-10 17:28:47 +02:00
Arne Döring
0a29c05a1b fix #12332 (#12402) [backport] 2019-10-10 14:35:26 +02:00
Andreas Rumpf
00e06bba28 minor improvements for htmlgen.nim 2019-10-10 13:47:55 +02:00
Andreas Rumpf
d783c0f7ff fixes a koch regression that made 'koch boot --listcmd' not work anymore [backport] (#12400) 2019-10-10 11:56:01 +02:00
Araq
7f904e2c66 fixes #12244 [backport] 2019-10-10 10:00:57 +02:00
awr1
3b1760df72 [backport] Mention "lambdas" and => in the manual (#12397) [ci skip]
(so that "lambda" can be CTRL+F'd)
2019-10-10 09:28:54 +02:00
Andreas Rumpf
f728614ef8 fixes #12366 [backport] (#12393) 2019-10-09 14:48:42 +02:00
Gampol T
82fe19769a documented behaviour of recv on bufferd socket (#12374) 2019-10-09 10:48:15 +02:00
Nindaleth
84c956d9da fix a few dead links and a missing sentence in documentation (#12387) 2019-10-08 15:24:34 -04:00
Andreas Rumpf
f30da2f266 fixes #12315 [backport]; refs #12314 (#12385) 2019-10-08 20:49:45 +02:00
Clyybber
00c31e8766 Fixes #12187 (#12321)
* Fixes #12187
* Point to fork of compactdict
Since the original repo is now archived / read-only
2019-10-08 14:15:47 +02:00
alaviss
edb24b7ce0 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.
2019-10-08 14:14:18 +02:00
Ray Imber
7c23522b29 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
2019-10-08 11:24:06 +02:00
Ridho Pratama
7ef4bffa79 renderer letAux fix only for octal literal (#12343)
* renderer letAux fix only for octal literal

* Handle when it's octal -1 for i64

* Added testcases
2019-10-08 11:12:24 +02:00
treeform
dbcffcfccb 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
2019-10-08 11:00:37 +02:00
pietroppeter
89c37fada7 [doc/tut1] removed discard discussion in comments (#12352) 2019-10-08 09:08:38 +02:00
alaviss
e9fa4c9b9c 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.
2019-10-08 08:11:18 +02:00
cooldome
0355c64b92 External file compilation improvement (#12380) 2019-10-08 08:10:55 +02:00
Tomohiro
509f53b782 On windows, os.relativePath returns path as is when roots are different (#12329)
* On windows, os.relativePath returns path as is when roots are different
* Implement os.sameRoot without windows API
* Fix compile error when compiling lib/nimhcr.nim
* Fix compile error when compiling lib/nimhcr.nim on Windows
2019-10-07 19:57:16 +02:00
Ray Imber
b347490f91 lowered the number of events in the test because some CI's have an extremely low FD limit 2019-10-07 10:07:05 -07:00
Federico Ceratto
f9d95fd6a7 Refactor closeEmitter to make it more modular (#12365) 2019-10-07 17:26:27 +02:00
Andreas Rumpf
a60f18d025 fixes #12323 [backport] 2019-10-07 06:47:30 +02:00
Andreas Rumpf
9d000c519a render typeof as typeof 2019-10-07 06:47:30 +02:00
Ray Imber
0338516e70 Additional fix for User key unregister in the KQueue backend 2019-10-06 17:33:58 -07:00
Ray Imber
adc1419499 Test + fix for epoll and kqueue selector modules to properly unregister
event handles that have the key type "User"
2019-10-06 16:02:12 -07:00
Andreas Rumpf
5be8e0b088 VM: no special casing for big endian machines; refs #9690 [backport] (#12364) 2019-10-06 19:28:53 +02:00
Federico Ceratto
a03d8ed4c2 Expose some layouter elements, improve readme (#12361)
Useful for writing linters and static code analysis
2019-10-04 22:43:47 +02:00
Ico Doornekamp
26676066cc added cpuTime to VM (#12346)
* added cpuTime to VM

* Hide VM-time cpuTime() behind --benchmarkVM flag
2019-10-04 19:32:16 +02:00
kraptor
412011eb96 Fix reference to parseSpec proc in readme (#12359) 2019-10-04 19:30:58 +02:00
Hideki Okamoto
294d5fb560 Fixes #12010; Add the description for "cc" option into --fullhelp (#12350) 2019-10-04 19:30:20 +02:00
Miran
2909e41370 [backport] bundle nimpretty on Windows (#12358) 2019-10-04 17:13:04 +02:00
Andreas Rumpf
60d64d1aef use system.move instead of system.shallowCopy if the GC mode requires it 2019-10-04 09:48:45 +02:00
Andreas Rumpf
68ce808db1 minor optimization for asynchttpserver.nim 2019-10-04 09:48:45 +02:00
Andrew Owen
64acc9dbfb [backport] Fix typo in docs (#12356) [ci skip] 2019-10-04 08:40:15 +02:00
Dominik Picheta
4ab9b6146b Change future version number in changelog 2019-10-03 21:26:20 +01:00
Ridho Pratama
678775601a Fixed sizeOf to sizeof (#12347) 2019-10-03 19:38:37 +02:00
Leorize
73c8391fd3 azure: disable failing tests 2019-10-03 18:36:18 +02:00
Leorize
acebcd7899 testament: add azure integration 2019-10-03 18:36:07 +02:00
Leorize
880df4de62 azure-pipelines: add pipelines for linux, mac and win
This is the equivalent to the current AppVeyor + Travis setup.
2019-10-03 18:35:54 +02:00
Andreas Rumpf
c51857f434 fixes #12291 [backport] (#12338) 2019-10-03 07:50:32 +02:00
Ico Doornekamp
982086dbe9 Fixed #12337, leaking pipe after gorge (#12339) 2019-10-03 00:48:31 -04:00
hlaaftana
ba43156363 Sets need copying in JS (#11392)
* Sets need copying in JS
* Fixes #11353
* Add test for #11353
2019-10-02 21:01:59 +02:00
zah
ad13e18c7c system.writeFile has been overloaded to also support openarray[byte] (#12313) 2019-10-02 20:34:03 +02:00
Timothee Cour
2446570350 fixes #12330 (#12331) 2019-10-02 17:57:24 +02:00
Andreas Rumpf
98e76a1058 fixes #12336 [backport] 2019-10-02 17:01:27 +02:00
narimiran
032c3b77db test more packages 2019-10-02 12:35:18 +02:00
Andrew Smith
0d94ee15c0 Updated the code example in the os module to use better grammar. (#12328) 2019-10-02 00:43:38 -04:00
Jasper Jenkins
c20778d2d3 Macro docs additions (#12270)
* small macros doc additions

* more changes

* fixes [ci skip]

* capitalization, couple additions

* nkNodeKind to nnkNodeKind
2019-10-01 08:55:26 -04:00
Clyybber
5f5879dc4c Refactor injectdestructors (#12295)
One improvement over #devel is visible in the transformation of getEnv. With this approach we move to result whenever possible.
2019-10-01 14:09:24 +02:00
Tomohiro
64d5e25821 Fix how relativePath handle case sensitiviy (#12312) [backport] 2019-10-01 09:09:59 +02:00
Andreas Rumpf
6dd4cbc3af fixes #12240 [backport] (#12308) 2019-10-01 05:52:51 +02:00
zah
a4ade43536 macros.newLit now works for ref object types (#12307) 2019-09-30 22:24:57 +02:00
Andreas Rumpf
dd082b6ec8 fixes #12264 [backport] (#12302) 2019-09-30 21:44:24 +02:00
Andreas Rumpf
72acf5de94 fixes #12281 [backport] 2019-09-30 20:42:16 +02:00
Andreas Rumpf
1964589a29 fixes #12294 [backport] 2019-09-30 20:01:25 +02:00
narimiran
5732bb41ef [backport] run nimpretty on the remaining files 2019-09-30 13:58:17 +02:00
narimiran
34d0be2ec1 [backport] run nimpretty on os-related stuff 2019-09-30 13:58:15 +02:00
narimiran
dcf3181bd1 [backport] run nimpretty on string stuff 2019-09-30 13:58:13 +02:00
narimiran
0ca9cc7419 [backport] run nimpretty on web stuff 2019-09-30 13:58:11 +02:00
narimiran
15895ebc3f [backport] run nimpretty on hashes 2019-09-30 13:58:10 +02:00
narimiran
b17ed2ca9c [backport] run nimpretty on parsers 2019-09-30 13:58:08 +02:00
narimiran
6c994b2498 [backport] run nimpretty on numbers stuff 2019-09-30 13:58:05 +02:00
narimiran
aa513d78e7 [backport] run nimpretty on async 2019-09-30 13:57:58 +02:00
Araq
63bcbea700 JS: gensym is stricter for 'this'; refs #12246 [backport] 2019-09-30 13:21:46 +02:00
Araq
c5a1149e00 different fix for #12279 [backport] 2019-09-30 13:11:24 +02:00
Araq
0ecf3806c4 fixes #12298 2019-09-30 12:06:41 +02:00
Araq
86de2cddf6 fixes #12279 [backport] 2019-09-30 10:40:00 +02:00
Clyybber
16c39f9b2e More of StringStream now works at compile time (#12284)
* readLine of StringStream now works at compile time
* Work for js backend only at compile time
* readAll now works at CT
* readAll works in js ct now
* Add test
2019-09-29 22:20:00 +02:00
Clyybber
85db42ad8c Fixes #10514 (#12268)
* Fixes #10514

(cherry picked from commit f6f789bb4d)

* Add comment

* Add changelog entry
2019-09-28 19:50:20 +02:00
Andrey Makarov
5a65243e14 fix nimgrep color on posix #7591 (#12288) 2019-09-28 00:19:57 +02:00
narimiran
f804245087 [backport] fix nimpretty removing space before pragma 2019-09-27 10:36:22 +02:00
narimiran
e0cd52365c [backport] fix #12278, don't expose internal PCRE documentation 2019-09-27 10:13:04 +02:00
narimiran
ce4eb4ac91 Nim now has Patreon account [ci skip] 2019-09-27 08:22:46 +02:00
Federico Ceratto
39290cf88c Fix spellings (#12277) [backport] 2019-09-27 07:02:54 +02:00
Ray Imber
9dd297f613 Locks modules should give a compile error when threads are not enabled. (#12231)
* Locks modules should give a compile error when threads are not enabled.

* fix the compile flags to make the tests pass, or ignore files where necessary.

* Fixed when statement to account for doc builds.
2019-09-26 15:45:50 +02:00
John Paul Adrian Glaubitz
944fcc0e62 Add build support for Linux/hppa (#12271)
* build.sh: Enable CPU detection for hppa
* compiler: Add hppa as target architecture on Linux
* lib/system: Add platform support for hppa
2019-09-26 15:45:05 +02:00
Endeg
657e09e79d Fix #12242, replacing ":" with "@c" in packages [backport] (#12265) 2019-09-25 20:32:36 +02:00
Mathias Stearn
920f9be9aa Explicitly state that trailing underscores are banned (#12257)
It was explicit in the BNF, but the English text implied it was allowed.
2019-09-25 19:12:54 +02:00
Andreas Rumpf
5f44651769 updated the contributing.rst guidelines 2019-09-25 15:01:35 +02:00
narimiran
6b4b329f45 devel version is 1.0.99 [ci skip] 2019-09-25 09:14:38 +02:00
Jjp137
e065e51245 threadpool: fix link in docs [ci skip] (#12258) [backport]
[backport]
2019-09-25 07:12:08 +02:00
treeform
cbefb266bb Fix -d:logGC compile cerror: 'stdout not defined' (#12237) 2019-09-24 12:02:53 +02:00
Jasper Jenkins
b49fb2d90f remove nimnomagic64 (#12243) 2019-09-24 12:02:25 +02:00
Andreas Rumpf
13960066cb fixes the --verbosity:2 regression [backport] 2019-09-24 01:31:03 +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
1406 changed files with 55618 additions and 133730 deletions

37
.builds/freebsd.yml Normal file
View File

@@ -0,0 +1,37 @@
# see https://man.sr.ht/builds.sr.ht/compatibility.md#freebsd
image: freebsd/latest
# packages:
# - databases/sqlite3
# - devel/boehm-gc-threaded
# - devel/pcre
# - devel/sdl20
# - devel/sfml
# - www/node
# - devel/gmake
# - devel/git
sources:
- https://github.com/nim-lang/Nim
environment:
CC: /usr/bin/clang
tasks:
- setup: |
# workaround https://github.com/timotheecour/Nim/issues/76
sudo pkg update -q -f
sudo pkg install -y -q databases/sqlite3 devel/boehm-gc-threaded devel/pcre \
devel/sdl20 devel/sfml www/node devel/gmake devel/git
cd Nim
git clone --depth 1 -q https://github.com/nim-lang/csources.git
gmake -C csources -j $(sysctl -n hw.ncpu)
bin/nim c --skipUserCfg --skipParentCfg koch
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
- test: |
cd Nim
if ! ./koch runCI; then
nim c -r tools/ci_testresults.nim
exit 1
fi
triggers:
- action: email
condition: failure
to: Andreas Rumpf <rumpf_a@web.de>

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
# Avoids changelog conflicts by assuming additions-only, which is by far the common case.
# In the rare case where branch b1 rebases against branch b2 and both branches
# modified the same changelog entry, you'll end up with that changelog entry
# duplicated, which is easily identifiable and fixable.
/changelog.md merge=union

2
.github/FUNDING.yml vendored
View File

@@ -1,7 +1,7 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
patreon: 'araq' # Replace with a single Patreon username
open_collective: 'nim' # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel

View File

@@ -1,45 +1,39 @@
---
name: Bug report
about: Have you found an unexpected behavior? Use this template.
title: Think about the title, twice
labels: ''
assignees: ''
---
<!-- Think about the title, twice. -->
<!-- Summarize the problem here, keep it short and simple. -->
Function `echo` outputs the wrong string.
### Example
<!-- Paste your example in the code-block below. -->
```nim
echo "Hello World!"
```
### Current Output
```
Hola mundo!
```
### Expected Output
<!-- What should be the correct output? -->
```
Hello World!
```
### Possible Solution
<!--- Have you found a possible solution? Post it here. -->
* In file xyz there is a call that might be the cause of it.
### Additional Information
<!--- For Example:
* Your Nim version (output of `nim -v`).
* Was it working in the previous Nim releases?
* A link to a related issue or discussion.
* A project reference where (and how) the issue causes problems.
-->
* It was working in version a.b.c
* Issue #abc is related, but different because of ...
* This issue is blocking my project xyz
```
$ nim -v
Nim Compiler Version 0.1.2

View File

@@ -1,6 +1,9 @@
---
name: Feature request
about: Do you want to suggest a new feature? Use this template.
title: ''
labels: ''
assignees: ''
---

122
.github/workflows/ci.yml.disabled vendored Normal file
View File

@@ -0,0 +1,122 @@
name: Continous Integration
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
os: [ubuntu-18.04, macos-10.15, windows-2019]
cpu: [amd64, i386]
cpp: ['false', 'true']
pkg: ['false', 'true']
exclude:
- os: ubuntu-18.04
cpp: 'true'
- os: ubuntu-18.04
pkg: 'true'
- os: macos-10.15
cpu: i386
- os: macos-10.15
pkg: 'true'
- os: windows-2019
cpu: i386
- os: windows-2019
cpp: 'true'
name: '${{ matrix.os }} (${{ matrix.cpu }}, cpp: ${{ matrix.cpp }}, pkg: ${{ matrix.pkg }})'
runs-on: ${{ matrix.os }}
env:
NIM_COMPILE_TO_CPP: ${{ matrix.cpp }}
NIM_TEST_PACKAGES: ${{ matrix.pkg }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Checkout csources'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Install node.js 8.x'
uses: actions/setup-node@v1
with:
node-version: '8.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
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
- name: 'Install dependencies (Linux i386)'
if: runner.os == 'Linux' && matrix.cpu == 'i386'
run: |
sudo dpkg --add-architecture i386
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 \
libffi-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++
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install boehmgc make sfml
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.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 "::add-path::${{ github.workspace }}/dist/mingw64/bin"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Build csources'
shell: bash
run: |
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Run CI'
shell: bash
run: ./koch runCI
- name: 'Show failed tests'
if: failure()
shell: bash
run: nim c -r tools/ci_testresults.nim

133
.github/workflows/ci_docs.yml vendored Normal file
View File

@@ -0,0 +1,133 @@
name: Nim Docs CI
on:
push:
# Run only on changes on these files
paths:
- 'lib/**.nim'
- 'doc/**.rst'
- 'doc/nimdoc.css'
- '.github/workflows/ci_docs.yml'
pull_request:
# Run only on changes on these files
paths:
- 'lib/**.nim'
- 'doc/**.rst'
- '.github/workflows/ci_docs.yml'
jobs:
build:
strategy:
fail-fast: false
matrix:
target: [linux, windows, osx]
include:
- target: linux
os: ubuntu-18.04
- target: windows
os: windows-2019
- target: osx
os: macos-10.15
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Install build dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install make
- name: 'Install build dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.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 "::add-path::${{ github.workspace }}/dist/mingw64/bin"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Get current csources version'
id: csources-version
shell: bash
run: |
sha=$(git ls-remote https://github.com/nim-lang/csources master | cut -f 1)
echo "::set-output name=sha::$sha"
- name: 'Get prebuilt csources from cache'
id: csources-cache
uses: actions/cache@v1
with:
path: bin
key: '${{ matrix.os }}-${{ steps.csources-version.outputs.sha }}'
- name: 'Checkout csources'
if: steps.csources-cache.outputs.cache-hit != 'true'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Build 1-stage compiler from csources'
shell: bash
run: |
ext=
[[ '${{ runner.os }}' == 'Windows' ]] && ext=.exe
if [[ ! -x bin/nim-csources$ext ]]; then
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc
cp bin/nim{,-csources}$ext
else
echo 'Cache hit, using prebuilt csources'
cp bin/nim{-csources,}$ext
fi
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Build the real compiler'
shell: bash
run: ./koch boot -d:release
- name: 'Build documentation'
shell: bash
run: ./koch doc --git.commit:devel
- name: 'Prepare documentation for deployment'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
shell: bash
run: cp -f doc/html/{overview,index}.html
- name: 'Publish documentation to Github Pages'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
uses: crazy-max/ghaction-github-pages@v1
with:
build_dir: doc/html
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

91
.github/workflows/ci_ssl.yml vendored Normal file
View File

@@ -0,0 +1,91 @@
name: Nim SSL CI
on:
pull_request:
# Run only on changes on related files
paths:
- 'lib/pure/httpclient.nim'
- 'lib/pure/net.nim'
- 'lib/pure/ssl_certs.nim'
- 'lib/wrappers/openssl.nim'
- 'tests/stdlib/thttpclient_ssl*'
- 'tests/untestable/thttpclient_ssl*'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04, macos-10.15, windows-2019]
cpu: [amd64]
name: '${{ matrix.os }} (${{ matrix.cpu }})'
runs-on: ${{ matrix.os }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Checkout csources'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -y libssl1.1
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install make
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.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 "::add-path::${{ github.workspace }}/dist/mingw64/bin"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Build 1-stage compiler from csources'
shell: bash
run: |
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Build the real compiler'
shell: bash
run: ./koch boot
- name: 'Run SSL nimDisableCertificateValidation integration tests'
shell: bash
run: nim c -d:nimDisableCertificateValidation -d:ssl -r -p:. tests/untestable/thttpclient_ssl_disabled.nim
- name: 'Run SSL certificate check integration tests'
# Not supported on Windows due to old openssl version
if: runner.os != 'Windows'
shell: bash
run: nim c -d:ssl -p:. --threads:on -r tests/untestable/thttpclient_ssl.nim

14
.gitignore vendored
View File

@@ -65,7 +65,7 @@ testament.db
/tests/**/*.json
/tests/**/*.js
/csources
dist/
/dist/
# Private directories and files (IDEs)
.*/
@@ -84,3 +84,15 @@ megatest.nim
/outputGotten.txt
/lib/pure/*.js
!/.builds/
!/.github
# ignore debug dirs generated by dsymutil on OSX
*.dSYM
nimdoc.out.css
# for `nim c -r nimdoc/tester` etc; this can be in multiple places
htmldocs

View File

@@ -4,45 +4,12 @@ language: c
dist: xenial
matrix:
fast_finish: true
include:
- os: linux
env:
- NIM_COMPILE_TO_CPP=false
- CPU=amd64
- os: linux
env:
- NIM_COMPILE_TO_CPP=false
- CPU=i386
addons:
apt:
packages:
- gcc-multilib
- g++-multilib
- libcurl4-openssl-dev:i386
- libgc-dev:i386
- libglib2.0-dev:i386
- libpulse-dev:i386
- libsdl1.2-dev:i386
- libsfml-dev:i386
- os: osx
env:
- NIM_COMPILE_TO_CPP=false
- CPU=amd64
- os: osx
env:
- NIM_COMPILE_TO_CPP=true
- CPU=amd64
# To allow failures for a failing configuration, use something like:
# allow_failures:
# - env: NIM_COMPILE_TO_CPP=true
# - os: osx
addons:
apt:
# update the list above if more deps are introduced
@@ -51,17 +18,8 @@ addons:
- libsdl1.2-dev
- libgc-dev
- libsfml-dev
homebrew:
packages:
- boehmgc
- make
- sfml
install:
- if [[ $CPU = i386 ]]; then echo -e "#!/bin/bash\n$(which gcc) -m32 \"\$@\"" > bin/gcc; fi
- if [[ $CPU = i386 ]]; then chmod 755 bin/gcc; fi
- if [[ $CPU = i386 ]]; then echo -e "#!/bin/bash\n$(which g++) -m32 \"\$@\"" > bin/g++; fi
- if [[ $CPU = i386 ]]; then chmod 755 bin/g++; fi
- libc6-dbg
- valgrind
before_script:
- git clone --depth 1 https://github.com/nim-lang/csources.git
@@ -72,11 +30,17 @@ script:
- echo "travis_fold:start:nim_c_koch"
- nim c koch
- echo "travis_fold:end:nim_c_koch"
- ./koch runCI
- echo "travis_fold:start:koch_boot"
- ./koch boot
- echo "travis_fold:end:koch_boot"
- echo "travis_fold:start:koch_doc"
- ./koch doc
- echo "travis_fold:end:koch_doc"
before_deploy:
# Make https://nim-lang.github.io/Nim work the same as https://nim-lang.github.io/Nim/overview.html
- cp -f ./doc/html/overview.html ./doc/html/index.html
deploy: # https://nim-lang.github.io/Nim
provider: pages
# local-dir *has* to be a relative path from the repo root.
@@ -86,6 +50,3 @@ deploy: # https://nim-lang.github.io/Nim
keep-history: false
on:
branch: devel
# Extract failed tests
after_failure: nim c -r tools/ci_testresults.nim

View File

@@ -1,14 +1,11 @@
version: '{build}'
environment:
DLLS_URL: https://nim-lang.org/download/dlls.zip
DLLS_ARCHIVE: dlls.zip
MINGW_DIR: mingw64
MINGW_URL: https://nim-lang.org/download/mingw64-6.3.0.7z
MINGW_ARCHIVE: mingw64-6.3.0.7z
OPENBLAS_URL: https://sourceforge.net/projects/openblas/files/v0.3.5/OpenBLAS%200.3.5%20version.zip/download
OPENBLAS_ARCHIVE: OpenBLAS-0.3.5.zip
SQLITE_URL: http://www.sqlite.org/2017/sqlite-dll-win64-x64-3160200.zip
SQLITE_ARCHIVE: sqlite-dll-win64-x64-3160200.zip
platform: x64
MINGW_URL: https://nim-lang.org/download/mingw64.7z
MINGW_ARCHIVE: mingw64.7z
matrix:
- NIM_TEST_PACKAGES: false
@@ -16,36 +13,24 @@ environment:
cache:
- '%MINGW_ARCHIVE%'
- '%SQLITE_ARCHIVE%'
- '%OPENBLAS_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
- MKDIR %CD%\DIST
- MKDIR %CD%\DIST\PCRE
- nuget install pcre -Verbosity quiet -Version 8.33.0.1 -OutputDirectory %CD%\DIST\PCRE
- IF not exist "%SQLITE_ARCHIVE%" appveyor DownloadFile "%SQLITE_URL%" -FileName "%SQLITE_ARCHIVE%"
- 7z x -y "%SQLITE_ARCHIVE%" -o"%CD%\DIST"> nul
- IF not exist "%DLLS_ARCHIVE%" appveyor DownloadFile "%DLLS_URL%" -FileName "%DLLS_ARCHIVE%"
- 7z x -y "%DLLS_ARCHIVE%" -o"%CD%\BIN"> nul
- IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%"
- 7z x -y "%MINGW_ARCHIVE%" -o"%CD%\DIST"> nul
- IF not exist "%OPENBLAS_ARCHIVE%" appveyor DownloadFile "%OPENBLAS_URL%" -FileName "%OPENBLAS_ARCHIVE%"
- 7z x -y "%OPENBLAS_ARCHIVE%" -o"%CD%\DIST"> nul
- SET PATH=%CD%\DIST\%MINGW_DIR%\BIN;%CD%\BIN;%PATH%
- IF "%PLATFORM%" == "x64" ( copy C:\OpenSSL-Win64\libeay32.dll %CD%\BIN\libeay64.dll & copy C:\OpenSSL-Win64\libeay32.dll %CD%\BIN\libeay32.dll & copy C:\OpenSSL-Win64\libssl32.dll %CD%\BIN\libssl64.dll & copy C:\OpenSSL-Win64\libssl32.dll %CD%\BIN\libssl32.dll )
ELSE ( copy C:\OpenSSL-Win32\libeay32.dll %CD%\BIN\libeay32.dll & copy C:\OpenSSL-Win32\libssl32.dll %CD%\BIN\libssl32.dll )
- IF "%PLATFORM%" == "x64" ( copy %CD%\DIST\sqlite3.dll %CD%\BIN\sqlite3_64.dll ) ELSE ( copy %CD%\DIST\sqlite3.dll %CD%\BIN\sqlite3_32.dll )
- IF "%PLATFORM%" == "x64" ( copy %CD%\DIST\PCRE\pcre.redist.8.33.0.1\build\native\bin\v100\x64\Release\dynamic\utf8\pcre8.dll %CD%\bin\pcre64.dll ) ELSE ( copy %CD%\DIST\PCRE\pcre.redist.8.33.0.1\build\native\bin\v100\Win32\Release\dynamic\utf8\pcre8.dll %CD%\bin\pcre32.dll )
- git clone --depth 1 https://github.com/nim-lang/csources
- cd csources
- IF "%PLATFORM%" == "x64" ( build64.bat ) else ( build.bat )
- build64.bat
- cd ..
build_script:
- openssl version
- openssl version -d
- bin\nim c koch
- koch runCI

178
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,178 @@
trigger:
branches:
include:
- '*'
pr:
branches:
include:
- '*'
jobs:
- job: packages
timeoutInMinutes: 90 # default `60` led to lots of cancelled jobs; use 0 for unlimited (may be undesirable)
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-16.04'
CPU: amd64
Linux_i386:
vmImage: 'ubuntu-16.04'
CPU: i386
OSX_amd64:
vmImage: 'macOS-10.15'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-10.15'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64:
vmImage: 'windows-2019'
CPU: amd64
Linux_amd64_pkg:
vmImage: 'ubuntu-16.04'
CPU: amd64
NIM_TEST_PACKAGES: true
OSX_amd64_pkg:
vmImage: 'macOS-10.15'
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
fetchDepth: 1
- bash: git clone --depth 1 https://github.com/nim-lang/csources
displayName: 'Checkout Nim csources'
- task: NodeTool@0
inputs:
versionSpec: '12.x'
displayName: 'Install node.js 12.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:
# - llvm has to be downgraded to have 32bit version installed for sfml.
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
Package: libllvm6.0
Pin: origin "azure.archive.ubuntu.com"
Pin-Priority: 1001
EOF
sudo apt-fast update -qq
# `:i386` (e.g. in `libffi-dev:i386`) is needed otherwise you may get:
# `could not load: libffi.so` during dynamic loading.
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 libffi-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 gtk+3
displayName: 'Install dependencies (OSX)'
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.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: echo '##vso[task.setvariable variable=csources_version]'"$(git -C csources rev-parse HEAD)"
displayName: 'Get csources version'
- task: Cache@2
inputs:
key: 'csources | "$(Agent.OS)" | $(CPU) | $(csources_version)'
path: csources/bin
displayName: 'Restore built csources'
- bash: |
ncpu=
ext=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
;;
'Darwin')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
ext=.exe
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
if [[ -x csources/bin/nim$ext ]]; then
echo "Found cached compiler, skipping build"
else
make -C csources -j $ncpu CC=gcc ucpu=$(CPU) koch=no
fi
cp csources/bin/nim$ext bin
displayName: 'Build 1-stage compiler from 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)

View File

@@ -6,8 +6,16 @@ set -e
which nim > /dev/null || (echo "nim not in PATH"; exit 1)
which gdb > /dev/null || (echo "gdb not in PATH"; exit 1)
if [[ "$(uname -s)" == "Darwin" ]]; then
which greadlink > /dev/null || (echo "readlink not in PATH. Please install coreutils from homebrew."; exit 1)
READLINK=greadlink
else
which readlink > /dev/null || (echo "readlink not in PATH."; exit 1)
READLINK=readlink
fi
# Find out where the pretty printer Python module is
NIM_SYSROOT=$(dirname $(dirname $(readlink -e $(which nim))))
NIM_SYSROOT=$(dirname $(dirname $($READLINK -e $(which nim))))
GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/nim-gdb.py"
# Run GDB with the additional arguments that load the pretty printers
@@ -16,6 +24,4 @@ GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/nim-gdb.py"
NIM_GDB="${NIM_GDB:-gdb}"
# exec replaces the new process of bash with gdb. It is always good to
# have fewer processes.
exec ${NIM_GDB} \
-eval-command "source $GDB_PYTHON_MODULE_PATH" \
"$@"
exec "${NIM_GDB}" -eval-command="source $GDB_PYTHON_MODULE_PATH" "$@"

1
bin/nim-gdb.bash Symbolic link
View File

@@ -0,0 +1 @@
nim-gdb

14
bin/nim-gdb.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
for %%i in (nim.exe) do (set NIM_BIN=%%~dp$PATH:i)
for %%i in ("%NIM_BIN%\..\") do (set NIM_ROOT=%%~fi)
set @GDB_PYTHON_MODULE_PATH=%NIM_ROOT%\tools\nim-gdb.py
set @NIM_GDB=gdb.exe
@echo source %@GDB_PYTHON_MODULE_PATH%> wingdbcommand.txt
%@NIM_GDB% --command="wingdbcommand.txt" %*
del wingdbcommand.txt /f /q
EXIT /B %ERRORLEVEL%
@echo on

BIN
build.out Executable file

Binary file not shown.

17
build_all.bat Normal file
View File

@@ -0,0 +1,17 @@
@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 --skipUserCfg --skipParentCfg
koch.exe tools --skipUserCfg --skipParentCfg

View File

@@ -1,23 +1,41 @@
#! /bin/sh
# build development version of the compiler; can be rerun safely
# build development version of the compiler; can be rerun safely.
# arguments can be passed, eg `--os freebsd`
set -u # error on undefined variables
set -e # exit on first error
echo_run(){
printf "\n$*\n"
echo "$*"
"$@"
}
[ -d csources ] || echo_run git clone --depth 1 https://github.com/nim-lang/csources.git
[ -d csources ] || echo_run git clone -q --depth 1 https://github.com/nim-lang/csources.git
nim_csources=bin/nim_csources
build_nim_csources_via_script(){
echo_run cd csources
echo_run sh build.sh "$@"
}
build_nim_csources(){
## avoid changing dir in case of failure
# avoid changing dir in case of failure
(
echo_run cd csources
echo_run sh build.sh $@
if [ $# -ne 0 ]; then
# some args were passed (eg: `--cpu i386`), need to call build.sh
build_nim_csources_via_script "$@"
else
# no args, use multiple Make jobs (5X faster on 16 cores: 10s instead of 50s)
makeX=make
unamestr=$(uname)
if [ "$unamestr" = 'FreeBSD' ]; then
makeX=gmake
fi
nCPU=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || 1)
which $makeX && echo_run $makeX -C csources -j $((nCPU + 2)) -l $nCPU || build_nim_csources_via_script
fi
)
# keep $nim_csources in case needed to investigate bootstrap issues
# without having to rebuild from csources
@@ -29,5 +47,6 @@ build_nim_csources(){
# Note: if fails, may need to `cd csources && git pull`
echo_run bin/nim c --skipUserCfg --skipParentCfg koch
echo_run ./koch boot -d:release
echo_run ./koch tools # Compile Nimble and other tools.
echo_run ./koch boot -d:release --skipUserCfg --skipParentCfg
echo_run ./koch tools --skipUserCfg --skipParentCfg # Compile Nimble and other tools.

View File

@@ -1,33 +1,177 @@
## v0.20.2 - XXXX-XX-XX
### Changes affecting backwards compatibility
#### Breaking changes in the standard library
#### Breaking changes in the compiler
### Library additions
### Library changes
# v1.4.0 - yyyy-mm-dd
### Language additions
## Standard library additions and changes
### Language changes
For `net` and `nativesockets`, an `inheritable` flag has been added to all
`proc`s that create sockets, allowing the user to control whether the
resulting socket is inheritable. This flag is provided to ease the writing of
multi-process servers, where sockets inheritance is desired.
For a transistion period, define `nimInheritHandles` to enable file handle
inheritance by default. This flag does **not** affect the `selectors` module
due to the differing semantics between operating systems.
`system.setInheritable` and `nativesockets.setInheritable` is also introduced
for setting file handle or socket inheritance. Not all platform have these
`proc`s defined.
- The file descriptors created for internal bookkeeping by `ioselector_kqueue`
and `ioselector_epoll` will no longer be leaked to child processes.
- `strutils.formatFloat` with `precision = 0` has been restored to the version
1 behaviour that produces a trailing dot, e.g. `formatFloat(3.14159, precision = 0)`
is now `3.`, not `3`.
- `critbits` adds `commonPrefixLen`.
- `relativePath(rel, abs)` and `relativePath(abs, rel)` used to silently give wrong results
(see #13222); instead they now use `getCurrentDir` to resolve those cases,
and this can now throw in edge cases where `getCurrentDir` throws.
`relativePath` also now works for js with `-d:nodejs`.
- JavaScript and NimScript standard library changes: `streams.StringStream` is
now supported in JavaScript, with the limitation that any buffer `pointer`s
used must be castable to `ptr string`, any incompatible pointer type will not
work. The `lexbase` and `streams` modules used to fail to compile on
NimScript due to a bug, but this has been fixed.
The following modules now compile on both JS and NimScript: `parsecsv`,
`parsecfg`, `parsesql`, `xmlparser`, `htmlparser` and `ropes`. Additionally
supported for JS is `cstrutils.startsWith` and `cstrutils.endsWith`, for
NimScript: `json`, `parsejson`, `strtabs` and `unidecode`.
- Added `streams.readStr` and `streams.peekStr` overloads to
accept an existing string to modify, which avoids memory
allocations, similar to `streams.readLine` (#13857).
- Added high-level `asyncnet.sendTo` and `asyncnet.recvFrom`. UDP functionality.
- `paramCount` & `paramStr` are now defined in os.nim instead of nimscript.nim for nimscript/nimble.
- `dollars.$` now works for unsigned ints with `nim js`
- Improvements to the `bitops` module, including bitslices, non-mutating versions
of the original masking functions, `mask`/`masked`, and varargs support for
`bitand`, `bitor`, and `bitxor`.
- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed
into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` in consistency
with regular proc definitions (although you cannot use semicolons).
Pragmas and using a name are now allowed on the lefthand side of `=>`. Here
is an aggregate example of these changes:
```nim
import sugar
foo(x, y: int) {.noSideEffect.} => x + y
# is transformed into
proc foo(x: int, y: int): auto {.noSideEffect.} = x + y
```
- The fields of `times.DateTime` are now private, and are accessed with getters and deprecated setters.
- The `times` module now handles the default value for `DateTime` more consistently. Most procs raise an assertion error when given
an uninitialized `DateTime`, the exceptions are `==` and `$` (which returns `"Uninitialized DateTime"`). The proc `times.isInitialized`
has been added which can be used to check if a `DateTime` has been initialized.
- Fix a bug where calling `close` on io streams in osproc.startProcess was a noop and led to
hangs if a process had both reads from stdin and writes (eg to stdout).
- The callback that is passed to `system.onThreadDestruction` must now be `.raises: []`.
- The callback that is assigned to `system.onUnhandledException` must now be `.gcsafe`.
- `osproc.execCmdEx` now takes an optional `input` for stdin, `workingDir` and `env`
parameters.
- Added a `ssl_config` module containing lists of secure ciphers as recommended by
[Mozilla OpSec](https://wiki.mozilla.org/Security/Server_Side_TLS)
- `net.newContext` now defaults to the list of ciphers targeting
["Intermediate compatibility"](https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29)
per Mozilla's recommendation instead of `ALL`. This change should protect
users from the use of weak and insecure ciphers while still provides
adequate compatibility with the majority of the Internet.
- A new module `std/jsonutils` with hookable `jsonTo,toJson,fromJson` operations for json
serialization/deserialization of custom types was added.
- A new proc `heapqueue.find[T](heap: HeapQueue[T], x: T): int` to get index of element ``x``
was added.
- Added `rstgen.rstToLatex` convenience proc for `renderRstToOut` and `initRstGenerator`
with `outLatex` output.
- Added `os.normalizeExe`, e.g.: `koch` => `./koch`.
- `macros.newLit` now preserves named vs unnamed tuples; use `-d:nimHasWorkaround14720`
to keep old behavior.
- Added `random.gauss`, that uses the ratio of uniforms method of sampling from a Gaussian distribution.
- Added `typetraits.elementType` to get element type of an iterable.
- `typetraits.$` changes: `$(int,)` is now `"(int,)"` instead of `"(int)"`;
`$tuple[]` is now `"tuple[]"` instead of `"tuple"`;
`$((int, float), int)` is now `"((int, float), int)"` instead of `"(tuple of (int, float), int)"`
- Added `macros.extractDocCommentsAndRunnables` helper
- `strformat.fmt` and `strformat.&` support `= specifier`. `fmt"{expr=}"` now
expands to `fmt"expr={expr}"`.
- deprecations: `os.existsDir` => `dirExists`, `os.existsFile` => `fileExists`
- Added `jsre` module, [Regular Expressions for the JavaScript target.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
- Made `maxLines` argument `Positive` in `logging.newRollingFileLogger`,
because negative values will result in a new file being created for each logged
line which doesn't make sense.
- Changed `log` in `logging` to use proper log level on JavaScript target,
e.g. `debug` uses `console.debug`, `info` uses `console.info`, `warn` uses `console.warn`, etc.
- Tables, HashSets, SharedTables and deques don't require anymore that the passed
initial size must be a power of two - this is done internally.
Proc `rightSize` for Tables and HashSets is deprecated, as it is not needed anymore.
`CountTable.inc` takes `val: int` again not `val: Positive`; I.e. it can "count down" again.
- Removed deprecated symbols from `macros` module, deprecated as far back as `0.15`.
### Tool changes
## Language changes
- In newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this:
- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
`wasMoved` calls where needed.
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
is no need to update your code. This change was backported to 1.2 too so you can use the
more readability `=copy` without loss of compatibility.
- In the newruntime it is now allowed to assign to the discriminator field
without restrictions as long as case object doesn't have custom destructor.
The discriminator value doesn't have to be a constant either. If you have a
custom destructor for a case object and you do want to freely assign discriminator
fields, it is recommended to refactor object into 2 objects like this:
```nim
type
MyObj = object
case kind: bool
of true: y: ptr UncheckedArray[float]
of false: z: seq[int]
proc `=destroy`(x: MyObj) =
if x.kind and x.y != nil:
deallocShared(x.y)
x.y = nil
```
Refactor into:
```nim
type
MySubObj = object
val: ptr UncheckedArray[float]
MyObj = object
case kind: bool
of true: y: MySubObj
of false: z: seq[int]
proc `=destroy`(x: MySubObj) =
if x.val != nil:
deallocShared(x.val)
x.val = nil
```
## Compiler 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,55 @@
# v0.20.2 - 2019-07-17
## Changes affecting backwards compatibility
- All `strutils.rfind` procs now take `start` and `last` like `strutils.find`
with the same data slice/index meaning. This is backwards compatible for
calls *not* changing the `rfind` `start` parameter from its default. (#11487)
In the unlikely case that you were using `rfind X, start=N`, or `rfind X, N`,
then you need to change that to `rfind X, last=N` or `rfind X, 0, N`. (This
should minimize gotchas porting code from other languages like Python or C++.)
- On Windows stderr/stdout/stdin are not opened as binary files anymore. Use the switch
`-d:nimBinaryStdFiles` for a transition period.
### Breaking changes in the standard library
- Mac OS X / BSD: TSa_Family is now the ``uint8`` type, so type
conversions like ``x.sin_family = uint16 toInt(nativesockets.AF_INET)``
need to be changed into ``x.sin_family = TSa_Family toInt(nativesockets.AF_INET)``.
### Breaking changes in the compiler
## Library additions
- `toOpenArray` is now available for the JS target.
## Library changes
- Fix async IO operations stalling even after socket is closed. (#11232)
- More informative error message for `streams.openFileStream`. (#11438)
## Language additions
## Language changes
### Tool changes
### Compiler changes
- Better error message for IndexError for empty containers. (#11476)
- Fix regression in semfold for old right shift. (#11477)
- Fix for passing tuples as static params to macros. (#11423)
## Bugfixes

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,532 @@
# v1.2.0 - 2020-04-02
## Standard library additions and changes
- Added overloaded `strformat.fmt` macro that use specified characters as
delimiter instead of '{' and '}'.
- Added new procs in `tables.nim`: `OrderedTable.pop`, `CountTable.del`,
`CountTable.pop`, `Table.pop`.
- Added `strtabs.clear` overload that reuses the existing mode.
- Added `browsers.osOpen` const alias for the operating system specific *"open"* command.
- Added `sugar.dup` for turning in-place algorithms like `sort` and `shuffle`
into operations that work on a copy of the data and return the mutated copy,
like the existing `sorted` does.
- Added `sugar.collect` that does comprehension for seq/set/table collections.
- Added `sugar.capture` for capturing some local loop variables when creating a
closure. This is an enhanced version of `closureScope`.
- Added `typetraits.tupleLen` to get number of elements of a tuple/type tuple,
and `typetraits.get` to get the ith element of a type tuple.
- Added `typetraits.genericParams` to return a tuple of generic params from a
generic instantiation.
- `options` now treats `proc` like other pointer types, meaning `nil` proc variables
are converted to `None`.
- Added `os.normalizePathEnd` for additional path sanitization.
- Added `times.fromUnixFloat,toUnixFloat`, sub-second resolution versions of
`fromUnix`,`toUnixFloat`.
- Added `wrapnils` module for chains of field-access and indexing where the LHS
can be nil. This simplifies code by reducing need for if-else branches around
intermediate maybe nil values. E.g. `echo ?.n.typ.kind`.
- Added `minIndex`, `maxIndex` and `unzip` to the `sequtils` module.
- Added `os.isRelativeTo` to tell whether a path is relative to another.
- Added `resetOutputFormatters` to `unittest`.
- Added `expectIdent` to the `macros` module.
- Added `os.isValidFilename` that returns `true` if `filename` argument is valid
for cross-platform use.
- Added `times.isLeapDay`
- `base64` adds URL-Safe Base64, implements RFC-4648 Section-7.
- Added a new module, `std / compilesettings` for querying the compiler about
diverse configuration settings.
- Added `net.getPeerCertificates` and `asyncnet.getPeerCertificates` for
retrieving the verified certificate chain of the peer we are connected to
through an SSL-wrapped `Socket`/`AsyncSocket`.
- Added `browsers.openDefaultBrowser` without URL, implements IETF RFC-6694 Section-3.
- Added `jsconsole.trace`, `jsconsole.table`, `jsconsole.exception` for JavaScript target.
- Added `distinctBase` overload for values: `assert 12.MyInt.distinctBase == 12`
- Added new module `std/stackframes`, in particular `setFrameMsg`, which enables
custom runtime annotation of stackframes, see #13351 for examples.
Turn on/off via `--stackTraceMsgs:on/off`.
- Added `sequtils.countIt`, allowing for counting items using a predicate.
- Added a `with` macro for easy function chaining that's available everywhere,
there is no need to concern your APIs with returning the first argument
to enable "chaining", instead use the dedicated macro `with` that
was designed for it. For example:
```nim
type
Foo = object
col, pos: string
proc setColor(f: var Foo; r, g, b: int) = f.col = $(r, g, b)
proc setPosition(f: var Foo; x, y: float) = f.pos = $(x, y)
var f: Foo
with(f, setColor(2, 3, 4), setPosition(0.0, 1.0))
echo f
```
- `macros.newLit` now works for ref object types.
- `macro pragmas` can now be used in type sections.
- 5 new pragmas were added to Nim in order to make the upcoming tooling more
convenient to use. Nim compiler checks these pragmas for syntax but otherwise
ignores them. The pragmas are `requires`, `ensures`, `assume`, `assert`, `invariant`.
- `system.writeFile` has been overloaded to also support `openarray[byte]`.
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
and only returns once all pending async operations are guaranteed to have completed.
- `sequtils.zip` now returns a sequence of anonymous tuples i.e. those tuples
now do not have fields named "a" and "b".
- `distinctBase` has been moved from `sugar` to `typetraits` and now it is
implemented as compiler type trait instead of macro. `distinctBase` in sugar
module is now deprecated.
- `CountTable.mget` has been removed from `tables.nim`. It didn't work, and it
was an oversight to be included in v1.0.
- `tables.merge(CountTable, CountTable): CountTable` has been removed.
It didn't work well together with the existing inplace version of the same proc
(`tables.merge(var CountTable, CountTable)`).
It was an oversight to be included in v1.0.
- `asyncdispatch.drain` now consistently uses the passed timeout value for all
iterations of the event loop, and not just the first iteration.
This is more consistent with the other asyncdispatch APIs, and allows
`asyncdispatch.drain` to be more efficient.
- `base64.encode` and `base64.decode` were made faster by about 50%.
- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support
(ISO 40314).
- `macros.eqIdent` is now invariant to export markers and backtick quotes.
- `htmlgen.html` allows `lang` in the `<html>` tag and common valid attributes.
- `macros.basename` and `basename=` got support for `PragmaExpr`,
so that an expression like `MyEnum {.pure.}` is handled correctly.
- `httpclient.maxredirects` changed from `int` to `Natural`, because negative values
serve no purpose whatsoever.
- `httpclient.newHttpClient` and `httpclient.newAsyncHttpClient` added `headers`
argument to set initial HTTP Headers, instead of a hardcoded empty `newHttpHeader()`.
- `parseutils.parseUntil` has now a different behaviour if the `until` parameter is
empty. This was required for intuitive behaviour of the strscans module
(see bug #13605).
- `strutils.formatFloat` with `precision = 0` has the same behavior in all
backends, and it is compatible with Python's behavior,
e.g. `formatFloat(3.14159, precision = 0)` is now `3`, not `3.`.
- `times.parse` now only uses input to compute its result, and not `now`:
`parse("2020", "YYYY", utc())` is now `2020-01-01T00:00:00Z` instead of
`2020-03-02T00:00:00Z` if run on 03-02; it also doesn't crash anymore when
used on 29th, 30th, 31st of each month.
- `httpcore.==(string, HttpCode)` is now deprecated due to lack of practical
usage. The `$` operator can be used to obtain the string form of `HttpCode`
for comparison if desired.
- `std/oswalkdir` was buggy, it's now deprecated and reuses `std/os` procs.
- `net.newContext` now performs SSL Certificate checking on Linux and OSX.
Define `nimDisableCertificateValidation` to disable it globally.
- `os.walkDir` and `os.walkDirRec` now have new flag, `checkDir` (default: false).
If it is set to true, it will throw if input dir is invalid instead of a noop
(which is the default behaviour, as it was before this change),
`os.walkDirRec` only throws if top-level dir is invalid, but ignores errors for
subdirs, otherwise it would be impossible to resume iteration.
- The `FD` variant of `selector.unregister` for `ioselector_epoll` and
`ioselector_select` now properly handle the `Event.User` select event type.
- `joinPath` path normalization when `/` is the first argument works correctly:
`assert "/" / "/a" == "/a"`. Fixed the edge case: `assert "" / "" == ""`.
- `xmltree` now adds indentation consistently to child nodes for any number
of children nodes.
- `os.splitPath()` behavior synchronized with `os.splitFile()` to return "/"
as the dir component of `/root_sub_dir` instead of the empty string.
- The deprecated `lc` macro has been removed from `sugar`. It is now replaced with the
more powerful `collect` macro.
- `os.relativePath("foo", "foo")` is now `"."`, not `""`, as `""` means invalid
path and shouldn't be conflated with `"."`; use `-d:nimOldRelativePathBehavior`
to restore the old behavior.
- `os.joinPath(a, b)` now honors trailing slashes in `b` (or `a` if `b` = "").
- `base64.encode` no longer supports `lineLen` and `newLine`.
Use `base64.encodeMime` instead.
## Language changes
- An `align` pragma can now be used for variables and object fields, similar
to the `alignas` declaration modifier in C/C++.
- `=sink` type bound operator is now optional. Compiler can now use combination
of `=destroy` and `copyMem` to move objects efficiently.
- Unsigned integer operators have been fixed to allow promotion of the first operand.
- 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.
- New syntax for lvalue references: `var b {.byaddr.} = expr` enabled by
`import std/decls`.
- `var a {.foo.}: MyType = expr` now lowers to `foo(a, MyType, expr)` for
non-builtin pragmas, enabling things like lvalue references (see `decls.byaddr`).
## Compiler changes
- Generated JS code uses spaces, instead of mixed spaces and tabs.
- The Nim compiler now supports the ``--asm`` command option for easier
inspection of the produced assembler code.
- The Nim compiler now supports a new pragma called ``.localPassc`` to
pass specific compiler options to the C(++) backend for the C(++) file
that was produced from the current Nim module.
- The compiler now inferes "sink parameters". To disable this for a specific routine,
annotate it with `.nosinks`. To disable it for a section of code, use
`{.push sinkInference: off.}`...`{.pop.}`.
- The compiler now supports a new switch `--panics:on` that turns runtime
errors like `IndexError` or `OverflowError` into fatal errors that **cannot**
be caught via Nim's `try` statement. `--panics:on` can improve the
runtime efficiency and code size of your program significantly.
- The compiler now warns about inheriting directly from `system.Exception` as
this is **very bad** style. You should inherit from `ValueError`, `IOError`,
`OSError` or from a different specific exception type that inherits from
`CatchableError` and cannot be confused with a `Defect`.
- The error reporting for Nim's effect system has been improved.
- Implicit conversions for `const` behave correctly now, meaning that code like
`const SOMECONST = 0.int; procThatTakesInt32(SOMECONST)` will be illegal now.
Simply write `const SOMECONST = 0` instead.
- The `{.dynlib.}` pragma is now required for exporting symbols when making
shared objects on POSIX and macOS, which make it consistent with the behavior
on Windows.
- The compiler is now more strict about type conversions concerning proc
types: Type conversions cannot be used to hide `.raise` effects or side
effects, instead a `cast` must be used. With the flag `--useVersion:1.0` the
old behaviour is emulated.
- The Nim compiler now implements a faster way to detect overflows based
on GCC's `__builtin_sadd_overflow` family of functions. (Clang also
supports these). Some versions of GCC lack this feature and unfortunately
we cannot detect this case reliably. So if you get compilation errors like
"undefined reference to `__builtin_saddll_overflow`" compile your programs
with `-d:nimEmulateOverflowChecks`.
## Tool changes
- Nimpretty doesn't accept negative indentation argument anymore, because it was
breaking files.
## Bugfixes
- Fixed "`nimgrep --nocolor` is ignored on posix; should be instead: `--nimgrep --color=[auto]|true|false`"
([#7591](https://github.com/nim-lang/Nim/issues/7591))
- Fixed "Runtime index on const array (of converted obj) causes C-compiler error"
([#10514](https://github.com/nim-lang/Nim/issues/10514))
- Fixed "windows x86 with vcc compile error with "asmNoStackFrame""
([#12298](https://github.com/nim-lang/Nim/issues/12298))
- Fixed "[TODO] regression: Error: Locks requires --threads:on option"
([#12330](https://github.com/nim-lang/Nim/issues/12330))
- Fixed "Add --cc option to --help or --fullhelp output"
([#12010](https://github.com/nim-lang/Nim/issues/12010))
- Fixed "questionable `csize` definition in `system.nim`"
([#12187](https://github.com/nim-lang/Nim/issues/12187))
- Fixed "os.getAppFilename() returns incorrect results on OpenBSD"
([#12389](https://github.com/nim-lang/Nim/issues/12389))
- Fixed "HashSet[uint64] slow insertion depending on values"
([#11764](https://github.com/nim-lang/Nim/issues/11764))
- Fixed "Differences between compiling 'classic call syntax' vs 'method call syntax' ."
([#12453](https://github.com/nim-lang/Nim/issues/12453))
- Fixed "c -d:nodejs --> SIGSEGV: Illegal storage access"
([#12502](https://github.com/nim-lang/Nim/issues/12502))
- Fixed "Closure iterator crashes on --newruntime due to "dangling references""
([#12443](https://github.com/nim-lang/Nim/issues/12443))
- 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 "strutils:formatBiggestFloat() gives different results in JS mode"
([#8242](https://github.com/nim-lang/Nim/issues/8242))
- Fixed "Regression (devel): the new `csize_t` definition isn't consistently used, nor tested thoroughly..."
([#12597](https://github.com/nim-lang/Nim/issues/12597))
- Fixed "tables.take() is defined only for `Table` and missed for other table containers"
([#12519](https://github.com/nim-lang/Nim/issues/12519))
- Fixed "`pthread_key_t` errors on OpenBSD"
([#12135](https://github.com/nim-lang/Nim/issues/12135))
- Fixed "newruntime: simple seq pop at ct results in compile error"
([#12644](https://github.com/nim-lang/Nim/issues/12644))
- Fixed "[Windows] finish.exe C:\Users\<USERNAME>\.nimble\bin is not in your PATH environment variable."
([#12319](https://github.com/nim-lang/Nim/issues/12319))
- Fixed "Error with strformat + asyncdispatch + const"
([#12612](https://github.com/nim-lang/Nim/issues/12612))
- Fixed "MultipartData needs $"
([#11863](https://github.com/nim-lang/Nim/issues/11863))
- Fixed "Nim stdlib style issues with --styleCheck:error"
([#12687](https://github.com/nim-lang/Nim/issues/12687))
- Fixed "new $nimbleDir path substitution yields unexpected search paths"
([#12767](https://github.com/nim-lang/Nim/issues/12767))
- Fixed "Regression: inlined procs now get multiple rounds of destructor injection"
([#12766](https://github.com/nim-lang/Nim/issues/12766))
- Fixed "newruntime: compiler generates defective code"
([#12669](https://github.com/nim-lang/Nim/issues/12669))
- Fixed "broken windows modules path handling because of 'os.relativePath' breaking changes"
([#12734](https://github.com/nim-lang/Nim/issues/12734))
- Fixed "for loop tuple syntax not rendered correctly"
([#12740](https://github.com/nim-lang/Nim/issues/12740))
- Fixed "Crash when trying to use `type.name[0]`"
([#12804](https://github.com/nim-lang/Nim/issues/12804))
- Fixed "Enums should be considered Trivial types in Atomics"
([#12812](https://github.com/nim-lang/Nim/issues/12812))
- Fixed "Produce static/const initializations for variables when possible"
([#12216](https://github.com/nim-lang/Nim/issues/12216))
- Fixed "Assigning descriminator field leads to internal assert with --gc:destructors"
([#12821](https://github.com/nim-lang/Nim/issues/12821))
- Fixed "nimsuggest `use` command does not return all instances of symbol"
([#12832](https://github.com/nim-lang/Nim/issues/12832))
- Fixed "@[] is a problem for --gc:destructors"
([#12820](https://github.com/nim-lang/Nim/issues/12820))
- Fixed "Codegen ICE in allPathsAsgnResult"
([#12827](https://github.com/nim-lang/Nim/issues/12827))
- Fixed "seq[Object with ref and destructor type] doesn't work in old runtime"
([#12882](https://github.com/nim-lang/Nim/issues/12882))
- Fixed "Destructor not invoked because it is instantiated too late, old runtime"
([#12883](https://github.com/nim-lang/Nim/issues/12883))
- Fixed "The collect macro does not handle if/case correctly"
([#12874](https://github.com/nim-lang/Nim/issues/12874))
- Fixed "allow typed/untyped params in magic procs (even if not in stdlib)"
([#12911](https://github.com/nim-lang/Nim/issues/12911))
- Fixed "ARC/newruntime memory corruption"
([#12899](https://github.com/nim-lang/Nim/issues/12899))
- Fixed "tasyncclosestall.nim still flaky test: Address already in use"
([#12919](https://github.com/nim-lang/Nim/issues/12919))
- Fixed "newruntime and computed goto: variables inside the loop are in generated code uninitialised"
([#12785](https://github.com/nim-lang/Nim/issues/12785))
- Fixed "osx: dsymutil needs to be called for debug builds to keep debug info"
([#12735](https://github.com/nim-lang/Nim/issues/12735))
- Fixed "codegen ICE with ref objects, gc:destructors"
([#12826](https://github.com/nim-lang/Nim/issues/12826))
- Fixed "mutable iterator cannot yield named tuples"
([#12945](https://github.com/nim-lang/Nim/issues/12945))
- Fixed "parsecfg stores "\r\n" line breaks just as "\n""
([#12970](https://github.com/nim-lang/Nim/issues/12970))
- Fixed "db_postgres.getValue issues warning when no rows found"
([#12973](https://github.com/nim-lang/Nim/issues/12973))
- Fixed "ARC: Unpacking tuple with seq causes segfault"
([#12989](https://github.com/nim-lang/Nim/issues/12989))
- Fixed "ARC/newruntime: strutils.join on seq with only empty strings causes segfault"
([#12965](https://github.com/nim-lang/Nim/issues/12965))
- Fixed "regression (1.0.4): `{.push exportc.}` wrongly affects generic instantiations, causing codegen errors"
([#12985](https://github.com/nim-lang/Nim/issues/12985))
- Fixed "cdt, crash with --gc:arc, works fine with default gc"
([#12978](https://github.com/nim-lang/Nim/issues/12978))
- Fixed "ARC: No indexError thrown on out-of-bound seq access, SIGSEGV instead"
([#12961](https://github.com/nim-lang/Nim/issues/12961))
- Fixed "ARC/async: Returning in a try-block results in wrong codegen"
([#12956](https://github.com/nim-lang/Nim/issues/12956))
- Fixed "asm keyword is generating wrong output C code when --cc:tcc"
([#12988](https://github.com/nim-lang/Nim/issues/12988))
- Fixed "Destructor not invoked"
([#13026](https://github.com/nim-lang/Nim/issues/13026))
- Fixed "ARC/newruntime: Adding inherited var ref object to seq with base type causes segfault"
([#12964](https://github.com/nim-lang/Nim/issues/12964))
- Fixed "Style check error with JS compiler target"
([#13032](https://github.com/nim-lang/Nim/issues/13032))
- Fixed "regression(1.0.4): undeclared identifier: 'readLines'; plus another regression and bug"
([#13013](https://github.com/nim-lang/Nim/issues/13013))
- Fixed "regression(1.04) `invalid pragma: since` with nim js"
([#12996](https://github.com/nim-lang/Nim/issues/12996))
- Fixed "Sink to MemMove optimization in injectdestructors"
([#13002](https://github.com/nim-lang/Nim/issues/13002))
- Fixed "--gc:arc: `catch` doesn't work with exception subclassing"
([#13072](https://github.com/nim-lang/Nim/issues/13072))
- Fixed "nim c --gc:arc --exceptions:{setjmp,goto} incorrectly handles raise; `nim cpp --gc:arc` is ok"
([#13070](https://github.com/nim-lang/Nim/issues/13070))
- Fixed "typetraits feature request - get subtype of a generic type"
([#6454](https://github.com/nim-lang/Nim/issues/6454))
- Fixed "CountTable inconsistencies between keys() and len() after setting value to 0"
([#12813](https://github.com/nim-lang/Nim/issues/12813))
- Fixed "{.align.} pragma is not applied if there is a generic field"
([#13122](https://github.com/nim-lang/Nim/issues/13122))
- Fixed "ARC, finalizer, allow rebinding the same function multiple times"
([#13112](https://github.com/nim-lang/Nim/issues/13112))
- Fixed "`nim doc` treats `export localSymbol` incorrectly"
([#13100](https://github.com/nim-lang/Nim/issues/13100))
- Fixed "--gc:arc SIGSEGV (double free?)"
([#13119](https://github.com/nim-lang/Nim/issues/13119))
- Fixed "codegen bug with arc"
([#13105](https://github.com/nim-lang/Nim/issues/13105))
- Fixed "symbols not defined in the grammar"
([#10665](https://github.com/nim-lang/Nim/issues/10665))
- Fixed "[JS] Move is not defined"
([#9674](https://github.com/nim-lang/Nim/issues/9674))
- Fixed "[TODO] pathutils.`/` can return invalid AbsoluteFile"
([#13121](https://github.com/nim-lang/Nim/issues/13121))
- Fixed "regression(1.04) `nim doc main.nim` generates broken html (no css)"
([#12998](https://github.com/nim-lang/Nim/issues/12998))
- Fixed "Wrong supportsCopyMem on string in type section"
([#13095](https://github.com/nim-lang/Nim/issues/13095))
- Fixed "Arc, finalizer, out of memory"
([#13157](https://github.com/nim-lang/Nim/issues/13157))
- Fixed "`--genscript` messes up nimcache and future nim invocations"
([#13144](https://github.com/nim-lang/Nim/issues/13144))
- Fixed "--gc:arc with --exceptions:goto for "nim c" generate invalid c code"
([#13186](https://github.com/nim-lang/Nim/issues/13186))
- Fixed "[regression] duplicate member `_i1` codegen bug"
([#13195](https://github.com/nim-lang/Nim/issues/13195))
- Fixed "RTree investigations with valgrind for --gc:arc"
([#13110](https://github.com/nim-lang/Nim/issues/13110))
- Fixed "relativePath("foo", ".") returns wrong path"
([#13211](https://github.com/nim-lang/Nim/issues/13211))
- Fixed "asyncftpclient - problem with welcome.msg"
([#4684](https://github.com/nim-lang/Nim/issues/4684))
- Fixed "Unclear error message, lowest priority"
([#13256](https://github.com/nim-lang/Nim/issues/13256))
- Fixed "Channel messages are corrupted"
([#13219](https://github.com/nim-lang/Nim/issues/13219))
- Fixed "Codegen bug with exportc and case objects"
([#13281](https://github.com/nim-lang/Nim/issues/13281))
- Fixed "[bugfix] fix #11590: c compiler warnings silently ignored, giving undefined behavior"
([#11591](https://github.com/nim-lang/Nim/issues/11591))
- Fixed "[CI] tnetdial flaky test"
([#13132](https://github.com/nim-lang/Nim/issues/13132))
- Fixed "Cross-Compiling with -d:mingw fails to locate compiler under OSX"
([#10717](https://github.com/nim-lang/Nim/issues/10717))
- Fixed "`nim doc --project` broken with imports below main project file or duplicate names"
([#13150](https://github.com/nim-lang/Nim/issues/13150))
- Fixed "regression: isNamedTuple(MyGenericTuple[int]) is false, should be true"
([#13349](https://github.com/nim-lang/Nim/issues/13349))
- Fixed "--gc:arc codegen bug copying objects bound to C structs with missing C struct fields"
([#13269](https://github.com/nim-lang/Nim/issues/13269))
- Fixed "write requires conversion to string"
([#13182](https://github.com/nim-lang/Nim/issues/13182))
- Fixed "Some remarks to stdlib documentation"
([#13352](https://github.com/nim-lang/Nim/issues/13352))
- Fixed "a `check` in unittest generated by template doesn't show actual value"
([#6736](https://github.com/nim-lang/Nim/issues/6736))
- Fixed "Implicit return with case expression fails with 'var' return."
([#3339](https://github.com/nim-lang/Nim/issues/3339))
- Fixed "Segfault with closure on arc"
([#13314](https://github.com/nim-lang/Nim/issues/13314))
- Fixed "[Macro] Crash on malformed case statement with multiple else"
([#13255](https://github.com/nim-lang/Nim/issues/13255))
- Fixed "regression: `echo 'discard' | nim c -r -` generates a file '-' ; `-` should be treated specially"
([#13374](https://github.com/nim-lang/Nim/issues/13374))
- Fixed "on OSX, debugging (w gdb or lldb) a nim program crashes at the 1st call to `execCmdEx`"
([#9634](https://github.com/nim-lang/Nim/issues/9634))
- Fixed "Internal error in getTypeDescAux"
([#13378](https://github.com/nim-lang/Nim/issues/13378))
- Fixed "gc:arc mode breaks tuple let"
([#13368](https://github.com/nim-lang/Nim/issues/13368))
- Fixed "Nim compiler hangs for certain C/C++ compiler errors"
([#8648](https://github.com/nim-lang/Nim/issues/8648))
- Fixed "htmlgen does not support `data-*` attributes"
([#13444](https://github.com/nim-lang/Nim/issues/13444))
- Fixed "[gc:arc] setLen will cause string not to be null-terminated."
([#13457](https://github.com/nim-lang/Nim/issues/13457))
- Fixed "joinPath("", "") is "/" ; should be """
([#13455](https://github.com/nim-lang/Nim/issues/13455))
- Fixed "[CI] flaky test on windows: tests/osproc/texitcode.nim"
([#13449](https://github.com/nim-lang/Nim/issues/13449))
- Fixed "Casting to float32 on NimVM is broken"
([#13479](https://github.com/nim-lang/Nim/issues/13479))
- Fixed "`--hints:off` doesn't work (doesn't override ~/.config/nim.cfg)"
([#8312](https://github.com/nim-lang/Nim/issues/8312))
- Fixed "joinPath("", "") is "/" ; should be """
([#13455](https://github.com/nim-lang/Nim/issues/13455))
- Fixed "tables.values is broken"
([#13496](https://github.com/nim-lang/Nim/issues/13496))
- Fixed "global user config can override project specific config"
([#9405](https://github.com/nim-lang/Nim/issues/9405))
- Fixed "Non deterministic macros and id consistency problem"
([#12627](https://github.com/nim-lang/Nim/issues/12627))
- Fixed "try expression doesn't work with return on expect branch"
([#13490](https://github.com/nim-lang/Nim/issues/13490))
- Fixed "CI will break every 4 years on feb 28: times doesn't handle leap years properly"
([#13543](https://github.com/nim-lang/Nim/issues/13543))
- Fixed "[minor] `nimgrep --word` doesn't work with operators (eg misses `1 +% 2`)"
([#13528](https://github.com/nim-lang/Nim/issues/13528))
- Fixed "`as` is usable as infix operator but its existence and precedence are not documented"
([#13409](https://github.com/nim-lang/Nim/issues/13409))
- Fixed "JSON unmarshalling drops seq's items"
([#13531](https://github.com/nim-lang/Nim/issues/13531))
- Fixed "os.joinPath returns wrong path when head ends '\' or '/' and tail starts '..'."
([#13579](https://github.com/nim-lang/Nim/issues/13579))
- Fixed "Block-local types with the same name lead to bad codegen (sighashes regression)"
([#5170](https://github.com/nim-lang/Nim/issues/5170))
- Fixed "tuple codegen error"
([#12704](https://github.com/nim-lang/Nim/issues/12704))
- Fixed "newHttpHeaders does not accept repeated headers"
([#13573](https://github.com/nim-lang/Nim/issues/13573))
- Fixed "regression: --incremental:on fails on simplest example"
([#13319](https://github.com/nim-lang/Nim/issues/13319))
- Fixed "strscan can't get value of last element in format"
([#13605](https://github.com/nim-lang/Nim/issues/13605))
- Fixed "hashes_examples crashes with "Bus Error" (unaligned access) on sparc64"
([#12508](https://github.com/nim-lang/Nim/issues/12508))
- Fixed "gc:arc bug with re-used `seq[T]`"
([#13596](https://github.com/nim-lang/Nim/issues/13596))
- Fixed "`raise CatchableError` is broken with --gc:arc when throwing inside a proc"
([#13599](https://github.com/nim-lang/Nim/issues/13599))
- Fixed "cpp --gc:arc --exceptions:goto fails to raise with discard"
([#13436](https://github.com/nim-lang/Nim/issues/13436))
- Fixed "terminal doesn't compile with -d:useWinAnsi"
([#13607](https://github.com/nim-lang/Nim/issues/13607))
- Fixed "Parsing "sink ptr T" - region needs to be an object type"
([#12757](https://github.com/nim-lang/Nim/issues/12757))
- Fixed "gc:arc + threads:on + closures compilation error"
([#13519](https://github.com/nim-lang/Nim/issues/13519))
- Fixed "[ARC] segmentation fault"
([#13240](https://github.com/nim-lang/Nim/issues/13240))
- Fixed "times.toDateTime buggy on 29th, 30th and 31th of each month"
([#13558](https://github.com/nim-lang/Nim/issues/13558))
- Fixed "Deque misbehaves on VM"
([#13310](https://github.com/nim-lang/Nim/issues/13310))
- Fixed "Nimscript listFiles should throw exception when path is not found"
([#12676](https://github.com/nim-lang/Nim/issues/12676))
- Fixed "koch boot fails if even an empty config.nims is present in ~/.config/nims/ [devel regression]"
([#13633](https://github.com/nim-lang/Nim/issues/13633))
- Fixed "nim doc generates lots of false positive LockLevel warnings"
([#13218](https://github.com/nim-lang/Nim/issues/13218))
- Fixed "Arrays are passed by copy to iterators, causing crashes, unnecessary allocations and slowdowns"
([#12747](https://github.com/nim-lang/Nim/issues/12747))
- Fixed "Range types always uses signed integer as a base type"
([#13646](https://github.com/nim-lang/Nim/issues/13646))
- Fixed "Generate c code cannot compile with recent devel version"
([#13645](https://github.com/nim-lang/Nim/issues/13645))
- Fixed "[regression] VM: Error: cannot convert -1 to uint64"
([#13661](https://github.com/nim-lang/Nim/issues/13661))
- Fixed "Spurious raiseException(Exception) detected"
([#13654](https://github.com/nim-lang/Nim/issues/13654))
- Fixed "gc:arc memory leak"
([#13659](https://github.com/nim-lang/Nim/issues/13659))
- Fixed "Error: cannot convert -1 to uint (inside tuples)"
([#13671](https://github.com/nim-lang/Nim/issues/13671))
- Fixed "strformat issue with --gc:arc"
([#13622](https://github.com/nim-lang/Nim/issues/13622))
- Fixed "astToStr doesn't work inside generics"
([#13524](https://github.com/nim-lang/Nim/issues/13524))
- Fixed "oswalkdir.walkDirRec wont return folders"
([#11458](https://github.com/nim-lang/Nim/issues/11458))
- Fixed "`echo 'echo 1' | nim c -r -` silently gives wrong results (nimBetterRun not updated for stdin)"
([#13412](https://github.com/nim-lang/Nim/issues/13412))
- Fixed "gc:arc destroys the global variable accidentally."
([#13691](https://github.com/nim-lang/Nim/issues/13691))
- Fixed "[minor] sigmatch errors should be sorted, for reproducible errors"
([#13538](https://github.com/nim-lang/Nim/issues/13538))
- Fixed "Exception when converting csize to clong"
([#13698](https://github.com/nim-lang/Nim/issues/13698))
- Fixed "ARC: variables are no copied on the thread spawn causing crashes"
([#13708](https://github.com/nim-lang/Nim/issues/13708))
- Fixed "Illegal distinct seq causes compiler crash"
([#13720](https://github.com/nim-lang/Nim/issues/13720))
- Fixed "cyclic seq definition crashes the compiler"
([#13715](https://github.com/nim-lang/Nim/issues/13715))
- Fixed "Iterator with openArray parameter make the argument evaluated many times"
([#13417](https://github.com/nim-lang/Nim/issues/13417))
- Fixed "net/asyncnet: Unable to access peer's certificate chain"
([#13299](https://github.com/nim-lang/Nim/issues/13299))
- Fixed "Accidentally "SIGSEGV: Illegal storage access" error after arc optimizations (#13325)"
([#13709](https://github.com/nim-lang/Nim/issues/13709))
- Fixed "Base64 Regression"
([#13722](https://github.com/nim-lang/Nim/issues/13722))
- Fixed "A regression (?) with --gc:arc and repr"
([#13731](https://github.com/nim-lang/Nim/issues/13731))
- Fixed "Internal compiler error when using the new variable pragmas"
([#13737](https://github.com/nim-lang/Nim/issues/13737))
- Fixed "bool conversion produces vcc 2019 warning at cpp compilation stage"
([#13744](https://github.com/nim-lang/Nim/issues/13744))
- Fixed "Compiler "does not detect" a type recursion error in the wrong code, remaining frozen"
([#13763](https://github.com/nim-lang/Nim/issues/13763))
- Fixed "[minor] regression: `Foo[0.0] is Foo[-0.0]` is now false"
([#13730](https://github.com/nim-lang/Nim/issues/13730))
- Fixed "`nim doc` - only whitespace on first line causes segfault"
([#13631](https://github.com/nim-lang/Nim/issues/13631))
- Fixed "hashset regression"
([#13794](https://github.com/nim-lang/Nim/issues/13794))
- Fixed "`os.getApplFreebsd` could return incorrect paths in the case of a long path"
([#13806](https://github.com/nim-lang/Nim/issues/13806))
- Fixed "Destructors are not inherited"
([#13810](https://github.com/nim-lang/Nim/issues/13810))
- Fixed "io.readLines AssertionError on devel"
([#13829](https://github.com/nim-lang/Nim/issues/13829))
- Fixed "exceptions:goto accidentally reset the variable during exception handling"
([#13782](https://github.com/nim-lang/Nim/issues/13782))

View File

@@ -1,27 +1,20 @@
## v0.XX.0 - XX/XX/2018
# v1.xx.x - yyyy-mm-dd
### Changes affecting backwards compatibility
- Example item: ``Foo`` changed to ``Bar``.
#### Breaking changes in the standard library
This is an example file.
The changes should go to changelog.md!
#### Breaking changes in the compiler
## Standard library additions and changes
### Library additions
### Library changes
- Added `example.exampleProc`.
- Changed `example.foo` to take additional `bar` parameter.
### Language additions
## Language changes
### Language changes
## Compiler changes
### Tool changes
## Tool changes
### Compiler changes
### Bugfixes

View File

@@ -10,7 +10,7 @@
## Simple alias analysis for the HLO and the code generators.
import
ast, astalgo, types, trees, intsets, msgs
ast, astalgo, types, trees, intsets
type
TAnalysisResult* = enum
@@ -22,17 +22,17 @@ proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
result = arNo
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = isPartOfAux(n.sons[i], b, marker)
for i in 0..<n.len:
result = isPartOfAux(n[i], b, marker)
if result == arYes: return
of nkRecCase:
assert(n.sons[0].kind == nkSym)
result = isPartOfAux(n.sons[0], b, marker)
assert(n[0].kind == nkSym)
result = isPartOfAux(n[0], b, marker)
if result == arYes: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
result = isPartOfAux(lastSon(n[i]), b, marker)
if result == arYes: return
else: discard "isPartOfAux(record case branch)"
of nkSym:
@@ -46,14 +46,14 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
case a.kind
of tyObject:
if a.sons[0] != nil:
result = isPartOfAux(a.sons[0].skipTypes(skipPtrs), b, marker)
if a[0] != nil:
result = isPartOfAux(a[0].skipTypes(skipPtrs), b, marker)
if result == arNo: result = isPartOfAux(a.n, b, marker)
of tyGenericInst, tyDistinct, tyAlias, tySink:
result = isPartOfAux(lastSon(a), b, marker)
of tyArray, tySet, tyTuple:
for i in 0 ..< sonsLen(a):
result = isPartOfAux(a.sons[i], b, marker)
for i in 0..<a.len:
result = isPartOfAux(a[i], b, marker)
if result == arYes: return
else: discard
@@ -108,7 +108,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
result = arMaybe
of nkBracketExpr:
result = isPartOf(a[0], b[0])
if len(a) >= 2 and len(b) >= 2:
if a.len >= 2 and b.len >= 2:
# array accesses:
if result == arYes and isDeepConstExpr(a[1]) and isDeepConstExpr(b[1]):
# we know it's the same array and we have 2 constant indexes;
@@ -181,16 +181,19 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
else: discard
of nkObjConstr:
result = arNo
for i in 1 ..< b.len:
for i in 1..<b.len:
let res = isPartOf(a, b[i][1])
if res != arNo:
result = res
if res == arYes: break
of nkCall:
of nkCallKinds:
result = arNo
for i in 1 ..< b.len:
for i in 1..<b.len:
let res = isPartOf(a, b[i])
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

File diff suppressed because it is too large Load Diff

View File

@@ -24,46 +24,55 @@ proc typeToYaml*(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int =
proc symToYaml*(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope
proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): Rope
when declared(echo):
# these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements:
proc debug*(n: PSym; conf: ConfigRef = nil) {.exportc: "debugSym", deprecated.}
proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.}
proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.}
template debug*(x: PSym|PType|PNode) {.deprecated.} =
when compiles(c.config):
debug(c.config, x)
elif compiles(c.graph.config):
debug(c.graph.config, x)
# these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements:
proc debug*(n: PSym; conf: ConfigRef = nil) {.exportc: "debugSym", deprecated.}
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)
elif compiles(c.graph.config):
debug(c.graph.config, x)
else:
error()
template debug*(x: auto) {.deprecated.} =
echo x
template mdbg*: bool {.deprecated.} =
when compiles(c.graph):
c.module.fileIdx == c.graph.config.projectMainIdx
elif compiles(c.module):
c.module.fileIdx == c.config.projectMainIdx
elif compiles(c.c.module):
c.c.module.fileIdx == c.c.config.projectMainIdx
elif compiles(m.c.module):
m.c.module.fileIdx == m.c.config.projectMainIdx
elif compiles(cl.c.module):
cl.c.module.fileIdx == cl.c.config.projectMainIdx
elif compiles(p):
when compiles(p.lex):
p.lex.fileIdx == p.lex.config.projectMainIdx
else:
error()
template debug*(x: auto) {.deprecated.} =
echo x
template mdbg*: bool {.deprecated.} =
when compiles(c.graph):
c.module.fileIdx == c.graph.config.projectMainIdx
elif compiles(c.module):
c.module.fileIdx == c.config.projectMainIdx
elif compiles(c.c.module):
c.c.module.fileIdx == c.c.config.projectMainIdx
elif compiles(m.c.module):
m.c.module.fileIdx == m.c.config.projectMainIdx
elif compiles(cl.c.module):
cl.c.module.fileIdx == cl.c.config.projectMainIdx
elif compiles(p):
when compiles(p.lex):
p.lex.fileIdx == p.lex.config.projectMainIdx
else:
p.module.module.fileIdx == p.config.projectMainIdx
elif compiles(m.module.fileIdx):
m.module.fileIdx == m.config.projectMainIdx
elif compiles(L.fileIdx):
L.fileIdx == L.config.projectMainIdx
else:
error()
p.module.module.fileIdx == p.config.projectMainIdx
elif compiles(m.module.fileIdx):
m.module.fileIdx == m.config.projectMainIdx
elif compiles(L.fileIdx):
L.fileIdx == L.config.projectMainIdx
else:
error()
# --------------------------- ident tables ----------------------------------
proc idTableGet*(t: TIdTable, key: PIdObj): RootRef
@@ -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.}
@@ -108,16 +116,16 @@ proc skipConvAndClosure*(n: PNode): PNode =
case result.kind
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64,
nkClosure:
result = result.sons[0]
result = result[0]
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = result.sons[1]
result = result[1]
else: break
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,17 +160,17 @@ proc lookupInRecord(n: PNode, field: PIdent): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = lookupInRecord(n.sons[i], field)
for i in 0..<n.len:
result = lookupInRecord(n[i], field)
if result != nil: return
of nkRecCase:
if (n.sons[0].kind != nkSym): return nil
result = lookupInRecord(n.sons[0], field)
if (n[0].kind != nkSym): return nil
result = lookupInRecord(n[0], field)
if result != nil: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = lookupInRecord(lastSon(n.sons[i]), field)
result = lookupInRecord(lastSon(n[i]), field)
if result != nil: return
else: return nil
of nkSym:
@@ -174,14 +182,55 @@ 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):
if list.sons[i].kind == nkSym:
result = list.sons[i].sym
proc fromSystem*(op: PSym): bool {.inline.} = sfSystemModule in getModule(op).flags
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym =
for i in start..<list.len:
if list[i].kind == nkSym:
result = list[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..<list.len:
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))
@@ -206,15 +255,15 @@ proc makeYamlString*(s: string): Rope =
const MaxLineLength = 64
result = nil
var res = "\""
for i in 0 ..< s.len:
for i in 0..<s.len:
if (i + 1) mod MaxLineLength == 0:
add(res, '\"')
add(res, "\n")
add(result, rope(res))
res.add('\"')
res.add("\n")
result.add(rope(res))
res = "\"" # reset
add(res, toYamlChar(s[i]))
add(res, '\"')
add(result, rope(res))
res.add(toYamlChar(s[i]))
res.add('\"')
result.add(rope(res))
proc flagsToStr[T](flags: set[T]): Rope =
if flags == {}:
@@ -222,8 +271,8 @@ proc flagsToStr[T](flags: set[T]): Rope =
else:
result = nil
for x in items(flags):
if result != nil: add(result, ", ")
add(result, makeYamlString($x))
if result != nil: result.add(", ")
result.add(makeYamlString($x))
result = "[" & result & "]"
proc lineInfoToStr(conf: ConfigRef; info: TLineInfo): Rope =
@@ -250,25 +299,25 @@ proc symToYamlAux(conf: ConfigRef; n: PSym, marker: var IntSet, indent: int,
# indent + 2, maxRecDepth - 1),
let istr = rspaces(indent + 2)
result = rope("{")
addf(result, "$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
addf(result, "$N$1\"name\": $2", [istr, makeYamlString(n.name.s)])
addf(result, "$N$1\"typ\": $2", [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
result.addf("$N$1\"name\": $2", [istr, makeYamlString(n.name.s)])
result.addf("$N$1\"typ\": $2", [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth - 1)])
if conf != nil:
# if we don't pass the config, we probably don't care about the line info
addf(result, "$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
result.addf("$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
if card(n.flags) > 0:
addf(result, "$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
addf(result, "$N$1\"magic\": $2", [istr, makeYamlString($n.magic)])
addf(result, "$N$1\"ast\": $2", [istr, ast])
addf(result, "$N$1\"options\": $2", [istr, flagsToStr(n.options)])
addf(result, "$N$1\"position\": $2", [istr, rope(n.position)])
addf(result, "$N$1\"k\": $2", [istr, makeYamlString($n.loc.k)])
addf(result, "$N$1\"storage\": $2", [istr, makeYamlString($n.loc.storage)])
result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
result.addf("$N$1\"magic\": $2", [istr, makeYamlString($n.magic)])
result.addf("$N$1\"ast\": $2", [istr, ast])
result.addf("$N$1\"options\": $2", [istr, flagsToStr(n.options)])
result.addf("$N$1\"position\": $2", [istr, rope(n.position)])
result.addf("$N$1\"k\": $2", [istr, makeYamlString($n.loc.k)])
result.addf("$N$1\"storage\": $2", [istr, makeYamlString($n.loc.storage)])
if card(n.loc.flags) > 0:
addf(result, "$N$1\"flags\": $2", [istr, makeYamlString($n.loc.flags)])
addf(result, "$N$1\"r\": $2", [istr, n.loc.r])
addf(result, "$N$1\"lode\": $2", [istr, treeToYamlAux(conf, n.loc.lode, marker, indent + 2, maxRecDepth - 1)])
addf(result, "$N$1}", [rspaces(indent)])
result.addf("$N$1\"flags\": $2", [istr, makeYamlString($n.loc.flags)])
result.addf("$N$1\"r\": $2", [istr, n.loc.r])
result.addf("$N$1\"lode\": $2", [istr, treeToYamlAux(conf, n.loc.lode, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1}", [rspaces(indent)])
proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
maxRecDepth: int): Rope =
@@ -279,27 +328,27 @@ 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 n.len > 0:
sonsRope = rope("[")
for i in 0 ..< sonsLen(n):
if i > 0: add(sonsRope, ",")
addf(sonsRope, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n.sons[i],
for i in 0..<n.len:
if i > 0: sonsRope.add(",")
sonsRope.addf("$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n[i],
marker, indent + 4, maxRecDepth - 1)])
addf(sonsRope, "$N$1]", [rspaces(indent + 2)])
sonsRope.addf("$N$1]", [rspaces(indent + 2)])
else:
sonsRope = rope("null")
let istr = rspaces(indent + 2)
result = rope("{")
addf(result, "$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
addf(result, "$N$1\"sym\": $2", [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)])
addf(result, "$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
result.addf("$N$1\"sym\": $2", [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
if card(n.flags) > 0:
addf(result, "$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
addf(result, "$N$1\"callconv\": $2", [istr, makeYamlString(CallingConvToStr[n.callConv])])
addf(result, "$N$1\"size\": $2", [istr, rope(n.size)])
addf(result, "$N$1\"align\": $2", [istr, rope(n.align)])
addf(result, "$N$1\"sons\": $2", [istr, sonsRope])
result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
result.addf("$N$1\"callconv\": $2", [istr, makeYamlString(CallingConvToStr[n.callConv])])
result.addf("$N$1\"size\": $2", [istr, rope(n.size)])
result.addf("$N$1\"align\": $2", [istr, rope(n.align)])
result.addf("$N$1\"sons\": $2", [istr, sonsRope])
proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
maxRecDepth: int): Rope =
@@ -310,34 +359,34 @@ proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
result = "{$N$1\"kind\": $2" % [istr, makeYamlString($n.kind)]
if maxRecDepth != 0:
if conf != nil:
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
result.addf(",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
case n.kind
of nkCharLit..nkInt64Lit:
addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
result.addf(",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
addf(result, ",$N$1\"floatVal\": $2",
result.addf(",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
result.addf(",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
addf(result, ",$N$1\"sym\": $2",
result.addf(",$N$1\"sym\": $2",
[istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)])
of nkIdent:
if n.ident != nil:
addf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
result.addf(",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
else:
addf(result, ",$N$1\"ident\": null", [istr])
result.addf(",$N$1\"ident\": null", [istr])
else:
if sonsLen(n) > 0:
addf(result, ",$N$1\"sons\": [", [istr])
for i in 0 ..< sonsLen(n):
if i > 0: add(result, ",")
addf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n.sons[i],
if n.len > 0:
result.addf(",$N$1\"sons\": [", [istr])
for i in 0..<n.len:
if i > 0: result.add(",")
result.addf("$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n[i],
marker, indent + 4, maxRecDepth - 1)])
addf(result, "$N$1]", [istr])
addf(result, ",$N$1\"typ\": $2",
result.addf("$N$1]", [istr])
result.addf(",$N$1\"typ\": $2",
[istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth)])
addf(result, "$N$1}", [rspaces(indent)])
result.addf("$N$1}", [rspaces(indent)])
proc treeToYaml(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope =
var marker = initIntSet()
@@ -379,7 +428,7 @@ proc indentLess(this: var DebugPrinter) =
proc newlineAndIndent(this: var DebugPrinter) =
this.res.add "\n"
this.currentLine += 1
for i in 0 ..< this.indent:
for i in 0..<this.indent:
this.res.add ' '
proc openCurly(this: var DebugPrinter) =
@@ -515,12 +564,12 @@ proc value(this: var DebugPrinter; value: PType) =
this.key "n"
this.value value.n
if sonsLen(value) > 0:
if value.len > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
for i in 0..<value.len:
this.value value[i]
if i != value.len - 1:
this.comma
this.closeBracket
@@ -568,41 +617,41 @@ 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 value.len > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
for i in 0..<value.len:
this.value value[i]
if i != value.len - 1:
this.comma
this.closeBracket
this.closeCurly
when declared(echo):
proc debug(n: PSym; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PType; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PSym; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PNode; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
#this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PType; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PNode; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
#this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc nextTry(h, maxHash: Hash): Hash =
result = ((5 * h) + 1) and maxHash
@@ -629,13 +678,13 @@ proc objectSetRawInsert(data: var TObjectSeq, obj: RootRef) =
proc objectSetEnlarge(t: var TObjectSet) =
var n: TObjectSeq
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
swap(t.data, n)
proc objectSetIncl*(t: var TObjectSet, obj: RootRef) =
if mustRehash(len(t.data), t.counter): objectSetEnlarge(t)
if mustRehash(t.data.len, t.counter): objectSetEnlarge(t)
objectSetRawInsert(t.data, obj)
inc(t.counter)
@@ -648,7 +697,7 @@ proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool =
if it == obj:
return true # found it
h = nextTry(h, high(t.data))
if mustRehash(len(t.data), t.counter):
if mustRehash(t.data.len, t.counter):
objectSetEnlarge(t)
objectSetRawInsert(t.data, obj)
else:
@@ -691,13 +740,13 @@ proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
proc strTableEnlarge(t: var TStrTable) =
var n: seq[PSym]
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i] != nil: strTableRawInsert(n, t.data[i])
swap(t.data, n)
proc strTableAdd*(t: var TStrTable, n: PSym) =
if mustRehash(len(t.data), t.counter): strTableEnlarge(t)
if mustRehash(t.data.len, t.counter): strTableEnlarge(t)
strTableRawInsert(t.data, n)
inc(t.counter)
@@ -724,7 +773,7 @@ proc strTableInclReportConflict*(t: var TStrTable, n: PSym;
if not onConflictKeepOld:
t.data[replaceSlot] = n # overwrite it with newer definition!
return t.data[replaceSlot] # found it
elif mustRehash(len(t.data), t.counter):
elif mustRehash(t.data.len, t.counter):
strTableEnlarge(t)
strTableRawInsert(t.data, n)
else:
@@ -828,7 +877,7 @@ iterator items*(tab: TStrTable): PSym =
s = nextIter(it, tab)
proc hasEmptySlot(data: TIdPairSeq): bool =
for h in 0 .. high(data):
for h in 0..high(data):
if data[h].key == nil:
return true
result = false
@@ -881,9 +930,9 @@ proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) =
assert(t.data[index].key != nil)
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter):
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
if mustRehash(t.data.len, t.counter):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i].key != nil:
idTableRawInsert(n, t.data[i].key, t.data[i].val)
assert(hasEmptySlot(n))
@@ -892,7 +941,7 @@ proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) =
inc(t.counter)
iterator idTablePairs*(t: TIdTable): tuple[key: PIdObj, val: RootRef] =
for i in 0 .. high(t.data):
for i in 0..high(t.data):
if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
proc idNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int =
@@ -926,10 +975,10 @@ proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
assert(t.data[index].key != nil)
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter):
if mustRehash(t.data.len, t.counter):
var n: TIdNodePairSeq
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i].key != nil:
idNodeTableRawInsert(n, t.data[i].key, t.data[i].val)
swap(t.data, n)
@@ -937,13 +986,13 @@ proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
inc(t.counter)
iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
for i in 0 .. high(t.data):
for i in 0..high(t.data):
if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
proc initIITable(x: var TIITable) =
x.counter = 0
newSeq(x.data, StartSize)
for i in 0 ..< StartSize: x.data[i].key = InvalidKey
for i in 0..<StartSize: x.data[i].key = InvalidKey
proc iiTableRawGet(t: TIITable, key: int): int =
var h: Hash
@@ -974,11 +1023,11 @@ proc iiTablePut(t: var TIITable, key, val: int) =
assert(t.data[index].key != InvalidKey)
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter):
if mustRehash(t.data.len, t.counter):
var n: TIIPairSeq
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(n): n[i].key = InvalidKey
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(n): n[i].key = InvalidKey
for i in 0..high(t.data):
if t.data[i].key != InvalidKey:
iiTableRawInsert(n, t.data[i].key, t.data[i].val)
swap(t.data, n)
@@ -992,3 +1041,14 @@ proc isAddrNode*(n: PNode): bool =
if n[0].kind == nkSym and n[0].sym.magic == mAddr: true
else: false
else: false
proc listSymbolNames*(symbols: openArray[PSym]): string =
for sym in symbols:
if result.len > 0:
result.add ", "
result.add sym.name.s
proc isDiscriminantField*(n: PNode): bool =
if n.kind == nkCheckedFieldExpr: sfDiscriminant in n[0][1].sym.flags
elif n.kind == nkDotExpr: sfDiscriminant in n[1].sym.flags
else: false

View File

@@ -11,12 +11,17 @@
# the code here should be reused in the Nim standard library
type
TBitSet* = seq[int8] # we use byte here to avoid issues with
ElemType = byte
TBitSet* = seq[ElemType] # we use byte here to avoid issues with
# cross-compiling; uint would be more efficient
# however
const
ElemSize* = sizeof(int8) * 8
ElemSize* = 8
One = ElemType(1)
Zero = ElemType(0)
template modElemSize(arg: untyped): untyped = arg and 7
template divElemSize(arg: untyped): untyped = arg shr 3
proc bitSetInit*(b: var TBitSet, length: int)
proc bitSetUnion*(x: var TBitSet, y: TBitSet)
@@ -32,48 +37,47 @@ proc bitSetCard*(x: TBitSet): BiggestInt
# implementation
proc bitSetIn(x: TBitSet, e: BiggestInt): bool =
result = (x[int(e div ElemSize)] and toU8(int(1 shl (e mod ElemSize)))) !=
toU8(0)
result = (x[int(e.divElemSize)] and (One shl e.modElemSize)) != Zero
proc bitSetIncl(x: var TBitSet, elem: BiggestInt) =
assert(elem >= 0)
x[int(elem div ElemSize)] = x[int(elem div ElemSize)] or
toU8(int(1 shl (elem mod ElemSize)))
x[int(elem.divElemSize)] = x[int(elem.divElemSize)] or
(One shl elem.modElemSize)
proc bitSetExcl(x: var TBitSet, elem: BiggestInt) =
x[int(elem div ElemSize)] = x[int(elem div ElemSize)] and
not toU8(int(1 shl (elem mod ElemSize)))
x[int(elem.divElemSize)] = x[int(elem.divElemSize)] and
not(One shl elem.modElemSize)
proc bitSetInit(b: var TBitSet, length: int) =
newSeq(b, length)
proc bitSetUnion(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] or y[i]
for i in 0..high(x): x[i] = x[i] or y[i]
proc bitSetDiff(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] and not y[i]
for i in 0..high(x): x[i] = x[i] and not y[i]
proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] xor y[i]
for i in 0..high(x): x[i] = x[i] xor y[i]
proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] and y[i]
for i in 0..high(x): x[i] = x[i] and y[i]
proc bitSetEquals(x, y: TBitSet): bool =
for i in 0 .. high(x):
for i in 0..high(x):
if x[i] != y[i]:
return false
result = true
proc bitSetContains(x, y: TBitSet): bool =
for i in 0 .. high(x):
if (x[i] and not y[i]) != int8(0):
for i in 0..high(x):
if (x[i] and not y[i]) != Zero:
return false
result = true
# Number of set bits for all values of int8
const populationCount: array[low(int8)..high(int8), int8] = block:
var arr: array[low(int8)..high(int8), int8]
const populationCount: array[uint8, uint8] = block:
var arr: array[uint8, uint8]
proc countSetBits(x: uint8): uint8 =
return
@@ -87,11 +91,11 @@ const populationCount: array[low(int8)..high(int8), int8] = block:
((x and 0b10000000'u8) shr 7)
for it in low(int8)..high(int8):
arr[it] = cast[int8](countSetBits(cast[uint8](it)))
for it in low(uint8)..high(uint8):
arr[it] = countSetBits(cast[uint8](it))
arr
proc bitSetCard(x: TBitSet): BiggestInt =
for it in x:
result.inc populationCount[it]
result.inc int(populationCount[it])

View File

@@ -37,34 +37,34 @@ template eq(a, b): bool = cmp(a, b) == 0
proc getOrDefault*[Key, Val](b: BTree[Key, Val], key: Key): Val =
var x = b.root
while x.isInternal:
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if j+1 == x.entries or less(key, x.keys[j+1]):
x = x.links[j]
break
assert(not x.isInternal)
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if eq(key, x.keys[j]): return x.vals[j]
proc contains*[Key, Val](b: BTree[Key, Val], key: Key): bool =
var x = b.root
while x.isInternal:
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if j+1 == x.entries or less(key, x.keys[j+1]):
x = x.links[j]
break
assert(not x.isInternal)
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if eq(key, x.keys[j]): return true
return false
proc copyHalf[Key, Val](h, result: Node[Key, Val]) =
for j in 0 ..< Mhalf:
for j in 0..<Mhalf:
result.keys[j] = h.keys[Mhalf + j]
if h.isInternal:
for j in 0 ..< Mhalf:
for j in 0..<Mhalf:
result.links[j] = h.links[Mhalf + j]
else:
for j in 0 ..< Mhalf:
for j in 0..<Mhalf:
shallowCopy(result.vals[j], h.vals[Mhalf + j])
proc split[Key, Val](h: Node[Key, Val]): Node[Key, Val] =
@@ -191,7 +191,7 @@ when isMainModule:
st.add("www.yahoo.com", "216.109.118.65")
assert st.getOrDefault("www.cs.princeton.edu") == "abc"
assert st.getOrDefault("www.harvardsucks.com") == nil
assert st.getOrDefault("www.harvardsucks.com") == ""
assert st.getOrDefault("www.simpsons.com") == "209.052.165.60"
assert st.getOrDefault("www.apple.com") == "17.112.152.32"

View File

@@ -102,7 +102,7 @@ proc hashTree(c: var MD5Context, n: PNode) =
of nkStrLit..nkTripleStrLit:
c &= n.strVal
else:
for i in 0..<n.len: hashTree(c, n.sons[i])
for i in 0..<n.len: hashTree(c, n[i])
proc hashType(c: var MD5Context, t: PType) =
# modelled after 'typeToString'
@@ -120,44 +120,44 @@ proc hashType(c: var MD5Context, t: PType) =
case t.kind
of tyGenericBody, tyGenericInst, tyGenericInvocation:
for i in 0 ..< sonsLen(t)-ord(t.kind != tyGenericInvocation):
c.hashType t.sons[i]
for i in 0..<t.len-ord(t.kind != tyGenericInvocation):
c.hashType t[i]
of tyUserTypeClass:
internalAssert t.sym != nil and t.sym.owner != nil
c &= t.sym.owner.name.s
of tyUserTypeClassInst:
let body = t.base
c.hashSym body.sym
for i in 1 .. sonsLen(t) - 2:
c.hashType t.sons[i]
for i in 1..<t.len-1:
c.hashType t[i]
of tyFromExpr:
c.hashTree(t.n)
of tyArray:
c.hashTree(t.sons[0].n)
c.hashType(t.sons[1])
c.hashTree(t[0].n)
c.hashType(t[1])
of tyTuple:
if t.n != nil:
assert(sonsLen(t.n) == sonsLen(t))
for i in 0 ..< sonsLen(t.n):
assert(t.n.sons[i].kind == nkSym)
c &= t.n.sons[i].sym.name.s
assert(t.n.len == t.len)
for i in 0..<t.n.len:
assert(t.n[i].kind == nkSym)
c &= t.n[i].sym.name.s
c &= ":"
c.hashType(t.sons[i])
c.hashType(t[i])
c &= ","
else:
for i in 0 ..< sonsLen(t): c.hashType t.sons[i]
for i in 0..<t.len: c.hashType t[i]
of tyRange:
c.hashTree(t.n)
c.hashType(t.sons[0])
c.hashType(t[0])
of tyProc:
c &= (if tfIterator in t.flags: "iterator " else: "proc ")
for i in 0..<t.len: c.hashType(t.sons[i])
for i in 0..<t.len: c.hashType(t[i])
md5Update(c, cast[cstring](addr(t.callConv)), 1)
if tfNoSideEffect in t.flags: c &= ".noSideEffect"
if tfThread in t.flags: c &= ".thread"
else:
for i in 0..<t.len: c.hashType(t.sons[i])
for i in 0..<t.len: c.hashType(t[i])
if tfNotNil in t.flags: c &= "not nil"
proc canonConst(n: PNode): TUid =
@@ -238,35 +238,35 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
encodeVInt(n.sym.id, result)
pushSym(w, n.sym)
else:
for i in 0 ..< sonsLen(n):
encodeNode(w, n.info, n.sons[i], result)
add(result, ')')
for i in 0..<n.len:
encodeNode(w, n.info, n[i], result)
result.add(')')
proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
var oldLen = result.len
result.add('<')
if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
if loc.s != low(loc.s):
add(result, '*')
result.add('*')
encodeVInt(ord(loc.s), result)
if loc.flags != {}:
add(result, '$')
result.add('$')
encodeVInt(cast[int32](loc.flags), result)
if loc.t != nil:
add(result, '^')
result.add('^')
encodeVInt(cast[int32](loc.t.id), result)
pushType(w, loc.t)
if loc.r != nil:
add(result, '!')
result.add('!')
encodeStr($loc.r, result)
if loc.a != 0:
add(result, '?')
result.add('?')
encodeVInt(loc.a, result)
if oldLen + 1 == result.len:
# no data was necessary, so remove the '<' again:
setLen(result, oldLen)
else:
add(result, '>')
result.add('>')
proc encodeType(w: PRodWriter, t: PType, result: var string) =
if t == nil:
@@ -277,47 +277,47 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
if t.kind == tyForward: internalError("encodeType: tyForward")
# for the new rodfile viewer we use a preceding [ so that the data section
# can easily be disambiguated:
add(result, '[')
result.add('[')
encodeVInt(ord(t.kind), result)
add(result, '+')
result.add('+')
encodeVInt(t.id, result)
if t.n != nil:
encodeNode(w, unknownLineInfo(), t.n, result)
encodeNode(w, unknownLineInfo, t.n, result)
if t.flags != {}:
add(result, '$')
result.add('$')
encodeVInt(cast[int32](t.flags), result)
if t.callConv != low(t.callConv):
add(result, '?')
result.add('?')
encodeVInt(ord(t.callConv), result)
if t.owner != nil:
add(result, '*')
result.add('*')
encodeVInt(t.owner.id, result)
pushSym(w, t.owner)
if t.sym != nil:
add(result, '&')
result.add('&')
encodeVInt(t.sym.id, result)
pushSym(w, t.sym)
if t.size != - 1:
add(result, '/')
result.add('/')
encodeVBiggestInt(t.size, result)
if t.align != - 1:
add(result, '=')
result.add('=')
encodeVInt(t.align, result)
encodeLoc(w, t.loc, result)
for i in 0 ..< sonsLen(t):
if t.sons[i] == nil:
add(result, "^()")
for i in 0..<t.len:
if t[i] == nil:
result.add("^()")
else:
add(result, '^')
encodeVInt(t.sons[i].id, result)
pushType(w, t.sons[i])
result.add('^')
encodeVInt(t[i].id, result)
pushType(w, t[i])
proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) =
add(result, '|')
result.add('|')
encodeVInt(ord(lib.kind), result)
add(result, '|')
result.add('|')
encodeStr($lib.name, result)
add(result, '|')
result.add('|')
encodeNode(w, info, lib.path, result)
proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
@@ -363,8 +363,8 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
encodeLoc(w, s.loc, result)
if s.annex != nil: encodeLib(w, s.annex, s.info, result)
if s.constraint != nil:
add(result, '#')
encodeNode(w, unknownLineInfo(), s.constraint, result)
result.add('#')
encodeNode(w, unknownLineInfo, s.constraint, result)
# lazy loading will soon reload the ast lazily, so the ast needs to be
# the last entry of a symbol:
if s.ast != nil:

View File

@@ -9,43 +9,95 @@
#
# included from cgen.nim
proc leftAppearsOnRightSide(le, ri: PNode): bool =
proc canRaiseDisp(p: BProc; n: PNode): bool =
# we assume things like sysFatal cannot raise themselves
if n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}:
result = false
elif optPanics in p.config.globalOptions or
(n.kind == nkSym and sfSystemModule in getModule(n.sym).flags):
# we know we can be strict:
result = canRaise(n)
else:
# we have to be *very* conservative:
result = canRaiseConservative(n)
proc preventNrvo(p: BProc; le, ri: PNode): bool =
proc locationEscapes(p: BProc; le: PNode; inTryStmt: bool): bool =
var n = le
while true:
# do NOT follow nkHiddenDeref here!
case n.kind
of nkSym:
# we don't own the location so it escapes:
if n.sym.owner != p.prc:
return true
elif inTryStmt and sfUsedInFinallyOrExcept in n.sym.flags:
# it is also an observable store if the location is used
# in 'except' or 'finally'
return true
return false
of nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
nkCheckedFieldExpr:
n = n[0]
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
n = n[1]
else:
# cannot analyse the location; assume the worst
return true
if le != nil:
for i in 1 ..< ri.len:
for i in 1..<ri.len:
let r = ri[i]
if isPartOf(le, r) != arNo: return true
# we use the weaker 'canRaise' here in order to prevent too many
# annoying warnings, see #14514
if canRaise(ri[0]) and
locationEscapes(p, le, p.nestedTryStmts.len > 0):
message(p.config, le.info, warnObservableStores, $le)
proc hasNoInit(call: PNode): bool {.inline.} =
result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
result = call[0].kind == nkSym and sfNoInit in call[0].sym.flags
proc isHarmlessStore(p: BProc; canRaise: bool; d: TLoc): bool =
if d.k in {locTemp, locNone} or not canRaise:
result = true
elif d.k == locLocalVar and p.withinTryWithExcept == 0:
# we cannot observe a store to a local variable if the current proc
# has no error handler:
result = true
else:
result = false
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
callee, params: Rope) =
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
genLineDir(p, ri)
var pl = callee & ~"(" & params
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
var typ = skipTypes(ri[0].typ, abstractInst)
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
if params != nil: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri):
# Great, we can use 'd':
if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
elif d.k notin {locTemp} and not hasNoInit(ri):
# reset before pass as 'result' var:
discard "resetLoc(p, d)"
add(pl, addrLoc(p.config, d))
add(pl, ~");$n")
pl.add(addrLoc(p.config, d))
pl.add(~");$n")
line(p, cpsStmts, pl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true)
add(pl, addrLoc(p.config, tmp))
add(pl, ~");$n")
getTemp(p, typ[0], tmp, needsInit=true)
pl.add(addrLoc(p.config, tmp))
pl.add(~");$n")
line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying
if canRaise: raiseExit(p)
else:
add(pl, ~")")
pl.add(~")")
if p.module.compileToCpp:
if lfSingleUse in d.flags:
# do not generate spurious temporaries for C++! For C we're better off
@@ -56,32 +108,55 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
excl d.flags, lfSingleUse
else:
if d.k == locNone and p.splitDecls == 0:
getTempCpp(p, typ.sons[0], d, pl)
getTempCpp(p, typ[0], d, pl)
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
if d.k == locNone: getTemp(p, typ[0], d)
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
if canRaise: raiseExit(p)
elif isHarmlessStore(p, canRaise, d):
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
if canRaise: raiseExit(p)
else:
var tmp: TLoc
getTemp(p, typ[0], tmp, needsInit=true)
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, tmp, list, {}) # no need for deep copying
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {})
else:
add(pl, ~");$n")
pl.add(~");$n")
line(p, cpsStmts, pl)
if canRaise: raiseExit(p)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc openArrayLoc(p: BProc, n: PNode): Rope =
proc openArrayLoc(p: BProc, formalType: PType, 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-1:
genStmts(p, q[i])
q = q.lastSon
var b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
@@ -90,21 +165,26 @@ 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[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)]
let atyp = skipTypes(a.t, abstractInst)
if formalType.skipTypes(abstractInst).kind == tyVar and atyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind == tyVar and not compileToCpp(p.module):
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:
@@ -113,8 +193,11 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
of tyOpenArray, tyVarargs:
result = "$1, $1Len_0" % [rdLoc(a)]
of tyString, tySequence:
if skipTypes(n.typ, abstractInst).kind == tyVar and
not compileToCpp(p.module):
let ntyp = skipTypes(n.typ, abstractInst)
if formalType.skipTypes(abstractInst).kind == tyVar and ntyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if ntyp.kind == tyVar and not compileToCpp(p.module):
var t: TLoc
t.r = "(*$1)" % [a.rdLoc]
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
@@ -136,7 +219,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
proc genArgStringToCString(p: BProc, n: PNode): Rope {.inline.} =
var a: TLoc
initLocExpr(p, n.sons[0], a)
initLocExpr(p, n[0], a)
result = ropecg(p.module, "#nimToCStringConv($1)", [a.rdLoc])
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
@@ -144,19 +227,19 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
if n.kind == nkStringToCString:
result = genArgStringToCString(p, n)
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
var n = if n.kind != nkHiddenAddr: n else: n.sons[0]
result = openArrayLoc(p, n)
var n = if n.kind != nkHiddenAddr: n else: n[0]
result = openArrayLoc(p, param.typ, n)
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
initLocExpr(p, n, a)
result = addrLoc(p.config, a)
elif p.module.compileToCpp and param.typ.kind == tyVar and
n.kind == nkHiddenAddr:
initLocExprSingleUse(p, n.sons[0], a)
initLocExprSingleUse(p, n[0], a)
# if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
# means '*T'. See posix.nim for lots of examples that do that in the wild.
let callee = call.sons[0]
let callee = call[0]
if callee.kind == nkSym and
{sfImportC, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportC} and
{sfImportc, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportc} and
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {}:
result = addrLoc(p.config, a)
else:
@@ -174,36 +257,35 @@ proc genArgNoParam(p: BProc, n: PNode): Rope =
result = rdLoc(a)
template genParamLoop(params) {.dirty.} =
if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym)
let paramType = typ.n.sons[i]
if i < typ.len:
assert(typ.n[i].kind == nkSym)
let paramType = typ.n[i]
if not paramType.typ.isCompileTimeOnly:
if params != nil: add(params, ~", ")
add(params, genArg(p, ri.sons[i], paramType.sym, ri))
if params != nil: params.add(~", ")
params.add(genArg(p, ri[i], paramType.sym, ri))
else:
if params != nil: add(params, ~", ")
add(params, genArgNoParam(p, ri.sons[i]))
if params != nil: params.add(~", ")
params.add(genArgNoParam(p, ri[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
proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc
# this is a hotspot in the compiler
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
var params: Rope
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInstOwned)
var typ = skipTypes(ri[0].typ, abstractInstOwned)
assert(typ.kind == tyProc)
assert(sonsLen(typ) == sonsLen(typ.n))
var length = sonsLen(ri)
for i in 1 ..< length:
assert(typ.len == typ.n.len)
for i in 1..<ri.len:
genParamLoop(params)
var callee = rdLoc(op)
if p.hcrOn and ri.sons[0].kind == nkSym:
callee.addActualPrefixForHCR(p.module.module, ri.sons[0].sym)
if p.hcrOn and ri[0].kind == nkSym:
callee.addActualSuffixForHCR(p.module.module, ri[0].sym)
fixupCall(p, le, ri, d, callee, params)
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
@@ -217,14 +299,13 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
var op: TLoc
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
var pl: Rope
var typ = skipTypes(ri.sons[0].typ, abstractInst)
var typ = skipTypes(ri[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
for i in 1 ..< length:
assert(sonsLen(typ) == sonsLen(typ.n))
for i in 1..<ri.len:
assert(typ.len == typ.n.len)
genParamLoop(pl)
template genCallPattern {.dirty.} =
@@ -234,27 +315,29 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
lineF(p, cpsStmts, PatProc & ";$n", [rdLoc(op), pl, pl.addComma, rawProc])
let rawProc = getRawProcType(p, typ)
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
if sonsLen(ri) > 1: add(pl, ~", ")
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
if ri.len > 1: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri):
# Great, we can use 'd':
if d.k == locNone:
getTemp(p, typ.sons[0], d, needsInit=true)
getTemp(p, typ[0], d, needsInit=true)
elif d.k notin {locTemp} and not hasNoInit(ri):
# reset before pass as 'result' var:
discard "resetLoc(p, d)"
add(pl, addrLoc(p.config, d))
pl.add(addrLoc(p.config, d))
genCallPattern()
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true)
add(pl, addrLoc(p.config, tmp))
getTemp(p, typ[0], tmp, needsInit=true)
pl.add(addrLoc(p.config, tmp))
genCallPattern()
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
elif isHarmlessStore(p, canRaise, d):
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
@@ -262,29 +345,43 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
else:
list.r = PatProc % [rdLoc(op), pl, pl.addComma, rawProc]
genAssignment(p, d, list, {}) # no need for deep copying
if canRaise: raiseExit(p)
else:
var tmp: TLoc
getTemp(p, typ[0], tmp)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
if tfIterator in typ.flags:
list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
else:
list.r = PatProc % [rdLoc(op), pl, pl.addComma, rawProc]
genAssignment(p, tmp, list, {})
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {})
else:
genCallPattern()
if canRaise: raiseExit(p)
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
if i < sonsLen(typ):
if i < typ.len:
# '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]
let paramType = typ.n[i]
assert(paramType.kind == nkSym)
if paramType.typ.isCompileTimeOnly:
result = nil
elif typ.sons[i].kind == tyVar and ri.sons[i].kind == nkHiddenAddr:
result = genArgNoParam(p, ri.sons[i][0])
elif typ[i].kind == tyVar and ri[i].kind == nkHiddenAddr:
result = genArgNoParam(p, ri[i][0])
else:
result = genArgNoParam(p, ri.sons[i]) #, typ.n.sons[i].sym)
result = genArgNoParam(p, ri[i]) #, typ.n[i].sym)
else:
if tfVarargs notin typ.flags:
localError(p.config, ri.info, "wrong argument count")
result = nil
else:
result = genArgNoParam(p, ri.sons[i])
result = genArgNoParam(p, ri[i])
discard """
Dot call syntax in C++
@@ -328,16 +425,16 @@ proc skipAddrDeref(node: PNode): PNode =
var isAddr = false
case n.kind
of nkAddr, nkHiddenAddr:
n = n.sons[0]
n = n[0]
isAddr = true
of nkDerefExpr, nkHiddenDeref:
n = n.sons[0]
n = n[0]
else: return n
if n.kind == nkObjDownConv: n = n.sons[0]
if n.kind == nkObjDownConv: n = n[0]
if isAddr and n.kind in {nkDerefExpr, nkHiddenDeref}:
result = n.sons[0]
result = n[0]
elif n.kind in {nkAddr, nkHiddenAddr}:
result = n.sons[0]
result = n[0]
else:
result = node
@@ -345,13 +442,13 @@ 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)
assert(typ.n.sons[i].kind == nkSym)
internalAssert p.config, i < typ.len
assert(typ.n[i].kind == nkSym)
# if the parameter is lying (tyVar) and thus we required an additional deref,
# skip the deref:
var ri = ri[i]
while ri.kind == nkObjDownConv: ri = ri[0]
let t = typ.sons[i].skipTypes({tyGenericInst, tyAlias, tySink})
let t = typ[i].skipTypes({tyGenericInst, tyAlias, tySink})
if t.kind == tyVar:
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
if x.typ.kind == tyPtr:
@@ -373,7 +470,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
else:
ri = skipAddrDeref(ri)
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0]
result = genArgNoParam(p, ri) #, typ.n.sons[i].sym)
result = genArgNoParam(p, ri) #, typ.n[i].sym)
result.add(".")
proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
@@ -382,22 +479,25 @@ 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 {'+', '@'}:
let ri = ri[j]
if ri.kind in nkCallKinds:
let typ = skipTypes(ri.sons[0].typ, abstractInst)
if pat[i+1] == '+': result.add genArgNoParam(p, ri.sons[0])
let typ = skipTypes(ri[0].typ, abstractInst)
if pat[i+1] == '+': result.add genArgNoParam(p, ri[0])
result.add(~"(")
if 1 < ri.len:
result.add genOtherArg(p, ri, 1, typ)
for k in j+1 ..< ri.len:
for k in j+1..<ri.len:
result.add(~", ")
result.add genOtherArg(p, ri, k, typ)
result.add(~")")
@@ -408,7 +508,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
result.add genThisArg(p, ri, j, typ)
inc i
elif i+1 < pat.len and pat[i+1] == '[':
var arg = ri.sons[j].skipAddrDeref
var arg = ri[j].skipAddrDeref
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0]
result.add genArgNoParam(p, arg)
#result.add debugTree(arg, 0, 10)
@@ -428,24 +528,23 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
if pat[i] notin {'@', '#', '\''}: inc(i)
else: break
if i - 1 >= start:
add(result, substr(pat, start, i - 1))
result.add(substr(pat, start, i - 1))
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
var typ = skipTypes(ri[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
assert(sonsLen(typ) == sonsLen(typ.n))
assert(typ.len == typ.n.len)
# don't call '$' here for efficiency:
let pat = ri.sons[0].sym.loc.r.data
let pat = ri[0].sym.loc.r.data
internalAssert p.config, pat.len > 0
if pat.contains({'#', '(', '@', '\''}):
var pl = genPatternCall(p, ri, pat, typ)
# simpler version of 'fixupCall' that works with the pl+params combination:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
if typ.sons[0] != nil:
var typ = skipTypes(ri[0].typ, abstractInst)
if typ[0] != nil:
if p.module.compileToCpp and lfSingleUse in d.flags:
# do not generate spurious temporaries for C++! For C we're better off
# with them to prevent undefined behaviour and because the codegen
@@ -454,115 +553,114 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
d.r = pl
excl d.flags, lfSingleUse
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
add(pl, ~";$n")
pl.add(~";$n")
line(p, cpsStmts, pl)
else:
var pl: Rope = nil
#var param = typ.n.sons[1].sym
#var param = typ.n[1].sym
if 1 < ri.len:
add(pl, genThisArg(p, ri, 1, typ))
add(pl, op.r)
pl.add(genThisArg(p, ri, 1, typ))
pl.add(op.r)
var params: Rope
for i in 2 ..< length:
for i in 2..<ri.len:
if params != nil: params.add(~", ")
assert(sonsLen(typ) == sonsLen(typ.n))
add(params, genOtherArg(p, ri, i, typ))
assert(typ.len == typ.n.len)
params.add(genOtherArg(p, ri, i, typ))
fixupCall(p, le, ri, d, pl, params)
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
# generates a crappy ObjC call
var op: TLoc
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
var pl = ~"["
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
var typ = skipTypes(ri[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
assert(sonsLen(typ) == sonsLen(typ.n))
assert(typ.len == typ.n.len)
# don't call '$' here for efficiency:
let pat = ri.sons[0].sym.loc.r.data
let pat = ri[0].sym.loc.r.data
internalAssert p.config, pat.len > 0
var start = 3
if ' ' in pat:
start = 1
add(pl, op.r)
if length > 1:
add(pl, ~": ")
add(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
pl.add(op.r)
if ri.len > 1:
pl.add(~": ")
pl.add(genArg(p, ri[1], typ.n[1].sym, ri))
start = 2
else:
if length > 1:
add(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
add(pl, ~" ")
add(pl, op.r)
if length > 2:
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):
if ri.len > 1:
pl.add(genArg(p, ri[1], typ.n[1].sym, ri))
pl.add(~" ")
pl.add(op.r)
if ri.len > 2:
pl.add(~": ")
pl.add(genArg(p, ri[2], typ.n[2].sym, ri))
for i in start..<ri.len:
assert(typ.len == typ.n.len)
if i >= typ.len:
internalError(p.config, ri.info, "varargs for objective C method?")
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
add(pl, ~" ")
add(pl, param.name.s)
add(pl, ~": ")
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, ~" ")
assert(typ.n[i].kind == nkSym)
var param = typ.n[i].sym
pl.add(~" ")
pl.add(param.name.s)
pl.add(~": ")
pl.add(genArg(p, ri[i], param, ri))
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
if ri.len > 1: pl.add(~" ")
# 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:
if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
add(pl, ~"Result: ")
add(pl, addrLoc(p.config, d))
add(pl, ~"];$n")
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
pl.add(~"Result: ")
pl.add(addrLoc(p.config, d))
pl.add(~"];$n")
line(p, cpsStmts, pl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true)
add(pl, addrLoc(p.config, tmp))
add(pl, ~"];$n")
getTemp(p, typ[0], tmp, needsInit=true)
pl.add(addrLoc(p.config, tmp))
pl.add(~"];$n")
line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
add(pl, ~"]")
if d.k == locNone: getTemp(p, typ.sons[0], d)
pl.add(~"]")
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, ri, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
add(pl, ~"];$n")
pl.add(~"];$n")
line(p, cpsStmts, pl)
proc genCall(p: BProc, e: PNode, d: var TLoc) =
if e.sons[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
if e[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
genClosureCall(p, nil, e, d)
elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags:
elif e[0].kind == nkSym and sfInfixCall in e[0].sym.flags:
genInfixCall(p, nil, e, d)
elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags:
elif e[0].kind == nkSym and sfNamedParamCall in e[0].sym.flags:
genNamedParamCall(p, e, d)
else:
genPrefixCall(p, nil, e, d)
postStmtActions(p)
proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
if ri.sons[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
if ri[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
genClosureCall(p, le, ri, d)
elif ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags:
elif ri[0].kind == nkSym and sfInfixCall in ri[0].sym.flags:
genInfixCall(p, le, ri, d)
elif ri.sons[0].kind == nkSym and sfNamedParamCall in ri.sons[0].sym.flags:
elif ri[0].kind == nkSym and sfNamedParamCall in ri[0].sym.flags:
genNamedParamCall(p, ri, d)
else:
genPrefixCall(p, le, ri, d)

File diff suppressed because it is too large Load Diff

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 =
@@ -33,8 +35,8 @@ proc detectSeqVersion(m: BModule): int =
proc genStringLiteralDataOnlyV1(m: BModule, s: string): Rope =
discard cgsym(m, "TGenericSeq")
result = getTempName(m)
addf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), rope(len(s))])
m.s[cfsData].addf("STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), rope(s.len)])
proc genStringLiteralV1(m: BModule; n: PNode): Rope =
if s.isNil:
@@ -51,29 +53,31 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
# ------ Version 2: destructor based strings and seqs -----------------------
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope) =
addf(m.s[cfsData], "static const struct {$n" &
" NI cap; void* allocator; NIM_CHAR data[$2+1];$n" &
"} $1 = { $2, NIM_NIL, $3 };$n",
[result, rope(len(s)), makeCString(s)])
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
m.s[cfsData].addf("static $4 struct {$n" &
" NI cap; NIM_CHAR data[$2+1];$n" &
"} $1 = { $2 | NIM_STRLIT_FLAG, $3 };$n",
[result, rope(s.len), makeCString(s),
rope(if isConst: "const" else: "")])
proc genStringLiteralV2(m: BModule; n: PNode): Rope =
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool): Rope =
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
if id == m.labels:
let pureLit = getTempName(m)
genStringLiteralDataOnlyV2(m, n.strVal, pureLit)
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
result = getTempName(m)
discard cgsym(m, "NimStrPayload")
discard cgsym(m, "NimStringV2")
# string literal not found in the cache:
addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(len(n.strVal)), pureLit])
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(n.strVal.len), pureLit, rope(if isConst: "const" else: "")])
else:
result = getTempName(m)
addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(len(n.strVal)), m.tmpBase & rope(id)])
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(n.strVal.len), m.tmpBase & rope(id),
rope(if isConst: "const" else: "")])
proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool): Rope =
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
var pureLit: Rope
if id == m.labels:
@@ -81,19 +85,20 @@ proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
discard cgsym(m, "NimStrPayload")
discard cgsym(m, "NimStringV2")
# string literal not found in the cache:
genStringLiteralDataOnlyV2(m, n.strVal, pureLit)
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
else:
pureLit = m.tmpBase & rope(id)
result = "{$1, (NimStrPayload*)&$2}" % [rope(len(n.strVal)), pureLit]
result = "{$1, (NimStrPayload*)&$2}" % [rope(n.strVal.len), pureLit]
# ------ Version selector ---------------------------------------------------
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope =
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
isConst: bool): Rope =
case detectStrVersion(m)
of 0, 1: result = genStringLiteralDataOnlyV1(m, s)
of 2:
result = getTempName(m)
genStringLiteralDataOnlyV2(m, s, result)
genStringLiteralDataOnlyV2(m, s, result, isConst)
else:
localError(m.config, info, "cannot determine how to produce code for string literal")
@@ -103,6 +108,6 @@ proc genNilStringLiteral(m: BModule; info: TLineInfo): Rope =
proc genStringLiteral(m: BModule; n: PNode): Rope =
case detectStrVersion(m)
of 0, 1: result = genStringLiteralV1(m, n)
of 2: result = genStringLiteralV2(m, n)
of 2: result = genStringLiteralV2(m, n, isConst = true)
else:
localError(m.config, n.info, "cannot determine how to produce code for string literal")

View File

@@ -11,8 +11,8 @@
## is needed for incremental compilation.
import
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
intsets, platform, llstream, tables, sighashes, modulegraphs, pathutils
ast, ropes, options, strutils, nimlexbase, cgendata, rodutils,
intsets, llstream, tables, modulegraphs, pathutils
# Careful! Section marks need to contain a tabulator so that they cannot
# be part of C string literals.
@@ -28,8 +28,8 @@ const
cfsFieldInfo: "NIM_merge_FIELD_INFO",
cfsTypeInfo: "NIM_merge_TYPE_INFO",
cfsProcHeaders: "NIM_merge_PROC_HEADERS",
cfsVars: "NIM_merge_VARS",
cfsData: "NIM_merge_DATA",
cfsVars: "NIM_merge_VARS",
cfsProcs: "NIM_merge_PROCS",
cfsInitProc: "NIM_merge_INIT_PROC",
cfsDatInitProc: "NIM_merge_DATINIT_PROC",
@@ -50,9 +50,9 @@ const
proc genSectionStart*(fs: TCFileSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):
result = nil
add(result, "\n/*\t")
add(result, CFileSectionNames[fs])
add(result, ":*/\n")
result.add("\n/*\t")
result.add(CFileSectionNames[fs])
result.add(":*/\n")
proc genSectionEnd*(fs: TCFileSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):
@@ -61,9 +61,9 @@ proc genSectionEnd*(fs: TCFileSection; conf: ConfigRef): Rope =
proc genSectionStart*(ps: TCProcSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):
result = rope("")
add(result, "\n/*\t")
add(result, CProcSectionNames[ps])
add(result, ":*/\n")
result.add("\n/*\t")
result.add(CProcSectionNames[ps])
result.add(":*/\n")
proc genSectionEnd*(ps: TCProcSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):

94
compiler/ccgreset.nim Normal file
View File

@@ -0,0 +1,94 @@
#
#
# The Nim Compiler
# (c) Copyright 2020 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# included from cgen.nim
## Code specialization instead of the old, incredibly slow 'genericReset'
## implementation.
proc specializeResetT(p: BProc, accessor: Rope, typ: PType)
proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
typ: PType) =
if n == nil: return
case n.kind
of nkRecList:
for i in 0..<n.len:
specializeResetN(p, accessor, n[i], typ)
of nkRecCase:
if (n[0].kind != nkSym): internalError(p.config, n.info, "specializeResetN")
let disc = n[0].sym
if disc.loc.r == nil: fillObjectFields(p.module, typ)
if disc.loc.t == nil:
internalError(p.config, n.info, "specializeResetN()")
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(p, branch)
else:
lineF(p, cpsStmts, "default:$n", [])
specializeResetN(p, accessor, lastSon(branch), typ)
lineF(p, cpsStmts, "break;$n", [])
lineF(p, cpsStmts, "} $n", [])
specializeResetT(p, "$1.$2" % [accessor, disc.loc.r], disc.loc.t)
of nkSym:
let field = n.sym
if field.typ.kind == tyVoid: return
if field.loc.r == nil: fillObjectFields(p.module, typ)
if field.loc.t == nil:
internalError(p.config, n.info, "specializeResetN()")
specializeResetT(p, "$1.$2" % [accessor, field.loc.r], field.loc.t)
else: internalError(p.config, n.info, "specializeResetN()")
proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
if typ == nil: return
case typ.kind
of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias, tyDistinct, tyInferred,
tySink, tyOwned:
specializeResetT(p, accessor, lastSon(typ))
of tyArray:
let arraySize = lengthOrd(p.config, typ[0])
var i: TLoc
getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i)
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.r, arraySize])
specializeResetT(p, ropecg(p.module, "$1[$2]", [accessor, i.r]), typ[1])
lineF(p, cpsStmts, "}$n", [])
of tyObject:
for i in 0..<typ.len:
var x = typ[i]
if x != nil: x = x.skipTypes(skipPtrs)
specializeResetT(p, accessor.parentObj(p.module), x)
if typ.n != nil: specializeResetN(p, accessor, typ.n, typ)
of tyTuple:
let typ = getUniqueType(typ)
for i in 0..<typ.len:
specializeResetT(p, ropecg(p.module, "$1.Field$2", [accessor, i]), typ[i])
of tyString, tyRef, tySequence:
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1, NIM_NIL);$n", [accessor])
of tyProc:
if typ.callConv == ccClosure:
lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1.ClE_0, NIM_NIL);$n", [accessor])
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
else:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
of tyChar, tyBool, tyEnum, tyInt..tyUInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
of tyCString, tyPointer, tyPtr, tyVar, tyLent:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
else:
discard
proc specializeReset(p: BProc, a: TLoc) =
specializeResetT(p, rdLoc(a), a.t)

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,11 @@ proc emulatedThreadVars(conf: ConfigRef): bool =
result = {optThreads, optTlsEmulation} <= conf.globalOptions
proc accessThreadLocalVar(p: BProc, s: PSym) =
if emulatedThreadVars(p.config) and not p.threadVarAccessed:
p.threadVarAccessed = true
if emulatedThreadVars(p.config) and threadVarAccessed notin p.flags:
p.flags.incl threadVarAccessed
incl p.module.flags, usesThreadVars
addf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV_;$n", [])
add(p.procSec(cpsInit),
p.procSec(cpsLocals).addf("\tNimThreadVars* NimTV_;$n", [])
p.procSec(cpsInit).add(
ropecg(p.module, "\tNimTV_ = (NimThreadVars*) #GetThreadLocalVars();$n", []))
proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
@@ -30,23 +30,25 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
# allocator for it :-(
if not containsOrIncl(m.g.nimtvDeclared, s.id):
m.g.nimtvDeps.add(s.loc.t)
addf(m.g.nimtv, "$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
m.g.nimtv.addf("$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
else:
if isExtern: add(m.s[cfsVars], "extern ")
if optThreads in m.config.globalOptions: add(m.s[cfsVars], "NIM_THREADVAR ")
add(m.s[cfsVars], getTypeDesc(m, s.loc.t))
addf(m.s[cfsVars], " $1;$n", [s.loc.r])
if isExtern: m.s[cfsVars].add("extern ")
elif lfExportLib in s.loc.flags: m.s[cfsVars].add("N_LIB_EXPORT_VAR ")
else: m.s[cfsVars].add("N_LIB_PRIVATE ")
if optThreads in m.config.globalOptions: m.s[cfsVars].add("NIM_THREADVAR ")
m.s[cfsVars].add(getTypeDesc(m, s.loc.t))
m.s[cfsVars].addf(" $1;$n", [s.loc.r])
proc generateThreadLocalStorage(m: BModule) =
if m.g.nimtv != nil and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
addf(m.s[cfsSeqTypes], "typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
m.s[cfsSeqTypes].addf("typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
proc generateThreadVarsSize(m: BModule) =
if m.g.nimtv != nil:
let externc = if m.config.cmd == cmdCompileToCpp or
sfCompileToCpp in m.module.flags: "extern \"C\" "
else: ""
addf(m.s[cfsProcs],
m.s[cfsProcs].addf(
"$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",
[externc.rope])

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,18 +28,18 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
if n == nil: return
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
genTraverseProc(c, accessor, n.sons[i], typ)
for i in 0..<n.len:
genTraverseProc(c, accessor, n[i], typ)
of nkRecCase:
if (n.sons[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
if (n[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
var p = c.p
let disc = n.sons[0].sym
let disc = n[0].sym
if disc.loc.r == nil: fillObjectFields(c.p.module, typ)
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):
let branch = n.sons[i]
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(c.p, branch)
@@ -73,38 +73,39 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
tySink, tyOwned:
genTraverseProc(c, accessor, lastSon(typ))
of tyArray:
let arraySize = lengthOrd(c.p.config, typ.sons[0])
let arraySize = lengthOrd(c.p.config, typ[0])
var i: TLoc
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
let oldCode = p.s(cpsStmts)
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.r, arraySize])
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.r]), typ.sons[1])
genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.r]), typ[1])
if p.s(cpsStmts).len == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
else:
lineF(p, cpsStmts, "}$n", [])
of tyObject:
for i in 0 ..< sonsLen(typ):
var x = typ.sons[i]
for i in 0..<typ.len:
var x = typ[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):
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ.sons[i])
for i in 0..<typ.len:
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ[i])
of tyRef:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
of tySequence:
if tfHasAsgn notin typ.flags:
if optSeqDestructors notin c.p.module.config.globalOptions:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
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])
@@ -118,7 +119,7 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
var p = c.p
assert typ.kind == tySequence
var i: TLoc
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
let oldCode = p.s(cpsStmts)
var a: TLoc
a.r = accessor
@@ -126,7 +127,7 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.r, lenExpr(c.p, a)])
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ.sons[0])
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ[0])
if p.s(cpsStmts).len == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
@@ -154,11 +155,11 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
if typ.kind == tySequence:
genTraverseProcSeq(c, "a".rope, typ)
else:
if skipTypes(typ.sons[0], typedescInst+{tyOwned}).kind == tyArray:
if skipTypes(typ[0], typedescInst+{tyOwned}).kind == tyArray:
# C's arrays are broken beyond repair:
genTraverseProc(c, "a".rope, typ.sons[0])
genTraverseProc(c, "a".rope, typ[0])
else:
genTraverseProc(c, "(*a)".rope, typ.sons[0])
genTraverseProc(c, "(*a)".rope, typ[0])
let generatedProc = "$1 {$n$2$3$4}\n" %
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]
@@ -167,8 +168,8 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
m.s[cfsProcs].add(generatedProc)
if hcrOn:
addf(m.s[cfsProcHeaders], "N_NIMCALL_PTR(void, $1)(void*, NI);\n", [result])
addf(m.s[cfsDynLibInit], "\t$1 = (N_NIMCALL_PTR(void, )(void*, NI)) hcrRegisterProc($3, \"$1\", (void*)$2);\n",
m.s[cfsProcHeaders].addf("N_NIMCALL_PTR(void, $1)(void*, NI);\n", [result])
m.s[cfsDynLibInit].addf("\t$1 = (N_NIMCALL_PTR(void, )(void*, NI)) hcrRegisterProc($3, \"$1\", (void*)$2);\n",
[result, markerName, getModuleDllPath(m)])
proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =

File diff suppressed because it is too large Load Diff

View File

@@ -10,17 +10,17 @@
# This module declares some helpers for the C code generator.
import
ast, astalgo, ropes, hashes, strutils, types, msgs, wordrecg,
ast, hashes, strutils, msgs, wordrecg,
platform, trees, options
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
case n.kind
of nkStmtList:
for i in 0 ..< n.len:
for i in 0..<n.len:
result = getPragmaStmt(n[i], w)
if result != nil: break
of nkPragma:
for i in 0 ..< n.len:
for i in 0..<n.len:
if whichPragma(n[i]) == w: return n[i]
else: discard
@@ -33,7 +33,7 @@ proc hashString*(conf: ConfigRef; s: string): BiggestInt =
# we have to use the same bitwidth
# as the target CPU
var b = 0'u64
for i in 0 ..< len(s):
for i in 0..<s.len:
b = b + uint(s[i])
b = b + (b shl 10)
b = b xor (b shr 6)
@@ -43,7 +43,7 @@ proc hashString*(conf: ConfigRef; s: string): BiggestInt =
result = cast[Hash](b)
else:
var a = 0'u32
for i in 0 ..< len(s):
for i in 0..<s.len:
a = a + uint32(s[i])
a = a + (a shl 10)
a = a xor (a shr 6)
@@ -70,18 +70,18 @@ proc mangle*(name: string): string =
template special(x) =
result.add x
requiresUnderscore = true
for i in start..(name.len-1):
for i in start..<name.len:
let c = name[i]
case c
of 'a'..'z', '0'..'9', 'A'..'Z':
add(result, c)
result.add(c)
of '_':
# we generate names like 'foo_9' for scope disambiguations and so
# disallow this here:
if i > 0 and i < name.len-1 and name[i+1] in Digits:
discard
else:
add(result, c)
result.add(c)
of '$': special "dollar"
of '%': special "percent"
of '&': special "amp"
@@ -102,7 +102,7 @@ proc mangle*(name: string): string =
of '@': special "at"
of '|': special "bar"
else:
add(result, "X" & toHex(ord(c), 2))
result.add("X" & toHex(ord(c), 2))
requiresUnderscore = true
if requiresUnderscore:
result.add "_"

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
## This module contains the data structures for the C code generation phase.
import
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
ast, ropes, options, intsets,
tables, ndi, lineinfos, pathutils, modulegraphs
type
@@ -27,8 +27,8 @@ type
cfsFieldInfo, # section for field information
cfsTypeInfo, # section for type information
cfsProcHeaders, # section for C procs prototypes
cfsVars, # section for C variable declarations
cfsData, # section for C constant data
cfsVars, # section for C variable declarations
cfsProcs, # section for C procs that are not inline
cfsInitProc, # section for the C init proc
cfsDatInitProc, # section for the C datInit proc
@@ -58,22 +58,27 @@ 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
frameLen*: int16
TCProcFlag* = enum
beforeRetNeeded,
threadVarAccessed,
hasCurFramePointer,
noSafePoints,
nimErrorFlagAccessed,
nimErrorFlagDeclared,
nimErrorFlagDisabled
TCProc = object # represents C proc that is currently generated
prc*: PSym # the Nim proc that this C proc belongs to
beforeRetNeeded*: bool # true iff 'BeforeRet' label for proc is needed
threadVarAccessed*: bool # true if the proc already accessed some threadvar
hasCurFramePointer*: bool # true if _nimCurFrame var needed to recover after
# exception is generated
noSafePoints*: bool # the proc doesn't use safe points in exception handling
flags*: set[TCProcFlag]
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, label: Natural]]
# 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
@@ -86,21 +91,19 @@ type
options*: TOptions # options that should be used for code
# generation; this is the same as prc.options
# unless prc == nil
maxFrameLen*: int # max length of frame descriptor
module*: BModule # used to prevent excessive parameter passing
withinLoop*: int # > 0 if we are within a loop
splitDecls*: int # > 0 if we are in some context for C++ that
# requires 'T x = T()' to become 'T x; x = T()'
# (yes, C++ is weird like that)
gcFrameId*: Natural # for the GC stack marking
gcFrameType*: Rope # the struct {} we put the GC markers into
withinTryWithExcept*: int # required for goto based exception handling
sigConflicts*: CountTable[string]
TTypeSeq* = seq[PType]
TypeCache* = Table[SigHash, Rope]
TypeCacheWithOwner* = Table[SigHash, tuple[str: Rope, owner: PSym]]
Codegenflag* = enum
CodegenFlag* = enum
preventStackTrace, # true if stack traces need to be prevented
usesThreadVars, # true if the module uses a thread var
frameDeclared, # hack for ROD support so that we don't declare
@@ -114,11 +117,9 @@ type
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
mapping*: Rope # the generated mapping file (if requested)
modules*: seq[BModule] # list of all compiled modules
modules_closed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
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
@@ -137,7 +138,7 @@ type
TCGen = object of PPassContext # represents a C source file
s*: TCFileSections # sections of the C file
flags*: set[Codegenflag]
flags*: set[CodegenFlag]
module*: PSym
filename*: AbsoluteFile
cfilename*: AbsoluteFile # filename of the module (including path,
@@ -152,7 +153,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
@@ -174,7 +175,7 @@ proc includeHeader*(this: BModule; header: string) =
proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
# section in the current block
result = p.blocks[p.blocks.len-1].sections[s]
result = p.blocks[^1].sections[s]
proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
# top level proc sections
@@ -196,6 +197,6 @@ proc newModuleList*(g: ModuleGraph): BModuleList =
config: g.config, graph: g, nimtvDeclared: initIntSet())
iterator cgenModules*(g: BModuleList): BModule =
for m in g.modules_closed:
for m in g.modulesClosed:
# iterate modules in the order they were closed
yield m

View File

@@ -7,10 +7,10 @@
# distribution, for details about the copyright.
#
## This module implements code generation for multi methods.
## This module implements code generation for methods.
import
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
intsets, options, ast, msgs, idents, renderer, types, magicsys,
sempass2, strutils, modulegraphs, lineinfos
proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
@@ -23,11 +23,11 @@ proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
result = n
elif diff < 0:
result = newNodeIT(nkObjUpConv, n.info, d)
addSon(result, n)
result.add n
if downcast: internalError(conf, n.info, "cgmeth.genConv: no upcast allowed")
elif diff > 0:
result = newNodeIT(nkObjDownConv, n.info, d)
addSon(result, n)
result.add n
if not downcast:
internalError(conf, n.info, "cgmeth.genConv: no downcast allowed")
else:
@@ -44,26 +44,26 @@ proc getDispatcher*(s: PSym): PSym =
proc methodCall*(n: PNode; conf: ConfigRef): PNode =
result = n
# replace ordinary method by dispatcher method:
let disp = getDispatcher(result.sons[0].sym)
let disp = getDispatcher(result[0].sym)
if disp != nil:
result.sons[0].sym = disp
result[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in 1 ..< sonsLen(result):
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true, conf)
for i in 1..<result.len:
result[i] = genConv(result[i], disp.typ[i], true, conf)
else:
localError(conf, n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
localError(conf, n.info, "'" & $result[0] & "' lacks a dispatcher")
type
MethodResult = enum No, Invalid, Yes
proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
if a.name.id != b.name.id: return
if sonsLen(a.typ) != sonsLen(b.typ):
if a.typ.len != b.typ.len:
return
for i in 1 ..< sonsLen(a.typ):
var aa = a.typ.sons[i]
var bb = b.typ.sons[i]
for i in 1..<a.typ.len:
var aa = a.typ[i]
var bb = b.typ[i]
while true:
aa = skipTypes(aa, {tyGenericInst, tyAlias})
bb = skipTypes(bb, {tyGenericInst, tyAlias})
@@ -72,7 +72,7 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
bb = bb.lastSon
else:
break
if sameType(a.typ.sons[i], b.typ.sons[i]):
if sameType(a.typ[i], b.typ[i]):
if aa.kind == tyObject and result != Invalid:
result = Yes
elif aa.kind == tyObject and bb.kind == tyObject and (i == 1 or multiMethods):
@@ -90,22 +90,22 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
return No
if result == Yes:
# check for return type:
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]):
if b.typ.sons[0] != nil and b.typ.sons[0].kind == tyUntyped:
if not sameTypeOrNil(a.typ[0], b.typ[0]):
if b.typ[0] != nil and b.typ[0].kind == tyUntyped:
# infer 'auto' from the base to make it consistent:
b.typ.sons[0] = a.typ.sons[0]
b.typ[0] = a.typ[0]
else:
return No
proc attachDispatcher(s: PSym, dispatcher: PNode) =
if dispatcherPos < s.ast.len:
# we've added a dispatcher already, so overwrite it
s.ast.sons[dispatcherPos] = dispatcher
s.ast[dispatcherPos] = dispatcher
else:
setLen(s.ast.sons, dispatcherPos+1)
if s.ast[resultPos] == nil:
s.ast[resultPos] = newNodeI(nkEmpty, s.info)
s.ast.sons[dispatcherPos] = dispatcher
s.ast[dispatcherPos] = dispatcher
proc createDispatcher(s: PSym): PSym =
var disp = copySym(s)
@@ -115,16 +115,16 @@ proc createDispatcher(s: PSym): PSym =
# we can't inline the dispatcher itself (for now):
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
disp.ast = copyTree(s.ast)
disp.ast.sons[bodyPos] = newNodeI(nkEmpty, s.info)
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
disp.loc.r = nil
if s.typ.sons[0] != nil:
if disp.ast.sonsLen > resultPos:
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
if s.typ[0] != nil:
if disp.ast.len > resultPos:
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym)
else:
# We've encountered a method prototype without a filled-in
# resultPos slot. We put a placeholder in there that will
# be updated in fixupDispatcher().
disp.ast.addSon(newNodeI(nkEmpty, s.info))
disp.ast.add newNodeI(nkEmpty, s.info)
attachDispatcher(s, newSymNode(disp))
# attach to itself to prevent bugs:
attachDispatcher(disp, newSymNode(disp))
@@ -136,9 +136,9 @@ 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
disp.ast.sons[resultPos].kind == nkEmpty:
disp.ast.sons[resultPos] = copyTree(meth.ast.sons[resultPos])
if disp.ast.len > resultPos and meth.ast.len > resultPos and
disp.ast[resultPos].kind == nkEmpty:
disp.ast[resultPos] = copyTree(meth.ast[resultPos])
# The following code works only with lock levels, so we disable
# it when they're not available.
@@ -158,13 +158,12 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
disp.typ.lockLevel = meth.typ.lockLevel
proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
let L = len(g.methods)
var witness: PSym
for i in 0 ..< L:
for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher
case sameMethodBucket(disp, s, multimethods = optMultiMethods in g.config.globalOptions)
of Yes:
add(g.methods[i].methods, s)
g.methods[i].methods.add(s)
attachDispatcher(s, disp.ast[dispatcherPos])
fixupDispatcher(s, disp, g.config)
#echo "fixup ", disp.name.s, " ", disp.id
@@ -178,7 +177,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
of Invalid:
if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher:
add(g.methods, (methods: @[s], dispatcher: createDispatcher(s)))
g.methods.add((methods: @[s], dispatcher: createDispatcher(s)))
#echo "adding ", s.info
#if fromCache:
# internalError(s.info, "no method dispatcher found")
@@ -190,32 +189,32 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
proc relevantCol(methods: seq[PSym], col: int): bool =
# returns true iff the position is relevant
var t = methods[0].typ.sons[col].skipTypes(skipPtrs)
var t = methods[0].typ[col].skipTypes(skipPtrs)
if t.kind == tyObject:
for i in 1 .. high(methods):
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
for i in 1..high(methods):
let t2 = skipTypes(methods[i].typ[col], skipPtrs)
if not sameType(t2, t):
return true
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
for col in 1 ..< sonsLen(a.typ):
for col in 1..<a.typ.len:
if contains(relevantCols, col):
var aa = skipTypes(a.typ.sons[col], skipPtrs)
var bb = skipTypes(b.typ.sons[col], skipPtrs)
var aa = skipTypes(a.typ[col], skipPtrs)
var bb = skipTypes(b.typ[col], skipPtrs)
var d = inheritanceDiff(aa, bb)
if (d != high(int)) and d != 0:
return d
proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
# we use shellsort here; fast and simple
var n = len(a)
var n = a.len
var h = 1
while true:
h = 3 * h + 1
if h > n: break
while true:
h = h div 3
for i in h ..< n:
for i in h..<n:
var v = a[i]
var j = i
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
@@ -228,71 +227,70 @@ 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 = base.typ.len
var nilchecks = newNodeI(nkStmtList, base.info)
var disp = newNodeI(nkIfStmt, base.info)
var ands = getSysMagic(g, unknownLineInfo(), "and", mAnd)
var iss = getSysMagic(g, unknownLineInfo(), "of", mOf)
let boolType = getSysType(g, unknownLineInfo(), tyBool)
for col in 1 ..< paramLen:
var ands = getSysMagic(g, unknownLineInfo, "and", mAnd)
var iss = getSysMagic(g, unknownLineInfo, "of", mOf)
let boolType = getSysType(g, unknownLineInfo, tyBool)
for col in 1..<paramLen:
if contains(relevantCols, col):
let param = base.typ.n.sons[col].sym
let param = base.typ.n[col].sym
if param.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
addSon(nilchecks, newTree(nkCall,
newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param)))
for meth in 0 .. high(methods):
nilchecks.add newTree(nkCall,
newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param))
for meth in 0..high(methods):
var curr = methods[meth] # generate condition:
var cond: PNode = nil
for col in 1 ..< paramLen:
for col in 1..<paramLen:
if contains(relevantCols, col):
var isn = newNodeIT(nkCall, base.info, boolType)
addSon(isn, newSymNode(iss))
let param = base.typ.n.sons[col].sym
addSon(isn, newSymNode(param))
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
isn.add newSymNode(iss)
let param = base.typ.n[col].sym
isn.add newSymNode(param)
isn.add newNodeIT(nkType, base.info, curr.typ[col])
if cond != nil:
var a = newNodeIT(nkCall, base.info, boolType)
addSon(a, newSymNode(ands))
addSon(a, cond)
addSon(a, isn)
a.add newSymNode(ands)
a.add cond
a.add isn
cond = a
else:
cond = isn
let retTyp = base.typ.sons[0]
let retTyp = base.typ[0]
let call = newNodeIT(nkCall, base.info, retTyp)
addSon(call, newSymNode(curr))
for col in 1 ..< paramLen:
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
curr.typ.sons[col], false, g.config))
call.add newSymNode(curr)
for col in 1..<paramLen:
call.add genConv(newSymNode(base.typ.n[col].sym),
curr.typ[col], false, g.config)
var ret: PNode
if retTyp != nil:
var a = newNodeI(nkFastAsgn, base.info)
addSon(a, newSymNode(base.ast.sons[resultPos].sym))
addSon(a, call)
a.add newSymNode(base.ast[resultPos].sym)
a.add call
ret = newNodeI(nkReturnStmt, base.info)
addSon(ret, a)
ret.add a
else:
ret = call
if cond != nil:
var a = newNodeI(nkElifBranch, base.info)
addSon(a, cond)
addSon(a, ret)
addSon(disp, a)
a.add cond
a.add ret
disp.add a
else:
disp = ret
nilchecks.add disp
nilchecks.flags.incl nfTransf # should not be further transformed
result.ast.sons[bodyPos] = nilchecks
result.ast[bodyPos] = nilchecks
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList)
for bucket in 0 ..< len(g.methods):
for bucket in 0..<g.methods.len:
var relevantCols = initIntSet()
for col in 1 ..< sonsLen(g.methods[bucket].methods[0].typ):
for col in 1..<g.methods[bucket].methods[0].typ.len:
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
break
sortBucket(g.methods[bucket].methods, relevantCols)
addSon(result,
newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols)))
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))

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,13 +123,15 @@
# if :curExc.isNil:
# return :tmpResult
# else:
# closureIterSetupExc(nil)
# raise
# state = -1 # Goto next state. In this case we just exit
# break :stateLoop
import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, idents,
renderer, types, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
ast, msgs, idents,
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
tables, options
type
Ctx = object
@@ -156,8 +155,8 @@ type
# is their finally. For finally it is parent finally. Otherwise -1
const
nkSkip = { nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
nkCommentStmt } + procDefs
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
nkCommentStmt} + procDefs
proc newStateAccess(ctx: var Ctx): PNode =
if ctx.stateVarSym.isNil:
@@ -174,7 +173,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)
@@ -239,7 +238,7 @@ proc toStmtList(n: PNode): PNode =
proc addGotoOut(n: PNode, gotoOut: PNode): PNode =
# Make sure `n` is a stmtlist, and ends with `gotoOut`
result = toStmtList(n)
if result.len == 0 or result.sons[^1].kind != nkGotoState:
if result.len == 0 or result[^1].kind != nkGotoState:
result.add(gotoOut)
proc newTempVar(ctx: var Ctx, typ: PType): PSym =
@@ -275,7 +274,7 @@ proc transformBreaksAndContinuesInWhile(ctx: var Ctx, n: PNode, before, after: P
if ctx.blockLevel == 0:
result = after
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformBreaksAndContinuesInWhile(n[i], before, after)
proc transformBreaksInBlock(ctx: var Ctx, n: PNode, label, after: PNode): PNode =
@@ -295,7 +294,7 @@ proc transformBreaksInBlock(ctx: var Ctx, n: PNode, label, after: PNode): PNode
if label.kind == nkSym and n[0].sym == label.sym:
result = after
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformBreaksInBlock(n[i], label, after)
proc newNullifyCurExc(ctx: var Ctx, info: TLineInfo): PNode =
@@ -320,7 +319,7 @@ proc collectExceptState(ctx: var Ctx, n: PNode): PNode {.inline.} =
if c.len > 1:
var cond: PNode
for i in 0 .. c.len - 2:
for i in 0..<c.len - 1:
assert(c[i].kind == nkType)
let nextCond = newTree(nkCall,
newSymNode(g.getSysMagic(c.info, "of", mOf)),
@@ -359,7 +358,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,
@@ -403,7 +402,7 @@ proc exprToStmtList(n: PNode): tuple[s, res: PNode] =
var n = n
while n.kind == nkStmtListExpr:
result.s.sons.add(n.sons)
result.s.sons.setLen(result.s.sons.len - 1) # delete last son
result.s.sons.setLen(result.s.len - 1) # delete last son
n = n[^1]
result.res = n
@@ -437,7 +436,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkYieldStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -451,7 +450,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkPar, nkObjConstr, nkTupleConstr, nkBracket:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -461,7 +460,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
if n.typ.isNil: internalError(ctx.g.config, "lowerStmtListExprs: constr typ.isNil")
result.typ = n.typ
for i in 0 ..< n.len:
for i in 0..<n.len:
case n[i].kind
of nkExprColonExpr:
if n[i][1].kind == nkStmtListExpr:
@@ -477,7 +476,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkIfStmt, nkIfExpr:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -543,7 +542,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkTryStmt, nkHiddenTryStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -556,7 +555,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
let tmp = ctx.newTempVar(n.typ)
n[0] = ctx.convertExprBodyToAsgn(n[0], tmp)
for i in 1 ..< n.len:
for i in 1..<n.len:
let branch = n[i]
case branch.kind
of nkExceptBranch:
@@ -573,7 +572,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkCaseStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -591,7 +590,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(st)
n[0] = ex
for i in 1 ..< n.len:
for i in 1..<n.len:
let branch = n[i]
case branch.kind
of nkOfBranch:
@@ -603,9 +602,9 @@ 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:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -645,7 +644,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(ifNode)
result.add(ctx.newEnvVarAccess(tmp))
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
if n[i].kind == nkStmtListExpr:
let (st, ex) = exprToStmtList(n[i])
result.add(st)
@@ -674,7 +673,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkDiscardStmt, nkReturnStmt, nkRaiseStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -685,9 +684,10 @@ 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:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -701,7 +701,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkAsgn, nkFastAsgn:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -759,7 +759,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:
@@ -779,14 +779,14 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result = newNodeI(nkStmtListExpr, n.info)
result.typ = n.typ
let (st, ex) = exprToStmtList(n[1])
n.kind = nkBlockStmt
n.transitionSonsKind(nkBlockStmt)
n.typ = nil
n[1] = st
result.add(n)
result.add(ex)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], needsSplit)
proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
@@ -809,10 +809,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,13 +833,14 @@ 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:
let asgnTmpResult = newNodeI(nkAsgn, n.info)
asgnTmpResult.add(ctx.newTmpResultAccess())
asgnTmpResult.add(n[0])
let x = if n[0].kind in {nkAsgn, nkFastAsgn}: n[0][1] else: n[0]
asgnTmpResult.add(x)
result.add(asgnTmpResult)
result.add(ctx.newNullifyCurExc(n.info))
@@ -849,161 +851,160 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
of nkSkip:
discard
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformReturnsInTry(n[i])
proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode =
result = n
case n.kind:
of nkSkip:
discard
case n.kind
of nkSkip: discard
of nkStmtList, nkStmtListExpr:
result = addGotoOut(result, gotoOut)
for i in 0 ..< n.len:
if n[i].hasYields:
# Create a new split
let go = newNodeI(nkGotoState, n[i].info)
n[i] = ctx.transformClosureIteratorBody(n[i], go)
of nkStmtList, nkStmtListExpr:
result = addGotoOut(result, gotoOut)
for i in 0..<n.len:
if n[i].hasYields:
# Create a new split
let go = newNodeI(nkGotoState, n[i].info)
n[i] = ctx.transformClosureIteratorBody(n[i], go)
let s = newNodeI(nkStmtList, n[i + 1].info)
for j in i + 1 ..< n.len:
s.add(n[j])
let s = newNodeI(nkStmtList, n[i + 1].info)
for j in i + 1..<n.len:
s.add(n[j])
n.sons.setLen(i + 1)
discard ctx.newState(s, go)
if ctx.transformClosureIteratorBody(s, gotoOut) != s:
internalError(ctx.g.config, "transformClosureIteratorBody != s")
break
n.sons.setLen(i + 1)
discard ctx.newState(s, go)
if ctx.transformClosureIteratorBody(s, gotoOut) != s:
internalError(ctx.g.config, "transformClosureIteratorBody != s")
break
of nkYieldStmt:
result = newNodeI(nkStmtList, n.info)
result.add(n)
result.add(gotoOut)
of nkYieldStmt:
result = newNodeI(nkStmtList, n.info)
result.add(n)
result.add(gotoOut)
of nkElse, nkElseExpr:
result[0] = addGotoOut(result[0], gotoOut)
result[0] = ctx.transformClosureIteratorBody(result[0], gotoOut)
of nkElse, nkElseExpr:
result[0] = addGotoOut(result[0], gotoOut)
result[0] = ctx.transformClosureIteratorBody(result[0], gotoOut)
of nkElifBranch, nkElifExpr, nkOfBranch:
result[^1] = addGotoOut(result[^1], gotoOut)
result[^1] = ctx.transformClosureIteratorBody(result[^1], gotoOut)
of nkIfStmt, nkCaseStmt:
for i in 0 ..< n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
if n[^1].kind != nkElse:
# We don't have an else branch, but every possible branch has to end with
# gotoOut, so add else here.
let elseBranch = newTree(nkElse, gotoOut)
n.add(elseBranch)
of nkWhileStmt:
# while e:
# s
# ->
# BEGIN_STATE:
# if e:
# s
# goto BEGIN_STATE
# else:
# goto OUT
result = newNodeI(nkGotoState, n.info)
let s = newNodeI(nkStmtList, n.info)
discard ctx.newState(s, result)
let ifNode = newNodeI(nkIfStmt, n.info)
let elifBranch = newNodeI(nkElifBranch, n.info)
elifBranch.add(n[0])
var body = addGotoOut(n[1], result)
body = ctx.transformBreaksAndContinuesInWhile(body, result, gotoOut)
body = ctx.transformClosureIteratorBody(body, result)
elifBranch.add(body)
ifNode.add(elifBranch)
of nkElifBranch, nkElifExpr, nkOfBranch:
result[^1] = addGotoOut(result[^1], gotoOut)
result[^1] = ctx.transformClosureIteratorBody(result[^1], gotoOut)
of nkIfStmt, nkCaseStmt:
for i in 0..<n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
if n[^1].kind != nkElse:
# We don't have an else branch, but every possible branch has to end with
# gotoOut, so add else here.
let elseBranch = newTree(nkElse, gotoOut)
ifNode.add(elseBranch)
s.add(ifNode)
n.add(elseBranch)
of nkBlockStmt:
result[1] = addGotoOut(result[1], gotoOut)
result[1] = ctx.transformBreaksInBlock(result[1], result[0], gotoOut)
result[1] = ctx.transformClosureIteratorBody(result[1], gotoOut)
of nkWhileStmt:
# while e:
# s
# ->
# BEGIN_STATE:
# if e:
# s
# goto BEGIN_STATE
# else:
# goto OUT
of nkTryStmt, nkHiddenTryStmt:
# See explanation above about how this works
ctx.hasExceptions = true
result = newNodeI(nkGotoState, n.info)
result = newNodeI(nkGotoState, n.info)
var tryBody = toStmtList(n[0])
var exceptBody = ctx.collectExceptState(n)
var finallyBody = newTree(nkStmtList, getFinallyNode(ctx, n))
finallyBody = ctx.transformReturnsInTry(finallyBody)
finallyBody.add(ctx.newEndFinallyNode(finallyBody.info))
let s = newNodeI(nkStmtList, n.info)
discard ctx.newState(s, result)
let ifNode = newNodeI(nkIfStmt, n.info)
let elifBranch = newNodeI(nkElifBranch, n.info)
elifBranch.add(n[0])
# The following index calculation is based on the knowledge how state
# indexes are assigned
let tryIdx = ctx.states.len
var exceptIdx, finallyIdx: int
if exceptBody.kind != nkEmpty:
exceptIdx = -(tryIdx + 1)
finallyIdx = tryIdx + 2
else:
exceptIdx = tryIdx + 1
finallyIdx = tryIdx + 1
var body = addGotoOut(n[1], result)
let outToFinally = newNodeI(nkGotoState, finallyBody.info)
body = ctx.transformBreaksAndContinuesInWhile(body, result, gotoOut)
body = ctx.transformClosureIteratorBody(body, result)
block: # Create initial states.
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
let realTryIdx = ctx.newState(tryBody, result)
assert(realTryIdx == tryIdx)
elifBranch.add(body)
ifNode.add(elifBranch)
if exceptBody.kind != nkEmpty:
ctx.curExcHandlingState = finallyIdx
let realExceptIdx = ctx.newState(exceptBody, nil)
assert(realExceptIdx == -exceptIdx)
let elseBranch = newTree(nkElse, gotoOut)
ifNode.add(elseBranch)
s.add(ifNode)
ctx.curExcHandlingState = oldExcHandlingState
let realFinallyIdx = ctx.newState(finallyBody, outToFinally)
assert(realFinallyIdx == finallyIdx)
of nkBlockStmt:
result[1] = addGotoOut(result[1], gotoOut)
result[1] = ctx.transformBreaksInBlock(result[1], result[0], gotoOut)
result[1] = ctx.transformClosureIteratorBody(result[1], gotoOut)
block: # Subdivide the states
let oldNearestFinally = ctx.nearestFinally
ctx.nearestFinally = finallyIdx
of nkTryStmt, nkHiddenTryStmt:
# See explanation above about how this works
ctx.hasExceptions = true
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
if ctx.transformReturnsInTry(tryBody) != tryBody:
internalError(ctx.g.config, "transformReturnsInTry != tryBody")
if ctx.transformClosureIteratorBody(tryBody, outToFinally) != tryBody:
internalError(ctx.g.config, "transformClosureIteratorBody != tryBody")
ctx.curExcHandlingState = finallyIdx
ctx.addElseToExcept(exceptBody)
if ctx.transformReturnsInTry(exceptBody) != exceptBody:
internalError(ctx.g.config, "transformReturnsInTry != exceptBody")
if ctx.transformClosureIteratorBody(exceptBody, outToFinally) != exceptBody:
internalError(ctx.g.config, "transformClosureIteratorBody != exceptBody")
ctx.curExcHandlingState = oldExcHandlingState
ctx.nearestFinally = oldNearestFinally
if ctx.transformClosureIteratorBody(finallyBody, gotoOut) != finallyBody:
internalError(ctx.g.config, "transformClosureIteratorBody != finallyBody")
of nkGotoState, nkForStmt:
internalError(ctx.g.config, "closure iter " & $n.kind)
result = newNodeI(nkGotoState, n.info)
var tryBody = toStmtList(n[0])
var exceptBody = ctx.collectExceptState(n)
var finallyBody = newTree(nkStmtList, getFinallyNode(ctx, n))
finallyBody = ctx.transformReturnsInTry(finallyBody)
finallyBody.add(ctx.newEndFinallyNode(finallyBody.info))
# The following index calculation is based on the knowledge how state
# indexes are assigned
let tryIdx = ctx.states.len
var exceptIdx, finallyIdx: int
if exceptBody.kind != nkEmpty:
exceptIdx = -(tryIdx + 1)
finallyIdx = tryIdx + 2
else:
for i in 0 ..< n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
exceptIdx = tryIdx + 1
finallyIdx = tryIdx + 1
let outToFinally = newNodeI(nkGotoState, finallyBody.info)
block: # Create initial states.
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
let realTryIdx = ctx.newState(tryBody, result)
assert(realTryIdx == tryIdx)
if exceptBody.kind != nkEmpty:
ctx.curExcHandlingState = finallyIdx
let realExceptIdx = ctx.newState(exceptBody, nil)
assert(realExceptIdx == -exceptIdx)
ctx.curExcHandlingState = oldExcHandlingState
let realFinallyIdx = ctx.newState(finallyBody, outToFinally)
assert(realFinallyIdx == finallyIdx)
block: # Subdivide the states
let oldNearestFinally = ctx.nearestFinally
ctx.nearestFinally = finallyIdx
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
if ctx.transformReturnsInTry(tryBody) != tryBody:
internalError(ctx.g.config, "transformReturnsInTry != tryBody")
if ctx.transformClosureIteratorBody(tryBody, outToFinally) != tryBody:
internalError(ctx.g.config, "transformClosureIteratorBody != tryBody")
ctx.curExcHandlingState = finallyIdx
ctx.addElseToExcept(exceptBody)
if ctx.transformReturnsInTry(exceptBody) != exceptBody:
internalError(ctx.g.config, "transformReturnsInTry != exceptBody")
if ctx.transformClosureIteratorBody(exceptBody, outToFinally) != exceptBody:
internalError(ctx.g.config, "transformClosureIteratorBody != exceptBody")
ctx.curExcHandlingState = oldExcHandlingState
ctx.nearestFinally = oldNearestFinally
if ctx.transformClosureIteratorBody(finallyBody, gotoOut) != finallyBody:
internalError(ctx.g.config, "transformClosureIteratorBody != finallyBody")
of nkGotoState, nkForStmt:
internalError(ctx.g.config, "closure iter " & $n.kind)
else:
for i in 0..<n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
proc stateFromGotoState(n: PNode): int =
assert(n.kind == nkGotoState)
@@ -1039,18 +1040,18 @@ proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(ctx.newStateAssgn(stateFromGotoState(n[1])))
var retStmt = newNodeI(nkReturnStmt, n.info)
if n[0].sons[0].kind != nkEmpty:
var a = newNodeI(nkAsgn, n[0].sons[0].info)
var retVal = n[0].sons[0] #liftCapturedVars(n.sons[0], owner, d, c)
addSon(a, newSymNode(getClosureIterResult(ctx.g, ctx.fn)))
addSon(a, retVal)
if n[0][0].kind != nkEmpty:
var a = newNodeI(nkAsgn, n[0][0].info)
var retVal = n[0][0] #liftCapturedVars(n[0], owner, d, c)
a.add newSymNode(getClosureIterResult(ctx.g, ctx.fn))
a.add retVal
retStmt.add(a)
else:
retStmt.add(ctx.g.emptyNode)
result.add(retStmt)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformStateAssignments(n[i])
of nkSkip:
@@ -1070,7 +1071,7 @@ proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(breakState)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformStateAssignments(n[i])
proc skipStmtList(ctx: Ctx; n: PNode): PNode =
@@ -1102,7 +1103,7 @@ proc skipEmptyStates(ctx: Ctx, stateIdx: int): int =
result = ctx.states[stateIdx][0].intVal.int
proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode =
proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode=
result = n
case n.kind
of nkSkip:
@@ -1111,7 +1112,7 @@ proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode =
result = copyTree(n)
result[0].intVal = ctx.skipEmptyStates(result[0].intVal.int)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.skipThroughEmptyStates(n[i])
proc newArrayType(g: ModuleGraph; n: int, t: PType, owner: PSym): PType =
@@ -1149,7 +1150,6 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
# :state = exceptionTable[:state]
block:
# exceptionTable[:state]
let getNextState = newTree(nkBracketExpr,
ctx.createExceptionTable(),
@@ -1164,7 +1164,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)
@@ -1176,7 +1176,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
@@ -1188,7 +1188,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,
@@ -1283,19 +1283,117 @@ proc deleteEmptyStates(ctx: var Ctx) =
else:
inc i
type
PreprocessContext = object
finallys: seq[PNode]
config: ConfigRef
blocks: seq[(PNode, int)]
FreshVarsContext = object
tab: Table[int, PSym]
config: ConfigRef
info: TLineInfo
proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
case n.kind
of nkSym:
let x = c.tab.getOrDefault(n.sym.id)
if x == nil:
result = n
else:
result = newSymNode(x, n.info)
of nkSkip - {nkSym}:
result = n
of nkLetSection, nkVarSection:
result = copyNode(n)
for it in n:
if it.kind in {nkIdentDefs, nkVarTuple}:
let idefs = copyNode(it)
for v in 0..it.len-3:
if it[v].kind == nkSym:
let x = copySym(it[v].sym)
c.tab[it[v].sym.id] = x
idefs.add newSymNode(x)
else:
idefs.add it[v]
for rest in it.len-2 ..< it.len: idefs.add it[rest]
result.add idefs
else:
result.add it
of nkRaiseStmt:
localError(c.config, c.info, "unsupported control flow: 'finally: ... raise' duplicated because of 'break'")
else:
result = n
for i in 0..<n.safeLen:
result[i] = freshVars(n[i], c)
proc preprocess(c: var PreprocessContext; n: PNode): PNode =
# in order to fix bug #15243 without risking regressions, we preprocess
# the AST so that 'break' statements inside a 'try finally' also have the
# finally section. We need to duplicate local variables here and also
# detect: 'finally: raises X' which is currently not supported. We produce
# an error for this case for now. All this will be done properly with Yuriy's
# patch.
result = n
case n.kind
of nkTryStmt:
let f = n.lastSon
if f.kind == nkFinally:
c.finallys.add f.lastSon
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
if f.kind == nkFinally:
discard c.finallys.pop()
of nkWhileStmt, nkBlockStmt:
c.blocks.add((n, c.finallys.len))
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
discard c.blocks.pop()
of nkBreakStmt:
if c.blocks.len == 0:
discard
else:
var fin = -1
if n[0].kind == nkEmpty:
fin = c.blocks[^1][1]
elif n[0].kind == nkSym:
for i in countdown(c.blocks.high, 0):
if c.blocks[i][0].kind == nkBlockStmt and c.blocks[i][0][0].kind == nkSym and
c.blocks[i][0][0].sym == n[0].sym:
fin = c.blocks[i][1]
break
if fin >= 0:
result = newNodeI(nkStmtList, n.info)
for i in countdown(c.finallys.high, fin):
var vars = FreshVarsContext(tab: initTable[int, PSym](), config: c.config, info: n.info)
result.add freshVars(preprocess(c, c.finallys[i]), vars)
result.add n
of nkSkip: discard
else:
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
var ctx: Ctx
ctx.g = g
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)
var n = n.toStmtList
var pc = PreprocessContext(finallys: @[], config: g.config)
var n = preprocess(pc, n.toStmtList)
#echo "transformed into ", n
#var n = n.toStmtList
discard ctx.newState(n, nil)
let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1))
@@ -1312,7 +1410,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

@@ -10,9 +10,11 @@
## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
import
options, idents, nimconf, scriptconfig, extccomp, commands, msgs,
options, idents, nimconf, extccomp, commands, msgs,
lineinfos, modulegraphs, condsyms, os, pathutils
from strutils import normalize
type
NimProg* = ref object
suggestMode*: bool
@@ -27,10 +29,7 @@ proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) =
proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
self.processCmdLine(passCmd1, "", conf)
if self.supportsStdinFile and conf.projectName == "-":
conf.projectName = "stdinfile"
conf.projectFull = AbsoluteFile "stdinfile"
conf.projectPath = AbsoluteDir getCurrentDir()
conf.projectIsStdin = true
handleStdinInput(conf)
elif conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, AbsoluteFile conf.projectName)
@@ -44,45 +43,31 @@ proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile getCurrentDir())
proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef): bool =
loadConfigs(DefaultConfig, cache, conf) # load all config files
if self.suggestMode:
conf.command = "nimsuggest"
loadConfigs(DefaultConfig, cache, conf) # load all config files
template runNimScriptIfExists(path: AbsoluteFile) =
let p = path # eval once
if fileExists(p):
runNimScript(cache, p, freshDefines = false, conf)
# Caution: make sure this stays in sync with `loadConfigs`
if optSkipSystemConfigFile notin conf.globalOptions:
runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims))
if optSkipUserConfigFile notin conf.globalOptions:
runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
if optSkipParentConfigFiles notin conf.globalOptions:
for dir in parentDirs(conf.projectPath.string, fromRoot = true, inclusive = false):
runNimScriptIfExists(AbsoluteDir(dir) / DefaultConfigNims)
if optSkipProjConfigFile notin conf.globalOptions:
runNimScriptIfExists(conf.projectPath / DefaultConfigNims)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
if not self.suggestMode:
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
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile)
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard
if conf.command == "":
conf.command = "e"
return false
elif conf.command.normalize == "e":
return false
# 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)
# XXX This is hacky. We need to find a better way.
case conf.command
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
else:
discard
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")

View File

@@ -17,7 +17,9 @@ template bootSwitch(name, expr, userString) =
const name = if expr: " " & userString else: ""
bootSwitch(usedRelease, defined(release), "-d:release")
bootSwitch(usedGnuReadline, defined(useLinenoise), "-d:useLinenoise")
bootSwitch(usedDanger, defined(danger), "-d:danger")
# `useLinenoise` deprecated in favor of `nimUseLinenoise`, kept for backward compatibility
bootSwitch(useLinenoise, defined(nimUseLinenoise) or defined(useLinenoise), "-d:nimUseLinenoise")
bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
@@ -26,9 +28,12 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
import
os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos,
wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos,
pathutils, strtabs
from incremental import nimIncremental
from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect
# but some have deps to imported modules. Yay.
bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
bootSwitch(usedNativeStacktrace,
@@ -47,15 +52,16 @@ const
"Compiled at $4\n" &
"Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
proc genFeatureDesc[T: enum](t: typedesc[T]): string {.compileTime.} =
var x = ""
for f in low(T)..high(T):
if x.len > 0: x.add "|"
x.add $f
x
const
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
FeatureDesc = block:
var x = ""
for f in low(Feature)..high(Feature):
if x.len > 0: x.add "|"
x.add $f
x
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % FeatureDesc
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
proc getCommandLineDesc(conf: ConfigRef): string =
result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,
@@ -96,8 +102,8 @@ proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
when gitHash.len == 40:
msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
msgWriteln(conf, "active boot switches:" & usedRelease &
usedTinyC & usedGnuReadline & usedNativeStacktrace &
msgWriteln(conf, "active boot switches:" & usedRelease & usedDanger &
usedTinyC & useLinenoise & usedNativeStacktrace &
usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
{msgStdout})
msgQuit(0)
@@ -106,7 +112,7 @@ proc writeCommandLineUsage*(conf: ConfigRef) =
msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
proc addPrefix(switch: string): string =
if len(switch) <= 1: result = "-" & switch
if switch.len <= 1: result = "-" & switch
else: result = "--" & switch
const
@@ -123,14 +129,14 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
info: TLineInfo) =
cmd = ""
var i = 0
if i < len(switch) and switch[i] == '-': inc(i)
if i < len(switch) and switch[i] == '-': inc(i)
while i < len(switch):
if i < switch.len and switch[i] == '-': inc(i)
if i < switch.len and switch[i] == '-': inc(i)
while i < switch.len:
case switch[i]
of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': add(cmd, switch[i])
of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': cmd.add(switch[i])
else: break
inc(i)
if i >= len(switch): arg = ""
if i >= switch.len: arg = ""
# cmd:arg => (cmd,arg)
elif switch[i] in {':', '='}: arg = substr(switch, i + 1)
# cmd[sub]:rest => (cmd,[sub]:rest)
@@ -174,17 +180,17 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
var i = 0
var n = hintMin
var isBracket = false
if i < len(arg) and arg[i] == '[':
if i < arg.len and arg[i] == '[':
isBracket = true
inc(i)
while i < len(arg) and (arg[i] notin {':', '=', ']'}):
add(id, arg[i])
while i < arg.len and (arg[i] notin {':', '=', ']'}):
id.add(arg[i])
inc(i)
if isBracket:
if i < len(arg) and arg[i] == ']': inc(i)
if i < arg.len and arg[i] == ']': inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if i < len(arg) and (arg[i] in {':', '='}): inc(i)
if i < arg.len and (arg[i] in {':', '='}): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if state == wHint:
let x = findStr(lineinfos.HintsToStr, id)
@@ -194,17 +200,21 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
let x = findStr(lineinfos.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin))
else: localError(conf, info, "unknown warning: " & id)
case substr(arg, i).normalize
of "on":
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
incl(conf.enableNotes, n)
of "off":
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
incl(conf.disableNotes, n)
excl(conf.foreignPackageNotes, n)
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
let val = substr(arg, i).normalize
if val notin ["on", "off"]:
localError(conf, info, errOnOrOffExpectedButXFound % arg)
elif n notin conf.cmdlineNotes or pass == passCmd1:
if pass == passCmd1: incl(conf.cmdlineNotes, n)
incl(conf.modifiedyNotes, n)
case val
of "on":
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
of "off":
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
proc processCompile(conf: ConfigRef; filename: string) =
var found = findFile(conf, filename)
@@ -215,19 +225,22 @@ const
errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
case switch.normalize
of "gc":
case arg.normalize
of "boehm": result = conf.selectedGC == gcBoehm
of "refc": result = conf.selectedGC == gcRefc
of "v2": result = false
of "boehm": result = conf.selectedGC == gcBoehm
of "refc": result = conf.selectedGC == gcRefc
of "v2": result = false
of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
of "generational": result = false
of "destructors": result = conf.selectedGC == gcDestructors
of "go": result = conf.selectedGC == gcGo
of "none": result = conf.selectedGC == gcNone
of "destructors", "arc": result = conf.selectedGC == gcArc
of "orc": result = conf.selectedGC == gcOrc
of "hooks": result = conf.selectedGC == gcHooks
of "go": result = conf.selectedGC == gcGo
of "none": result = conf.selectedGC == gcNone
of "stack", "regions": result = conf.selectedGC == gcRegions
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
of "opt":
@@ -239,15 +252,22 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
of "verbosity": result = $conf.verbosity == arg
of "app":
case arg.normalize
of "gui": result = contains(conf.globalOptions, optGenGuiApp)
of "console": result = not contains(conf.globalOptions, optGenGuiApp)
of "lib": result = contains(conf.globalOptions, optGenDynLib) and
of "gui": result = contains(conf.globalOptions, optGenGuiApp)
of "console": result = not contains(conf.globalOptions, optGenGuiApp)
of "lib": result = contains(conf.globalOptions, optGenDynLib) and
not contains(conf.globalOptions, optGenGuiApp)
of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
not contains(conf.globalOptions, optGenGuiApp)
else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
of "dynliboverride":
result = isDynlibOverride(conf, arg)
of "exceptions":
case arg.normalize
of "cpp": result = conf.exc == excCpp
of "setjmp": result = conf.exc == excSetjmp
of "quirky": result = conf.exc == excQuirky
of "goto": result = conf.exc == excGoto
else: localError(conf, info, errInvalidExceptionSystem % arg)
else: invalidCmdLineOption(conf, passCmd1, switch, info)
proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool =
@@ -261,8 +281,9 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "hints": result = contains(conf.options, optHints)
of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
of "stacktrace": result = contains(conf.options, optStackTrace)
of "stacktracemsgs": result = contains(conf.options, optStackTraceMsgs)
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
@@ -275,8 +296,10 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "fieldchecks": result = contains(conf.options, optFieldCheck)
of "rangechecks": result = contains(conf.options, optRangeCheck)
of "boundchecks": result = contains(conf.options, optBoundsCheck)
of "refchecks": result = contains(conf.options, optRefCheck)
of "overflowchecks": result = contains(conf.options, optOverflowCheck)
of "movechecks": result = contains(conf.options, optMoveCheck)
of "staticboundchecks": result = contains(conf.options, optStaticBoundsCheck)
of "stylechecks": result = contains(conf.options, optStyleCheck)
of "linedir": result = contains(conf.options, optLineDir)
of "assertions", "a": result = contains(conf.options, optAssert)
of "run", "r": result = contains(conf.globalOptions, optRun)
@@ -354,6 +377,14 @@ proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, in
expectArg(conf, switch, arg, pass, info)
options.inclDynlibOverride(conf, arg)
proc handleStdinInput*(conf: ConfigRef) =
conf.projectName = "stdinfile"
conf.projectFull = conf.projectName.AbsoluteFile
conf.projectPath = AbsoluteDir getCurrentDir()
conf.projectIsStdin = true
if conf.outDir.isEmpty:
conf.outDir = getNimcacheDir(conf)
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf: ConfigRef) =
var
@@ -361,8 +392,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
case switch.normalize
of "path", "p":
expectArg(conf, switch, arg, pass, info)
addPath(conf, if pass == passPP: processCfgPath(conf, arg, info)
else: processPath(conf, arg, info), info)
for path in nimbleSubs(conf, arg):
addPath(conf, if pass == passPP: processCfgPath(conf, path, info)
else: processPath(conf, path, info), info)
of "nimblepath", "babelpath":
# keep the old name for compat
if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
@@ -375,6 +407,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)
@@ -382,26 +417,32 @@ 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
of "docroot":
conf.docRoot = if arg.len == 0: "@default" else: arg
of "mainmodule", "m":
discard "allow for backwards compatibility, but don't do anything"
of "define", "d":
expectArg(conf, switch, arg, pass, info)
if {':', '='} in arg:
splitSwitch(conf, arg, key, val, pass, info)
if cmpIgnoreStyle(key, "nimQuirky") == 0:
conf.exc = excQuirky
defineSymbol(conf.symbols, key, val)
else:
if cmpIgnoreStyle(arg, "nimQuirky") == 0:
conf.exc = excQuirky
defineSymbol(conf.symbols, arg)
of "undef", "u":
expectArg(conf, switch, arg, pass, info)
@@ -432,30 +473,58 @@ 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")
incl conf.globalOptions, optTlsEmulation # Boehm GC doesn't scan the real TLS
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", "arc":
conf.selectedGC = gcArc
if conf.cmd != cmdCompileToCpp:
conf.exc = excGoto
defineSymbol(conf.symbols, "gcdestructors")
defineSymbol(conf.symbols, "gcarc")
incl conf.globalOptions, optSeqDestructors
incl conf.globalOptions, optTinyRtti
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
defineSymbol(conf.symbols, "nimV2")
of "orc":
conf.selectedGC = gcOrc
if conf.cmd != cmdCompileToCpp:
conf.exc = excGoto
defineSymbol(conf.symbols, "gcdestructors")
defineSymbol(conf.symbols, "gcorc")
incl conf.globalOptions, optSeqDestructors
incl conf.globalOptions, optTinyRtti
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
defineSymbol(conf.symbols, "nimV2")
of "hooks":
conf.selectedGC = gcHooks
defineSymbol(conf.symbols, "gchooks")
incl conf.globalOptions, optSeqDestructors
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
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)
@@ -464,28 +533,23 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info)
of "stacktracemsgs": processOnOffSwitch(conf, {optStackTraceMsgs}, arg, pass, info)
of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info)
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")
@@ -508,7 +572,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
undefSymbol(conf.symbols, "useNimRtl")
of "oldnewlines":
case arg.normalize
of "","on":
of "", "on":
conf.oldNewlines = true
defineSymbol(conf.symbols, "nimOldNewlines")
of "off":
@@ -529,14 +593,16 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "fieldchecks": processOnOffSwitch(conf, {optFieldCheck}, arg, pass, info)
of "rangechecks": processOnOffSwitch(conf, {optRangeCheck}, arg, pass, info)
of "boundchecks": processOnOffSwitch(conf, {optBoundsCheck}, arg, pass, info)
of "refchecks": processOnOffSwitch(conf, {optRefCheck}, arg, pass, info)
of "overflowchecks": processOnOffSwitch(conf, {optOverflowCheck}, arg, pass, info)
of "movechecks": processOnOffSwitch(conf, {optMoveCheck}, arg, pass, info)
of "staticboundchecks": processOnOffSwitch(conf, {optStaticBoundsCheck}, arg, pass, info)
of "stylechecks": processOnOffSwitch(conf, {optStyleCheck}, arg, pass, info)
of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
of "deadcodeelim": discard # deprecated, dead code elim always on
of "threads":
processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
#if optThreads in conf.globalOptions: incl(conf.notes, warnGcUnsafe)
#if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
of "implicitstatic":
@@ -609,28 +675,31 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf.implicitIncludes.add findModule(conf, arg, toFullPath(conf, info)).string
of "listcmd":
processOnOffSwitchG(conf, {optListCmd}, arg, pass, info)
of "asm":
processOnOffSwitchG(conf, {optProduceAsm}, arg, pass, info)
of "genmapping":
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 "maxloopiterationsvm":
expectArg(conf, switch, arg, pass, info)
conf.maxLoopIterationsVM = parseInt(arg)
of "errormax":
expectArg(conf, switch, arg, pass, info)
# Note: `nim check` (etc) can overwrite this.
@@ -645,9 +714,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if verbosity notin {0..3}:
localError(conf, info, "invalid verbosity level: '$1'" % arg)
conf.verbosity = verbosity
conf.notes = NotesVerbosity[conf.verbosity]
incl(conf.notes, conf.enableNotes)
excl(conf.notes, conf.disableNotes)
var verb = NotesVerbosity[conf.verbosity]
## We override the default `verb` by explicitly modified (set/unset) notes.
conf.notes = (conf.modifiedyNotes * conf.notes + verb) -
(conf.modifiedyNotes * verb - conf.notes)
conf.mainPackageNotes = conf.notes
of "parallelbuild":
expectArg(conf, switch, arg, pass, info)
@@ -666,7 +736,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
helpOnError(conf, pass)
of "symbolfiles": discard "ignore for backwards compat"
of "incremental":
when not defined(nimIncremental):
when not nimIncremental:
localError(conf, info, "the compiler was not built with " &
"incremental compilation features; bootstrap with " &
"-d:nimIncremental to enable")
@@ -739,10 +809,22 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf.features.incl parseEnum[Feature](arg)
except ValueError:
localError(conf, info, "unknown experimental feature")
of "legacy":
try:
conf.legacyFeatures.incl parseEnum[LegacyFeature](arg)
except ValueError:
localError(conf, info, "unknown obsolete feature")
of "nocppexceptions":
expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optNoCppExceptions)
conf.exc = low(ExceptionSystem)
defineSymbol(conf.symbols, "noCppExceptions")
of "exceptions":
case arg.normalize
of "cpp": conf.exc = excCpp
of "setjmp": conf.exc = excSetjmp
of "quirky": conf.exc = excQuirky
of "goto": conf.exc = excGoto
else: localError(conf, info, errInvalidExceptionSystem % arg)
of "cppdefine":
expectArg(conf, switch, arg, pass, info)
if conf != nil:
@@ -752,14 +834,22 @@ 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")
conf.selectedGC = gcHooks
defineSymbol(conf.symbols, "gchooks")
defineSymbol(conf.symbols, "nimSeqsV2")
defineSymbol(conf.symbols, "nimOwnedEnabled")
of "seqsv2":
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
of "stylecheck":
case arg.normalize
of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint}
of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint} - {optStyleError}
of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
else: localError(conf, info, errOffHintsError % arg)
of "showallmismatches":
@@ -777,13 +867,41 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "expandmacro":
expectArg(conf, switch, arg, pass, info)
conf.macrosToExpand[arg] = "T"
of "":
conf.projectName = "-"
of "oldgensym":
processOnOffSwitchG(conf, {optNimV019}, arg, pass, info)
of "useversion":
expectArg(conf, switch, arg, pass, info)
case arg
of "1.0":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "0")
# always be compatible with 1.0.100:
defineSymbol(conf.symbols, "NimPatch", "100")
# old behaviors go here:
defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
conf.globalOptions.incl optNimV1Emulation
else:
localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
of "benchmarkvm":
processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
of "sinkinference":
processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
of "panics":
processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
if optPanics in conf.globalOptions:
defineSymbol(conf.symbols, "nimPanics")
of "sourcemap":
conf.globalOptions.incl optSourcemap
conf.options.incl optLineDir
# processOnOffSwitchG(conf, {optSourcemap, opt}, arg, pass, info)
of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
handleStdinInput(conf)
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
@@ -806,7 +924,7 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
argsCount: var int; config: ConfigRef): bool =
if argsCount == 0:
# nim filename.nims is the same as "nim e filename.nims":
if p.key.endswith(".nims"):
if p.key.endsWith(".nims"):
config.command = "e"
incl(config.globalOptions, optWasNimscript)
config.projectName = unixToNativePath(p.key)

View File

@@ -10,7 +10,7 @@
# This module handles the conditional symbols.
import
strtabs, platform, strutils, idents
strtabs
from options import Feature
from lineinfos import HintsToStr, WarningsToStr
@@ -48,13 +48,11 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimalias")
defineSymbol("nimlocks")
defineSymbol("nimnode")
defineSymbol("nimnomagic64")
defineSymbol("nimvarargstyped")
defineSymbol("nimtypedescfixed")
defineSymbol("nimKnowsNimvm")
defineSymbol("nimArrIdx")
defineSymbol("nimHasalignOf")
defineSymbol("nimNewShiftOps")
defineSymbol("nimDistros")
defineSymbol("nimHasCppDefine")
defineSymbol("nimGenericInOutFlags")
@@ -86,6 +84,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasSignatureHashInMacro")
defineSymbol("nimHasDefault")
defineSymbol("nimMacrosSizealignof")
defineSymbol("nimNoZeroExtendMagic")
defineSymbol("nimMacrosGetNodeId")
for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f)
@@ -93,3 +93,27 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasWarning" & s)
for s in HintsToStr:
defineSymbol("nimHasHint" & s)
defineSymbol("nimFixedOwned")
defineSymbol("nimHasStyleChecks")
defineSymbol("nimToOpenArrayCString")
defineSymbol("nimHasUsed")
defineSymbol("nimFixedForwardGeneric")
defineSymbol("nimnomagic64")
defineSymbol("nimNewShiftOps")
defineSymbol("nimHasCursor")
defineSymbol("nimHasExceptionsQuery")
defineSymbol("nimHasIsNamedTuple")
defineSymbol("nimHashOrdinalFixed")
when defined(nimHasLibFFI):
# Renaming as we can't conflate input vs output define flags; e.g. this
# will report the right thing regardless of whether user adds
# `-d:nimHasLibFFI` in his user config.
defineSymbol("nimHasLibFFIEnabled")
defineSymbol("nimHasSinkInference")
defineSymbol("nimNewIntegerOps")
defineSymbol("nimHasInvariant")
defineSymbol("nimHasStacktraceMsgs")
defineSymbol("nimHasStacktracesModule")

View File

@@ -1,6 +0,0 @@
## Use the module 'lineinfos' instead!
{.deprecated.}
import lineinfos
export lineinfos

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

@@ -10,8 +10,7 @@
# This module implements a dependency file generator.
import
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
pathutils
options, ast, ropes, idents, passes, modulepaths, pathutils
from modulegraphs import ModuleGraph, PPassContext
@@ -26,7 +25,7 @@ type
dotGraph: Rope
proc addDependencyAux(b: Backend; importing, imported: string) =
addf(b.dotGraph, "$1 -> \"$2\";$n", [rope(importing), rope(imported)])
b.dotGraph.addf("$1 -> \"$2\";$n", [rope(importing), rope(imported)])
# s1 -> s2_4[label="[0-9]"];
proc addDotDependency(c: PPassContext, n: PNode): PNode =
@@ -35,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):
var imported = getModuleName(g.config, n.sons[i])
for i in 0..<n.len:
var imported = getModuleName(g.config, n[i])
addDependencyAux(b, g.module.name.s, imported)
of nkFromStmt, nkImportExceptStmt:
var imported = getModuleName(g.config, n.sons[0])
var imported = getModuleName(g.config, n[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..<n.len: discard addDotDependency(c, n[i])
else:
discard

View File

@@ -29,35 +29,36 @@
## "A GraphFree Approach to DataFlow Analysis" by Markus Mohnen.
## https://link.springer.com/content/pdf/10.1007/3-540-45937-5_6.pdf
import ast, astalgo, types, intsets, tables, msgs, options, lineinfos, renderer
import ast, types, intsets, lineinfos, renderer
from patterns import sameTrees
type
InstrKind* = enum
goto, fork, join, def, use
goto, fork, def, use
Instr* = object
n*: PNode
n*: PNode # contains the def/use location.
case kind*: InstrKind
of def, use: sym*: PSym # 'sym' can also be 'nil' and
# then 'n' contains the def/use location.
# This is used so that we can track object
# and tuple field accesses precisely.
of goto, fork, join: dest*: int
of goto, fork: dest*: int
else: discard
ControlFlowGraph* = seq[Instr]
TPosition = distinct int
TBlock = object
label: PSym
fixups: seq[TPosition]
case isTryBlock: bool
of false:
label: PSym
breakFixups: seq[(TPosition, seq[PNode])] #Contains the gotos for the breaks along with their pending finales
of true:
finale: PNode
raiseFixups: seq[TPosition] #Contains the gotos for the raises
Con = object
code: ControlFlowGraph
inCall, inTryStmt: int
blocks: seq[TBlock]
tryStmtFixups: seq[TPosition]
forks: seq[TPosition]
owner: PSym
proc debugInfo(info: TLineInfo): string =
@@ -69,7 +70,7 @@ proc codeListing(c: ControlFlowGraph, result: var string, start=0; last = -1) =
var jumpTargets = initIntSet()
let last = if last < 0: c.len-1 else: min(last, c.len-1)
for i in start..last:
if c[i].kind in {goto, fork, join}:
if c[i].kind in {goto, fork}:
jumpTargets.incl(i+c[i].dest)
var i = start
while i <= last:
@@ -80,7 +81,7 @@ proc codeListing(c: ControlFlowGraph, result: var string, start=0; last = -1) =
case c[i].kind
of def, use:
result.add renderTree(c[i].n)
of goto, fork, join:
of goto, fork:
result.add "L"
result.addInt c[i].dest+i
result.add("\t#")
@@ -94,13 +95,11 @@ proc echoCfg*(c: ControlFlowGraph; start=0; last = -1) {.deprecated.} =
## echos the ControlFlowGraph for debugging purposes.
var buf = ""
codeListing(c, buf, start, last)
when declared(echo):
echo buf
echo buf
proc forkI(c: var Con; n: PNode): TPosition =
result = TPosition(c.code.len)
c.code.add Instr(n: n, kind: fork, dest: 0)
c.forks.add result
proc gotoI(c: var Con; n: PNode): TPosition =
result = TPosition(c.code.len)
@@ -108,6 +107,24 @@ proc gotoI(c: var Con; n: PNode): TPosition =
#[
Join is no more
===============
Instead of generating join instructions we adapt our traversal of the CFG.
When encountering a fork we split into two paths, we follow the path
starting at "pc + 1" until it encounters the joinpoint: "pc + forkInstr.dest".
If we encounter gotos that would jump further than the current joinpoint,
as can happen with gotos generated by unstructured controlflow such as break, raise or return,
we simply suspend following the current path, and follow the other path until the new joinpoint
which is simply the instruction pointer returned to us by the now suspended path.
If the path we are following now, also encounters a goto that exceeds the joinpoint
we repeat the process; suspending the current path and evaluating the other one with a new joinpoint.
If we eventually reach a common joinpoint we join the two paths.
This new "ping-pong" approach has the obvious advantage of not requiring join instructions, as such
cutting down on the CFG size but is also mandatory for correctly handling complicated cases
of unstructured controlflow.
Design of join
==============
@@ -119,10 +136,10 @@ use(x)
Generates:
L0: fork L1
L0: fork lab1
join L0 # patched.
goto Louter
L1:
lab1:
def x
join L0
Louter:
@@ -256,33 +273,38 @@ duplicate the 'join' instructions on breaks and return exits!
]#
proc joinI(c: var Con; fromFork: TPosition; n: PNode) =
let dist = fromFork.int - c.code.len
c.code.add Instr(n: n, kind: join, dest: dist)
proc genLabel(c: Con): TPosition =
result = TPosition(c.code.len)
proc jmpBack(c: var Con, n: PNode, p = TPosition(0)) =
let dist = p.int - c.code.len
doAssert(-0x7fff < dist and dist < 0x7fff)
doAssert(low(int) div 2 + 1 < dist and dist < high(int) div 2)
c.code.add Instr(n: n, kind: goto, dest: dist)
proc patch(c: var Con, p: TPosition) =
# patch with current index
let p = p.int
let diff = c.code.len - p
doAssert(-0x7fff < diff and diff < 0x7fff)
doAssert(low(int) div 2 + 1 < diff and diff < high(int) div 2)
c.code[p].dest = diff
proc gen(c: var Con; n: PNode) # {.noSideEffect.}
proc popBlock(c: var Con; oldLen: int) =
for f in c.blocks[oldLen].fixups:
c.patch(f)
var exits: seq[TPosition]
exits.add c.gotoI(newNode(nkEmpty))
for f in c.blocks[oldLen].breakFixups:
c.patch(f[0])
for finale in f[1]:
c.gen(finale)
exits.add c.gotoI(newNode(nkEmpty))
for e in exits:
c.patch e
c.blocks.setLen(oldLen)
template withBlock(labl: PSym; body: untyped) {.dirty.} =
var oldLen {.gensym.} = c.blocks.len
c.blocks.add TBlock(label: labl, fixups: @[])
c.blocks.add TBlock(isTryBlock: false, label: labl)
body
popBlock(c, oldLen)
@@ -290,8 +312,6 @@ proc isTrue(n: PNode): bool =
n.kind == nkSym and n.sym.kind == skEnumField and n.sym.position != 0 or
n.kind == nkIntLit and n.intVal != 0
proc gen(c: var Con; n: PNode) # {.noSideEffect.}
when true:
proc genWhile(c: var Con; n: PNode) =
# We unroll every loop 3 times. We emulate 0, 1, 2 iterations
@@ -303,12 +323,13 @@ when true:
Becomes:
if cond:
body
block:
if cond:
body
if cond:
body
if cond:
body
We still need to ensure 'break' resolves properly, so an AST to AST
translation is impossible.
@@ -331,76 +352,48 @@ when true:
L4:
join F1
]#
if isTrue(n.sons[0]):
if isTrue(n[0]):
# 'while true' is an idiom in Nim and so we produce
# better code for it:
for i in 0..2:
withBlock(nil):
c.gen(n.sons[1])
withBlock(nil):
for i in 0..2:
c.gen(n[1])
else:
let oldForksLen = c.forks.len
var endings: array[3, TPosition]
for i in 0..2:
withBlock(nil):
c.gen(n.sons[0])
withBlock(nil):
var endings: array[3, TPosition]
for i in 0..2:
c.gen(n[0])
endings[i] = c.forkI(n)
c.gen(n.sons[1])
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
c.joinI(c.forks.pop(), n)
doAssert(c.forks.len == oldForksLen)
c.gen(n[1])
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
else:
proc genWhile(c: var Con; n: PNode) =
# L1:
# lab1:
# cond, tmp
# fork tmp, L2
# fork tmp, lab2
# body
# jmp L1
# L2:
let oldForksLen = c.forks.len
let L1 = c.genLabel
# jmp lab1
# lab2:
let lab1 = c.genLabel
withBlock(nil):
if isTrue(n.sons[0]):
c.gen(n.sons[1])
c.jmpBack(n, L1)
if isTrue(n[0]):
c.gen(n[1])
c.jmpBack(n, lab1)
else:
c.gen(n.sons[0])
let L2 = c.forkI(n)
c.gen(n.sons[1])
c.jmpBack(n, L1)
c.patch(L2)
setLen(c.forks, oldForksLen)
proc genBlock(c: var Con; n: PNode) =
withBlock(n.sons[0].sym):
c.gen(n.sons[1])
proc genJoins(c: var Con; n: PNode) =
for i in countdown(c.forks.high, 0): joinI(c, c.forks[i], n)
proc genBreak(c: var Con; n: PNode) =
genJoins(c, n)
let L1 = c.gotoI(n)
if n.sons[0].kind == nkSym:
#echo cast[int](n.sons[0].sym)
for i in countdown(c.blocks.len-1, 0):
if c.blocks[i].label == n.sons[0].sym:
c.blocks[i].fixups.add L1
return
#globalError(n.info, "VM problem: cannot find 'break' target")
else:
c.blocks[c.blocks.high].fixups.add L1
c.gen(n[0])
let lab2 = c.forkI(n)
c.gen(n[1])
c.jmpBack(n, lab1)
c.patch(lab2)
template forkT(n, body) =
let oldLen = c.forks.len
let L1 = c.forkI(n)
let lab1 = c.forkI(n)
body
c.patch(L1)
c.joinI(L1, n)
setLen(c.forks, oldLen)
c.patch(lab1)
proc genIf(c: var Con, n: PNode) =
#[
@@ -415,15 +408,15 @@ proc genIf(c: var Con, n: PNode) =
D
cond
fork L1
fork lab1
A
goto Lend
L1:
lab1:
condB
fork L2
fork lab2
B
goto Lend2
L2:
lab2:
condC
fork L3
C
@@ -439,53 +432,49 @@ proc genIf(c: var Con, n: PNode) =
join F1
]#
let oldLen = c.forks.len
var endings: seq[TPosition] = @[]
for i in 0 ..< len(n):
var it = n.sons[i]
c.gen(it.sons[0])
for i in 0..<n.len:
var it = n[i]
c.gen(it[0])
if it.len == 2:
let elsePos = forkI(c, it[1])
c.gen(it.sons[1])
endings.add(c.gotoI(it.sons[1]))
c.gen(it[1])
endings.add(c.gotoI(it[1]))
c.patch(elsePos)
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
c.joinI(c.forks.pop(), n)
doAssert(c.forks.len == oldLen)
proc genAndOr(c: var Con; n: PNode) =
# asgn dest, a
# fork L1
# fork lab1
# asgn dest, b
# L1:
# lab1:
# join F1
c.gen(n.sons[1])
c.gen(n[1])
forkT(n):
c.gen(n.sons[2])
c.gen(n[2])
proc genCase(c: var Con; n: PNode) =
# if (!expr1) goto L1;
# if (!expr1) goto lab1;
# thenPart
# goto LEnd
# L1:
# if (!expr2) goto L2;
# lab1:
# if (!expr2) goto lab2;
# thenPart2
# goto LEnd
# L2:
# lab2:
# elsePart
# Lend:
let isExhaustive = skipTypes(n.sons[0].typ,
let isExhaustive = skipTypes(n[0].typ,
abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString}
var endings: seq[TPosition] = @[]
let oldLen = c.forks.len
c.gen(n.sons[0])
for i in 1 ..< n.len:
let it = n.sons[i]
c.gen(n[0])
for i in 1..<n.len:
let it = n[i]
if it.len == 1:
c.gen(it.sons[0])
c.gen(it[0])
elif i == n.len-1 and isExhaustive:
# treat the last branch as 'else' if this is an exhaustive case statement.
c.gen(it.lastSon)
@@ -497,33 +486,58 @@ proc genCase(c: var Con; n: PNode) =
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
c.joinI(c.forks.pop(), n)
doAssert(c.forks.len == oldLen)
proc genBlock(c: var Con; n: PNode) =
withBlock(n[0].sym):
c.gen(n[1])
proc genBreakOrRaiseAux(c: var Con, i: int, n: PNode) =
let lab1 = c.gotoI(n)
if c.blocks[i].isTryBlock:
c.blocks[i].raiseFixups.add lab1
else:
var trailingFinales: seq[PNode]
if c.inTryStmt > 0: #Ok, we are in a try, lets see which (if any) try's we break out from:
for b in countdown(c.blocks.high, i):
if c.blocks[b].isTryBlock:
trailingFinales.add c.blocks[b].finale
c.blocks[i].breakFixups.add (lab1, trailingFinales)
proc genBreak(c: var Con; n: PNode) =
if n[0].kind == nkSym:
#echo cast[int](n[0].sym)
for i in countdown(c.blocks.high, 0):
if not c.blocks[i].isTryBlock and c.blocks[i].label == n[0].sym:
genBreakOrRaiseAux(c, i, n)
return
#globalError(n.info, "VM problem: cannot find 'break' target")
else:
for i in countdown(c.blocks.high, 0):
if not c.blocks[i].isTryBlock:
genBreakOrRaiseAux(c, i, n)
return
proc genTry(c: var Con; n: PNode) =
let oldLen = c.forks.len
var endings: seq[TPosition] = @[]
let oldLen = c.blocks.len
c.blocks.add TBlock(isTryBlock: true, finale: if n[^1].kind == nkFinally: n[^1] else: newNode(nkEmpty))
inc c.inTryStmt
let oldFixups = c.tryStmtFixups.len
#let elsePos = c.forkI(n)
c.gen(n.sons[0])
c.gen(n[0])
dec c.inTryStmt
for i in oldFixups..c.tryStmtFixups.high:
let f = c.tryStmtFixups[i]
c.patch(f)
# we also need to produce join instructions
# for the 'fork' that might preceed the goto instruction
if f.int-1 >= 0 and c.code[f.int-1].kind == fork:
c.joinI(TPosition(f.int-1), n)
setLen(c.tryStmtFixups, oldFixups)
for f in c.blocks[oldLen].raiseFixups:
c.patch(f)
c.blocks.setLen oldLen
#c.patch(elsePos)
for i in 1 ..< n.len:
let it = n.sons[i]
for i in 1..<n.len:
let it = n[i]
if it.kind != nkFinally:
var blen = len(it)
let endExcept = c.forkI(it)
c.gen(it.lastSon)
endings.add(c.gotoI(it))
@@ -531,39 +545,39 @@ proc genTry(c: var Con; n: PNode) =
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
c.joinI(c.forks.pop(), n)
# join the 'elsePos' forkI instruction:
#c.joinI(c.forks.pop(), n)
#c.joinI(c.blocks[^1].forks.pop(), n)
let fin = lastSon(n)
if fin.kind == nkFinally:
c.gen(fin.sons[0])
doAssert(c.forks.len == oldLen)
c.gen(fin[0])
template genNoReturn(c: var Con; n: PNode) =
# leave the graph
c.code.add Instr(n: n, kind: goto, dest: high(int) - c.code.len)
proc genRaise(c: var Con; n: PNode) =
genJoins(c, n)
gen(c, n.sons[0])
gen(c, n[0])
if c.inTryStmt > 0:
c.tryStmtFixups.add c.gotoI(n)
for i in countdown(c.blocks.high, 0):
if c.blocks[i].isTryBlock:
genBreakOrRaiseAux(c, i, n)
return
assert false #Unreachable
else:
genNoReturn(c, n)
proc genImplicitReturn(c: var Con) =
if c.owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter} and resultPos < c.owner.ast.len:
gen(c, c.owner.ast.sons[resultPos])
gen(c, c.owner.ast[resultPos])
proc genReturn(c: var Con; n: PNode) =
genJoins(c, n)
if n.sons[0].kind != nkEmpty:
gen(c, n.sons[0])
if n[0].kind != nkEmpty:
gen(c, n[0])
else:
genImplicitReturn(c)
genNoReturn(c, n)
genBreakOrRaiseAux(c, 0, n)
const
InterestingSyms = {skVar, skResult, skLet, skParam, skForVar, skTemp}
@@ -573,16 +587,6 @@ const
nkObjDownConv, nkObjUpConv}
PathKinds1 = {nkHiddenStdConv, nkHiddenSubConv}
proc getRoot(n: PNode): PNode =
result = n
while true:
case result.kind
of PathKinds0:
result = result[0]
of PathKinds1:
result = result[1]
else: break
proc skipConvDfa*(n: PNode): PNode =
result = n
while true:
@@ -594,64 +598,72 @@ proc skipConvDfa*(n: PNode): PNode =
else: break
proc genUse(c: var Con; orig: PNode) =
let n = dfa.getRoot(orig)
var n = orig
while true:
case n.kind
of PathKinds0 - {nkBracketExpr}:
n = n[0]
of nkBracketExpr:
gen(c, n[1])
n = n[0]
of PathKinds1:
n = n[1]
else: break
if n.kind in nkCallKinds:
gen(c, n)
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: orig, kind: use, sym: if orig != n: nil else: n.sym)
c.code.add Instr(n: orig, kind: use)
proc aliases(obj, field: PNode): bool =
proc aliases*(obj, field: PNode): bool =
var n = field
var obj = obj
while obj.kind in {nkHiddenSubConv, nkHiddenStdConv, nkObjDownConv, nkObjUpConv}:
while obj.kind in {nkHiddenSubConv, nkHiddenStdConv, nkObjDownConv, nkObjUpConv,
nkAddr, nkHiddenAddr, nkDerefExpr, nkHiddenDeref}:
obj = obj[0]
while true:
if sameTrees(obj, n): return true
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenDeref, nkDerefExpr:
of PathKinds0, PathKinds1:
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
proc instrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind in {def, use}
if ins.sym != nil and loc.kind == nkSym:
result = ins.sym == loc.sym
else:
result = ins.n == loc or sameTrees(ins.n, loc)
if not result:
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
result = aliases(ins.n, loc) or aliases(loc, ins.n)
proc useInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == use
result = sameTrees(ins.n, loc) or
ins.n.aliases(loc) or loc.aliases(ins.n)
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
proc defInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == def
result = sameTrees(ins.n, loc) or ins.n.aliases(loc)
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
var n = orig
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv:
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr:
n = n[0]
of nkBracketExpr:
# in a[i] the 'i' must be known
if n.len > 1 and n[1].kind in {nkCharLit..nkUInt64Lit}:
n = n[0]
else:
return false
of nkHiddenDeref, nkDerefExpr:
# We "own" sinkparam[].loc but not ourVar[].location as it is a nasty
# pointer indirection.
# bug #14159, we cannot reason about sinkParam[].location as it can
# still be shared for tyRef.
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, tyVar})
of nkBracketExpr:
let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
n = x
else:
break
return n.kind == nkSym and n.sym.owner == owner and (
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
else:
break
# XXX Allow closure deref operations here if we know
@@ -671,18 +683,29 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
# lower level C++ optimizer to specialize this code.
proc genDef(c: var Con; n: PNode) =
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: n, kind: def, sym: n.sym)
elif isAnalysableFieldAccess(n, c.owner):
c.code.add Instr(n: n, kind: def, sym: nil)
var m = n
# XXX do something about this duplicated logic here.
while true:
case m.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr:
m = m[0]
of nkBracketExpr:
gen(c, m[1])
m = m[0]
of nkHiddenDeref, nkDerefExpr:
m = m[0]
else:
break
proc canRaise(fn: PNode): bool =
const magicsThatCanRaise = {
mNone, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst}
if fn.kind == nkSym and fn.sym.magic notin magicsThatCanRaise:
result = false
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: n, kind: def)
elif isAnalysableFieldAccess(n, c.owner):
c.code.add Instr(n: n, kind: def)
else:
result = true
# bug #13314: An assignment to t5.w = -5 is a usage of 't5'
# we still need to gather the use information:
gen(c, n)
proc genCall(c: var Con; n: PNode) =
gen(c, n[0])
@@ -692,22 +715,24 @@ proc genCall(c: var Con; n: PNode) =
for i in 1..<n.len:
gen(c, n[i])
when false:
if t != nil and i < t.len and t.sons[i].kind == tyVar:
if t != nil and i < t.len and t[i].kind == tyVar:
# This is wrong! Pass by var is a 'might def', not a 'must def'
# like the other defs we emit. This is not good enough for a move
# optimizer.
genDef(c, n[i])
# every call can potentially raise:
if c.inTryStmt > 0 and canRaise(n[0]):
if c.inTryStmt > 0 and canRaiseConservative(n[0]):
# we generate the instruction sequence:
# fork L1
# fork lab1
# goto exceptionHandler (except or finally)
# L1:
# lab1:
# join F1
let endGoto = c.forkI(n)
c.tryStmtFixups.add c.gotoI(n)
for i in countdown(c.blocks.high, 0):
if c.blocks[i].isTryBlock:
genBreakOrRaiseAux(c, i, n)
break
c.patch(endGoto)
c.joinI(c.forks.pop(), n)
dec c.inCall
proc genMagic(c: var Con; n: PNode; m: TMagic) =
@@ -725,23 +750,23 @@ proc genVarSection(c: var Con; n: PNode) =
discard
elif a.kind == nkVarTuple:
gen(c, a.lastSon)
for i in 0 .. a.len-3: genDef(c, a[i])
for i in 0..<a.len-2: genDef(c, a[i])
else:
gen(c, a.lastSon)
if a.lastSon.kind != nkEmpty:
genDef(c, a.sons[0])
genDef(c, a[0])
proc gen(c: var Con; n: PNode) =
case n.kind
of nkSym: genUse(c, n)
of nkCallKinds:
if n.sons[0].kind == nkSym:
let s = n.sons[0].sym
if n[0].kind == nkSym:
let s = n[0].sym
if s.magic != mNone:
genMagic(c, n, s.magic)
else:
genCall(c, n)
if sfNoReturn in n.sons[0].sym.flags:
if sfNoReturn in n[0].sym.flags:
genNoReturn(c, n)
else:
genCall(c, n)
@@ -757,7 +782,7 @@ proc gen(c: var Con; n: PNode) =
of nkIfStmt, nkIfExpr: genIf(c, n)
of nkWhenStmt:
# This is "when nimvm" node. Chose the first branch.
gen(c, n.sons[0].sons[1])
gen(c, n[0][1])
of nkCaseStmt: genCase(c, n)
of nkWhileStmt: genWhile(c, n)
of nkBlockExpr, nkBlockStmt: genBlock(c, n)
@@ -766,13 +791,13 @@ proc gen(c: var Con; n: PNode) =
of nkBreakStmt: genBreak(c, n)
of nkTryStmt, nkHiddenTryStmt: genTry(c, n)
of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange,
nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr:
nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr, nkYieldStmt:
for x in n: gen(c, x)
of nkPragmaBlock: gen(c, n.lastSon)
of nkDiscardStmt, nkObjDownConv, nkObjUpConv: gen(c, n.sons[0])
of nkDiscardStmt, nkObjDownConv, nkObjUpConv: gen(c, n[0])
of nkConv, nkExprColonExpr, nkExprEqExpr, nkCast, nkHiddenSubConv, nkHiddenStdConv:
gen(c, n.sons[1])
of nkStringToCString, nkCStringToString: gen(c, n.sons[0])
gen(c, n[1])
of nkStringToCString, nkCStringToString: gen(c, n[0])
of nkVarSection, nkLetSection: genVarSection(c, n)
of nkDefer:
doAssert false, "dfa construction pass requires the elimination of 'defer'"
@@ -781,6 +806,7 @@ proc gen(c: var Con; n: PNode) =
proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
## constructs a control flow graph for ``body``.
var c = Con(code: @[], blocks: @[], owner: s)
gen(c, body)
genImplicitReturn(c)
withBlock(s):
gen(c, body)
genImplicitReturn(c)
shallowCopy(result, c.code)

View File

@@ -15,17 +15,19 @@ import
ast, strutils, strtabs, options, msgs, os, ropes, idents,
wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast,
packages/docutils/rst, packages/docutils/rstgen,
packages/docutils/highlite, json, xmltree, cgi, trees, types,
typesrenderer, astalgo, modulepaths, lineinfos, sequtils, intsets,
json, xmltree, cgi, trees, types,
typesrenderer, astalgo, lineinfos, intsets,
pathutils, trees
const
exportSection = skField
htmldocsDir = RelativeDir"htmldocs"
type
TSections = array[TSymKind, Rope]
TDocumentor = object of rstgen.RstGenerator
modDesc: Rope # module description
module: PSym
modDeprecationMsg: Rope
toc, section: TSections
indexValFilename: string
@@ -42,20 +44,68 @@ type
destFile*: AbsoluteFile
thisDir*: AbsoluteDir
examples: string
wroteCss*: bool
PDoc* = ref TDocumentor ## Alias to type less.
proc nativeToUnix(path: string): string =
doAssert not path.isAbsolute # absolute files need more care for the drive
when DirSep == '\\':
result = replace(path, '\\', '/')
else: result = path
proc docOutDir(conf: ConfigRef, subdir: RelativeDir = RelativeDir""): AbsoluteDir =
if not conf.outDir.isEmpty: conf.outDir else: conf.projectPath / subdir
proc presentationPath*(conf: ConfigRef, file: AbsoluteFile, isTitle = false): RelativeFile =
## returns a relative file that will be appended to outDir
let file2 = $file
template bail() =
result = relativeTo(file, conf.projectPath)
proc nimbleDir(): AbsoluteDir =
getNimbleFile(conf, file2).parentDir.AbsoluteDir
case conf.docRoot:
of "@default": # using `@` instead of `$` to avoid shell quoting complications
result = getRelativePathFromConfigPath(conf, file)
let dir = nimbleDir()
if not dir.isEmpty:
let result2 = relativeTo(file, dir)
if not result2.isEmpty and (result.isEmpty or result2.string.len < result.string.len):
result = result2
if result.isEmpty: bail()
of "@pkg":
let dir = nimbleDir()
if dir.isEmpty: bail()
else: result = relativeTo(file, dir)
of "@path":
result = getRelativePathFromConfigPath(conf, file)
if result.isEmpty: bail()
elif conf.docRoot.len > 0:
doAssert conf.docRoot.isAbsolute, conf.docRoot # or globalError
doAssert conf.docRoot.existsDir, conf.docRoot
result = relativeTo(file, conf.docRoot.AbsoluteDir)
else:
bail()
if isAbsolute(result.string):
result = file.string.splitPath()[1].RelativeFile
if isTitle:
result = result.string.nativeToUnix.RelativeFile
else:
result = result.string.replace("..", "@@").RelativeFile ## refs #13223
doAssert not result.isEmpty
doAssert not isAbsolute(result.string)
proc whichType(d: PDoc; n: PNode): PSym =
if n.kind == nkSym:
if d.types.strTableContains(n.sym):
result = n.sym
else:
for i in 0..<safeLen(n):
for i in 0..<n.safeLen:
let x = whichType(d, n[i])
if x != nil: return x
proc attachToType(d: PDoc; p: PSym): PSym =
let params = p.ast.sons[paramsPos]
let params = p.ast[paramsPos]
template check(i) =
result = whichType(d, params[i])
if result != nil: return result
@@ -68,7 +118,7 @@ proc attachToType(d: PDoc; p: PSym): PSym =
template declareClosures =
proc compilerMsgHandler(filename: string, line, col: int,
msgKind: rst.MsgKind, arg: string) {.procvar, gcsafe.} =
msgKind: rst.MsgKind, arg: string) {.gcsafe.} =
# translate msg kind:
var k: TMsgKind
case msgKind
@@ -85,7 +135,7 @@ template declareClosures =
{.gcsafe.}:
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
proc docgenFindFile(s: string): string {.procvar, gcsafe.} =
proc docgenFindFile(s: string): string {.gcsafe.} =
result = options.findFile(conf, s).string
if result.len == 0:
result = getCurrentDir() / s
@@ -102,12 +152,11 @@ proc parseRst(text, filename: string,
proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
ext: string, dir: RelativeDir; guessTarget: bool): AbsoluteFile =
if optWholeProject in conf.globalOptions:
let d = if conf.outDir.isEmpty: conf.projectPath / dir else: conf.outDir
let d = conf.docOutDir(dir)
createDir(d)
result = d / changeFileExt(filename, ext)
elif guessTarget:
let d = if not conf.outDir.isEmpty: conf.outDir
else: conf.projectPath
let d = conf.docOutDir
createDir(d)
result = d / changeFileExt(filename, ext)
elif not conf.outFile.isEmpty:
@@ -115,9 +164,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),
@@ -146,10 +196,10 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
initStrTable result.types
result.onTestSnippet =
proc (gen: var RstGenerator; filename, cmd: string; status: int; content: string) =
inc(gen.id)
var d = TDocumentor(gen)
var outp: AbsoluteFile
if filename.len == 0:
inc(d.id)
let nameOnly = splitFile(d.filename).name
outp = getNimcacheDir(conf) / RelativeDir(nameOnly) /
RelativeFile(nameOnly & "_snippet_" & $d.id & ".nim")
@@ -171,16 +221,16 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
if execShellCmd(c2) != status:
rawMessage(conf, errGenerated, "executing of external program failed: " & c2)
result.emitted = initIntSet()
result.destFile = getOutFile2(conf, relativeTo(filename, conf.projectPath),
outExt, RelativeDir"htmldocs", false)
result.destFile = getOutFile2(conf, presentationPath(conf, filename),
outExt, htmldocsDir, false)
result.thisDir = result.destFile.splitFile.dir
template dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
if conf.cmd != cmdRst2tex: addf(dest, xml, args)
else: addf(dest, tex, args)
if conf.cmd != cmdRst2tex: dest.addf(xml, args)
else: dest.addf(tex, args)
proc getVarIdx(varnames: openArray[string], id: string): int =
for i in 0 .. high(varnames):
for i in 0..high(varnames):
if cmpIgnoreStyle(varnames[i], id) == 0:
return i
result = -1
@@ -189,44 +239,43 @@ proc ropeFormatNamedVars(conf: ConfigRef; frmt: FormatStr,
varnames: openArray[string],
varvalues: openArray[Rope]): Rope =
var i = 0
var L = len(frmt)
result = nil
var num = 0
while i < L:
while i < frmt.len:
if frmt[i] == '$':
inc(i) # skip '$'
case frmt[i]
of '#':
add(result, varvalues[num])
result.add(varvalues[num])
inc(num)
inc(i)
of '$':
add(result, "$")
result.add("$")
inc(i)
of '0'..'9':
var j = 0
while true:
j = (j * 10) + ord(frmt[i]) - ord('0')
inc(i)
if (i > L + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
if (i > frmt.len + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
if j > high(varvalues) + 1:
rawMessage(conf, errGenerated, "Invalid format string; too many $s: " & frmt)
num = j
add(result, varvalues[j - 1])
result.add(varvalues[j - 1])
of 'A'..'Z', 'a'..'z', '\x80'..'\xFF':
var id = ""
while true:
add(id, frmt[i])
id.add(frmt[i])
inc(i)
if not (frmt[i] in {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}): break
var idx = getVarIdx(varnames, id)
if idx >= 0: add(result, varvalues[idx])
if idx >= 0: result.add(varvalues[idx])
else: rawMessage(conf, errGenerated, "unknown substition variable: " & id)
of '{':
var id = ""
inc(i)
while i < frmt.len and frmt[i] != '}':
add(id, frmt[i])
id.add(frmt[i])
inc(i)
if i >= frmt.len:
rawMessage(conf, errGenerated, "expected closing '}'")
@@ -234,15 +283,15 @@ proc ropeFormatNamedVars(conf: ConfigRef; frmt: FormatStr,
inc(i) # skip }
# search for the variable:
let idx = getVarIdx(varnames, id)
if idx >= 0: add(result, varvalues[idx])
if idx >= 0: result.add(varvalues[idx])
else: rawMessage(conf, errGenerated, "unknown substition variable: " & id)
else:
add(result, "$")
result.add("$")
var start = i
while i < L:
while i < frmt.len:
if frmt[i] != '$': inc(i)
else: break
if i - 1 >= start: add(result, substr(frmt, start, i - 1))
if i - 1 >= start: result.add(substr(frmt, start, i - 1))
proc genComment(d: PDoc, n: PNode): string =
result = ""
@@ -259,8 +308,8 @@ proc genRecCommentAux(d: PDoc, n: PNode): Rope =
if n.kind in {nkStmtList, nkStmtListExpr, nkTypeDef, nkConstDef,
nkObjectTy, nkRefTy, nkPtrTy, nkAsgn, nkFastAsgn, nkHiddenStdConv}:
# notin {nkEmpty..nkNilLit, nkEnumTy, nkTupleTy}:
for i in 0 ..< len(n):
result = genRecCommentAux(d, n.sons[i])
for i in 0..<n.len:
result = genRecCommentAux(d, n[i])
if result != nil: return
else:
when defined(nimNoNilSeqs): n.comment = ""
@@ -287,19 +336,18 @@ proc getPlainDocstring(n: PNode): string =
if startsWith(n.comment, "##"):
result = n.comment
if result.len < 1:
for i in 0 ..< safeLen(n):
result = getPlainDocstring(n.sons[i])
for i in 0..<n.safeLen:
result = getPlainDocstring(n[i])
if result.len > 0: return
proc belongsToPackage(conf: ConfigRef; module: PSym): bool =
result = module.kind == skModule and module.owner != nil and
module.owner.id == conf.mainPackageId
result = module.kind == skModule and module.getnimblePkgId == conf.mainPackageId
proc externalDep(d: PDoc; module: PSym): string =
if optWholeProject in d.conf.globalOptions:
if optWholeProject in d.conf.globalOptions or d.conf.docRoot.len > 0:
let full = AbsoluteFile toFullPath(d.conf, FileIndex module.position)
let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath), HtmlExt,
RelativeDir"htmldocs", sfMainModule notin module.flags)
let tmp = getOutFile2(d.conf, presentationPath(d.conf, full), HtmlExt,
htmldocsDir, sfMainModule notin module.flags)
result = relativeTo(tmp, d.thisDir, '/').string
else:
result = extractFilename toFullPath(d.conf, FileIndex module.position)
@@ -358,7 +406,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
dispA(d.conf, result, "<span class=\"Identifier\">$1</span>",
"\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
of tkSpaces, tkInvalid:
add(result, literal)
result.add(literal)
of tkCurlyDotLe:
dispA(d.conf, result, "<span>" & # This span is required for the JS to work properly
"""<span class="Other">{</span><span class="Other pragmadots">...</span><span class="Other">}</span>
@@ -406,6 +454,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 +464,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 +473,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
@@ -462,7 +513,7 @@ proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
nodeToHighlightedHtml(d, b, dest, {}, nil)
dest.add(d.config.getOrDefault"doc.listing_end" % id)
else: discard
for i in 0 ..< n.safeLen:
for i in 0..<n.safeLen:
getAllRunnableExamplesRec(d, n[i], orig, dest)
proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
@@ -471,8 +522,8 @@ proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
proc isVisible(d: PDoc; n: PNode): bool =
result = false
if n.kind == nkPostfix:
if n.len == 2 and n.sons[0].kind == nkIdent:
var v = n.sons[0].ident
if n.len == 2 and n[0].kind == nkIdent:
var v = n[0].ident
result = v.id == ord(wStar) or v.id == ord(wMinus)
elif n.kind == nkSym:
# we cannot generate code for forwarded symbols here as we have no
@@ -485,12 +536,12 @@ proc isVisible(d: PDoc; n: PNode): bool =
if result and containsOrIncl(d.emitted, n.sym.id):
result = false
elif n.kind == nkPragmaExpr:
result = isVisible(d, n.sons[0])
result = isVisible(d, n[0])
proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
case n.kind
of nkPostfix: result = getName(d, n.sons[1], splitAfter)
of nkPragmaExpr: result = getName(d, n.sons[0], splitAfter)
of nkPostfix: result = getName(d, n[1], splitAfter)
of nkPragmaExpr: result = getName(d, n[0], splitAfter)
of nkSym: result = esc(d.target, n.sym.renderDefinitionName, splitAfter)
of nkIdent: result = esc(d.target, n.ident.s, splitAfter)
of nkAccQuoted:
@@ -504,8 +555,8 @@ proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
case n.kind
of nkPostfix: result = getNameIdent(cache, n.sons[1])
of nkPragmaExpr: result = getNameIdent(cache, n.sons[0])
of nkPostfix: result = getNameIdent(cache, n[1])
of nkPragmaExpr: result = getNameIdent(cache, n[0])
of nkSym: result = n.sym.name
of nkIdent: result = n.ident
of nkAccQuoted:
@@ -519,13 +570,13 @@ proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
proc getRstName(n: PNode): PRstNode =
case n.kind
of nkPostfix: result = getRstName(n.sons[1])
of nkPragmaExpr: result = getRstName(n.sons[0])
of nkPostfix: result = getRstName(n[1])
of nkPragmaExpr: result = getRstName(n[0])
of nkSym: result = newRstNode(rnLeaf, n.sym.renderDefinitionName)
of nkIdent: result = newRstNode(rnLeaf, n.ident.s)
of nkAccQuoted:
result = getRstName(n.sons[0])
for i in 1 ..< n.len: result.text.add(getRstName(n[i]).text)
result = getRstName(n[0])
for i in 1..<n.len: result.text.add(getRstName(n[i]).text)
of nkOpenSymChoice, nkClosedSymChoice:
result = getRstName(n[0])
else:
@@ -570,7 +621,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
of skTemplate: result.add(".t")
of skConverter: result.add(".c")
else: discard
if len(n) > paramsPos and n[paramsPos].kind == nkFormalParams:
if n.len > paramsPos and n[paramsPos].kind == nkFormalParams:
let params = renderParamTypes(n[paramsPos])
if params.len > 0:
result.add(defaultParamSeparator)
@@ -589,7 +640,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 +679,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
@@ -650,8 +705,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
plainName.add(literal)
var pragmaNode: PNode = nil
if n.isCallable and n.sons[pragmasPos].kind != nkEmpty:
pragmaNode = findPragma(n.sons[pragmasPos], wDeprecated)
if n.isCallable and n[pragmasPos].kind != nkEmpty:
pragmaNode = findPragma(n[pragmasPos], wDeprecated)
inc(d.id)
let
@@ -677,17 +732,19 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
let cwd = canonicalizePath(d.conf, getCurrentDir())
var path = toFullPath(d.conf, n.info)
if path.startsWith(cwd):
path = path[cwd.len+1 .. ^1].replace('\\', '/')
path = path[cwd.len+1..^1].replace('\\', '/')
let gitUrl = getConfigVar(d.conf, "git.url")
if gitUrl.len > 0:
let defaultBranch = if NimPatch mod 2 == 1: "devel" else: "master"
let defaultBranch =
if NimPatch mod 2 == 1: "devel"
else: "version-$1-$2" % [$NimMajor, $NimMinor]
let commit = getConfigVar(d.conf, "git.commit", defaultBranch)
let develBranch = getConfigVar(d.conf, "git.devel", "devel")
dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc,
["path", "line", "url", "commit", "devel"], [rope path.string,
rope($n.info.line), rope gitUrl, rope commit, rope develBranch])])
add(d.section[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"),
d.section[k].add(ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "seeSrc", "deprecationMsg"],
[nameRope, result, comm, itemIDRope, plainNameRope, plainSymbolRope,
@@ -710,7 +767,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
setIndexTerm(d[], external, symbolOrId, plain, nameNode.sym.name.s & '.' & plain,
xmltree.escape(getPlainDocstring(e).docstringSummary))
add(d.toc[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item.toc"),
d.toc[k].add(ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item.toc"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "attype"],
[rope(getName(d, nameNode, d.splitAfter)), result, comm,
@@ -742,6 +799,35 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode =
result["description"] = %comm
if r.buf.len > 0:
result["code"] = %r.buf
if k in routineKinds:
result["signature"] = newJObject()
if n[paramsPos][0].kind != nkEmpty:
result["signature"]["return"] = %($n[paramsPos][0])
if n[paramsPos].len > 1:
result["signature"]["arguments"] = newJArray()
for paramIdx in 1 ..< n[paramsPos].len:
for identIdx in 0 ..< n[paramsPos][paramIdx].len - 2:
let
paramName = $n[paramsPos][paramIdx][identIdx]
paramType = $n[paramsPos][paramIdx][^2]
if n[paramsPos][paramIdx][^1].kind != nkEmpty:
let paramDefault = $n[paramsPos][paramIdx][^1]
result["signature"]["arguments"].add %{"name": %paramName, "type": %paramType, "default": %paramDefault}
else:
result["signature"]["arguments"].add %{"name": %paramName, "type": %paramType}
if n[pragmasPos].kind != nkEmpty:
result["signature"]["pragmas"] = newJArray()
for pragma in n[pragmasPos]:
result["signature"]["pragmas"].add %($pragma)
if n[genericParamsPos].kind != nkEmpty:
result["signature"]["genericParams"] = newJArray()
for genericParam in n[genericParamsPos]:
var param = %{"name": %($genericParam)}
if genericParam.sym.typ.sons.len > 0:
param["types"] = newJArray()
for kind in genericParam.sym.typ.sons:
param["types"].add %($kind)
result["signature"]["genericParams"].add param
proc checkForFalse(n: PNode): bool =
result = n.kind == nkIdent and cmpIgnoreStyle(n.ident.s, "false") == 0
@@ -756,11 +842,11 @@ proc traceDeps(d: PDoc, it: PNode) =
a.add dir
a.add sep # dummy entry, replaced in the loop
for x in it[2]:
a.sons[2] = x
a[2] = x
traceDeps(d, a)
elif it.kind == nkSym and belongsToPackage(d.conf, it.sym):
let external = externalDep(d, it.sym)
if d.section[k] != nil: add(d.section[k], ", ")
if d.section[k] != nil: d.section[k].add(", ")
dispA(d.conf, d.section[k],
"<a class=\"reference external\" href=\"$2\">$1</a>",
"$1", [rope esc(d.target, changeFileExt(external, "")),
@@ -770,7 +856,7 @@ proc exportSym(d: PDoc; s: PSym) =
const k = exportSection
if s.kind == skModule and belongsToPackage(d.conf, s):
let external = externalDep(d, s)
if d.section[k] != nil: add(d.section[k], ", ")
if d.section[k] != nil: d.section[k].add(", ")
dispA(d.conf, d.section[k],
"<a class=\"reference external\" href=\"$2\">$1</a>",
"$1", [rope esc(d.target, changeFileExt(external, "")),
@@ -779,7 +865,7 @@ proc exportSym(d: PDoc; s: PSym) =
let module = originatingModule(s)
if belongsToPackage(d.conf, module):
let external = externalDep(d, module)
if d.section[k] != nil: add(d.section[k], ", ")
if d.section[k] != nil: d.section[k].add(", ")
# XXX proper anchor generation here
dispA(d.conf, d.section[k],
"<a href=\"$2#$1\"><span class=\"Identifier\">$1</span></a>",
@@ -787,37 +873,37 @@ proc exportSym(d: PDoc; s: PSym) =
rope changeFileExt(external, "html")])
proc documentNewEffect(cache: IdentCache; n: PNode): PNode =
let s = n.sons[namePos].sym
let s = n[namePos].sym
if tfReturnsNew in s.typ.flags:
result = newIdentNode(getIdent(cache, "new"), n.info)
proc documentEffect(cache: IdentCache; n, x: PNode, effectType: TSpecialWord, idx: int): PNode =
let spec = effectSpec(x, effectType)
if isNil(spec):
let s = n.sons[namePos].sym
let s = n[namePos].sym
let actual = s.typ.n.sons[0]
let actual = s.typ.n[0]
if actual.len != effectListLen: return
let real = actual.sons[idx]
let real = actual[idx]
# warning: hack ahead:
var effects = newNodeI(nkBracket, n.info, real.len)
for i in 0 ..< real.len:
for i in 0..<real.len:
var t = typeToString(real[i].typ)
if t.startsWith("ref "): t = substr(t, 4)
effects.sons[i] = newIdentNode(getIdent(cache, t), n.info)
effects[i] = newIdentNode(getIdent(cache, t), n.info)
# set the type so that the following analysis doesn't screw up:
effects.sons[i].typ = real[i].typ
effects[i].typ = real[i].typ
result = newNode(nkExprColonExpr, n.info, @[
newIdentNode(getIdent(cache, specialWords[effectType]), n.info), effects])
proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName: string): PNode =
let s = n.sons[namePos].sym
let s = n[namePos].sym
let params = s.typ.n
var effects = newNodeI(nkBracket, n.info)
for i in 1 ..< params.len:
for i in 1..<params.len:
if params[i].kind == nkSym and flag in params[i].sym.flags:
effects.add params[i]
@@ -826,8 +912,8 @@ proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName
newIdentNode(getIdent(cache, pragmaName), n.info), effects])
proc documentRaises*(cache: IdentCache; n: PNode) =
if n.sons[namePos].kind != nkSym: return
let pragmas = n.sons[pragmasPos]
if n[namePos].kind != nkSym: return
let pragmas = n[pragmasPos]
let p1 = documentEffect(cache, n, pragmas, wRaises, exceptionEffects)
let p2 = documentEffect(cache, n, pragmas, wTags, tagEffects)
let p3 = documentWriteEffect(cache, n, sfWrittenTo, "writes")
@@ -836,59 +922,65 @@ proc documentRaises*(cache: IdentCache; n: PNode) =
if p1 != nil or p2 != nil or p3 != nil or p4 != nil or p5 != nil:
if pragmas.kind == nkEmpty:
n.sons[pragmasPos] = newNodeI(nkPragma, n.info)
if p1 != nil: n.sons[pragmasPos].add p1
if p2 != nil: n.sons[pragmasPos].add p2
if p3 != nil: n.sons[pragmasPos].add p3
if p4 != nil: n.sons[pragmasPos].add p4
if p5 != nil: n.sons[pragmasPos].add p5
n[pragmasPos] = newNodeI(nkPragma, n.info)
if p1 != nil: n[pragmasPos].add p1
if p2 != nil: n[pragmasPos].add p2
if p3 != nil: n[pragmasPos].add p3
if p4 != nil: n[pragmasPos].add p4
if p5 != nil: n[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)
add(d.modDeprecationMsg, genDeprecationMsg(d, pragmaNode))
of nkCommentStmt: add(d.modDesc, genComment(d, n))
d.modDeprecationMsg.add(genDeprecationMsg(d, pragmaNode))
of nkCommentStmt: d.modDesc.add(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):
if n.sons[i].kind != nkCommentStmt:
for i in 0..<n.len:
if n[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..<n.len: generateDoc(d, n[i], orig)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateDoc(d, lastSon(n.sons[0]), orig)
if not checkForFalse(n[0][0]):
generateDoc(d, lastSon(n[0]), orig)
of nkImportStmt:
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 nkFromStmt, nkImportExceptStmt: traceDeps(d, n[0])
of nkCallKinds:
var comm: Rope = nil
getAllRunnableExamples(d, n, comm)
if comm != nil: add(d.modDesc, comm)
if comm != nil: d.modDesc.add(comm)
else: discard
proc add(d: PDoc; j: JsonNode) =
@@ -900,39 +992,39 @@ proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
if includeComments:
d.add %*{"comment": genComment(d, n)}
else:
add(d.modDesc, genComment(d, n))
d.modDesc.add(genComment(d, n))
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skProc)
d.add genJsonItem(d, n, n[namePos], skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skFunc)
d.add genJsonItem(d, n, n[namePos], skFunc)
of nkMethodDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skMethod)
d.add genJsonItem(d, n, n[namePos], skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skIterator)
d.add genJsonItem(d, n, n[namePos], skIterator)
of nkMacroDef:
d.add genJsonItem(d, n, n.sons[namePos], skMacro)
d.add genJsonItem(d, n, n[namePos], skMacro)
of nkTemplateDef:
d.add genJsonItem(d, n, n.sons[namePos], skTemplate)
d.add genJsonItem(d, n, n[namePos], skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skConverter)
d.add genJsonItem(d, n, n[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
if n.sons[i].kind != nkCommentStmt:
for i in 0..<n.len:
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
d.add genJsonItem(d, n.sons[i], n.sons[i].sons[0],
d.add genJsonItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in 0 ..< sonsLen(n):
generateJson(d, n.sons[i], includeComments)
for i in 0..<n.len:
generateJson(d, n[i], includeComments)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateJson(d, lastSon(n.sons[0]), includeComments)
if not checkForFalse(n[0][0]):
generateJson(d, lastSon(n[0]), includeComments)
else: discard
proc genTagsItem(d: PDoc, n, nameNode: PNode, k: TSymKind): string =
@@ -946,36 +1038,36 @@ proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
r.add stripped
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skProc)
r.add genTagsItem(d, n, n[namePos], skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skFunc)
r.add genTagsItem(d, n, n[namePos], skFunc)
of nkMethodDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skMethod)
r.add genTagsItem(d, n, n[namePos], skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skIterator)
r.add genTagsItem(d, n, n[namePos], skIterator)
of nkMacroDef:
r.add genTagsItem(d, n, n.sons[namePos], skMacro)
r.add genTagsItem(d, n, n[namePos], skMacro)
of nkTemplateDef:
r.add genTagsItem(d, n, n.sons[namePos], skTemplate)
r.add genTagsItem(d, n, n[namePos], skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skConverter)
r.add genTagsItem(d, n, n[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
if n.sons[i].kind != nkCommentStmt:
for i in 0..<n.len:
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
r.add genTagsItem(d, n.sons[i], n.sons[i].sons[0],
r.add genTagsItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in 0 ..< sonsLen(n):
generateTags(d, n.sons[i], r)
for i in 0..<n.len:
generateTags(d, n[i], r)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateTags(d, lastSon(n.sons[0]), r)
if not checkForFalse(n[0][0]):
generateTags(d, lastSon(n[0]), r)
else: discard
proc genSection(d: PDoc, kind: TSymKind) =
@@ -992,6 +1084,12 @@ proc genSection(d: PDoc, kind: TSymKind) =
"sectionid", "sectionTitle", "sectionTitleID", "content"], [
ord(kind).rope, title, rope(ord(kind) + 50), d.toc[kind]])
const nimdocOutCss = "nimdoc.out.css"
# `out` to make it easier to use with gitignore in user's repos
proc cssHref(outDir: AbsoluteDir, destFile: AbsoluteFile): Rope =
rope($relativeTo(outDir / nimdocOutCss.RelativeFile, destFile.splitFile().dir, '/'))
proc genOutFile(d: PDoc): Rope =
var
code, content: Rope
@@ -1000,21 +1098,22 @@ proc genOutFile(d: PDoc): Rope =
var tmp = ""
renderTocEntries(d[], j, 1, tmp)
var toc = tmp.rope
for i in low(TSymKind) .. high(TSymKind):
for i in low(TSymKind)..high(TSymKind):
genSection(d, i)
add(toc, d.toc[i])
toc.add(d.toc[i])
if toc != nil:
toc = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.toc"), ["content"], [toc])
for i in low(TSymKind) .. high(TSymKind): add(code, d.section[i])
for i in low(TSymKind)..high(TSymKind): code.add(d.section[i])
# Extract the title. Non API modules generate an entry in the index table.
if d.meta[metaTitle].len != 0:
title = d.meta[metaTitle]
let external = AbsoluteFile(d.filename).relativeTo(d.conf.projectPath, '/').changeFileExt(HtmlExt).string
let external = presentationPath(d.conf, AbsoluteFile d.filename).changeFileExt(HtmlExt).string.nativeToUnix
setIndexTerm(d[], external, "", title)
else:
# Modules get an automatic title for the HTML, but no entry in the index.
title = extractFilename(changeFileExt(d.filename, ""))
# better than `extractFilename(changeFileExt(d.filename, ""))` as it disambiguates dups
title = $presentationPath(d.conf, AbsoluteFile d.filename, isTitle = true).changeFileExt("")
let bodyname = if d.hasToc and not d.isPureRst: "doc.body_toc_group"
elif d.hasToc: "doc.body_toc"
@@ -1025,25 +1124,30 @@ proc genOutFile(d: PDoc): Rope =
rope(getClockStr()), code, d.modDeprecationMsg])
if optCompileOnly notin d.conf.globalOptions:
# XXX what is this hack doing here? 'optCompileOnly' means raw output!?
code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time",
code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), [
"nimdoccss", "title", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics", "deprecationMsg"],
[title.rope, toc, d.modDesc, rope(getDateStr()),
rope(getClockStr()), content, d.meta[metaAuthor].rope,
d.meta[metaVersion].rope, d.analytics.rope, d.modDeprecationMsg])
[cssHref(d.conf.outDir, d.destFile), title.rope, toc, d.modDesc, rope(getDateStr()), rope(getClockStr()),
content, d.meta[metaAuthor].rope, d.meta[metaVersion].rope, d.analytics.rope, d.modDeprecationMsg])
else:
code = content
result = code
proc generateIndex*(d: PDoc) =
if optGenIndex in d.conf.globalOptions:
let dir = if not d.conf.outDir.isEmpty: d.conf.outDir
else: d.conf.projectPath / RelativeDir"htmldocs"
let dir = d.conf.docOutDir(htmldocsDir)
createDir(dir)
let dest = dir / changeFileExt(relativeTo(AbsoluteFile d.filename,
d.conf.projectPath), IndexExt)
let dest = dir / changeFileExt(presentationPath(d.conf, AbsoluteFile d.filename), IndexExt)
writeIndexFile(d[], dest.string)
proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
if d.module == nil or sfMainModule in d.module.flags: # nil for eg for commandRst2Html
if d.conf.outDir.isEmpty: d.conf.outDir = d.conf.docOutDir
if d.conf.outFile.isEmpty:
d.conf.outFile = outfile.relativeTo(d.conf.outDir)
if isAbsolute(d.conf.outFile.string):
d.conf.outFile = splitPath(d.conf.outFile.string)[1].RelativeFile
proc writeOutput*(d: PDoc, useWarning = false) =
runAllExamples(d)
var content = genOutFile(d)
@@ -1051,11 +1155,18 @@ proc writeOutput*(d: PDoc, useWarning = false) =
writeRope(stdout, content)
else:
template outfile: untyped = d.destFile
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt, "htmldocs")
createDir(outfile.splitFile.dir)
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt, htmldocsDir)
let dir = outfile.splitFile.dir
createDir(dir)
updateOutfile(d, outfile)
if not writeRope(content, outfile):
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile,
outfile.string)
elif not d.wroteCss:
let cssSource = $d.conf.getPrefixDir() / "doc" / "nimdoc.css"
let cssDest = $dir / nimdocOutCss
copyFile(cssSource, cssDest)
d.wroteCss = true
proc writeOutputJson*(d: PDoc, useWarning = false) =
runAllExamples(d)
@@ -1073,6 +1184,7 @@ proc writeOutputJson*(d: PDoc, useWarning = false) =
if open(f, d.destFile.string, fmWrite):
write(f, $content)
close(f)
updateOutfile(d, d.destFile)
else:
localError(d.conf, newLineInfo(d.conf, AbsoluteFile d.filename, -1, -1),
warnUser, "unable to open file \"" & d.destFile.string &
@@ -1158,12 +1270,17 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
var content = mergeIndexes(conf.projectFull.string).rope
let code = ropeFormatNamedVars(conf, getConfigVar(conf, "doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time",
var outFile = RelativeFile"theindex"
if conf.outFile != RelativeFile"":
outFile = conf.outFile
let filename = getOutFile(conf, outFile, HtmlExt)
let code = ropeFormatNamedVars(conf, getConfigVar(conf, "doc.file"), [
"nimdoccss", "title", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics"],
["Index".rope, nil, nil, rope(getDateStr()),
rope(getClockStr()), content, nil, nil, nil])
[cssHref(conf.outDir, filename), rope"Index", nil, nil, rope(getDateStr()),
rope(getClockStr()), content, nil, nil, nil])
# no analytics because context is not available
let filename = getOutFile(conf, RelativeFile"theindex", HtmlExt)
if not writeRope(code, filename):
rawMessage(conf, errCannotOpenFile, filename.string)

View File

@@ -11,8 +11,7 @@
# semantic checking.
import
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
pathutils
options, ast, msgs, passes, docgen, lineinfos, pathutils
from modulegraphs import ModuleGraph, PPassContext
@@ -23,8 +22,8 @@ type
config: ConfigRef
PGen = ref TGen
template shouldProcess(g): bool =
(g.module.owner.id == g.doc.conf.mainPackageId and optWholeProject in g.doc.conf.globalOptions) or
proc shouldProcess(g: PGen): bool =
(optWholeProject in g.doc.conf.globalOptions and g.module.getnimblePkgId == g.doc.conf.mainPackageId) or
sfMainModule in g.module.flags or g.config.projectMainIdx == g.module.info.fileIndex
template closeImpl(body: untyped) {.dirty.} =
@@ -63,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

@@ -13,7 +13,7 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
result.typ = newType(tyProc, t.owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
addSon(result.typ.n, newNodeI(nkEffectList, info))
result.typ.n.add newNodeI(nkEffectList, info)
result.typ.addParam dest
@@ -22,7 +22,7 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
caseStmt.add(newSymNode dest)
# copy the branches over, but replace the fields with the for loop body:
for i in 0 ..< t.n.len:
for i in 0..<t.n.len:
assert(t.n[i].kind == nkSym)
var field = t.n[i].sym
let val = if field.ast == nil: field.name.s else: field.ast.strVal
@@ -33,28 +33,35 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
body.add(caseStmt)
var n = newNodeI(nkProcDef, info, bodyPos+2)
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
n.sons[namePos] = newSymNode(result)
n.sons[paramsPos] = result.typ.n
n.sons[bodyPos] = body
n.sons[resultPos] = newSymNode(res)
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
n[namePos] = newSymNode(result)
n[paramsPos] = result.typ.n
n[bodyPos] = body
n[resultPos] = newSymNode(res)
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfNeverRaises
proc searchObjCase(obj: PNode; field: PSym): PNode =
proc searchObjCaseImpl(obj: PNode; field: PSym): PNode =
case obj.kind
of nkSym:
result = nil
of nkElse, nkOfBranch:
result = searchObjCase(obj.lastSon, field)
result = searchObjCaseImpl(obj.lastSon, field)
else:
if obj.kind == nkRecCase and obj[0].kind == nkSym and obj[0].sym == field:
result = obj
else:
for x in obj:
result = searchObjCase(x, field)
result = searchObjCaseImpl(x, field)
if result != nil: break
proc searchObjCase(t: PType; field: PSym): PNode =
result = searchObjCaseImpl(t.n, field)
if result == nil and t.len > 0:
result = searchObjCase(t[0].skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field)
doAssert result != nil
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph): PSym =
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), t.owner, info)
@@ -67,7 +74,7 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
result.typ = newType(tyProc, t.owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
addSon(result.typ.n, newNodeI(nkEffectList, info))
result.typ.n.add newNodeI(nkEffectList, info)
result.typ.addParam dest
@@ -75,12 +82,11 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
var caseStmt = newNodeI(nkCaseStmt, info)
caseStmt.add(newSymNode dest)
let subObj = searchObjCase(t.n, field)
doAssert subObj != nil
for i in 1 ..< subObj.len:
let subObj = searchObjCase(t, field)
for i in 1..<subObj.len:
let ofBranch = subObj[i]
var newBranch = newNodeI(ofBranch.kind, ofBranch.info)
for j in 0..ofBranch.len-2:
for j in 0..<ofBranch.len-1:
newBranch.add ofBranch[j]
newBranch.add newTree(nkStmtList, newTree(nkFastAsgn, newSymNode(res), newIntNode(nkInt8Lit, i)))
@@ -89,10 +95,11 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
body.add(caseStmt)
var n = newNodeI(nkProcDef, info, bodyPos+2)
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
n.sons[namePos] = newSymNode(result)
n.sons[paramsPos] = result.typ.n
n.sons[bodyPos] = body
n.sons[resultPos] = newSymNode(res)
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
n[namePos] = newSymNode(result)
n[paramsPos] = result.typ.n
n[bodyPos] = body
n[resultPos] = newSymNode(res)
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfNeverRaises

View File

@@ -9,13 +9,16 @@
## This file implements the FFI part of the evaluator for Nim code.
import ast, astalgo, ropes, types, options, tables, dynlib, msgs, os, lineinfos
import ast, types, options, tables, dynlib, msgs, lineinfos
from os import getAppFilename
import pkg/libffi
when defined(windows):
const libcDll = "msvcrt.dll"
elif defined(linux):
const libcDll = "libc.so(.6|.5|)"
elif defined(bsd):
const libcDll = "/lib/libc.so.7"
elif defined(osx):
const libcDll = "/usr/lib/libSystem.dylib"
else:
@@ -27,7 +30,7 @@ var
gDllCache = initTable[string, LibHandle]()
when defined(windows):
var gExeHandle = loadLib(os.getAppFilename())
var gExeHandle = loadLib(getAppFilename())
else:
var gExeHandle = loadLib()
@@ -46,38 +49,35 @@ proc getDll(conf: ConfigRef, cache: var TDllCache; dll: string; info: TLineInfo)
const
nkPtrLit = nkIntLit # hopefully we can get rid of this hack soon
var myerrno {.importc: "errno", header: "<errno.h>".}: cint ## error variable
proc importcSymbol*(conf: ConfigRef, sym: PSym): PNode =
let name = $sym.loc.r
let name = sym.cname # $sym.loc.r would point to internal name
# the AST does not support untyped pointers directly, so we use an nkIntLit
# that contains the address instead:
result = newNodeIT(nkPtrLit, sym.info, sym.typ)
case name
of "stdin": result.intVal = cast[ByteAddress](system.stdin)
of "stdout": result.intVal = cast[ByteAddress](system.stdout)
of "stderr": result.intVal = cast[ByteAddress](system.stderr)
of "vmErrnoWrapper": result.intVal = cast[ByteAddress](myerrno)
else:
when true:
var libPathMsg = ""
let lib = sym.annex
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:
libPathMsg = "current exe: " & getAppFilename() & " nor libc: " & libcDll
# 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)
theAddr = dllhandle.symAddr(name)
elif not lib.isNil:
let dll = if lib.kind == libHeader: libcDll else: lib.path.strVal
libPathMsg = dll
let dllhandle = getDll(conf, gDllCache, dll, sym.info)
theAddr = dllhandle.symAddr(name)
if theAddr.isNil: globalError(conf, sym.info, "cannot import: " & sym.name.s)
if theAddr.isNil: globalError(conf, sym.info,
"cannot import symbol: " & name & " from " & libPathMsg)
result.intVal = cast[ByteAddress](theAddr)
proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.TType =
proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.Type =
if t == nil: return addr libffi.type_void
case t.kind
@@ -94,7 +94,7 @@ proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.TType =
tyTyped, tyTypeDesc, tyProc, tyArray, tyStatic, tyNil:
result = addr libffi.type_pointer
of tyDistinct, tyAlias, tySink:
result = mapType(conf, t.sons[0])
result = mapType(conf, t[0])
else:
result = nil
# too risky:
@@ -120,16 +120,16 @@ proc packSize(conf: ConfigRef, v: PNode, typ: PType): int =
if v.kind in {nkNilLit, nkPtrLit}:
result = sizeof(pointer)
else:
result = sizeof(pointer) + packSize(conf, v.sons[0], typ.lastSon)
result = sizeof(pointer) + packSize(conf, v[0], typ.lastSon)
of tyDistinct, tyGenericInst, tyAlias, tySink:
result = packSize(conf, v, typ.sons[0])
result = packSize(conf, v, typ[0])
of tyArray:
# consider: ptr array[0..1000_000, int] which is common for interfacing;
# we use the real length here instead
if v.kind in {nkNilLit, nkPtrLit}:
result = sizeof(pointer)
elif v.len != 0:
result = v.len * packSize(conf, v.sons[0], typ.sons[1])
result = v.len * packSize(conf, v[0], typ[1])
else:
result = getSize(conf, typ).int
@@ -138,16 +138,16 @@ 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):
result = getField(conf, n.sons[i], position)
for i in 0..<n.len:
result = getField(conf, n[i], position)
if result != nil: return
of nkRecCase:
result = getField(conf, n.sons[0], position)
result = getField(conf, n[0], position)
if result != nil: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = getField(conf, lastSon(n.sons[i]), position)
result = getField(conf, lastSon(n[i]), position)
if result != nil: return
else: internalError(conf, n.info, "getField(record case branch)")
of nkSym:
@@ -158,12 +158,12 @@ 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):
var it = x.sons[i]
for i in ord(x.kind == nkObjConstr)..<x.len:
var it = x[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
let field = it.sons[0].sym
pack(conf, it.sons[1], field.typ, res +! field.offset)
internalAssert conf, it[0].kind == nkSym
let field = it[0].sym
pack(conf, it[1], field.typ, res +! field.offset)
elif typ.n != nil:
let field = getField(conf, typ.n, i)
pack(conf, it, field.typ, res +! field.offset)
@@ -224,19 +224,19 @@ proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer) =
packRecCheck = 0
globalError(conf, v.info, "cannot map value to FFI " & typeToString(v.typ))
inc packRecCheck
pack(conf, v.sons[0], typ.lastSon, res +! sizeof(pointer))
pack(conf, v[0], typ.lastSon, res +! sizeof(pointer))
dec packRecCheck
awr(pointer, res +! sizeof(pointer))
of tyArray:
let baseSize = getSize(conf, typ.sons[1])
for i in 0 ..< v.len:
pack(conf, v.sons[i], typ.sons[1], res +! i * baseSize)
let baseSize = getSize(conf, typ[1])
for i in 0..<v.len:
pack(conf, v[i], typ[1], res +! i * baseSize)
of tyObject, tyTuple:
packObject(conf, v, typ, res)
of tyNil:
discard
of tyDistinct, tyGenericInst, tyAlias, tySink:
pack(conf, v, typ.sons[0], res)
pack(conf, v, typ[0], res)
else:
globalError(conf, v.info, "cannot map value to FFI " & typeToString(v.typ))
@@ -245,14 +245,14 @@ 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):
unpackObjectAdd(conf, x, n.sons[i], result)
for i in 0..<n.len:
unpackObjectAdd(conf, x, n[i], result)
of nkRecCase:
globalError(conf, result.info, "case objects cannot be unpacked")
of nkSym:
var pair = newNodeI(nkExprColonExpr, result.info, 2)
pair.sons[0] = n
pair.sons[1] = unpack(conf, x +! n.sym.offset, n.sym.typ, nil)
pair[0] = n
pair[1] = unpack(conf, x +! n.sym.offset, n.sym.typ, nil)
#echo "offset: ", n.sym.name.s, " ", n.sym.offset
result.add pair
else: discard
@@ -275,28 +275,28 @@ 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):
var it = n.sons[i]
for i in ord(n.kind == nkObjConstr)..<n.len:
var it = n[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
let field = it.sons[0].sym
it.sons[1] = unpack(conf, x +! field.offset, field.typ, it.sons[1])
internalAssert conf, it[0].kind == nkSym
let field = it[0].sym
it[1] = unpack(conf, x +! field.offset, field.typ, it[1])
else:
let field = getField(conf, typ.n, i)
n.sons[i] = unpack(conf, x +! field.offset, field.typ, it)
n[i] = unpack(conf, x +! field.offset, field.typ, it)
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:
globalError(conf, n.info, "cannot map value from FFI")
let baseSize = getSize(conf, typ.sons[1])
for i in 0 ..< result.len:
result.sons[i] = unpack(conf, x +! i * baseSize, typ.sons[1], result.sons[i])
let baseSize = getSize(conf, typ[1])
for i in 0..<result.len:
result[i] = unpack(conf, x +! i * baseSize, typ[1], result[i])
proc canonNodeKind(k: TNodeKind): TNodeKind =
case k
@@ -327,7 +327,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
else:
reset n[]
result = n
result.kind = nkNilLit
result[] = TNode(kind: nkNilLit)
result.typ = typ
template awi(kind, v: untyped): untyped = aw(kind, v, intVal)
@@ -376,7 +376,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
awi(nkPtrLit, cast[ByteAddress](p))
elif n != nil and n.len == 1:
internalAssert(conf, n.kind == nkRefTy)
n.sons[0] = unpack(conf, p, typ.lastSon, n.sons[0])
n[0] = unpack(conf, p, typ.lastSon, n[0])
result = n
else:
globalError(conf, n.info, "cannot map value from FFI " & typeToString(typ))
@@ -419,41 +419,41 @@ proc fficast*(conf: ConfigRef, x: PNode, destTyp: PType): PNode =
dealloc a
proc callForeignFunction*(conf: ConfigRef, call: PNode): PNode =
internalAssert conf, call.sons[0].kind == nkPtrLit
internalAssert conf, call[0].kind == nkPtrLit
var cif: TCif
var sig: TParamList
var sig: ParamList
# use the arguments' types for varargs support:
for i in 1..call.len-1:
sig[i-1] = mapType(conf, call.sons[i].typ)
for i in 1..<call.len:
sig[i-1] = mapType(conf, call[i].typ)
if sig[i-1].isNil:
globalError(conf, call.info, "cannot map FFI type")
let typ = call.sons[0].typ
let typ = call[0].typ
if prep_cif(cif, mapCallConv(conf, typ.callConv, call.info), cuint(call.len-1),
mapType(conf, typ.sons[0]), sig) != OK:
mapType(conf, typ[0]), sig) != OK:
globalError(conf, call.info, "error in FFI call")
var args: TArgList
let fn = cast[pointer](call.sons[0].intVal)
for i in 1 .. call.len-1:
var t = call.sons[i].typ
args[i-1] = alloc0(packSize(conf, call.sons[i], t))
pack(conf, call.sons[i], t, args[i-1])
let retVal = if isEmptyType(typ.sons[0]): pointer(nil)
else: alloc(getSize(conf, typ.sons[0]).int)
var args: ArgList
let fn = cast[pointer](call[0].intVal)
for i in 1..<call.len:
var t = call[i].typ
args[i-1] = alloc0(packSize(conf, call[i], t))
pack(conf, call[i], t, args[i-1])
let retVal = if isEmptyType(typ[0]): pointer(nil)
else: alloc(getSize(conf, typ[0]).int)
libffi.call(cif, fn, retVal, args)
if retVal.isNil:
result = newNode(nkEmpty)
else:
result = unpack(conf, retVal, typ.sons[0], nil)
result = unpack(conf, retVal, typ[0], nil)
result.info = call.info
if retVal != nil: dealloc retVal
for i in 1 .. call.len-1:
call.sons[i] = unpack(conf, args[i-1], typ.sons[i], call[i])
for i in 1..<call.len:
call[i] = unpack(conf, args[i-1], typ[i], call[i])
dealloc args[i-1]
proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
@@ -462,39 +462,39 @@ proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
internalAssert conf, fn.kind == nkPtrLit
var cif: TCif
var sig: TParamList
var sig: ParamList
for i in 0..len-1:
var aTyp = args[i+start].typ
if aTyp.isNil:
internalAssert conf, i+1 < fntyp.len
aTyp = fntyp.sons[i+1]
aTyp = fntyp[i+1]
args[i+start].typ = aTyp
sig[i] = mapType(conf, aTyp)
if sig[i].isNil: globalError(conf, info, "cannot map FFI type")
if prep_cif(cif, mapCallConv(conf, fntyp.callConv, info), cuint(len),
mapType(conf, fntyp.sons[0]), sig) != OK:
mapType(conf, fntyp[0]), sig) != OK:
globalError(conf, info, "error in FFI call")
var cargs: TArgList
var cargs: ArgList
let fn = cast[pointer](fn.intVal)
for i in 0 .. len-1:
for i in 0..len-1:
let t = args[i+start].typ
cargs[i] = alloc0(packSize(conf, args[i+start], t))
pack(conf, args[i+start], t, cargs[i])
let retVal = if isEmptyType(fntyp.sons[0]): pointer(nil)
else: alloc(getSize(conf, fntyp.sons[0]).int)
let retVal = if isEmptyType(fntyp[0]): pointer(nil)
else: alloc(getSize(conf, fntyp[0]).int)
libffi.call(cif, fn, retVal, cargs)
if retVal.isNil:
result = newNode(nkEmpty)
else:
result = unpack(conf, retVal, fntyp.sons[0], nil)
result = unpack(conf, retVal, fntyp[0], nil)
result.info = info
if retVal != nil: dealloc retVal
for i in 0 .. len-1:
for i in 0..len-1:
let t = args[i+start].typ
args[i+start] = unpack(conf, cargs[i], t, args[i+start])
dealloc cargs[i]

View File

@@ -10,8 +10,7 @@
## Template evaluation engine. Now hygienic.
import
strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
lineinfos
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents
type
TemplCtx = object
@@ -21,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)
@@ -38,11 +38,11 @@ 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:
handleParam actual.sons[s.position]
if s.kind == skParam and {sfGenSym, sfTemplateParam} * s.flags == {sfTemplateParam}:
handleParam actual[s.position]
elif (s.owner != nil) and (s.kind == skGenericParam or
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
handleParam actual.sons[s.owner.typ.len + s.position - 1]
handleParam actual[s.owner.typ.len + s.position - 1]
else:
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
var x = PSym(idTableGet(c.mapping, s))
@@ -53,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
@@ -64,8 +68,8 @@ 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):
evalTemplateAux(templ.sons[i], actual, c, res)
for i in 0..<templ.len:
evalTemplateAux(templ[i], actual, c, res)
result.add res
else:
result.add newNodeI(nkEmpty, templ.info)
@@ -78,8 +82,8 @@ 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):
evalTemplateAux(templ.sons[i], actual, c, res)
for i in 0..<templ.len:
evalTemplateAux(templ[i], actual, c, res)
result.add res
if isDeclarative: c.isDeclarative = false
@@ -118,22 +122,22 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
n.renderTree)
result = newNodeI(nkArgList, n.info)
for i in 1 .. givenRegularParams:
result.addSon n[i]
for i in 1..givenRegularParams:
result.add n[i]
# handle parameters with default values, which were
# not supplied by the user
for i in givenRegularParams+1 .. expectedRegularParams:
let default = s.typ.n.sons[i].sym.ast
for i in givenRegularParams+1..expectedRegularParams:
let default = s.typ.n[i].sym.ast
if default.isNil or default.kind == nkEmpty:
localError(conf, n.info, errWrongNumberOfArguments)
addSon(result, newNodeI(nkEmpty, n.info))
result.add newNodeI(nkEmpty, n.info)
else:
addSon(result, default.copyTree)
result.add default.copyTree
# add any generic paramaters
for i in 1 .. genericParams:
result.addSon n.sons[givenRegularParams + i]
# add any generic parameters
for i in 1..genericParams:
result.add n[givenRegularParams + i]
# to prevent endless recursion in template instantiation
const evalTemplateLimit* = 1000
@@ -151,7 +155,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
if x.kind in nkCallKinds:
for i in 1..<x.len:
if x[i].kind in nkCallKinds:
x.sons[i].info = info
x[i].info = info
else:
result = newNodeI(nkStmtListExpr, info)
var d = newNodeI(nkComesFrom, info)
@@ -161,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)
@@ -173,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
@@ -180,7 +187,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
if isAtom(body):
result = newNodeI(nkPar, body.info)
evalTemplateAux(body, args, ctx, result)
if result.len == 1: result = result.sons[0]
if result.len == 1: result = result[0]
else:
localError(conf, result.info, "illformed AST: " &
renderTree(result, {renderNoComments}))
@@ -189,8 +196,8 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.instLines = sfCallsite in tmpl.flags
if ctx.instLines:
result.info = n.info
for i in 0 ..< safeLen(body):
evalTemplateAux(body.sons[i], args, ctx, result)
for i in 0..<body.safeLen:
evalTemplateAux(body[i], args, ctx, result)
result.flags.incl nfFromTemplate
result = wrapInComesFrom(n.info, tmpl, result)
#if ctx.debugActive:

View File

@@ -14,7 +14,7 @@
import
ropes, os, strutils, osproc, platform, condsyms, options, msgs,
lineinfos, std / sha1, streams, pathutils, sequtils, times
lineinfos, std / sha1, streams, pathutils, sequtils, times, strtabs
type
TInfoCCProp* = enum # properties of the C compiler:
@@ -48,6 +48,8 @@ type
# used on some platforms
asmStmtFrmt: string, # format of ASM statement
structStmtFmt: string, # Format for struct statement
produceAsm: string, # Format how to produce assembler listings
cppXsupport: string, # what to do to enable C++X support
props: TInfoCCProps] # properties of the C compiler
@@ -58,13 +60,16 @@ type
template compiler(name, settings: untyped): untyped =
proc name: TInfoCC {.compileTime.} = settings
const
gnuAsmListing = "-Wa,-acdl=$asmfile -g -fverbose-asm -masm=intel"
# GNU C and C++ Compiler
compiler gcc:
result = (
name: "gcc",
objExt: "o",
optSpeed: " -O3 ",
optSize: " -Os ",
optSpeed: " -O3 -fno-ident",
optSize: " -Os -fno-ident",
compilerExe: "gcc",
cppCompiler: "g++",
compileTmpl: "-c $options $include -o $objfile $file",
@@ -80,6 +85,8 @@ compiler gcc:
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
produceAsm: gnuAsmListing,
cppXsupport: "-std=gnu++14 -funsigned-char",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
@@ -105,6 +112,8 @@ compiler nintendoSwitchGCC:
pic: "-fPIE",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
produceAsm: gnuAsmListing,
cppXsupport: "-std=gnu++14 -funsigned-char",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
@@ -138,12 +147,12 @@ 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",
linkerExe: "cl",
linkTmpl: "$options $builddll$vccplatform /Fe$exefile $objfiles $buildgui",
linkTmpl: "$builddll$vccplatform /Fe$exefile $objfiles $buildgui $options",
includeCmd: " /I",
linkDirCmd: " /LIBPATH:",
linkLibCmd: " $1.lib",
@@ -151,6 +160,8 @@ compiler vcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
produceAsm: "/Fa$asmfile",
cppXsupport: "",
props: {hasCpp, hasAssume, hasDeclspec})
compiler clangcl:
@@ -196,6 +207,8 @@ compiler lcc:
pic: "",
asmStmtFrmt: "_asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
# Borland C Compiler
@@ -220,6 +233,8 @@ compiler bcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard,
hasAttribute})
@@ -245,6 +260,8 @@ compiler dmc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasCpp})
# Watcom C Compiler
@@ -269,6 +286,8 @@ compiler wcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasCpp})
# Tiny C Compiler
@@ -291,9 +310,11 @@ compiler tcc:
linkLibCmd: "", # XXX: not supported yet
debug: " -g ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $2",
props: {hasSwitchRange, hasComputedGoto})
produceAsm: gnuAsmListing,
cppXsupport: "",
props: {hasSwitchRange, hasComputedGoto, hasGnuAsm})
# Pelles C Compiler
compiler pcc:
@@ -318,6 +339,8 @@ compiler pcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
# Your C Compiler
@@ -342,6 +365,8 @@ compiler ucc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
const
@@ -370,13 +395,15 @@ proc libNameTmpl(conf: ConfigRef): string {.inline.} =
proc nameToCC*(name: string): TSystemCC =
## Returns the kind of compiler referred to by `name`, or ccNone
## if the name doesn't refer to any known compiler.
for i in succ(ccNone) .. high(TSystemCC):
for i in succ(ccNone)..high(TSystemCC):
if cmpIgnoreStyle(name, CC[i].name) == 0:
return i
result = ccNone
proc listCCnames(): seq[string] =
for i in succ(ccNone) .. high(TSystemCC):
proc listCCnames(): string =
result = ""
for i in succ(ccNone)..high(TSystemCC):
if i > succ(ccNone): result.add ", "
result.add CC[i].name
proc isVSCompatible*(conf: ConfigRef): bool =
@@ -404,7 +431,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)
@@ -412,17 +439,16 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
proc setCC*(conf: ConfigRef; ccname: string; info: TLineInfo) =
conf.cCompiler = nameToCC(ccname)
if conf.cCompiler == ccNone:
let ccList = listCCnames().join(", ")
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, ccList])
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, listCCnames()])
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
conf.linkOptions = ""
conf.ccompilerpath = getConfigVar(conf, conf.cCompiler, ".path")
for i in low(CC) .. high(CC): undefSymbol(conf.symbols, CC[i].name)
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
proc addOpt(dest: var string, src: string) =
if len(dest) == 0 or dest[len(dest)-1] != ' ': add(dest, " ")
add(dest, src)
if dest.len == 0 or dest[^1] != ' ': dest.add(" ")
dest.add(src)
proc addLinkOption*(conf: ConfigRef; option: string) =
addOpt(conf.linkOptions, option)
@@ -439,14 +465,14 @@ proc addCompileOptionCmd*(conf: ConfigRef; option: string) =
proc initVars*(conf: ConfigRef) =
# we need to define the symbol here, because ``CC`` may have never been set!
for i in low(CC) .. high(CC): undefSymbol(conf.symbols, CC[i].name)
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
addCompileOption(conf, getConfigVar(conf, conf.cCompiler, ".options.always"))
#addLinkOption(getConfigVar(cCompiler, ".options.linker"))
if len(conf.ccompilerpath) == 0:
conf.ccompilerpath = getConfigVar(conf, conf.cCompiler, ".path")
if conf.cCompilerPath.len == 0:
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
proc completeCFilePath*(conf: ConfigRef; cfile: AbsoluteFile,
proc completeCfilePath*(conf: ConfigRef; cfile: AbsoluteFile,
createSubDir: bool = true): AbsoluteFile =
result = completeGeneratedFilePath(conf, cfile, createSubDir)
@@ -457,6 +483,13 @@ proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
proc addFileToCompile*(conf: ConfigRef; cf: Cfile) =
conf.toCompile.add(cf)
proc addLocalCompileOption*(conf: ConfigRef; option: string; nimfile: AbsoluteFile) =
let key = completeCfilePath(conf, withPackageName(conf, nimfile)).string
var value = conf.cfileSpecificOptions.getOrDefault(key)
if strutils.find(value, option, 0) < 0:
addOpt(value, option)
conf.cfileSpecificOptions[key] = value
proc resetCompilationLists*(conf: ConfigRef) =
conf.toCompile.setLen 0
## XXX: we must associate these with their originating module
@@ -469,7 +502,7 @@ proc addExternalFileToLink*(conf: ConfigRef; filename: AbsoluteFile) =
conf.externalToLink.insert(filename.string, 0)
proc execWithEcho(conf: ConfigRef; cmd: string, msg = hintExecuting): int =
rawMessage(conf, msg, cmd)
rawMessage(conf, msg, if msg == hintLinking and not(optListCmd in conf.globalOptions or conf.verbosity > 1): "" else: cmd)
result = execCmd(cmd)
proc execExternalProgram*(conf: ConfigRef; cmd: string, msg = hintExecuting) =
@@ -481,10 +514,7 @@ proc generateScript(conf: ConfigRef; script: Rope) =
let (_, name, _) = splitFile(conf.outFile.string)
let filename = getNimcacheDir(conf) / RelativeFile(addFileExt("compile_" & name,
platform.OS[conf.target.targetOS].scriptExt))
if writeRope(script, filename):
copyFile(conf.libpath / RelativeFile"nimbase.h",
getNimcacheDir(conf) / RelativeFile"nimbase.h")
else:
if not writeRope(script, filename):
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)
proc getOptSpeed(conf: ConfigRef; c: TSystemCC): string =
@@ -509,8 +539,10 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
# `optGenMapping` is included here for niminst.
result = conf.globalOptions * {optGenScript, optGenMapping} != {}
proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
result = conf.compileOptions
addOpt(result, conf.cfileSpecificOptions.getOrDefault(fullNimFile))
for option in conf.compileOptionsCmd:
if strutils.find(result, option, 0) < 0:
addOpt(result, option)
@@ -531,20 +563,19 @@ proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
proc getCompileOptions(conf: ConfigRef): string =
result = cFileSpecificOptions(conf, "__dummy__")
result = cFileSpecificOptions(conf, "__dummy__", "__dummy__")
proc vccplatform(conf: ConfigRef): string =
# VCC specific but preferable over the config hacks people
# had to do before, see #11306
case conf.target.targetCPU
of cpuI386:
result = " --platform:x86"
of cpuArm:
result = " --platform:arm"
of cpuAmd64:
result = " --platform:amd64"
else:
result = ""
if conf.cCompiler == ccVcc:
let exe = getConfigVar(conf, conf.cCompiler, ".exe")
if "vccexe.exe" == extractFilename(exe):
result = case conf.target.targetCPU
of cpuI386: " --platform:x86"
of cpuArm: " --platform:arm"
of cpuAmd64: " --platform:amd64"
else: ""
proc getLinkOptions(conf: ConfigRef): string =
result = conf.linkOptions & " " & conf.linkOptionsCmd & " "
@@ -557,8 +588,11 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
result = (optGenScript in conf.globalOptions and conf.target.targetOS == osWindows) or
(conf.target.hostOS == osWindows)
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c")
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
result = if conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c"):
result = if useCpp(conf, cfile):
CC[compiler].cppCompiler
else:
CC[compiler].compilerExe
@@ -567,33 +601,65 @@ proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile):
"Compiler '$1' doesn't support the requested target" %
CC[compiler].name)
proc ccHasSaneOverflow*(conf: ConfigRef): bool =
if conf.cCompiler == ccGcc:
result = false # assume an old or crappy GCC
var exe = getConfigVar(conf, conf.cCompiler, ".exe")
if exe.len == 0: exe = CC[conf.cCompiler].compilerExe
let (s, exitCode) = try: execCmdEx(exe & " --version") except: ("", 1)
if exitCode == 0:
var i = 0
var j = 0
# the version is the last part of the first line:
while i < s.len and s[i] != '\n':
if s[i] in {' ', '\t'}: j = i+1
inc i
if j > 0:
var major = 0
while j < s.len and s[j] in {'0'..'9'}:
major = major * 10 + (ord(s[j]) - ord('0'))
inc j
if i < s.len and s[j] == '.': inc j
while j < s.len and s[j] in {'0'..'9'}:
inc j
if j+1 < s.len and s[j] == '.' and s[j+1] in {'0'..'9'}:
# we found a third version number, chances are high
# we really parsed the version:
result = major >= 5
else:
result = conf.cCompiler == ccCLang
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
elif optMixedMode in conf.globalOptions and conf.cmd != cmdCompileToCpp: CC[compiler].cppCompiler
else: getCompilerExe(conf, compiler, AbsoluteFile"")
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): string =
var c = conf.cCompiler
var options = cFileSpecificOptions(conf, cfile.nimname)
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
isMainFile = false; produceOutput = false): string =
let c = conf.cCompiler
# We produce files like module.nim.cpp, so the absolute Nim filename is not
# cfile.name but `cfile.cname.changeFileExt("")`:
var options = cFileSpecificOptions(conf, cfile.nimname, cfile.cname.changeFileExt("").string)
var exe = getConfigVar(conf, c, ".exe")
if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)
if needsExeExt(conf): exe = addFileExt(exe, "exe")
if (optGenDynLib in conf.globalOptions or (conf.hcrOn and not isMainFile)) and
ospNeedsPIC in platform.OS[conf.target.targetOS].props:
add(options, ' ' & CC[c].pic)
options.add(' ' & CC[c].pic)
var includeCmd, compilePattern: string
if useCpp(conf, cfile.cname):
options.add(' ' & CC[c].cppXsupport)
var compilePattern: string
# compute include paths:
var includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)
if not noAbsolutePaths(conf):
# compute include paths:
includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)
for includeDir in items(conf.cIncludes):
includeCmd.add(join([CC[c].includeCmd, includeDir.quoteShell]))
compilePattern = joinPath(conf.ccompilerpath, exe)
compilePattern = joinPath(conf.cCompilerPath, exe)
else:
includeCmd = ""
compilePattern = getCompilerExe(conf, c, cfile.cname)
includeCmd.add(join([CC[c].includeCmd, quoteShell(conf.projectPath.string)]))
@@ -603,10 +669,10 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): str
var objfile =
if cfile.obj.isEmpty:
if not cfile.flags.contains(CfileFlag.External) or noAbsolutePaths(conf):
if CfileFlag.External notin cfile.flags or noAbsolutePaths(conf):
toObjFile(conf, cf).string
else:
completeCFilePath(conf, toObjFile(conf, cf)).string
completeCfilePath(conf, toObjFile(conf, cf)).string
elif noAbsolutePaths(conf):
extractFilename(cfile.obj.string)
else:
@@ -614,19 +680,30 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): str
# D files are required by nintendo switch libs for
# compilation. They are basically a list of all includes.
let dfile = objfile.changeFileExt(".d").quoteShell()
let dfile = objfile.changeFileExt(".d").quoteShell
objfile = quoteShell(objfile)
let cfsh = quoteShell(cf)
result = quoteShell(compilePattern % [
"dfile", dfile,
"file", cfsh, "objfile", objfile, "options", options,
"file", cfsh, "objfile", quoteShell(objfile), "options", options,
"include", includeCmd, "nim", getPrefixDir(conf).string,
"lib", conf.libpath.string])
add(result, ' ')
addf(result, CC[c].compileTmpl, [
if optProduceAsm in conf.globalOptions:
if CC[conf.cCompiler].produceAsm.len > 0:
let asmfile = objfile.changeFileExt(".asm").quoteShell
addOpt(result, CC[conf.cCompiler].produceAsm % ["asmfile", asmfile])
if produceOutput:
rawMessage(conf, hintUserRaw, "Produced assembler here: " & asmfile)
else:
if produceOutput:
rawMessage(conf, hintUserRaw, "Couldn't produce assembler listing " &
"for the selected C compiler: " & CC[conf.cCompiler].name)
result.add(' ')
result.addf(CC[c].compileTmpl, [
"dfile", dfile,
"file", cfsh, "objfile", objfile,
"file", cfsh, "objfile", quoteShell(objfile),
"options", options, "include", includeCmd,
"nim", quoteShell(getPrefixDir(conf)),
"lib", quoteShell(conf.libpath),
@@ -641,7 +718,7 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
getCompileCFileCmd(conf, cfile))
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
if conf.cmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
if conf.cmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM, cmdNone}:
return false
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
@@ -662,30 +739,18 @@ proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
if optForceFullMake notin conf.globalOptions and fileExists(c.obj) and
not externalFileChanged(conf, c):
c.flags.incl CfileFlag.Cached
else:
# make sure Nim keeps recompiling the external file on reruns
# if compilation is not successful
discard tryRemoveFile(c.obj.string)
conf.toCompile.add(c)
proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
var c = Cfile(nimname: splitFile(filename).name, cname: filename,
obj: toObjFile(conf, completeCFilePath(conf, filename, false)),
obj: toObjFile(conf, completeCfilePath(conf, filename, false)),
flags: {CfileFlag.External})
addExternalFileToCompile(conf, c)
proc compileCFiles(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var TStringSeq,
prettyCmds: var TStringSeq) =
var currIdx = 0
for it in list:
# call the C compiler for the .c file:
if it.flags.contains(CfileFlag.Cached): continue
var compileCmd = getCompileCFileCmd(conf, it, currIdx == list.len - 1)
inc currIdx
if optCompileOnly notin conf.globalOptions:
add(cmds, compileCmd)
let (_, name, _) = splitFile(it.cname)
add(prettyCmds, if hintCC in conf.notes: "CC: " & demanglePackageName(name) else: "")
if optGenScript in conf.globalOptions:
add(script, compileCmd)
add(script, "\n")
proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
objfiles: string, isDllBuild: bool): string =
if optGenStaticLib in conf.globalOptions:
@@ -700,11 +765,11 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
"objfiles", objfiles]
else:
var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe")
if len(linkerExe) == 0: linkerExe = getLinkerExe(conf, conf.cCompiler)
if linkerExe.len == 0: linkerExe = getLinkerExe(conf, conf.cCompiler)
# bug #6452: We must not use ``quoteShell`` here for ``linkerExe``
if needsExeExt(conf): linkerExe = addFileExt(linkerExe, "exe")
if noAbsolutePaths(conf): result = linkerExe
else: result = joinPath(conf.cCompilerpath, linkerExe)
else: result = joinPath(conf.cCompilerPath, linkerExe)
let buildgui = if optGenGuiApp in conf.globalOptions and conf.target.targetOS == osWindows:
CC[conf.cCompiler].buildGui
else:
@@ -730,7 +795,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
"exefile", exefile, "nim", getPrefixDir(conf).string, "lib", conf.libpath.string])
result.add ' '
addf(result, linkTmpl, ["builddll", builddll,
result.addf(linkTmpl, ["builddll", builddll,
"mapfile", mapfile,
"buildgui", buildgui, "options", linkOptions,
"objfiles", objfiles, "exefile", exefile,
@@ -757,7 +822,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.
#
@@ -795,20 +860,27 @@ template tryExceptOSErrorMessage(conf: ConfigRef; errorPrefix: string = "", body
proc execLinkCmd(conf: ConfigRef; linkCmd: string) =
tryExceptOSErrorMessage(conf, "invocation of external linker program failed."):
execExternalProgram(conf, linkCmd,
if optListCmd in conf.globalOptions or conf.verbosity > 1: hintExecuting else: hintLinking)
execExternalProgram(conf, linkCmd, hintLinking)
proc maybeRunDsymutil(conf: ConfigRef; exe: AbsoluteFile) =
when defined(osx):
if optCDebug in conf.globalOptions and optGenStaticLib notin conf.globalOptions:
# if needed, add an option to skip or override location
let cmd = "dsymutil " & $(exe).quoteShell
conf.extraCmds.add cmd
tryExceptOSErrorMessage(conf, "invocation of dsymutil failed."):
execExternalProgram(conf, cmd, hintExecuting)
proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: int)) =
let runCb = proc (idx: int, p: Process) =
let exitCode = p.peekExitCode
if exitCode != 0:
rawMessage(conf, errGenerated, "execution of an external compiler program '" &
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
p.outputStream.readAll.strip)
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n")
if conf.numberOfProcessors == 0: conf.numberOfProcessors = countProcessors()
var res = 0
if conf.numberOfProcessors <= 1:
for i in 0 .. high(cmds):
for i in 0..high(cmds):
tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
res = execWithEcho(conf, cmds[i])
if res != 0:
@@ -816,15 +888,8 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
cmds[i])
else:
tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
if optListCmd in conf.globalOptions or conf.verbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath},
conf.numberOfProcessors, afterRunEvent=runCb)
elif conf.verbosity == 1:
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath},
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
conf.numberOfProcessors, prettyCb, afterRunEvent=runCb)
else:
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath},
conf.numberOfProcessors, afterRunEvent=runCb)
if res != 0:
if conf.numberOfProcessors <= 1:
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
@@ -856,7 +921,7 @@ proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
finally:
removeFile(linkerArgs)
proc getObjFilePath(conf: ConfigRef, f: CFile): string =
proc getObjFilePath(conf: ConfigRef, f: Cfile): string =
if noAbsolutePaths(conf): f.obj.extractFilename
else: f.obj.string
@@ -866,6 +931,13 @@ proc hcrLinkTargetName(conf: ConfigRef, objFile: string, isMain = false): Absolu
else: platform.OS[conf.target.targetOS].dllFrmt % basename
result = conf.getNimcacheDir / RelativeFile(targetName)
proc displayProgressCC(conf: ConfigRef, path, compileCmd: string): string =
if conf.hasHint(hintCC):
if optListCmd in conf.globalOptions or conf.verbosity > 1:
result = MsgKindToStr[hintCC] % (demanglePackageName(path.splitFile.name) & ": " & compileCmd)
else:
result = MsgKindToStr[hintCC] % demanglePackageName(path.splitFile.name)
proc callCCompiler*(conf: ConfigRef) =
var
linkCmd: string
@@ -874,13 +946,22 @@ proc callCCompiler*(conf: ConfigRef) =
# generated
#var c = cCompiler
var script: Rope = nil
var cmds: TStringSeq = @[]
var prettyCmds: TStringSeq = @[]
var cmds: TStringSeq
var prettyCmds: TStringSeq
let prettyCb = proc (idx: int) =
when declared(echo):
let cmd = prettyCmds[idx]
if cmd != "": echo cmd
compileCFiles(conf, conf.toCompile, script, cmds, prettyCmds)
if prettyCmds[idx].len > 0: echo prettyCmds[idx]
for idx, it in conf.toCompile:
# call the C compiler for the .c file:
if CfileFlag.Cached in it.flags: continue
let compileCmd = getCompileCFileCmd(conf, it, idx == conf.toCompile.len - 1, produceOutput=true)
if optCompileOnly notin conf.globalOptions:
cmds.add(compileCmd)
prettyCmds.add displayProgressCC(conf, $it.cname, compileCmd)
if optGenScript in conf.globalOptions:
script.add(compileCmd)
script.add("\n")
if optCompileOnly notin conf.globalOptions:
execCmdsInParallel(conf, cmds, prettyCb)
if optNoLinking notin conf.globalOptions:
@@ -888,8 +969,8 @@ proc callCCompiler*(conf: ConfigRef) =
var objfiles = ""
for it in conf.externalToLink:
let objFile = if noAbsolutePaths(conf): it.extractFilename else: it
add(objfiles, ' ')
add(objfiles, quoteShell(
objfiles.add(' ')
objfiles.add(quoteShell(
addFileExt(objFile, CC[conf.cCompiler].objExt)))
if conf.hcrOn: # lets assume that optCompileOnly isn't on
@@ -899,14 +980,14 @@ proc callCCompiler*(conf: ConfigRef) =
# don't relink each of the many binaries (one for each source file) if the nim code is
# cached because that would take too much time for small changes - the only downside to
# this is that if an external-to-link file changes the final target wouldn't be relinked
if x.flags.contains(CfileFlag.Cached): continue
if CfileFlag.Cached in x.flags: continue
# we pass each object file as if it is the project file - a .dll will be created for each such
# object file in the nimcache directory, and only in the case of the main project file will
# there be probably an executable (if the project is such) which will be copied out of the nimcache
let objFile = conf.getObjFilePath(x)
let buildDll = idx != mainFileIdx
let linkTarget = conf.hcrLinkTargetName(objFile, not buildDll)
add(cmds, getLinkCmd(conf, linkTarget, objfiles & " " & quoteShell(objFile), buildDll))
cmds.add(getLinkCmd(conf, linkTarget, objfiles & " " & quoteShell(objFile), buildDll))
# try to remove all .pdb files for the current binary so they don't accumulate endlessly in the nimcache
# for more info check the comment inside of getLinkCmd() where the /PDB:<filename> MSVC flag is used
if isVSCompatible(conf):
@@ -917,7 +998,7 @@ proc callCCompiler*(conf: ConfigRef) =
prettyCmds = map(prettyCmds, proc (curr: string): string = return curr.replace("CC", "Link"))
execCmdsInParallel(conf, cmds, prettyCb)
# only if not cached - copy the resulting main file from the nimcache folder to its originally intended destination
if not conf.toCompile[mainFileIdx].flags.contains(CfileFlag.Cached):
if CfileFlag.Cached notin conf.toCompile[mainFileIdx].flags:
let mainObjFile = getObjFilePath(conf, conf.toCompile[mainFileIdx])
var src = conf.hcrLinkTargetName(mainObjFile, true)
var dst = conf.prepareToWriteOutput
@@ -925,8 +1006,8 @@ proc callCCompiler*(conf: ConfigRef) =
else:
for x in conf.toCompile:
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string
add(objfiles, ' ')
add(objfiles, quoteShell(objFile))
objfiles.add(' ')
objfiles.add(quoteShell(objFile))
let mainOutput = if optGenScript notin conf.globalOptions: conf.prepareToWriteOutput
else: AbsoluteFile(conf.projectName)
linkCmd = getLinkCmd(conf, mainOutput, objfiles)
@@ -939,15 +1020,18 @@ proc callCCompiler*(conf: ConfigRef) =
linkViaResponseFile(conf, linkCmd)
else:
execLinkCmd(conf, linkCmd)
maybeRunDsymutil(conf, mainOutput)
else:
linkCmd = ""
if optGenScript in conf.globalOptions:
add(script, linkCmd)
add(script, "\n")
script.add(linkCmd)
script.add("\n")
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 +1044,16 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
f.write escapeJson(x)
proc cfiles(conf: ConfigRef; f: File; buf: var string; clist: CfileList, isExternal: bool) =
var pastStart = false
for it in clist:
var comma = false
for i, it in clist:
if CfileFlag.Cached in it.flags: continue
let compileCmd = getCompileCFileCmd(conf, it)
if pastStart: lit "],\L"
if comma: lit ",\L" else: comma = true
lit "["
str it.cname.string
lit ", "
str compileCmd
pastStart = true
lit "]\L"
lit "]"
proc linkfiles(conf: ConfigRef; f: File; buf, objfiles: var string; clist: CfileList;
llist: seq[string]) =
@@ -979,21 +1062,35 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
let objfile = if noAbsolutePaths(conf): it.extractFilename
else: it
let objstr = addFileExt(objfile, CC[conf.cCompiler].objExt)
add(objfiles, ' ')
add(objfiles, objstr)
objfiles.add(' ')
objfiles.add(objstr)
if pastStart: lit ",\L"
str objstr
pastStart = true
for it in clist:
let objstr = quoteShell(it.obj)
add(objfiles, ' ')
add(objfiles, objstr)
objfiles.add(' ')
objfiles.add(objstr)
if pastStart: lit ",\L"
str objstr
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,57 +1106,116 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
lit "],\L\"linkcmd\": "
str getLinkCmd(conf, conf.absOutFile, objfiles)
lit ",\L\"extraCmds\": "
lit $(%* conf.extraCmds)
lit ",\L\"stdinInput\": "
lit $(%* conf.projectIsStdin)
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
if not data.hasKey("stdinInput"): return true
let stdinInput = data["stdinInput"].getBool
if conf.projectIsStdin or stdinInput:
# could optimize by returning false if stdin input was the same,
# but I'm not sure how to get full stding input
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:
let data = json.parseFile(jsonFile.string)
let toCompile = data["compile"]
doAssert toCompile.kind == JArray
var cmds: TStringSeq = @[]
var prettyCmds: TStringSeq = @[]
var cmds: TStringSeq
var prettyCmds: TStringSeq
let prettyCb = proc (idx: int) =
if prettyCmds[idx].len > 0: echo prettyCmds[idx]
for c in toCompile:
doAssert c.kind == JArray
doAssert c.len >= 2
add(cmds, c[1].getStr)
let (_, name, _) = splitFile(c[0].getStr)
add(prettyCmds, "CC: " & name)
cmds.add(c[1].getStr)
prettyCmds.add displayProgressCC(conf, c[0].getStr, c[1].getStr)
let prettyCb = proc (idx: int) =
when declared(echo):
echo prettyCmds[idx]
execCmdsInParallel(conf, cmds, prettyCb)
let linkCmd = data["linkcmd"]
doAssert linkCmd.kind == JString
execLinkCmd(conf, linkCmd.getStr)
except:
when declared(echo):
echo getCurrentException().getStackTrace()
quit "error evaluating JSON file: " & jsonFile.string
if data.hasKey("extraCmds"):
let extraCmds = data["extraCmds"]
doAssert extraCmds.kind == JArray
for cmd in extraCmds:
doAssert cmd.kind == JString, $cmd.kind
let cmd2 = cmd.getStr
execExternalProgram(conf, cmd2, hintExecuting)
proc genMappingFiles(conf: ConfigRef; list: CFileList): Rope =
except:
let e = getCurrentException()
quit "\ncaught exception:\n" & e.msg & "\nstacktrace:\n" & e.getStackTrace() &
"error evaluating JSON file: " & jsonFile.string
proc genMappingFiles(conf: ConfigRef; list: CfileList): Rope =
for it in list:
addf(result, "--file:r\"$1\"$N", [rope(it.cname.string)])
result.addf("--file:r\"$1\"$N", [rope(it.cname.string)])
proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
if optGenMapping notin conf.globalOptions: return
var code = rope("[C_Files]\n")
add(code, genMappingFiles(conf, conf.toCompile))
add(code, "\n[C_Compiler]\nFlags=")
add(code, strutils.escape(getCompileOptions(conf)))
code.add(genMappingFiles(conf, conf.toCompile))
code.add("\n[C_Compiler]\nFlags=")
code.add(strutils.escape(getCompileOptions(conf)))
add(code, "\n[Linker]\nFlags=")
add(code, strutils.escape(getLinkOptions(conf) & " " &
code.add("\n[Linker]\nFlags=")
code.add(strutils.escape(getLinkOptions(conf) & " " &
getConfigVar(conf, conf.cCompiler, ".options.linker")))
add(code, "\n[Environment]\nlibpath=")
add(code, strutils.escape(conf.libpath.string))
code.add("\n[Environment]\nlibpath=")
code.add(strutils.escape(conf.libpath.string))
addf(code, "\n[Symbols]$n$1", [symbolMapping])
code.addf("\n[Symbols]$n$1", [symbolMapping])
let filename = conf.projectPath / RelativeFile"mapping.txt"
if not writeRope(code, filename):
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)

View File

@@ -10,8 +10,8 @@
# This module implements Nim's standard template filter.
import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
renderer, filters, lineinfos, pathutils
llstream, strutils, ast, msgs, options,
filters, lineinfos, pathutils
type
TParseState = enum
@@ -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
@@ -75,7 +75,7 @@ proc parseLine(p: var TTmplParser) =
let d = j
var keyw = ""
while j < len and p.x[j] in PatternChars:
add(keyw, p.x[j])
keyw.add(p.x[j])
inc(j)
scanPar(p, j)

View File

@@ -10,7 +10,7 @@
# This module implements Nim's simple filters and helpers for filters.
import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
llstream, idents, strutils, ast, msgs, options,
renderer, pathutils
proc invalidPragma(conf: ConfigRef; n: PNode) =
@@ -20,13 +20,13 @@ 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):
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:
return n.sons[i].sons[1]
for i in 1..<n.len:
if n[i].kind == nkExprEqExpr:
if n[i][0].kind != nkIdent: invalidPragma(conf, n)
if cmpIgnoreStyle(n[i][0].ident.s, name) == 0:
return n[i][1]
elif i == pos:
return n.sons[i]
return n[i]
proc charArg*(conf: ConfigRef; n: PNode, name: string, pos: int, default: char): char =
var x = getArg(conf, n, name, pos)
@@ -55,7 +55,7 @@ proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, cal
var line = newStringOfCap(80)
while llStreamReadLine(stdin, line):
var stripped = strip(line, leading, trailing)
if len(pattern) == 0 or startsWith(stripped, pattern):
if pattern.len == 0 or startsWith(stripped, pattern):
llStreamWriteln(result, stripped)
else:
llStreamWriteln(result, line)
@@ -63,7 +63,7 @@ proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, cal
proc filterReplace*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, call: PNode): PLLStream =
var sub = strArg(conf, call, "sub", 1, "")
if len(sub) == 0: invalidPragma(conf, call)
if sub.len == 0: invalidPragma(conf, call)
var by = strArg(conf, call, "by", 2, "")
result = llStreamOpen("")
var line = newStringOfCap(80)

View File

@@ -13,8 +13,8 @@ import ast, astalgo
const
someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
mEqUntracedRef, mLeI, mLeF64, mLeU, mLeU64, mLeEnum,
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtU64, mLtEnum,
mLeI, mLeF64, mLeU, mLeEnum,
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtEnum,
mLtCh, mLtB, mLtPtr}
proc isCounter(s: PSym): bool {.inline.} =
@@ -45,13 +45,13 @@ proc counterInTree(n, loop: PNode; counter: PSym): bool =
for it in n:
if counterInTree(it.lastSon): return true
else:
for i in 0 ..< safeLen(n):
for i in 0..<n.safeLen:
if counterInTree(n[i], loop, counter): return true
proc copyExcept(n: PNode, x, dest: PNode) =
if x == n: return
if n.kind in {nkStmtList, nkStmtListExpr}:
for i in 0 ..< n.len: copyExcept(n[i], x, dest)
for i in 0..<n.len: copyExcept(n[i], x, dest)
else:
dest.add n

View File

@@ -9,7 +9,7 @@
## Module that implements ``gorge`` for the compiler.
import msgs, std / sha1, os, osproc, streams, strutils, options,
import msgs, std / sha1, os, osproc, streams, options,
lineinfos, pathutils
proc readOutput(p: Process): (string, int) =
@@ -35,11 +35,12 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
var readSuccessful = false
try:
var p = startProcess(cmd, workingDir,
options={poEvalCommand, poStderrToStdout})
options={poEvalCommand, poStdErrToStdOut})
if input.len != 0:
p.inputStream.write(input)
p.inputStream.close()
result = p.readOutput
p.close()
readSuccessful = true
# only cache successful runs:
if result[1] == 0:
@@ -49,10 +50,11 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
else:
try:
var p = startProcess(cmd, workingDir,
options={poEvalCommand, poStderrToStdout})
options={poEvalCommand, poStdErrToStdOut})
if input.len != 0:
p.inputStream.write(input)
p.inputStream.close()
result = p.readOutput
p.close()
except IOError, OSError:
result = ("", -1)

View File

@@ -10,22 +10,21 @@
## 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,
mEqUntracedRef, mEqStr, mEqSet, mEqCString}
mEqStr, mEqSet, mEqCString}
# set excluded here as the semantics are vastly different:
someLe = {mLeI, mLeF64, mLeU, mLeU64, mLeEnum,
someLe = {mLeI, mLeF64, mLeU, mLeEnum,
mLeCh, mLeB, mLePtr, mLeStr}
someLt = {mLtI, mLtF64, mLtU, mLtU64, mLtEnum,
someLt = {mLtI, mLtF64, mLtU, mLtEnum,
mLtCh, mLtB, mLtPtr, mLtStr}
someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
mXLenStr, mXLenSeq}
someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq}
someIn = {mInRange, mInSet}
someIn = {mInSet}
someHigh = {mHigh}
# we don't list unsigned here because wrap around semantics suck for
@@ -35,8 +34,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}
@@ -65,16 +64,16 @@ proc isLetLocation(m: PNode, isApprox: bool): bool =
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkObjUpConv, nkObjDownConv:
n = n.sons[0]
n = n[0]
of nkDerefExpr, nkHiddenDeref:
n = n.sons[0]
n = n[0]
inc derefs
of nkBracketExpr:
if isConstExpr(n.sons[1]) or isLet(n.sons[1]) or isConstExpr(n.sons[1].skipConv):
n = n.sons[0]
if isConstExpr(n[1]) or isLet(n[1]) or isConstExpr(n[1].skipConv):
n = n[0]
else: return
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
n = n.sons[1]
n = n[1]
else:
break
result = n.isLet and derefs <= ord(isApprox)
@@ -105,34 +104,34 @@ proc initOperators*(g: ModuleGraph): Operators =
proc swapArgs(fact: PNode, newOp: PSym): PNode =
result = newNodeI(nkCall, fact.info, 3)
result.sons[0] = newSymNode(newOp)
result.sons[1] = fact.sons[2]
result.sons[2] = fact.sons[1]
result[0] = newSymNode(newOp)
result[1] = fact[2]
result[2] = fact[1]
proc neg(n: PNode; o: Operators): PNode =
if n == nil: return nil
case n.getMagic
of mNot:
result = n.sons[1]
result = n[1]
of someLt:
# not (a < b) == a >= b == b <= a
result = swapArgs(n, o.opLe)
of someLe:
result = swapArgs(n, o.opLt)
of mInSet:
if n.sons[1].kind != nkCurly: return nil
let t = n.sons[2].typ.skipTypes(abstractInst)
if n[1].kind != nkCurly: return nil
let t = n[2].typ.skipTypes(abstractInst)
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = n.sons[0]
result.sons[2] = n.sons[2]
result[0] = n[0]
result[2] = n[2]
if t.kind == tyEnum:
var s = newNodeIT(nkCurly, n.info, n.sons[1].typ)
var s = newNodeIT(nkCurly, n.info, n[1].typ)
for e in t.n:
let eAsNode = newIntNode(nkIntLit, e.sym.position)
if not inSet(n.sons[1], eAsNode): s.add eAsNode
result.sons[1] = s
if not inSet(n[1], eAsNode): s.add eAsNode
result[1] = s
#elif t.kind notin {tyString, tySequence} and lengthOrd(t) < 1000:
# result.sons[1] = complement(n.sons[1])
# result[1] = complement(n[1])
else:
# not ({2, 3, 4}.contains(x)) x != 2 and x != 3 and x != 4
# XXX todo
@@ -140,13 +139,13 @@ proc neg(n: PNode; o: Operators): PNode =
of mOr:
# not (a or b) --> not a and not b
let
a = n.sons[1].neg(o)
b = n.sons[2].neg(o)
a = n[1].neg(o)
b = n[2].neg(o)
if a != nil and b != nil:
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opAnd)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(o.opAnd)
result[1] = a
result[2] = b
elif a != nil:
result = a
elif b != nil:
@@ -154,19 +153,19 @@ proc neg(n: PNode; o: Operators): PNode =
else:
# leave not (a == 4) as it is
result = newNodeI(nkCall, n.info, 2)
result.sons[0] = newSymNode(o.opNot)
result.sons[1] = n
result[0] = newSymNode(o.opNot)
result[1] = n
proc buildCall(op: PSym; a: PNode): PNode =
result = newNodeI(nkCall, a.info, 2)
result.sons[0] = newSymNode(op)
result.sons[1] = a
result[0] = newSymNode(op)
result[1] = a
proc buildCall(op: PSym; a, b: PNode): PNode =
result = newNodeI(nkInfix, a.info, 3)
result.sons[0] = newSymNode(op)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(op)
result[1] = a
result[2] = b
proc `|+|`(a, b: PNode): PNode =
result = copyNode(a)
@@ -250,35 +249,35 @@ proc pred(n: PNode): PNode =
else:
result = n
proc buildLe*(o: Operators; a, b: PNode): PNode =
result = o.opLe.buildCall(a, b)
proc canon*(n: PNode; o: Operators): PNode =
# XXX for now only the new code in 'semparallel' uses this
if n.safeLen >= 1:
result = shallowCopy(n)
for i in 0 ..< n.len:
result.sons[i] = canon(n.sons[i], o)
for i in 0..<n.len:
result[i] = canon(n[i], o)
elif n.kind == nkSym and n.sym.kind == skLet and
n.sym.astdef.getMagic in (someEq + someAdd + someMul + someMin +
someMax + someHigh + {mUnaryLt} + someSub + someLen + someDiv):
someMax + someHigh + someSub + someLen + someDiv):
result = n.sym.astdef.copyTree
else:
result = n
case result.getMagic
of someEq, someAdd, someMul, someMin, someMax:
# these are symmetric; put value as last:
if result.sons[1].isValue and not result.sons[2].isValue:
result = swapArgs(result, result.sons[0].sym)
if result[1].isValue and not result[2].isValue:
result = swapArgs(result, result[0].sym)
# (4 + foo) + 2 --> (foo + 4) + 2
of someHigh:
# high == len+(-1)
result = o.opAdd.buildCall(o.opLen.buildCall(result[1]), minusOne())
of mUnaryLt:
result = buildCall(o.opAdd, result[1], minusOne())
of someSub:
# x - 4 --> x + (-4)
result = negate(result[1], result[2], result, o)
of someLen:
result.sons[0] = o.opLen.newSymNode
of someLt:
result[0] = o.opLen.newSymNode
of someLt - {mLtF64}:
# x < y same as x <= y-1:
let y = n[2].canon(o)
let p = pred(y)
@@ -318,16 +317,16 @@ proc canon*(n: PNode; o: Operators): PNode =
if plus != nil and not isLetLocation(x, true):
result = buildCall(result[0].sym, plus, y[1])
else: discard
elif x.isValue and y.getMagic in someAdd and y[2].isValue:
elif x.isValue and y.getMagic in someAdd and y[2].kind == x.kind:
# 0 <= a.len + 3
# -3 <= a.len
result.sons[1] = x |-| y[2]
result.sons[2] = y[1]
elif x.isValue and y.getMagic in someSub and y[2].isValue:
result[1] = x |-| y[2]
result[2] = y[1]
elif x.isValue and y.getMagic in someSub and y[2].kind == x.kind:
# 0 <= a.len - 3
# 3 <= a.len
result.sons[1] = x |+| y[2]
result.sons[2] = y[1]
result[1] = x |+| y[2]
result[2] = y[1]
else: discard
proc buildAdd*(a: PNode; b: BiggestInt; o: Operators): PNode =
@@ -336,41 +335,43 @@ proc buildAdd*(a: PNode; b: BiggestInt; o: Operators): PNode =
proc usefulFact(n: PNode; o: Operators): PNode =
case n.getMagic
of someEq:
if skipConv(n.sons[2]).kind == nkNilLit and (
isLetLocation(n.sons[1], false) or isVar(n.sons[1])):
result = o.opIsNil.buildCall(n.sons[1])
if skipConv(n[2]).kind == nkNilLit and (
isLetLocation(n[1], false) or isVar(n[1])):
result = o.opIsNil.buildCall(n[1])
else:
if isLetLocation(n.sons[1], true) or isLetLocation(n.sons[2], true):
if isLetLocation(n[1], true) or isLetLocation(n[2], true):
# XXX algebraic simplifications! 'i-1 < a.len' --> 'i < a.len+1'
result = n
elif n[1].getMagic in someLen or n[2].getMagic in someLen:
result = n
of someLe+someLt:
if isLetLocation(n.sons[1], true) or isLetLocation(n.sons[2], true):
if isLetLocation(n[1], true) or isLetLocation(n[2], true):
# XXX algebraic simplifications! 'i-1 < a.len' --> 'i < a.len+1'
result = n
elif n[1].getMagic in someLen or n[2].getMagic in someLen:
# XXX Rethink this whole idea of 'usefulFact' for semparallel
result = n
of mIsNil:
if isLetLocation(n.sons[1], false) or isVar(n.sons[1]):
if isLetLocation(n[1], false) or isVar(n[1]):
result = n
of someIn:
if isLetLocation(n.sons[1], true):
if isLetLocation(n[1], true):
result = n
of mAnd:
let
a = usefulFact(n.sons[1], o)
b = usefulFact(n.sons[2], o)
a = usefulFact(n[1], o)
b = usefulFact(n[2], o)
if a != nil and b != nil:
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opAnd)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(o.opAnd)
result[1] = a
result[2] = b
elif a != nil:
result = a
elif b != nil:
result = b
of mNot:
let a = usefulFact(n.sons[1], o)
let a = usefulFact(n[1], o)
if a != nil:
result = a.neg(o)
of mOr:
@@ -381,13 +382,13 @@ proc usefulFact(n: PNode; o: Operators): PNode =
# (x == 3) or (y == 2) ---> not ( not (x==3) and not (y == 2))
# not (x != 3 and y != 2)
let
a = usefulFact(n.sons[1], o).neg(o)
b = usefulFact(n.sons[2], o).neg(o)
a = usefulFact(n[1], o).neg(o)
b = usefulFact(n[2], o).neg(o)
if a != nil and b != nil:
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opAnd)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(o.opAnd)
result[1] = a
result[2] = b
result = result.neg(o)
elif n.kind == nkSym and n.sym.kind == skLet:
# consider:
@@ -404,10 +405,20 @@ type
TModel* = object
s*: seq[PNode] # the "knowledge base"
o*: Operators
beSmart*: bool
proc addFact*(m: var TModel, nn: PNode) =
let n = usefulFact(nn, m.o)
if n != nil: m.s.add n
if n != nil:
if not m.beSmart:
m.s.add n
else:
let c = canon(n, m.o)
if c.getMagic == mAnd:
addFact(m, c[1])
addFact(m, c[2])
else:
m.s.add c
proc addFactNeg*(m: var TModel, n: PNode) =
let n = n.neg(m.o)
@@ -436,22 +447,22 @@ 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 not sameTree(a.sons[i], b.sons[i]): return
if a.len == b.len:
for i in 0..<a.len:
if not sameTree(a[i], b[i]): return
result = true
proc hasSubTree(n, x: PNode): bool =
if n.sameTree(x): result = true
else:
for i in 0..safeLen(n)-1:
if hasSubTree(n.sons[i], x): return true
for i in 0..n.safeLen-1:
if hasSubTree(n[i], x): return true
proc invalidateFacts*(m: var TModel, n: PNode) =
# We are able to guard local vars (as opposed to 'let' variables)!
@@ -479,21 +490,21 @@ proc valuesUnequal(a, b: PNode): bool =
result = not sameValue(a, b)
proc impliesEq(fact, eq: PNode): TImplication =
let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1)
let (loc, val) = if isLocation(eq[1]): (1, 2) else: (2, 1)
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], eq.sons[loc]):
if sameTree(fact[1], eq[loc]):
# this is not correct; consider: a == b; a == 1 --> unknown!
if sameTree(fact.sons[2], eq.sons[val]): result = impYes
elif valuesUnequal(fact.sons[2], eq.sons[val]): result = impNo
elif sameTree(fact.sons[2], eq.sons[loc]):
if sameTree(fact.sons[1], eq.sons[val]): result = impYes
elif valuesUnequal(fact.sons[1], eq.sons[val]): result = impNo
if sameTree(fact[2], eq[val]): result = impYes
elif valuesUnequal(fact[2], eq[val]): result = impNo
elif sameTree(fact[2], eq[loc]):
if sameTree(fact[1], eq[val]): result = impYes
elif valuesUnequal(fact[1], eq[val]): result = impNo
of mInSet:
# remember: mInSet is 'contains' so the set comes first!
if sameTree(fact.sons[2], eq.sons[loc]) and isValue(eq.sons[val]):
if inSet(fact.sons[1], eq.sons[val]): result = impYes
if sameTree(fact[2], eq[loc]) and isValue(eq[val]):
if inSet(fact[1], eq[val]): result = impYes
else: result = impNo
of mNot, mOr, mAnd: assert(false, "impliesEq")
else: discard
@@ -522,7 +533,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
@@ -536,28 +547,28 @@ proc compareSets(a, b: PNode): TImplication =
elif intersectSets(nil, a, b).len == 0: result = impNo
proc impliesIn(fact, loc, aSet: PNode): TImplication =
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], loc):
if inSet(aSet, fact.sons[2]): result = impYes
if sameTree(fact[1], loc):
if inSet(aSet, fact[2]): result = impYes
else: result = impNo
elif sameTree(fact.sons[2], loc):
if inSet(aSet, fact.sons[1]): result = impYes
elif sameTree(fact[2], loc):
if inSet(aSet, fact[1]): result = impYes
else: result = impNo
of mInSet:
if sameTree(fact.sons[2], loc):
result = compareSets(fact.sons[1], aSet)
if sameTree(fact[2], loc):
result = compareSets(fact[1], aSet)
of someLe:
if sameTree(fact.sons[1], loc):
result = leImpliesIn(fact.sons[1], fact.sons[2], aSet)
elif sameTree(fact.sons[2], loc):
result = geImpliesIn(fact.sons[2], fact.sons[1], aSet)
if sameTree(fact[1], loc):
result = leImpliesIn(fact[1], fact[2], aSet)
elif sameTree(fact[2], loc):
result = geImpliesIn(fact[2], fact[1], aSet)
of someLt:
if sameTree(fact.sons[1], loc):
result = leImpliesIn(fact.sons[1], fact.sons[2].pred, aSet)
elif sameTree(fact.sons[2], loc):
if sameTree(fact[1], loc):
result = leImpliesIn(fact[1], fact[2].pred, aSet)
elif sameTree(fact[2], loc):
# 4 < x --> 3 <= x
result = geImpliesIn(fact.sons[2], fact.sons[1].pred, aSet)
result = geImpliesIn(fact[2], fact[1].pred, aSet)
of mNot, mOr, mAnd: assert(false, "impliesIn")
else: discard
@@ -567,90 +578,93 @@ proc valueIsNil(n: PNode): TImplication =
else: impUnknown
proc impliesIsNil(fact, eq: PNode): TImplication =
case fact.sons[0].sym.magic
case fact[0].sym.magic
of mIsNil:
if sameTree(fact.sons[1], eq.sons[1]):
if sameTree(fact[1], eq[1]):
result = impYes
of someEq:
if sameTree(fact.sons[1], eq.sons[1]):
result = valueIsNil(fact.sons[2].skipConv)
elif sameTree(fact.sons[2], eq.sons[1]):
result = valueIsNil(fact.sons[1].skipConv)
if sameTree(fact[1], eq[1]):
result = valueIsNil(fact[2].skipConv)
elif sameTree(fact[2], eq[1]):
result = valueIsNil(fact[1].skipConv)
of mNot, mOr, mAnd: assert(false, "impliesIsNil")
else: discard
proc impliesGe(fact, x, c: PNode): TImplication =
assert isLocation(x)
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x = 4; question x >= 56? --> true iff 4 >= 56
if leValue(c, fact.sons[2]): result = impYes
if leValue(c, fact[2]): result = impYes
else: result = impNo
elif sameTree(fact.sons[2], x):
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1]): result = impYes
elif sameTree(fact[2], x):
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1]): result = impYes
else: result = impNo
of someLt:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x < 4; question N <= x? --> false iff N <= 4
if leValue(fact.sons[2], c): result = impNo
if leValue(fact[2], c): result = impNo
# fact: x < 4; question 2 <= x? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 < x; question: N-1 < x ? --> true iff N-1 <= 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c.pred, fact.sons[1]): result = impYes
if isValue(fact[1]) and isValue(c):
if leValue(c.pred, fact[1]): result = impYes
of someLe:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x <= 4; question x >= 56? --> false iff 4 <= 56
if leValue(fact.sons[2], c): result = impNo
if leValue(fact[2], c): result = impNo
# fact: x <= 4; question x >= 2? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 <= x; question: x >= 2 ? --> true iff 2 <= 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1]): result = impYes
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1]): result = impYes
of mNot, mOr, mAnd: assert(false, "impliesGe")
else: discard
proc impliesLe(fact, x, c: PNode): TImplication =
if not isLocation(x):
if c.isValue:
if leValue(x, x): return impYes
else: return impNo
return impliesGe(fact, c, x)
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x = 4; question x <= 56? --> true iff 4 <= 56
if leValue(fact.sons[2], c): result = impYes
if leValue(fact[2], c): result = impYes
else: result = impNo
elif sameTree(fact.sons[2], x):
if isValue(fact.sons[1]) and isValue(c):
if leValue(fact.sons[1], c): result = impYes
elif sameTree(fact[2], x):
if isValue(fact[1]) and isValue(c):
if leValue(fact[1], c): result = impYes
else: result = impNo
of someLt:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x < 4; question x <= N? --> true iff N-1 <= 4
if leValue(fact.sons[2], c.pred): result = impYes
if leValue(fact[2], c.pred): result = impYes
# fact: x < 4; question x <= 2? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 < x; question: x <= 1 ? --> false iff 1 <= 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1]): result = impNo
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1]): result = impNo
of someLe:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x <= 4; question x <= 56? --> true iff 4 <= 56
if leValue(fact.sons[2], c): result = impYes
if leValue(fact[2], c): result = impYes
# fact: x <= 4; question x <= 2? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 <= x; question: x <= 2 ? --> false iff 2 < 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1].pred): result = impNo
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1].pred): result = impNo
of mNot, mOr, mAnd: assert(false, "impliesLe")
else: discard
@@ -686,32 +700,32 @@ proc factImplies(fact, prop: PNode): TImplication =
# (not a) -> b compute as not (a -> b) ???
# == not a or not b == not (a and b)
let arg = fact.sons[1]
let arg = fact[1]
case arg.getMagic
of mIsNil, mEqRef:
return ~factImplies(arg, prop)
of mAnd:
# not (a and b) means not a or not b:
# a or b --> both need to imply 'prop'
let a = factImplies(arg.sons[1], prop)
let b = factImplies(arg.sons[2], prop)
let a = factImplies(arg[1], prop)
let b = factImplies(arg[2], prop)
if a == b: return ~a
return impUnknown
else:
return impUnknown
of mAnd:
result = factImplies(fact.sons[1], prop)
result = factImplies(fact[1], prop)
if result != impUnknown: return result
return factImplies(fact.sons[2], prop)
return factImplies(fact[2], prop)
else: discard
case prop.sons[0].sym.magic
of mNot: result = ~fact.factImplies(prop.sons[1])
case prop[0].sym.magic
of mNot: result = ~fact.factImplies(prop[1])
of mIsNil: result = impliesIsNil(fact, prop)
of someEq: result = impliesEq(fact, prop)
of someLe: result = impliesLe(fact, prop.sons[1], prop.sons[2])
of someLt: result = impliesLt(fact, prop.sons[1], prop.sons[2])
of mInSet: result = impliesIn(fact, prop.sons[2], prop.sons[1])
of someLe: result = impliesLe(fact, prop[1], prop[2])
of someLt: result = impliesLt(fact, prop[1], prop[2])
of mInSet: result = impliesIn(fact, prop[2], prop[1])
else: result = impUnknown
proc doesImply*(facts: TModel, prop: PNode): TImplication =
@@ -802,7 +816,7 @@ proc ple(m: TModel; a, b: PNode): TImplication =
if lastOrd(nil, a.typ) <= b.intVal: return impYes
# 3 <= x iff low(x) <= 3
if a.isValue and b.typ != nil and b.typ.isOrdinalType:
if firstOrd(nil, b.typ) <= a.intVal: return impYes
if a.intVal <= firstOrd(nil, b.typ): return impYes
# x <= x
if sameTree(a, b): return impYes
@@ -813,7 +827,11 @@ proc ple(m: TModel; a, b: PNode): TImplication =
# x <= y+c if 0 <= c and x <= y
# x <= y+(-c) if c <= 0 and y >= x
if b.getMagic in someAdd and zero() <=? b[2] and a <=? b[1]: return impYes
if b.getMagic in someAdd:
if zero() <=? b[2] and a <=? b[1]: return impYes
# x <= y-c if x+c <= y
if b[2] <=? zero() and (canon(m.o.opSub.buildCall(a, b[2]), m.o) <=? b[1]):
return impYes
# x+c <= y if c <= 0 and x <= y
if a.getMagic in someAdd and a[2] <=? zero() and a[1] <=? b: return impYes
@@ -881,8 +899,8 @@ proc replaceSubTree(n, x, by: PNode): PNode =
result = by
elif hasSubTree(n, x):
result = shallowCopy(n)
for i in 0 .. safeLen(n)-1:
result.sons[i] = replaceSubTree(n.sons[i], x, by)
for i in 0..n.safeLen-1:
result[i] = replaceSubTree(n[i], x, by)
else:
result = n
@@ -902,10 +920,13 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication =
# --> true if (len-100) <= (len-1)
let x = fact[1]
let y = fact[2]
if sameTree(x, a) and y.getMagic in someAdd and b.getMagic in someAdd and
sameTree(y[1], b[1]):
if ple(m, b[2], y[2]) == impYes:
return impYes
# x <= y.
# Question: x <= b? True iff y <= b.
if sameTree(x, a):
if ple(m, y, b) == impYes: return impYes
if y.getMagic in someAdd and b.getMagic in someAdd and sameTree(y[1], b[1]):
if ple(m, b[2], y[2]) == impYes:
return impYes
# x <= y implies a <= b if a <= x and y <= b
if ple(m, a, x) == impYes:
@@ -964,6 +985,10 @@ proc proveLe*(m: TModel; a, b: PNode): TImplication =
proc addFactLe*(m: var TModel; a, b: PNode) =
m.s.add canon(m.o.opLe.buildCall(a, b), m.o)
proc addFactLt*(m: var TModel; a, b: PNode) =
let bb = m.o.opAdd.buildCall(b, minusOne())
addFactLe(m, a, bb)
proc settype(n: PNode): PType =
result = newType(tySet, n.typ.owner)
addSonSkipIntLit(result, n.typ)
@@ -971,36 +996,37 @@ proc settype(n: PNode): PType =
proc buildOf(it, loc: PNode; o: Operators): PNode =
var s = newNodeI(nkCurly, it.info, it.len-1)
s.typ = settype(loc)
for i in 0..it.len-2: s.sons[i] = it.sons[i]
for i in 0..<it.len-1: s[i] = it[i]
result = newNodeI(nkCall, it.info, 3)
result.sons[0] = newSymNode(o.opContains)
result.sons[1] = s
result.sons[2] = loc
result[0] = newSymNode(o.opContains)
result[1] = s
result[2] = loc
proc buildElse(n: PNode; o: Operators): PNode =
var s = newNodeIT(nkCurly, n.info, settype(n.sons[0]))
for i in 1..n.len-2:
let branch = n.sons[i]
assert branch.kind == nkOfBranch
for j in 0..branch.len-2:
s.add(branch.sons[j])
var s = newNodeIT(nkCurly, n.info, settype(n[0]))
for i in 1..<n.len-1:
let branch = n[i]
assert branch.kind != nkElse
if branch.kind == nkOfBranch:
for j in 0..<branch.len-1:
s.add(branch[j])
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opContains)
result.sons[1] = s
result.sons[2] = n.sons[0]
result[0] = newSymNode(o.opContains)
result[1] = s
result[2] = n[0]
proc addDiscriminantFact*(m: var TModel, n: PNode) =
var fact = newNodeI(nkCall, n.info, 3)
fact.sons[0] = newSymNode(m.o.opEq)
fact.sons[1] = n.sons[0]
fact.sons[2] = n.sons[1]
fact[0] = newSymNode(m.o.opEq)
fact[1] = n[0]
fact[2] = n[1]
m.s.add fact
proc addAsgnFact*(m: var TModel, key, value: PNode) =
var fact = newNodeI(nkCall, key.info, 3)
fact.sons[0] = newSymNode(m.o.opEq)
fact.sons[1] = key
fact.sons[2] = value
fact[0] = newSymNode(m.o.opEq)
fact[1] = key
fact[2] = value
m.s.add fact
proc sameSubexprs*(m: TModel; a, b: PNode): bool =
@@ -1014,34 +1040,34 @@ proc sameSubexprs*(m: TModel; a, b: PNode): bool =
# However, nil checking requires exactly the same mechanism! But for now
# we simply use sameTree and live with the unsoundness of the analysis.
var check = newNodeI(nkCall, a.info, 3)
check.sons[0] = newSymNode(m.o.opEq)
check.sons[1] = a
check.sons[2] = b
check[0] = newSymNode(m.o.opEq)
check[1] = a
check[2] = b
result = m.doesImply(check) == impYes
proc addCaseBranchFacts*(m: var TModel, n: PNode, i: int) =
let branch = n.sons[i]
let branch = n[i]
if branch.kind == nkOfBranch:
m.s.add buildOf(branch, n.sons[0], m.o)
m.s.add buildOf(branch, n[0], m.o)
else:
m.s.add n.buildElse(m.o).neg(m.o)
proc buildProperFieldCheck(access, check: PNode; o: Operators): PNode =
if check.sons[1].kind == nkCurly:
if check[1].kind == nkCurly:
result = copyTree(check)
if access.kind == nkDotExpr:
var a = copyTree(access)
a.sons[1] = check.sons[2]
result.sons[2] = a
a[1] = check[2]
result[2] = a
# 'access.kind != nkDotExpr' can happen for object constructors
# which we don't check yet
else:
# it is some 'not'
assert check.getMagic == mNot
result = buildProperFieldCheck(access, check.sons[1], o).neg(o)
result = buildProperFieldCheck(access, check[1], o).neg(o)
proc checkFieldAccess*(m: TModel, n: PNode; conf: ConfigRef) =
for i in 1..n.len-1:
let check = buildProperFieldCheck(n.sons[0], n.sons[i], m.o)
for i in 1..<n.len:
let check = buildProperFieldCheck(n[0], n[i], m.o)
if check != nil and m.doesImply(check) != impYes:
message(conf, n.info, warnProveField, renderTree(n.sons[0])); break
message(conf, n.info, warnProveField, renderTree(n[0])); break

View File

@@ -12,14 +12,14 @@
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
internalAssert c.config, n.kind == nkCall and n[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:
if c.config.hasHint(hintPattern):
rule = renderTree(n, {renderNoComments})
let s = n.sons[0].sym
let s = n[0].sym
case s.kind
of skMacro:
result = semMacroExpr(c, n, orig, s)
@@ -27,7 +27,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
result = semTemplateExpr(c, n, s, {efFromHlo})
else:
result = semDirectOp(c, n, {})
if optHints in c.config.options and hintPattern in c.config.notes:
if c.config.hasHint(hintPattern):
message(c.config, orig.info, hintPattern, rule & " --> '" &
renderTree(result, {renderNoComments}) & "'")
@@ -50,7 +50,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
c.patterns[i] = nil
if x.kind == nkStmtList:
assert x.len == 3
x.sons[1] = evalPattern(c, x.sons[1], result)
x[1] = evalPattern(c, x[1], result)
result = flattenStmts(x)
else:
result = evalPattern(c, x, result)
@@ -68,17 +68,17 @@ proc hlo(c: PContext, n: PNode): PNode =
result = n
else:
if n.kind in {nkFastAsgn, nkAsgn, nkIdentDefs, nkVarTuple} and
n.sons[0].kind == nkSym and
{sfGlobal, sfPure} * n.sons[0].sym.flags == {sfGlobal, sfPure}:
n[0].kind == nkSym and
{sfGlobal, sfPure} * n[0].sym.flags == {sfGlobal, sfPure}:
# do not optimize 'var g {.global} = re(...)' again!
return n
result = applyPatterns(c, n)
if result == n:
# no optimization applied, try subtrees:
for i in 0 ..< safeLen(result):
let a = result.sons[i]
for i in 0..<result.safeLen:
let a = result[i]
let h = hlo(c, a)
if h != a: result.sons[i] = h
if h != a: result[i] = h
else:
# perform type checking, so that the replacement still fits:
if isEmptyType(n.typ) and isEmptyType(result.typ):

View File

@@ -12,7 +12,7 @@
# id. This module is essential for the compiler's performance.
import
hashes, strutils, wordrecg
hashes, wordrecg
type
TIdObj* = object of RootObj
@@ -87,7 +87,7 @@ proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIden
new(result)
result.h = h
result.s = newString(length)
for i in 0 ..< length: result.s[i] = identifier[i]
for i in 0..<length: result.s[i] = identifier[i]
result.next = ic.buckets[idx]
ic.buckets[idx] = result
if id == 0:
@@ -97,11 +97,11 @@ proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIden
result.id = id
proc getIdent*(ic: IdentCache; identifier: string): PIdent =
result = getIdent(ic, cstring(identifier), len(identifier),
result = getIdent(ic, cstring(identifier), identifier.len,
hashIgnoreStyle(identifier))
proc getIdent*(ic: IdentCache; identifier: string, h: Hash): PIdent =
result = getIdent(ic, cstring(identifier), len(identifier), h)
result = getIdent(ic, cstring(identifier), identifier.len, h)
proc newIdentCache*(): IdentCache =
result = IdentCache()
@@ -110,7 +110,7 @@ proc newIdentCache*(): IdentCache =
result.idDelegator = result.getIdent":delegator"
result.emptyIdent = result.getIdent("")
# initialize the keywords:
for s in succ(low(specialWords)) .. high(specialWords):
for s in succ(low(specialWords))..high(specialWords):
result.getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s)
proc whichKeyword*(id: PIdent): TSpecialWord =

View File

@@ -9,7 +9,7 @@
## This module contains a simple persistent id generator.
import idents, strutils, os, options, pathutils
import idents, strutils, options, pathutils
var gFrontEndId*: int

View File

@@ -10,13 +10,13 @@
## This module implements the symbol importing mechanism.
import
intsets, strutils, os, ast, astalgo, msgs, options, idents, lookups,
semdata, passes, renderer, modulepaths, sigmatch, lineinfos
intsets, ast, astalgo, msgs, options, idents, lookups,
semdata, modulepaths, sigmatch, lineinfos, sets
proc readExceptSet*(c: PContext, n: PNode): IntSet =
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
result = initIntSet()
for i in 1 ..< n.len:
for i in 1..<n.len:
let ident = lookups.considerQuotedIdent(c, n[i])
result.incl(ident.id)
@@ -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,8 +47,8 @@ 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):
var e = etyp.n.sons[j].sym
for j in 0..<etyp.n.len:
var e = etyp.n[j].sym
if e.kind != skEnumField:
internalError(c.config, s.info, "rawImportSymbol")
# BUGFIX: because of aliases for enums the symbol may already
@@ -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)
@@ -79,19 +80,19 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
else:
when false:
if s.kind == skStub: loadStub(s)
if s.kind notin ExportableSymKinds:
internalError(c.config, n.info, "importSymbol: 2")
let multiImport = s.kind notin ExportableSymKinds or s.kind in skProcKinds
# for an enumeration we have to add all identifiers
case s.kind
of skProcKinds:
if multiImport:
# for a overloadable syms add all overloaded routines
var it: TIdentIter
var e = initIdentIter(it, fromMod.tab, s.name)
while e != nil:
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
rawImportSymbol(c, e)
if s.kind in ExportableSymKinds:
rawImportSymbol(c, e, fromMod)
e = nextIdentIter(it, fromMod.tab)
else: rawImportSymbol(c, s)
else:
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,38 +121,43 @@ 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)
for i in 0..n.safeLen-1:
importForwarded(c, n[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:
elif n.len != 2 or n[1].kind != nkIdent:
localError(c.config, n.info, "module alias must be an identifier")
elif n.sons[1].ident.id != realModule.name.id:
elif n[1].ident.id != realModule.name.id:
# some misguided guy will write 'import abc.foo as foo' ...
result = createModuleAlias(realModule, n.sons[1].ident, realModule.info,
result = createModuleAlias(realModule, n[1].ident, realModule.info,
c.config.options)
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
let f = checkModuleName(c.config, n)
if f != InvalidFileIDX:
if f != InvalidFileIdx:
let L = c.graph.importStack.len
let recursion = c.graph.importStack.find(f)
c.graph.importStack.add f
#echo "adding ", toFullPath(f), " at ", L+1
if recursion >= 0:
var err = ""
for i in recursion ..< L:
for i in recursion..<L:
if i > recursion: err.add "\n"
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
@@ -172,8 +178,8 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
proc transformImportAs(c: PContext; n: PNode): PNode =
if n.kind == nkInfix and considerQuotedIdent(c, n[0]).s == "as":
result = newNodeI(nkImportAs, n.info)
result.add n.sons[1]
result.add n.sons[2]
result.add n[1]
result.add n[2]
else:
result = n
@@ -185,12 +191,12 @@ 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):
let it = n.sons[i]
for i in 0..<n.len:
let it = n[i]
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
let sep = it[0]
let dir = it[1]
@@ -200,13 +206,13 @@ proc evalImport*(c: PContext, n: PNode): PNode =
imp.add sep # dummy entry, replaced in the loop
for x in it[2]:
# transform `a/b/[c as d]` to `/a/b/c as d`
if x.kind == nkInfix and x.sons[0].ident.s == "as":
if x.kind == nkInfix and x[0].ident.s == "as":
let impAs = copyTree(x)
imp.sons[2] = x.sons[1]
impAs.sons[1] = imp
imp[2] = x[1]
impAs[1] = imp
impMod(c, imp, result)
else:
imp.sons[2] = x
imp[2] = x
impMod(c, imp, result)
else:
impMod(c, it, result)
@@ -214,22 +220,22 @@ proc evalImport*(c: PContext, n: PNode): PNode =
proc evalFrom*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
checkMinSonsLen(n, 2, c.config)
n.sons[0] = transformImportAs(c, n.sons[0])
var m = myImportModule(c, n.sons[0], result)
n[0] = transformImportAs(c, n[0])
var m = myImportModule(c, n[0], result)
if m != nil:
n.sons[0] = newSymNode(m)
n[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
for i in 1 ..< sonsLen(n):
if n.sons[i].kind != nkNilLit:
importSymbol(c, n.sons[i], m)
for i in 1..<n.len:
if n[i].kind != nkNilLit:
importSymbol(c, n[i], m)
proc evalImportExcept*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
checkMinSonsLen(n, 2, c.config)
n.sons[0] = transformImportAs(c, n.sons[0])
var m = myImportModule(c, n.sons[0], result)
n[0] = transformImportAs(c, n[0])
var m = myImportModule(c, n[0], result)
if m != nil:
n.sons[0] = newSymNode(m)
n[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

@@ -12,11 +12,12 @@
const nimIncremental* = defined(nimIncremental)
import options, lineinfos, pathutils
import options, lineinfos
when nimIncremental:
import ast, msgs, intsets, btrees, db_sqlite, std / sha1
import ast, msgs, intsets, btrees, db_sqlite, std / sha1, pathutils
from strutils import parseInt
from os import isAbsolute
type
Writer* = object
@@ -47,7 +48,7 @@ when nimIncremental:
proc hashFileCached*(conf: ConfigRef; fileIdx: FileIndex; fullpath: AbsoluteFile): string =
result = msgs.getHash(conf, fileIdx)
if result.len == 0:
if result.len == 0 and isAbsolute(string fullpath):
result = $secureHashFile(string fullpath)
msgs.setHash(conf, fileIdx, result)

File diff suppressed because it is too large Load Diff

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;hppa;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;arm;arm64
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"
@@ -76,6 +77,7 @@ Files: "lib"
[Other]
Files: "examples"
Files: "dist/nimble"
Files: "dist/fusion"
Files: "tests"
@@ -86,6 +88,9 @@ Files: "bin/nimsuggest.exe"
Files: "bin/nimble.exe"
Files: "bin/vccexe.exe"
Files: "bin/nimgrab.exe"
Files: "bin/nimpretty.exe"
Files: "bin/testament.exe"
Files: "bin/nim-gdb.bat"
Files: "koch.exe"
Files: "finish.exe"
@@ -114,6 +119,8 @@ Files: "bin/nim"
[Unix]
InstallScript: "yes"
UninstallScript: "yes"
Files: "bin/nim-gdb"
Files: "bin/nim-gdb.bash"
[InnoSetup]
@@ -136,4 +143,4 @@ licenses: "bin/nim,MIT;lib/*,MIT;"
[nimble]
pkgName: "compiler"
pkgFiles: "compiler/*;doc/basicopt.txt;doc/advopt.txt"
pkgFiles: "compiler/*;doc/basicopt.txt;doc/advopt.txt;doc/nimdoc.css"

781
compiler/int128.nim Normal file
View File

@@ -0,0 +1,781 @@
## 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
udata: array[4,uint32]
template sdata(arg: Int128, idx: int): int32 =
# udata and sdata was supposed to be in a union, but unions are
# handled incorrectly in the VM.
cast[ptr int32](arg.udata[idx].unsafeAddr)[]
# encoding least significant int first (like LittleEndian)
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
proc `$`*(a: Int128): string
proc toInt128*[T: SomeInteger | bool](arg: T): Int128 =
when T is bool: result.sdata(0) = int32(arg)
elif T is SomeUnsignedInt:
when sizeof(arg) <= 4:
result.udata[0] = uint32(arg)
else:
result.udata[0] = uint32(arg and T(0xffffffff))
result.udata[1] = uint32(arg shr 32)
elif sizeof(arg) <= 4:
result.sdata(0) = int32(arg)
if arg < 0: # sign extend
result.sdata(1) = -1
result.sdata(2) = -1
result.sdata(3) = -1
else:
let tmp = int64(arg)
result.udata[0] = uint32(tmp and 0xffffffff)
result.sdata(1) = int32(tmp shr 32)
if arg < 0: # sign extend
result.sdata(2) = -1
result.sdata(3) = -1
template isNegative(arg: Int128): bool =
arg.sdata(3) < 0
template isNegative(arg: int32): bool =
arg < 0
proc bitconcat(a,b: uint32): uint64 =
(uint64(a) shl 32) or uint64(b)
proc bitsplit(a: uint64): (uint32,uint32) =
(cast[uint32](a shr 32), cast[uint32](a))
proc toInt64*(arg: Int128): int64 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
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
result.add "0123456789abcdef"[idx]
proc addToHex*(result: var string; arg: Int128) =
var i = 3
while i >= 0:
result.addToHex(arg.udata[i])
i -= 1
proc toHex*(arg: Int128): string =
result.addToHex(arg)
proc inc*(a: var Int128, y: uint32 = 1) =
let input = a
a.udata[0] += y
if unlikely(a.udata[0] < y):
a.udata[1].inc
if unlikely(a.udata[1] == 0):
a.udata[2].inc
if unlikely(a.udata[2] == 0):
a.udata[3].inc
doAssert(a.sdata(3) != low(int32), "overflow")
proc cmp*(a,b: Int128): int =
let tmp1 = cmp(a.sdata(3), b.sdata(3))
if tmp1 != 0: return tmp1
let tmp2 = cmp(a.udata[2], b.udata[2])
if tmp2 != 0: return tmp2
let tmp3 = cmp(a.udata[1], b.udata[1])
if tmp3 != 0: return tmp3
let tmp4 = cmp(a.udata[0], b.udata[0])
return tmp4
proc `<`*(a,b: Int128): bool =
cmp(a,b) < 0
proc `<=`*(a,b: Int128): bool =
cmp(a,b) <= 0
proc `==`*(a,b: Int128): bool =
if a.udata[0] != b.udata[0]: return false
if a.udata[1] != b.udata[1]: return false
if a.udata[2] != b.udata[2]: return false
if a.udata[3] != b.udata[3]: return false
return true
proc inplaceBitnot(a: var Int128) =
a.udata[0] = not a.udata[0]
a.udata[1] = not a.udata[1]
a.udata[2] = not a.udata[2]
a.udata[3] = not a.udata[3]
proc bitnot*(a: Int128): Int128 =
result.udata[0] = not a.udata[0]
result.udata[1] = not a.udata[1]
result.udata[2] = not a.udata[2]
result.udata[3] = not a.udata[3]
proc bitand*(a,b: Int128): Int128 =
result.udata[0] = a.udata[0] and b.udata[0]
result.udata[1] = a.udata[1] and b.udata[1]
result.udata[2] = a.udata[2] and b.udata[2]
result.udata[3] = a.udata[3] and b.udata[3]
proc bitor*(a,b: Int128): Int128 =
result.udata[0] = a.udata[0] or b.udata[0]
result.udata[1] = a.udata[1] or b.udata[1]
result.udata[2] = a.udata[2] or b.udata[2]
result.udata[3] = a.udata[3] or b.udata[3]
proc bitxor*(a,b: Int128): Int128 =
result.udata[0] = a.udata[0] xor b.udata[0]
result.udata[1] = a.udata[1] xor b.udata[1]
result.udata[2] = a.udata[2] xor b.udata[2]
result.udata[3] = a.udata[3] xor b.udata[3]
proc `shr`*(a: Int128, b: int): Int128 =
let b = b and 127
if b < 32:
result.sdata(3) = a.sdata(3) shr b
result.udata[2] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr b)
result.udata[1] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr b)
result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr b)
elif b < 64:
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = a.sdata(3) shr (b and 31)
result.udata[1] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr (b and 31))
result.udata[0] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr (b and 31))
elif b < 96:
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = -1
result.sdata(1) = a.sdata(3) shr (b and 31)
result.udata[0] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr (b and 31))
else: # b < 128
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = -1
result.sdata(1) = -1
result.sdata(0) = a.sdata(3) shr (b and 31)
proc `shl`*(a: Int128, b: int): Int128 =
let b = b and 127
if b < 32:
result.udata[0] = a.udata[0] shl b
result.udata[1] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl b) shr 32)
result.udata[2] = cast[uint32]((bitconcat(a.udata[2], a.udata[1]) shl b) shr 32)
result.udata[3] = cast[uint32]((bitconcat(a.udata[3], a.udata[2]) shl b) shr 32)
elif b < 64:
result.udata[0] = 0
result.udata[1] = a.udata[0] shl (b and 31)
result.udata[2] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl (b and 31)) shr 32)
result.udata[3] = cast[uint32]((bitconcat(a.udata[2], a.udata[1]) shl (b and 31)) shr 32)
elif b < 96:
result.udata[0] = 0
result.udata[1] = 0
result.udata[2] = a.udata[0] shl (b and 31)
result.udata[3] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl (b and 31)) shr 32)
else:
result.udata[0] = 0
result.udata[1] = 0
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)
let tmp1 = uint64(a.udata[1]) + uint64(b.udata[1]) + (tmp0 shr 32)
result.udata[1] = cast[uint32](tmp1)
let tmp2 = uint64(a.udata[2]) + uint64(b.udata[2]) + (tmp1 shr 32)
result.udata[2] = cast[uint32](tmp2)
let tmp3 = uint64(a.udata[3]) + uint64(b.udata[3]) + (tmp2 shr 32)
result.udata[3] = cast[uint32](tmp3)
proc `+=`*(a: var Int128, b: Int128) =
a = a + b
proc `-`*(a: Int128): Int128 =
result = bitnot(a)
result.inc
proc `-`*(a,b: Int128): Int128 =
a + (-b)
proc `-=`*(a: var Int128, b: Int128) =
a = a - b
proc abs*(a: Int128): Int128 =
if isNegative(a):
-a
else:
a
proc abs(a: int32): int =
if a < 0: -a else: a
proc `*`(a: Int128, b: uint32): Int128 =
let tmp0 = uint64(a.udata[0]) * uint64(b)
let tmp1 = uint64(a.udata[1]) * uint64(b)
let tmp2 = uint64(a.udata[2]) * uint64(b)
let tmp3 = uint64(a.udata[3]) * uint64(b)
if unlikely(tmp3 > uint64(high(int32))):
assert(false, "overflow")
result.udata[0] = cast[uint32](tmp0)
result.udata[1] = cast[uint32](tmp1) + cast[uint32](tmp0 shr 32)
result.udata[2] = cast[uint32](tmp2) + cast[uint32](tmp1 shr 32)
result.udata[3] = cast[uint32](tmp3) + cast[uint32](tmp2 shr 32)
proc `*`*(a: Int128, b: int32): Int128 =
result = a * cast[uint32](abs(b))
if b < 0:
result = -result
proc `*=`*(a: var Int128, b: int32): Int128 =
result = result * b
proc makeInt128(high,low: uint64): Int128 =
result.udata[0] = cast[uint32](low)
result.udata[1] = cast[uint32](low shr 32)
result.udata[2] = cast[uint32](high)
result.udata[3] = cast[uint32](high shr 32)
proc high64(a: Int128): uint64 =
bitconcat(a.udata[3], a.udata[2])
proc low64(a: Int128): uint64 =
bitconcat(a.udata[1], a.udata[0])
proc `*`*(lhs,rhs: Int128): Int128 =
let
a = cast[uint64](lhs.udata[0])
b = cast[uint64](lhs.udata[1])
c = cast[uint64](lhs.udata[2])
d = cast[uint64](lhs.udata[3])
e = cast[uint64](rhs.udata[0])
f = cast[uint64](rhs.udata[1])
g = cast[uint64](rhs.udata[2])
h = cast[uint64](rhs.udata[3])
let a32 = cast[uint64](lhs.udata[1])
let a00 = cast[uint64](lhs.udata[0])
let b32 = cast[uint64](rhs.udata[1])
let b00 = cast[uint64](rhs.udata[0])
result = makeInt128(high64(lhs) * low64(rhs) + low64(lhs) * high64(rhs) + a32 * b32, a00 * b00)
result = result + toInt128(a32 * b00) shl 32
result = result + toInt128(a00 * b32) shl 32
proc `*=`*(a: var Int128, b: Int128) =
a = a * b
import bitops
proc fastLog2*(a: Int128): int =
if a.udata[3] != 0:
return 96 + fastLog2(a.udata[3])
if a.udata[2] != 0:
return 64 + fastLog2(a.udata[2])
if a.udata[1] != 0:
return 32 + fastLog2(a.udata[1])
if a.udata[0] != 0:
return fastLog2(a.udata[0])
proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
assert(divisor != Zero)
let isNegativeA = isNegative(dividend)
let isNegativeB = isNegative(divisor)
var dividend = abs(dividend)
let divisor = abs(divisor)
if divisor > dividend:
result.quotient = Zero
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
return
if divisor == dividend:
if isNegativeA xor isNegativeB:
result.quotient = NegOne
else:
result.quotient = One
result.remainder = Zero
return
var denominator = divisor
var quotient = Zero
# Left aligns the MSB of the denominator and the dividend.
let shift = fastLog2(dividend) - fastLog2(denominator)
denominator = denominator shl shift
# Uses shift-subtract algorithm to divide dividend by denominator. The
# remainder will be left in dividend.
for i in 0..shift:
quotient = quotient shl 1
if dividend >= denominator:
dividend = dividend - denominator
quotient = bitor(quotient, One)
denominator = denominator shr 1
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)
return a
proc `mod`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
return b
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(value)
var value = abs(value)
while value > Zero:
let (quot, rem) = divMod(value, Ten)
result.add "0123456789"[rem.toInt64]
value = quot
if isNegative:
result.add '-'
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'})
var isNegative = false
var pos = pos
if arg[pos] == '-':
isNegative = true
pos += 1
result = Zero
while pos < arg.len and arg[pos] in '0'..'9':
result = result * Ten
result.inc(uint32(arg[pos]) - uint32('0'))
pos += 1
if isNegative:
result = -result
# fluff
proc `<`*(a: Int128, b: BiggestInt): bool =
cmp(a,toInt128(b)) < 0
proc `<`*(a: BiggestInt, b: Int128): bool =
cmp(toInt128(a), b) < 0
proc `<=`*(a: Int128, b: BiggestInt): bool =
cmp(a,toInt128(b)) <= 0
proc `<=`*(a: BiggestInt, b: Int128): bool =
cmp(toInt128(a), b) <= 0
proc `==`*(a: Int128, b: BiggestInt): bool =
a == toInt128(b)
proc `==`*(a: BiggestInt, b: Int128): bool =
toInt128(a) == b
proc `-`*(a: BiggestInt, b: Int128): Int128 =
toInt128(a) - b
proc `-`*(a: Int128, b: BiggestInt): Int128 =
a - toInt128(b)
proc `+`*(a: BiggestInt, b: Int128): Int128 =
toInt128(a) + b
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)
doAssert $One == "1"
doAssert $Ten == "10"
doAssert $Zero == "0"
let c = parseDecimalInt128("12345678989876543210123456789")
doAssert $c == "12345678989876543210123456789"
var d : array[39, Int128]
d[0] = parseDecimalInt128("1")
d[1] = parseDecimalInt128("10")
d[2] = parseDecimalInt128("100")
d[3] = parseDecimalInt128("1000")
d[4] = parseDecimalInt128("10000")
d[5] = parseDecimalInt128("100000")
d[6] = parseDecimalInt128("1000000")
d[7] = parseDecimalInt128("10000000")
d[8] = parseDecimalInt128("100000000")
d[9] = parseDecimalInt128("1000000000")
d[10] = parseDecimalInt128("10000000000")
d[11] = parseDecimalInt128("100000000000")
d[12] = parseDecimalInt128("1000000000000")
d[13] = parseDecimalInt128("10000000000000")
d[14] = parseDecimalInt128("100000000000000")
d[15] = parseDecimalInt128("1000000000000000")
d[16] = parseDecimalInt128("10000000000000000")
d[17] = parseDecimalInt128("100000000000000000")
d[18] = parseDecimalInt128("1000000000000000000")
d[19] = parseDecimalInt128("10000000000000000000")
d[20] = parseDecimalInt128("100000000000000000000")
d[21] = parseDecimalInt128("1000000000000000000000")
d[22] = parseDecimalInt128("10000000000000000000000")
d[23] = parseDecimalInt128("100000000000000000000000")
d[24] = parseDecimalInt128("1000000000000000000000000")
d[25] = parseDecimalInt128("10000000000000000000000000")
d[26] = parseDecimalInt128("100000000000000000000000000")
d[27] = parseDecimalInt128("1000000000000000000000000000")
d[28] = parseDecimalInt128("10000000000000000000000000000")
d[29] = parseDecimalInt128("100000000000000000000000000000")
d[30] = parseDecimalInt128("1000000000000000000000000000000")
d[31] = parseDecimalInt128("10000000000000000000000000000000")
d[32] = parseDecimalInt128("100000000000000000000000000000000")
d[33] = parseDecimalInt128("1000000000000000000000000000000000")
d[34] = parseDecimalInt128("10000000000000000000000000000000000")
d[35] = parseDecimalInt128("100000000000000000000000000000000000")
d[36] = parseDecimalInt128("1000000000000000000000000000000000000")
d[37] = parseDecimalInt128("10000000000000000000000000000000000000")
d[38] = parseDecimalInt128("100000000000000000000000000000000000000")
for i in 0..<d.len:
for j in 0..<d.len:
doAssert(cmp(d[i], d[j]) == cmp(i,j))
if i + j < d.len:
doAssert d[i] * d[j] == d[i+j]
if i - j >= 0:
doAssert d[i] div d[j] == d[i-j]
var sum: Int128
for it in d:
sum += it
doAssert $sum == "111111111111111111111111111111111111111"
for it in d.mitems:
it = -it
for i in 0..<d.len:
for j in 0..<d.len:
doAssert(cmp(d[i], d[j]) == -cmp(i,j))
if i + j < d.len:
doAssert d[i] * d[j] == -d[i+j]
if i - j >= 0:
doAssert d[i] div d[j] == -d[i-j]
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))
let e = parseDecimalInt128("70997106675279150998592376708984375")
let strArray = [
# toHex(e shr 0), toHex(e shr 1), toHex(e shr 2), toHex(e shr 3)
"000dac6d782d266a37300c32591eee37", "0006d636bc1693351b9806192c8f771b", "00036b1b5e0b499a8dcc030c9647bb8d", "0001b58daf05a4cd46e601864b23ddc6",
"0000dac6d782d266a37300c32591eee3", "00006d636bc1693351b9806192c8f771", "000036b1b5e0b499a8dcc030c9647bb8", "00001b58daf05a4cd46e601864b23ddc",
"00000dac6d782d266a37300c32591eee", "000006d636bc1693351b9806192c8f77", "0000036b1b5e0b499a8dcc030c9647bb", "000001b58daf05a4cd46e601864b23dd",
"000000dac6d782d266a37300c32591ee", "0000006d636bc1693351b9806192c8f7", "00000036b1b5e0b499a8dcc030c9647b", "0000001b58daf05a4cd46e601864b23d",
"0000000dac6d782d266a37300c32591e", "00000006d636bc1693351b9806192c8f", "000000036b1b5e0b499a8dcc030c9647", "00000001b58daf05a4cd46e601864b23",
"00000000dac6d782d266a37300c32591", "000000006d636bc1693351b9806192c8", "0000000036b1b5e0b499a8dcc030c964", "000000001b58daf05a4cd46e601864b2",
"000000000dac6d782d266a37300c3259", "0000000006d636bc1693351b9806192c", "00000000036b1b5e0b499a8dcc030c96", "0000000001b58daf05a4cd46e601864b",
"0000000000dac6d782d266a37300c325", "00000000006d636bc1693351b9806192", "000000000036b1b5e0b499a8dcc030c9", "00000000001b58daf05a4cd46e601864",
"00000000000dac6d782d266a37300c32", "000000000006d636bc1693351b980619", "0000000000036b1b5e0b499a8dcc030c", "000000000001b58daf05a4cd46e60186",
"000000000000dac6d782d266a37300c3", "0000000000006d636bc1693351b98061", "00000000000036b1b5e0b499a8dcc030", "0000000000001b58daf05a4cd46e6018",
"0000000000000dac6d782d266a37300c", "00000000000006d636bc1693351b9806", "000000000000036b1b5e0b499a8dcc03", "00000000000001b58daf05a4cd46e601",
"00000000000000dac6d782d266a37300", "000000000000006d636bc1693351b980", "0000000000000036b1b5e0b499a8dcc0", "000000000000001b58daf05a4cd46e60",
"000000000000000dac6d782d266a3730", "0000000000000006d636bc1693351b98", "00000000000000036b1b5e0b499a8dcc", "0000000000000001b58daf05a4cd46e6",
"0000000000000000dac6d782d266a373", "00000000000000006d636bc1693351b9", "000000000000000036b1b5e0b499a8dc", "00000000000000001b58daf05a4cd46e",
"00000000000000000dac6d782d266a37", "000000000000000006d636bc1693351b", "0000000000000000036b1b5e0b499a8d", "000000000000000001b58daf05a4cd46",
"000000000000000000dac6d782d266a3", "0000000000000000006d636bc1693351", "00000000000000000036b1b5e0b499a8", "0000000000000000001b58daf05a4cd4",
"0000000000000000000dac6d782d266a", "00000000000000000006d636bc169335", "000000000000000000036b1b5e0b499a", "00000000000000000001b58daf05a4cd",
"00000000000000000000dac6d782d266", "000000000000000000006d636bc16933", "0000000000000000000036b1b5e0b499", "000000000000000000001b58daf05a4c",
"000000000000000000000dac6d782d26", "0000000000000000000006d636bc1693", "00000000000000000000036b1b5e0b49", "0000000000000000000001b58daf05a4",
"0000000000000000000000dac6d782d2", "00000000000000000000006d636bc169", "000000000000000000000036b1b5e0b4", "00000000000000000000001b58daf05a",
"00000000000000000000000dac6d782d", "000000000000000000000006d636bc16", "0000000000000000000000036b1b5e0b", "000000000000000000000001b58daf05",
"000000000000000000000000dac6d782", "0000000000000000000000006d636bc1", "00000000000000000000000036b1b5e0", "0000000000000000000000001b58daf0",
"0000000000000000000000000dac6d78", "00000000000000000000000006d636bc", "000000000000000000000000036b1b5e", "00000000000000000000000001b58daf",
"00000000000000000000000000dac6d7", "000000000000000000000000006d636b", "0000000000000000000000000036b1b5", "000000000000000000000000001b58da",
"000000000000000000000000000dac6d", "0000000000000000000000000006d636", "00000000000000000000000000036b1b", "0000000000000000000000000001b58d",
"0000000000000000000000000000dac6", "00000000000000000000000000006d63", "000000000000000000000000000036b1", "00000000000000000000000000001b58",
"00000000000000000000000000000dac", "000000000000000000000000000006d6", "0000000000000000000000000000036b", "000000000000000000000000000001b5",
"000000000000000000000000000000da", "0000000000000000000000000000006d", "00000000000000000000000000000036", "0000000000000000000000000000001b",
"0000000000000000000000000000000d", "00000000000000000000000000000006", "00000000000000000000000000000003", "00000000000000000000000000000001",
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
]
for i in 0 ..< 128:
let str1 = toHex(e shr i)
let str2 = strArray[i]
doAssert str1 == str2
let strArray2 = [
"000dac6d782d266a37300c32591eee37", "001b58daf05a4cd46e601864b23ddc6e", "0036b1b5e0b499a8dcc030c9647bb8dc", "006d636bc1693351b9806192c8f771b8",
"00dac6d782d266a37300c32591eee370", "01b58daf05a4cd46e601864b23ddc6e0", "036b1b5e0b499a8dcc030c9647bb8dc0", "06d636bc1693351b9806192c8f771b80",
"0dac6d782d266a37300c32591eee3700", "1b58daf05a4cd46e601864b23ddc6e00", "36b1b5e0b499a8dcc030c9647bb8dc00", "6d636bc1693351b9806192c8f771b800",
"dac6d782d266a37300c32591eee37000", "b58daf05a4cd46e601864b23ddc6e000", "6b1b5e0b499a8dcc030c9647bb8dc000", "d636bc1693351b9806192c8f771b8000",
"ac6d782d266a37300c32591eee370000", "58daf05a4cd46e601864b23ddc6e0000", "b1b5e0b499a8dcc030c9647bb8dc0000", "636bc1693351b9806192c8f771b80000",
"c6d782d266a37300c32591eee3700000", "8daf05a4cd46e601864b23ddc6e00000", "1b5e0b499a8dcc030c9647bb8dc00000", "36bc1693351b9806192c8f771b800000",
"6d782d266a37300c32591eee37000000", "daf05a4cd46e601864b23ddc6e000000", "b5e0b499a8dcc030c9647bb8dc000000", "6bc1693351b9806192c8f771b8000000",
"d782d266a37300c32591eee370000000", "af05a4cd46e601864b23ddc6e0000000", "5e0b499a8dcc030c9647bb8dc0000000", "bc1693351b9806192c8f771b80000000",
"782d266a37300c32591eee3700000000", "f05a4cd46e601864b23ddc6e00000000", "e0b499a8dcc030c9647bb8dc00000000", "c1693351b9806192c8f771b800000000",
"82d266a37300c32591eee37000000000", "05a4cd46e601864b23ddc6e000000000", "0b499a8dcc030c9647bb8dc000000000", "1693351b9806192c8f771b8000000000",
"2d266a37300c32591eee370000000000", "5a4cd46e601864b23ddc6e0000000000", "b499a8dcc030c9647bb8dc0000000000", "693351b9806192c8f771b80000000000",
"d266a37300c32591eee3700000000000", "a4cd46e601864b23ddc6e00000000000", "499a8dcc030c9647bb8dc00000000000", "93351b9806192c8f771b800000000000",
"266a37300c32591eee37000000000000", "4cd46e601864b23ddc6e000000000000", "99a8dcc030c9647bb8dc000000000000", "3351b9806192c8f771b8000000000000",
"66a37300c32591eee370000000000000", "cd46e601864b23ddc6e0000000000000", "9a8dcc030c9647bb8dc0000000000000", "351b9806192c8f771b80000000000000",
"6a37300c32591eee3700000000000000", "d46e601864b23ddc6e00000000000000", "a8dcc030c9647bb8dc00000000000000", "51b9806192c8f771b800000000000000",
"a37300c32591eee37000000000000000", "46e601864b23ddc6e000000000000000", "8dcc030c9647bb8dc000000000000000", "1b9806192c8f771b8000000000000000",
"37300c32591eee370000000000000000", "6e601864b23ddc6e0000000000000000", "dcc030c9647bb8dc0000000000000000", "b9806192c8f771b80000000000000000",
"7300c32591eee3700000000000000000", "e601864b23ddc6e00000000000000000", "cc030c9647bb8dc00000000000000000", "9806192c8f771b800000000000000000",
"300c32591eee37000000000000000000", "601864b23ddc6e000000000000000000", "c030c9647bb8dc000000000000000000", "806192c8f771b8000000000000000000",
"00c32591eee370000000000000000000", "01864b23ddc6e0000000000000000000", "030c9647bb8dc0000000000000000000", "06192c8f771b80000000000000000000",
"0c32591eee3700000000000000000000", "1864b23ddc6e00000000000000000000", "30c9647bb8dc00000000000000000000", "6192c8f771b800000000000000000000",
"c32591eee37000000000000000000000", "864b23ddc6e000000000000000000000", "0c9647bb8dc000000000000000000000", "192c8f771b8000000000000000000000",
"32591eee370000000000000000000000", "64b23ddc6e0000000000000000000000", "c9647bb8dc0000000000000000000000", "92c8f771b80000000000000000000000",
"2591eee3700000000000000000000000", "4b23ddc6e00000000000000000000000", "9647bb8dc00000000000000000000000", "2c8f771b800000000000000000000000",
"591eee37000000000000000000000000", "b23ddc6e000000000000000000000000", "647bb8dc000000000000000000000000", "c8f771b8000000000000000000000000",
"91eee370000000000000000000000000", "23ddc6e0000000000000000000000000", "47bb8dc0000000000000000000000000", "8f771b80000000000000000000000000",
"1eee3700000000000000000000000000", "3ddc6e00000000000000000000000000", "7bb8dc00000000000000000000000000", "f771b800000000000000000000000000",
"eee37000000000000000000000000000", "ddc6e000000000000000000000000000", "bb8dc000000000000000000000000000", "771b8000000000000000000000000000",
"ee370000000000000000000000000000", "dc6e0000000000000000000000000000", "b8dc0000000000000000000000000000", "71b80000000000000000000000000000",
"e3700000000000000000000000000000", "c6e00000000000000000000000000000", "8dc00000000000000000000000000000", "1b800000000000000000000000000000",
"37000000000000000000000000000000", "6e000000000000000000000000000000", "dc000000000000000000000000000000", "b8000000000000000000000000000000",
"70000000000000000000000000000000", "e0000000000000000000000000000000", "c0000000000000000000000000000000", "80000000000000000000000000000000",
]
for i in 0 ..< 128:
let str1 = toHex(e shl i)
let str2 = strArray2[i]
doAssert str1 == str2

File diff suppressed because it is too large Load Diff

View File

@@ -7,28 +7,30 @@
# 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
s, u: Rope
length: int
field: PSym
b: PNode
result = nil
case n.kind
of nkRecList:
length = sonsLen(n)
if length == 1:
result = genObjectFields(p, typ, n.sons[0])
if n.len == 1:
result = genObjectFields(p, typ, n[0])
else:
s = nil
for i in 0 ..< length:
if i > 0: add(s, ", \L")
add(s, genObjectFields(p, typ, n.sons[i]))
for i in 0..<n.len:
if i > 0: s.add(", \L")
s.add(genObjectFields(p, typ, n[i]))
result = ("{kind: 2, len: $1, offset: 0, " &
"typ: null, name: null, sons: [$2]}") % [rope(length), s]
"typ: null, name: null, sons: [$2]}") % [rope(n.len), s]
of nkSym:
field = n.sym
s = genTypeInfo(p, field.typ)
@@ -37,29 +39,28 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
[mangleName(p.module, field), s,
makeJSString(field.name.s)]
of nkRecCase:
length = sonsLen(n)
if (n.sons[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
field = n.sons[0].sym
if (n[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
field = n[0].sym
s = genTypeInfo(p, field.typ)
for i in 1 ..< length:
b = n.sons[i] # branch
for i in 1..<n.len:
b = n[i] # branch
u = nil
case b.kind
of nkOfBranch:
if sonsLen(b) < 2:
if b.len < 2:
internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
for j in 0 .. sonsLen(b) - 2:
if u != nil: add(u, ", ")
if b.sons[j].kind == nkRange:
addf(u, "[$1, $2]", [rope(getOrdValue(b.sons[j].sons[0])),
rope(getOrdValue(b.sons[j].sons[1]))])
for j in 0..<b.len - 1:
if u != nil: u.add(", ")
if b[j].kind == nkRange:
u.addf("[$1, $2]", [rope(getOrdValue(b[j][0])),
rope(getOrdValue(b[j][1]))])
else:
add(u, rope(getOrdValue(b.sons[j])))
u.add(rope(getOrdValue(b[j])))
of nkElse:
u = rope(lengthOrd(p.config, field.typ))
else: internalError(p.config, n.info, "genObjectFields(nkRecCase)")
if result != nil: add(result, ", \L")
addf(result, "[setConstr($1), $2]",
if result != nil: result.add(", \L")
result.addf("[setConstr($1), $2]",
[u, genObjectFields(p, typ, lastSon(b))])
result = ("{kind: 3, offset: \"$1\", len: $3, " &
"typ: $2, name: $4, sons: [$5]}") % [
@@ -68,27 +69,27 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
else: internalError(p.config, n.info, "genObjectFields")
proc objHasTypeField(t: PType): bool {.inline.} =
tfInheritable in t.flags or t.sons[0] != nil
tfInheritable in t.flags or t[0] != nil
proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
let kind = if objHasTypeField(typ): tyObject else: tyTuple
var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n") % [name, rope(ord(kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "var NNI$1 = $2;$n",
p.g.typeInfo.addf("var NNI$1 = $2;$n",
[rope(typ.id), genObjectFields(p, typ, typ.n)])
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if (typ.kind == tyObject) and (typ.sons[0] != nil):
addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0].skipTypes(skipPtrs))])
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
if (typ.kind == tyObject) and (typ[0] != nil):
p.g.typeInfo.addf("$1.base = $2;$n",
[name, genTypeInfo(p, typ[0].skipTypes(skipPtrs))])
proc genTupleFields(p: PProc, typ: PType): Rope =
var s: Rope = nil
for i in 0 ..< typ.len:
if i > 0: add(s, ", \L")
for i in 0..<typ.len:
if i > 0: s.add(", \L")
s.addf("{kind: 1, offset: \"Field$1\", len: 0, " &
"typ: $2, name: \"Field$1\", sons: null}",
[i.rope, genTypeInfo(p, typ.sons[i])])
[i.rope, genTypeInfo(p, typ[i])])
result = ("{kind: 2, len: $1, offset: 0, " &
"typ: null, name: null, sons: [$2]}") % [rope(typ.len), s]
@@ -96,30 +97,29 @@ proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "var NNI$1 = $2;$n",
p.g.typeInfo.addf("var NNI$1 = $2;$n",
[rope(typ.id), genTupleFields(p, typ)])
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
let length = sonsLen(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")
let field = typ.n.sons[i].sym
if i > 0: add(s, ", \L")
for i in 0..<typ.n.len:
if (typ.n[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
let field = typ.n[i].sym
if i > 0: s.add(", \L")
let extName = if field.ast == nil: field.name.s else: field.ast.strVal
addf(s, "\"$1\": {kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}",
s.addf("\"$1\": {kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}",
[rope(field.position), name, makeJSString(extName)])
var n = ("var NNI$1 = {kind: 2, offset: 0, typ: null, " &
"name: null, len: $2, sons: {$3}};$n") % [rope(typ.id), rope(length), s]
"name: null, len: $2, sons: {$3}};$n") % [rope(typ.id), rope(typ.n.len), s]
s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s)
add(p.g.typeInfo, n)
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if typ.sons[0] != nil:
addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0])])
p.g.typeInfo.add(n)
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
if typ[0] != nil:
p.g.typeInfo.addf("$1.base = $2;$n",
[name, genTypeInfo(p, typ[0])])
proc genTypeInfo(p: PProc, typ: PType): Rope =
let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink, tyOwned})
@@ -127,7 +127,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
if containsOrIncl(p.g.typeInfoGenerated, t.id): return
case t.kind
of tyDistinct:
result = genTypeInfo(p, t.sons[0])
result = genTypeInfo(p, t[0])
of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64:
var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
@@ -138,15 +138,15 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "$1.base = $2;$n",
p.g.typeInfo.addf("$1.base = $2;$n",
[result, genTypeInfo(p, t.lastSon)])
of tyArray:
var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "$1.base = $2;$n",
[result, genTypeInfo(p, t.sons[1])])
p.g.typeInfo.addf("$1.base = $2;$n",
[result, genTypeInfo(p, t[1])])
of tyEnum: genEnumInfo(p, t, result)
of tyObject: genObjectInfo(p, t, result)
of tyTuple: genTupleInfo(p, t, result)

View File

@@ -10,9 +10,9 @@
# This file implements lambda lifting for the transformator.
import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs,
intsets, strutils, options, ast, astalgo, msgs,
idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos,
transf
transf, liftdestructors
discard """
The basic approach is that captured vars need to be put on the heap and
@@ -128,8 +128,8 @@ proc newCall(a: PSym, b: PNode): PNode =
proc createClosureIterStateType*(g: ModuleGraph; iter: PSym): PType =
var n = newNodeI(nkRange, iter.info)
addSon(n, newIntNode(nkIntLit, -1))
addSon(n, newIntNode(nkIntLit, 0))
n.add newIntNode(nkIntLit, -1)
n.add newIntNode(nkIntLit, 0)
result = newType(tyRange, iter)
result.n = n
var intType = nilOrSysInt(g)
@@ -148,27 +148,27 @@ proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType =
proc getClosureIterResult*(g: ModuleGraph; iter: PSym): PSym =
if resultPos < iter.ast.len:
result = iter.ast.sons[resultPos].sym
result = iter.ast[resultPos].sym
else:
# XXX a bit hacky:
result = newSym(skResult, getIdent(g.cache, ":result"), iter, iter.info, {})
result.typ = iter.typ.sons[0]
result.typ = iter.typ[0]
incl(result.flags, sfUsed)
iter.ast.add newSymNode(result)
proc addHiddenParam(routine: PSym, param: PSym) =
assert param.kind == skParam
var params = routine.ast.sons[paramsPos]
var params = routine.ast[paramsPos]
# -1 is correct here as param.position is 0 based but we have at position 0
# some nkEffect node:
param.position = routine.typ.n.len-1
addSon(params, newSymNode(param))
params.add newSymNode(param)
#incl(routine.typ.flags, tfCapturesEnv)
assert sfFromGeneric in param.flags
#echo "produced environment: ", param.id, " for ", routine.id
proc getHiddenParam(g: ModuleGraph; routine: PSym): PSym =
let params = routine.ast.sons[paramsPos]
let params = routine.ast[paramsPos]
let hidden = lastSon(params)
if hidden.kind == nkSym and hidden.sym.kind == skParam and hidden.sym.name.s == paramName:
result = hidden.sym
@@ -179,7 +179,7 @@ proc getHiddenParam(g: ModuleGraph; routine: PSym): PSym =
result = routine
proc getEnvParam*(routine: PSym): PSym =
let params = routine.ast.sons[paramsPos]
let params = routine.ast[paramsPos]
let hidden = lastSon(params)
if hidden.kind == nkSym and hidden.sym.name.s == paramName:
result = hidden.sym
@@ -206,8 +206,8 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
# which is however the only case when we generate an assignment in the first
# place.
result = newNodeI(nkAsgn, info, 2)
result.sons[0] = le
result.sons[1] = ri
result[0] = le
result[1] = ri
proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode =
result = newNodeIT(nkClosure, info, prc.typ)
@@ -218,6 +218,10 @@ proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode
if env.skipConv.kind == nkClosure:
localError(g.config, info, "internal error: taking closure of closure")
result.add(env)
#if isClosureIterator(result.typ):
createTypeBoundOps(g, nil, result.typ, info)
if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions:
prc.flags.incl sfInjectDestructors
proc interestingIterVar(s: PSym): bool {.inline.} =
# XXX optimization: Only lift the variable if it lives across
@@ -233,6 +237,12 @@ 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; owner: PSym) =
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors
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 +255,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})[0], hp, g.cache)
env = indirectAccess(newSymNode(it), hp, hp.info)
else:
let e = newSym(skLet, iter.name, owner, n.info)
@@ -257,11 +267,12 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result.add(v)
# add 'new' statement:
result.add newCall(getSysSym(g, n.info, "internalNew"), env)
createTypeBoundOpsLL(g, env.typ, n.info, owner)
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)
@@ -291,7 +302,7 @@ type
DetectionPass = object
processed, capturedVars: IntSet
ownerToType: Table[int, PType]
somethingToDo, noDestructors: bool
somethingToDo: bool
graph: ModuleGraph
proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass =
@@ -321,9 +332,10 @@ 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
result.rawAddSon t
else:
result = t
@@ -332,16 +344,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 c.graph.config.selectedGc == gcDestructors:
# This seems to be generally correct but since it's a bit risky it's disabled
# for now.
# XXX This is wrong for the 'hamming' test, so remove this logic again.
let fieldType = if isDefined(c.graph.config, "nimCycleBreaker"):
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
else:
c.getEnvTypeForOwner(dep, info)
@@ -351,11 +364,18 @@ 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")
when false:
if c.graph.config.selectedGC == gcDestructors and sfCursor notin upField.flags:
localError(c.graph.config, dep.info, "internal error: up reference is not a .cursor")
else:
let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
result.typ = fieldType
when false:
if c.graph.config.selectedGC == gcDestructors:
result.flags.incl sfCursor
rawAddField(obj, result)
discard """
@@ -412,8 +432,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
if innerProc:
if s.isIterator: c.somethingToDo = true
if not c.processed.containsOrIncl(s.id):
let body = transformBody(c.graph, s, cache = true,
noDestructors = c.noDestructors)
let body = transformBody(c.graph, s, cache = true)
detectCapturedVars(body, s, c)
let ow = s.skipGenericOwner
if ow == owner:
@@ -422,8 +441,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
@@ -448,8 +467,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
@@ -474,7 +493,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:
@@ -490,6 +509,7 @@ type
processed: IntSet
envVars: Table[int, PNode]
inContainer: int
unownedEnvVars: Table[int, PNode] # only required for --newruntime
proc initLiftingPass(fn: PSym): LiftingPass =
result.processed = initIntSet()
@@ -503,7 +523,7 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
if not envParam.isNil:
var access = newSymNode(envParam)
while true:
let obj = access.typ.sons[0]
let obj = access.typ[0]
assert obj.kind == tyObject
let field = getFieldFromObj(obj, s)
if field != nil:
@@ -514,56 +534,75 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
localError(g.config, n.info, "internal error: environment misses: " & s.name.s)
result = n
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType): PNode =
var v = newSym(skVar, getIdent(cache, envName), owner, owner.info)
incl(v.flags, sfShadowed)
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNode =
var v = newSym(skVar, getIdent(cache, envName), owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = typ
result = newSymNode(v)
when false:
if owner.kind == skIterator and owner.typ.callConv == ccClosure:
let it = getHiddenParam(owner)
addUniqueField(it.typ.sons[0], v)
addUniqueField(it.typ[0], v)
result = indirectAccess(newSymNode(it), v, v.info)
else:
result = newSymNode(v)
proc setupEnvVar(owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode =
c: var LiftingPass; info: TLineInfo): PNode =
if owner.isIterator:
return getHiddenParam(d.graph, owner).newSymNode
result = c.envvars.getOrDefault(owner.id)
result = c.envVars.getOrDefault(owner.id)
if result.isNil:
let envVarType = d.ownerToType.getOrDefault(owner.id)
if envVarType.isNil:
localError d.graph.config, owner.info, "internal error: could not determine closure type"
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType))
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info)
c.envVars[owner.id] = result
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
c.unownedEnvVars[owner.id] = newSymNode(v)
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:
result = rawIndirectAccess(result, upField, p.info)
proc rawClosureCreation(owner: PSym;
d: DetectionPass; c: var LiftingPass): PNode =
d: DetectionPass; c: var LiftingPass;
info: TLineInfo): PNode =
result = newNodeI(nkStmtList, owner.info)
var env: PNode
if owner.isIterator:
env = getHiddenParam(d.graph, owner).newSymNode
else:
env = setupEnvVar(owner, d, c)
env = setupEnvVar(owner, d, c, info)
if env.kind == nkSym:
var v = newNodeI(nkVarSection, env.info)
addVar(v, env)
result.add(v)
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 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)
createTypeBoundOpsLL(d.graph, unowned.typ, env.info, owner)
# add assignment statements for captured parameters:
for i in 1..<owner.typ.n.len:
let local = owner.typ.n[i].sym
@@ -571,11 +610,14 @@ proc rawClosureCreation(owner: PSym;
let fieldAccess = indirectAccess(env, local, env.info)
# add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
owner.flags.incl sfInjectDestructors
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:
@@ -583,6 +625,18 @@ proc rawClosureCreation(owner: PSym;
# oldenv, env.info))
else:
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:
createTypeBoundOpsLL(d.graph, env.typ, owner.info, owner)
proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass;
info: TLineInfo; res: PNode) =
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
let nilLit = newNodeIT(nkNilLit, info, unowned.typ)
res.add newAsgnStmt(unowned, nilLit, info)
createTypeBoundOpsLL(d.graph, unowned.typ, info, owner)
proc closureCreationForIter(iter: PNode;
d: DetectionPass; c: var LiftingPass): PNode =
@@ -594,7 +648,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
@@ -602,11 +656,12 @@ proc closureCreationForIter(iter: PNode;
addVar(vs, vnode)
result.add(vs)
result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, owner)
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)
if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}):
let u = setupEnvVar(owner, d, c, iter.info)
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:
@@ -615,8 +670,10 @@ proc closureCreationForIter(iter: PNode;
proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode =
let access = setupEnvVar(owner, d, c)
let obj = access.typ.skipTypes({tyOwned, tyRef})
var access = setupEnvVar(owner, d, c, n.info)
if optOwnedRefs in d.graph.config.globalOptions:
access = c.unownedEnvVars[owner.id]
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
let field = getFieldFromObj(obj, n.sym)
if field != nil:
result = rawIndirectAccess(access, field, n.info)
@@ -625,7 +682,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[0].sym
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode
@@ -641,7 +698,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
result = closureCreationForIter(n, d, c)
elif s.skipGenericOwner == owner:
# direct dependency, so use the outer's env variable:
result = makeClosure(d.graph, s, setupEnvVar(owner, d, c), n.info)
result = makeClosure(d.graph, s, setupEnvVar(owner, d, c, n.info), n.info)
else:
let available = getHiddenParam(d.graph, owner)
let wanted = getHiddenParam(d.graph, s).typ
@@ -650,7 +707,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")
@@ -669,12 +726,13 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# echo renderTree(s.getBody, {renderIds})
let oldInContainer = c.inContainer
c.inContainer = 0
var body = transformBody(d.graph, s)
var body = transformBody(d.graph, s, cache = false)
body = liftCapturedVars(body, s, d, c)
if c.envvars.getOrDefault(s.id).isNil:
if c.envVars.getOrDefault(s.id).isNil:
s.transformedBody = body
else:
s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c), body)
s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c, n.info), body)
finishClosureCreation(s, d, c, n.info, s.transformedBody)
c.inContainer = oldInContainer
if s.typ.callConv == ccClosure:
@@ -693,13 +751,13 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
discard
of nkClosure:
if n[1].kind == nkNilLit:
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
let x = n.sons[0].skipConv
n[0] = liftCapturedVars(n[0], owner, d, c)
let x = n[0].skipConv
if x.kind == nkClosure:
#localError(n.info, "internal error: closure to closure created")
# now we know better, so patch it:
n.sons[0] = x.sons[0]
n.sons[1] = x.sons[1]
n[0] = x[0]
n[1] = x[1]
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil and n[namePos].kind == nkSym:
let oldInContainer = c.inContainer
@@ -710,26 +768,29 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c.inContainer = oldInContainer
of nkHiddenStdConv:
if n.len == 2:
n.sons[1] = liftCapturedVars(n[1], owner, d, c)
n[1] = liftCapturedVars(n[1], owner, d, c)
if n[1].kind == nkClosure: result = n[1]
of nkReturnStmt:
if n[0].kind in {nkAsgn, nkFastAsgn}:
# we have a `result = result` expression produced by the closure
# transform, let's not touch the LHS in order to make the lifting pass
# correct when `result` is lifted
n[0].sons[1] = liftCapturedVars(n[0].sons[1], owner, d, c)
else: assert n[0].kind == nkEmpty
n[0][1] = liftCapturedVars(n[0][1], owner, d, c)
else:
n[0] = liftCapturedVars(n[0], owner, d, c)
of nkTypeOfExpr:
result = n
else:
if owner.isIterator:
if nfLL in n.flags:
# special case 'when nimVm' due to bug #3636:
n.sons[1] = liftCapturedVars(n[1], owner, d, c)
n[1] = liftCapturedVars(n[1], owner, d, c)
return
let inContainer = n.kind in {nkObjConstr, nkBracket}
if inContainer: inc c.inContainer
for i in 0..<n.len:
n.sons[i] = liftCapturedVars(n[i], owner, d, c)
n[i] = liftCapturedVars(n[i], owner, d, c)
if inContainer: dec c.inContainer
# ------------------ old stuff -------------------------------------------
@@ -776,16 +837,15 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
# pretend 'fn' is a closure iterator for the analysis:
let oldKind = fn.kind
let oldCC = fn.typ.callConv
fn.kind = skIterator
fn.transitionRoutineSymKind(skIterator)
fn.typ.callConv = ccClosure
d.ownerToType[fn.id] = ptrType
detectCapturedVars(body, fn, d)
result = liftCapturedVars(body, fn, d, c)
fn.kind = oldKind
fn.transitionRoutineSymKind(oldKind)
fn.typ.callConv = oldCC
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
noDestructors: bool): PNode =
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ...
@@ -801,7 +861,6 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
tooEarly = true
else:
var d = initDetectionPass(g, fn)
d.noDestructors = noDestructors
detectCapturedVars(body, fn, d)
if not d.somethingToDo and fn.isIterator:
addClosureParam(d, fn, body.info)
@@ -810,8 +869,9 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
var c = initLiftingPass(fn)
result = liftCapturedVars(body, fn, d, c)
# echo renderTree(result, {renderIds})
if c.envvars.getOrDefault(fn.id) != nil:
result = newTree(nkStmtList, rawClosureCreation(fn, d, c), result)
if c.envVars.getOrDefault(fn.id) != nil:
result = newTree(nkStmtList, rawClosureCreation(fn, d, c, body.info), result)
finishClosureCreation(fn, d, c, body.info, result)
else:
result = body
#if fn.name.s == "get2":
@@ -854,11 +914,10 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
...
"""
if liftingHarmful(g.config, owner): return body
var L = body.len
if not (body.kind == nkForStmt and body[L-2].kind in nkCallKinds):
if not (body.kind == nkForStmt and body[^2].kind in nkCallKinds):
localError(g.config, body.info, "ignored invalid for loop")
return body
var call = body[L-2]
var call = body[^2]
result = newNodeI(nkStmtList, body.info)
@@ -879,37 +938,39 @@ 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))
createTypeBoundOpsLL(g, env.typ, body.info, owner)
elif op.kind == nkStmtListExpr:
let closure = op.lastSon
if closure.kind == nkClosure:
call.sons[0] = closure
for i in 0 .. op.len-2:
call[0] = closure
for i in 0..<op.len-1:
result.add op[i]
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[1] = loopBody
whileLoop[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
whileLoop[1] = loopBody
result.add whileLoop
# setup loopBody:
# gather vars in a tuple:
var v2 = newNodeI(nkLetSection, body.info)
var vpart = newNodeI(if L == 3: nkIdentDefs else: nkVarTuple, body.info)
for i in 0 .. L-3:
var vpart = newNodeI(if body.len == 3: nkIdentDefs else: nkVarTuple, body.info)
for i in 0..<body.len-2:
if body[i].kind == nkSym:
body[i].sym.kind = skLet
addSon(vpart, body[i])
body[i].sym.transitionToLet()
vpart.add body[i]
addSon(vpart, newNodeI(nkEmpty, body.info)) # no explicit type
vpart.add newNodeI(nkEmpty, body.info) # no explicit type
if not env.isNil:
call.sons[0] = makeClosure(g, call.sons[0].sym, env.newSymNode, body.info)
addSon(vpart, call)
addSon(v2, vpart)
call[0] = makeClosure(g, call[0].sym, env.newSymNode, body.info)
vpart.add call
v2.add vpart
loopBody.sons[0] = v2
loopBody[0] = v2
var bs = newNodeI(nkBreakState, body.info)
bs.addSon(call.sons[0])
bs.add call[0]
let ibs = newNodeI(nkIfStmt, body.info)
let elifBranch = newNodeI(nkElifBranch, body.info)
@@ -921,5 +982,5 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
elifBranch.add(br)
ibs.add(elifBranch)
loopBody.sons[1] = ibs
loopBody.sons[2] = body[L-1]
loopBody[1] = ibs
loopBody[2] = body[^1]

View File

@@ -9,13 +9,10 @@
## 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
MaxLineLen = 80
MinLineLen = 15
type
SplitKind = enum
@@ -24,10 +21,15 @@ type
SemicolonKind = enum
detectSemicolonKind, useSemicolon, dontTouch
LayoutToken = enum
ltSpaces, ltNewline, ltTab,
LayoutToken* = enum
ltSpaces,
ltCrucialNewline, ## a semantically crucial newline (indentation!)
ltSplittingNewline, ## newline used for splitting up long
## expressions (like after a comma or a binary operator)
ltTab,
ltOptionalNewline, ## optional newline introduced by nimpretty
ltComment, ltLit, ltKeyword, ltExportMarker, ltIdent,
ltOther, ltOpr,
ltOther, ltOpr, ltSomeParLe, ltSomeParRi,
ltBeginSection, ltEndSection
Emitter* = object
@@ -36,18 +38,19 @@ type
lastTok: TTokType
inquote, lastTokWasTerse: bool
semicolons: SemicolonKind
col, lastLineNumber, lineSpan, indentLevel, indWidth*: int
col, lastLineNumber, lineSpan, indentLevel, indWidth*, inSection: int
keepIndents*: int
doIndentMore*: int
kinds: seq[LayoutToken]
tokens: seq[string]
kinds*: seq[LayoutToken]
tokens*: seq[string]
indentStack: seq[int]
fixedUntil: int # marks where we must not go in the content
altSplitPos: array[SplitKind, int] # alternative split positions
maxLineLen*: int
proc openEmitter*(em: var Emitter, cache: IdentCache;
config: ConfigRef, fileIdx: FileIndex) =
let fullPath = Absolutefile config.toFullPath(fileIdx)
let fullPath = AbsoluteFile config.toFullPath(fileIdx)
if em.indWidth == 0:
em.indWidth = getIndentWidth(fileIdx, llStreamOpen(fullPath, fmRead),
cache, config)
@@ -63,17 +66,20 @@ proc openEmitter*(em: var Emitter, cache: IdentCache;
proc computeMax(em: Emitter; pos: int): int =
var p = pos
var extraSpace = 0
result = 0
while p < em.tokens.len and em.kinds[p] != ltEndSection:
var lhs = 0
var lineLen = 0
var foundTab = false
while p < em.tokens.len and em.kinds[p] != ltEndSection:
if em.kinds[p] == ltNewline:
if foundTab and lineLen <= MaxLineLen: result = max(result, lhs)
if em.kinds[p] in {ltCrucialNewline, ltSplittingNewline}:
if foundTab and lineLen <= em.maxLineLen:
result = max(result, lhs + extraSpace)
inc p
break
if em.kinds[p] == ltTab:
extraSpace = if em.kinds[p-1] == ltSpaces: 0 else: 1
foundTab = true
else:
if not foundTab:
@@ -84,46 +90,17 @@ proc computeMax(em: Emitter; pos: int): int =
proc computeRhs(em: Emitter; pos: int): int =
var p = pos
result = 0
while p < em.tokens.len and em.kinds[p] != ltNewline:
while p < em.tokens.len and em.kinds[p] notin {ltCrucialNewline, ltSplittingNewline}:
inc result, em.tokens[p].len
inc p
proc closeEmitter*(em: var Emitter) =
let outFile = em.config.absOutFile
proc isLongEnough(lineLen, startPos, endPos: int): bool =
result = lineLen > MinLineLen and endPos > startPos + 4
var content = newStringOfCap(16_000)
var maxLhs = 0
var lineLen = 0
var lineBegin = 0
for i in 0..em.tokens.high:
case em.kinds[i]
of ltBeginSection:
maxLhs = computeMax(em, lineBegin)
of ltEndSection:
maxLhs = 0
of ltTab:
if maxLhs == 0 or computeRhs(em, i)+maxLhs > MaxLineLen:
content.add ' '
else:
let spaces = max(maxLhs - lineLen + 1, 1)
for j in 1..spaces: content.add ' '
of ltNewline:
content.add em.tokens[i]
lineLen = 0
lineBegin = i+1
else:
content.add em.tokens[i]
inc lineLen, em.tokens[i].len
if fileExists(outFile) and readFile(outFile.string) == content:
discard "do nothing, see #9499"
return
var f = llStreamOpen(outFile, fmWrite)
if f == nil:
rawMessage(em.config, errGenerated, "cannot open file: " & outFile.string)
return
f.llStreamWrite content
llStreamClose(f)
proc findNewline(em: Emitter; p, lineLen: var int) =
while p < em.tokens.len and em.kinds[p] notin {ltCrucialNewline, ltSplittingNewline}:
inc lineLen, em.tokens[p].len
inc p
proc countNewlines(s: string): int =
result = 0
@@ -137,17 +114,177 @@ proc calcCol(em: var Emitter; s: string) =
dec i
inc em.col
proc optionalIsGood(em: var Emitter; pos, currentLen: int): bool =
let ourIndent = em.tokens[pos].len
var p = pos+1
var lineLen = 0
em.findNewline(p, lineLen)
if p == pos+1: # optionalNewline followed by another newline
result = false
elif em.kinds[p-1] == ltComment and currentLen+lineLen < em.maxLineLen+MinLineLen:
result = false
elif p+1 < em.tokens.len and em.kinds[p+1] == ltSpaces and
em.kinds[p-1] == ltOptionalNewline:
if em.tokens[p+1].len == ourIndent:
# concatenate lines with the same indententation
var nlPos = p
var lineLenTotal = lineLen
inc p
em.findNewline(p, lineLenTotal)
if isLongEnough(lineLenTotal, nlPos, p):
em.kinds[nlPos] = ltOptionalNewline
if em.kinds[nlPos+1] == ltSpaces:
# inhibit extra spaces when concatenating two lines
em.tokens[nlPos+1] = if em.tokens[nlPos-2] == ",": " " else: ""
result = true
elif em.tokens[p+1].len < ourIndent:
result = isLongEnough(lineLen, pos, p)
elif em.kinds[pos+1] in {ltOther, ltSomeParLe, ltSomeParRi}: # note: pos+1, not p+1
result = false
else:
result = isLongEnough(lineLen, pos, p)
proc lenOfNextTokens(em: Emitter; pos: int): int =
result = 0
for i in 1..<em.tokens.len-pos:
if em.kinds[pos+i] in {ltCrucialNewline, ltSplittingNewline, ltOptionalNewline}: break
inc result, em.tokens[pos+i].len
proc guidingInd(em: Emitter; pos: int): int =
var i = pos - 1
while i >= 0 and em.kinds[i] != ltSomeParLe:
dec i
while i+1 <= em.kinds.high and em.kinds[i] != ltSomeParRi:
if em.kinds[i] == ltSplittingNewline and em.kinds[i+1] == ltSpaces:
return em.tokens[i+1].len
inc i
result = -1
proc renderTokens*(em: var Emitter): string =
## Render Emitter tokens to a string of code
template defaultCase() =
content.add em.tokens[i]
inc lineLen, em.tokens[i].len
var content = newStringOfCap(16_000)
var maxLhs = 0
var lineLen = 0
var lineBegin = 0
var openPars = 0
var i = 0
while i <= em.tokens.high:
when defined(debug):
echo (token: em.tokens[i], kind: em.kinds[i])
case em.kinds[i]
of ltBeginSection:
maxLhs = computeMax(em, lineBegin)
of ltEndSection:
maxLhs = 0
lineBegin = i+1
of ltTab:
if i >= 2 and em.kinds[i-2] in {ltCrucialNewline, ltSplittingNewline} and
em.kinds[i-1] in {ltCrucialNewline, ltSplittingNewline, ltSpaces}:
# a previous section has ended
maxLhs = 0
if maxLhs == 0:
if em.kinds[i-1] != ltSpaces:
content.add em.tokens[i]
inc lineLen, em.tokens[i].len
else:
# pick the shorter indentation token:
var spaces = maxLhs - lineLen
if spaces < em.tokens[i].len or computeRhs(em, i+1)+maxLhs <= em.maxLineLen+MinLineLen:
if spaces <= 0 and content[^1] notin {' ', '\L'}: spaces = 1
for j in 1..spaces: content.add ' '
inc lineLen, spaces
else:
content.add em.tokens[i]
inc lineLen, em.tokens[i].len
of ltCrucialNewline, ltSplittingNewline:
content.add em.tokens[i]
lineLen = 0
lineBegin = i+1
of ltOptionalNewline:
let totalLineLen = lineLen + lenOfNextTokens(em, i)
if totalLineLen > em.maxLineLen and optionalIsGood(em, i, lineLen):
if i-1 >= 0 and em.kinds[i-1] == ltSpaces:
let spaces = em.tokens[i-1].len
content.setLen(content.len - spaces)
content.add "\L"
let guide = if openPars > 0: guidingInd(em, i) else: -1
if guide >= 0:
content.add repeat(' ', guide)
lineLen = guide
else:
content.add em.tokens[i]
lineLen = em.tokens[i].len
lineBegin = i+1
if i+1 < em.kinds.len and em.kinds[i+1] == ltSpaces:
# inhibit extra spaces at the start of a new line
inc i
of ltLit:
let lineSpan = countNewlines(em.tokens[i])
if lineSpan > 0:
em.calcCol(em.tokens[i])
lineLen = em.col
else:
inc lineLen, em.tokens[i].len
content.add em.tokens[i]
of ltSomeParLe:
inc openPars
defaultCase()
of ltSomeParRi:
doAssert openPars > 0
dec openPars
defaultCase()
else:
defaultCase()
inc i
return content
proc writeOut*(em: Emitter, content: string) =
## Write to disk
let outFile = em.config.absOutFile
if fileExists(outFile) and readFile(outFile.string) == content:
discard "do nothing, see #9499"
return
var f = llStreamOpen(outFile, fmWrite)
if f == nil:
rawMessage(em.config, errGenerated, "cannot open file: " & outFile.string)
return
f.llStreamWrite content
llStreamClose(f)
proc closeEmitter*(em: var Emitter) =
## Renders emitter tokens and write to a file
let content = renderTokens(em)
em.writeOut(content)
proc wr(em: var Emitter; x: string; lt: LayoutToken) =
em.tokens.add x
em.kinds.add lt
inc em.col, x.len
assert em.tokens.len == em.kinds.len
proc wrNewline(em: var Emitter) =
proc wrNewline(em: var Emitter; kind = ltCrucialNewline) =
em.tokens.add "\L"
em.kinds.add ltNewline
em.kinds.add kind
em.col = 0
proc newlineWasSplitting*(em: var Emitter) =
if em.kinds.len >= 3 and em.kinds[^3] == ltCrucialNewline:
em.kinds[^3] = ltSplittingNewline
#[
Splitting newlines can occur:
- after commas, semicolon, '[', '('.
- after binary operators, '='.
- after ':' type
We only need parser support for the "after type" case.
]#
proc wrSpaces(em: var Emitter; spaces: int) =
if spaces > 0:
wr(em, strutils.repeat(' ', spaces), ltSpaces)
@@ -158,8 +295,19 @@ proc wrSpace(em: var Emitter) =
proc wrTab(em: var Emitter) =
wr(em, " ", ltTab)
proc beginSection*(em: var Emitter) = wr(em, "", ltBeginSection)
proc endSection*(em: var Emitter) = wr(em, "", ltEndSection)
proc beginSection*(em: var Emitter) =
let pos = max(0, em.tokens.len-2)
em.tokens.insert "", pos
em.kinds.insert ltBeginSection, pos
inc em.inSection
#wr(em, "", ltBeginSection)
proc endSection*(em: var Emitter) =
em.tokens.insert "", em.tokens.len-2
em.kinds.insert ltEndSection, em.kinds.len-2
dec em.inSection
#wr(em, "", ltEndSection)
proc removeSpaces(em: var Emitter) =
while em.kinds.len > 0 and em.kinds[^1] == ltSpaces:
@@ -168,87 +316,72 @@ proc removeSpaces(em: var Emitter) =
setLen(em.kinds, em.kinds.len-1)
dec em.col, tokenLen
template goodCol(col): bool = col in 40..MaxLineLen
const
openPars = {tkParLe, tkParDotLe,
tkBracketLe, tkBracketLeColon, tkCurlyDotLe,
tkCurlyLe}
tkBracketLe, tkBracketDotLe, tkBracketLeColon,
tkCurlyDotLe, tkCurlyLe}
closedPars = {tkParRi, tkParDotRi,
tkBracketRi, tkCurlyDotRi,
tkCurlyRi}
tkBracketRi, tkBracketDotRi,
tkCurlyDotRi, tkCurlyRi}
splitters = openPars + {tkComma, tkSemicolon}
splitters = openPars + {tkComma, tkSemiColon} # do not add 'tkColon' here!
oprSet = {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor}
template rememberSplit(kind) =
if goodCol(em.col):
em.altSplitPos[kind] = em.tokens.len
template goodCol(col): bool = col >= em.maxLineLen div 2
template moreIndent(em): int =
(if em.doIndentMore > 0: em.indWidth*2 else: em.indWidth)
if em.doIndentMore > 0: em.indWidth*2 else: em.indWidth
proc softLinebreak(em: var Emitter, lit: string) =
# XXX Use an algorithm that is outlined here:
# https://llvm.org/devmtg/2013-04/jasper-slides.pdf
# +2 because we blindly assume a comma or ' &' might follow
if not em.inquote and em.col+lit.len+2 >= MaxLineLen:
if em.lastTok in splitters:
# bug #10295, check first if even more indentation would help:
let spaces = em.indentLevel+moreIndent(em)
if spaces < em.col:
removeSpaces em
wrNewline(em)
em.col = 0
wrSpaces em, spaces
else:
# search backwards for a good split position:
for a in mitems(em.altSplitPos):
if a > em.fixedUntil:
var spaces = 0
while a+spaces < em.kinds.len and em.kinds[a+spaces] == ltSpaces:
inc spaces
if spaces > 0:
delete(em.tokens, a, a+spaces-1)
delete(em.kinds, a, a+spaces-1)
em.kinds.insert(ltNewline, a)
em.tokens.insert("\L", a)
em.kinds.insert(ltSpaces, a+1)
em.tokens.insert(repeat(' ', em.indentLevel+moreIndent(em)), a+1)
# recompute em.col:
var i = em.kinds.len-1
em.col = 0
while i >= 0 and em.kinds[i] != ltNewline:
inc em.col, em.tokens[i].len
dec i
# mark position as "already split here"
a = -1
break
template rememberSplit(kind) =
if goodCol(em.col) and not em.inquote:
let spaces = em.indentLevel+moreIndent(em)
if spaces < em.col and spaces > 0:
wr(em, strutils.repeat(' ', spaces), ltOptionalNewline)
#em.altSplitPos[kind] = em.tokens.len
proc emitMultilineComment(em: var Emitter, lit: string, col: int) =
proc emitMultilineComment(em: var Emitter, lit: string, col: int; dontIndent: bool) =
# re-align every line in the multi-line comment:
var i = 0
var lastIndent = em.indentStack[^1]
var lastIndent = if em.keepIndents > 0: em.indentLevel else: em.indentStack[^1]
var b = 0
var dontIndent = dontIndent
var hasEmptyLine = false
for commentLine in splitLines(lit):
let stripped = commentLine.strip()
var a = 0
while a < commentLine.len and commentLine[a] == ' ': inc a
if i == 0:
discard
elif stripped.len == 0:
wrNewline em
if i == 0 and (commentLine.endsWith("\\") or commentLine.endsWith("[")):
dontIndent = true
wr em, commentLine, ltComment
elif dontIndent:
if i > 0: wrNewline em
wr em, commentLine, ltComment
else:
if a > lastIndent:
b += em.indWidth
lastIndent = a
elif a < lastIndent:
b -= em.indWidth
lastIndent = a
wrNewline em
wrSpaces em, col + b
wr em, stripped, ltComment
let stripped = commentLine.strip()
if i == 0:
if em.kinds.len > 0 and em.kinds[^1] != ltTab:
wr(em, "", ltTab)
elif stripped.len == 0:
wrNewline em
hasEmptyLine = true
else:
var a = 0
while a < commentLine.len and commentLine[a] == ' ': inc a
if a > lastIndent:
b += em.indWidth
lastIndent = a
elif a < lastIndent:
b -= em.indWidth
lastIndent = a
wrNewline em
if not hasEmptyLine or col + b < 15:
if col + b > 0:
wr(em, repeat(' ', col+b), ltTab)
else:
wr(em, "", ltTab)
else:
wr(em, repeat(' ', a), ltSpaces)
wr em, stripped, ltComment
inc i
proc lastChar(s: string): char =
@@ -257,20 +390,20 @@ proc lastChar(s: string): char =
proc endsInWhite(em: Emitter): bool =
var i = em.tokens.len-1
while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection}: dec(i)
result = if i >= 0: em.kinds[i] in {ltSpaces, ltNewline, ltTab} else: true
result = if i >= 0: em.kinds[i] in {ltSpaces, ltCrucialNewline, ltSplittingNewline, ltTab} else: true
proc endsInNewline(em: Emitter): bool =
var i = em.tokens.len-1
while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection, ltSpaces}: dec(i)
result = if i >= 0: em.kinds[i] in {ltNewline, ltTab} else: true
result = if i >= 0: em.kinds[i] in {ltCrucialNewline, ltSplittingNewline, ltTab} else: true
proc endsInAlpha(em: Emitter): bool =
var i = em.tokens.len-1
while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection}: dec(i)
result = if i >= 0: em.tokens[i].lastChar in SymChars+{'_'} else: false
proc emitComment(em: var Emitter; tok: TToken) =
let col = em.col
proc emitComment(em: var Emitter; tok: TToken; dontIndent: bool) =
var col = em.col
let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB)
em.lineSpan = countNewlines(lit)
if em.lineSpan > 0: calcCol(em, lit)
@@ -281,7 +414,8 @@ proc emitComment(em: var Emitter; tok: TToken) =
else:
if not endsInWhite(em):
wrTab em
emitMultilineComment(em, lit, col)
inc col
emitMultilineComment(em, lit, col, dontIndent)
proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
template wasExportMarker(em): bool =
@@ -303,19 +437,25 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
return
var preventComment = false
if tok.tokType == tkComment and tok.line == em.lastLineNumber and tok.indent >= 0:
if tok.tokType == tkComment and tok.line == em.lastLineNumber:
# we have an inline comment so handle it before the indentation token:
emitComment(em, tok)
emitComment(em, tok, dontIndent = (em.inSection == 0))
preventComment = true
em.fixedUntil = em.tokens.high
elif tok.indent >= 0:
var newlineKind = ltCrucialNewline
if em.keepIndents > 0:
em.indentLevel = tok.indent
elif (em.lastTok in (splitters + oprSet) and tok.tokType notin closedPars):
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 = tok.indent - em.indentStack[^1]
let alignment = max(tok.indent - em.indentStack[^1], 0)
em.indentLevel = alignment + em.indentStack.high * em.indWidth
newlineKind = ltSplittingNewline
else:
if tok.indent > em.indentStack[^1]:
em.indentStack.add tok.indent
@@ -335,7 +475,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
]#
# remove trailing whitespace:
removeSpaces em
wrNewline em
wrNewline em, newlineKind
for i in 2..tok.line - em.lastLineNumber: wrNewline(em)
wrSpaces em, em.indentLevel
em.fixedUntil = em.tokens.high
@@ -346,20 +486,15 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
if endsInAlpha(em):
wrSpace em
elif not em.inquote and not endsInWhite(em) and
em.lastTok notin openPars and not em.lastTokWasTerse:
em.lastTok notin (openPars+{tkOpr, tkDotDot}) and not em.lastTokWasTerse:
#and tok.tokType in oprSet
wrSpace em
if not em.inquote:
wr(em, TokTypeToStr[tok.tokType], ltKeyword)
case tok.tokType
of tkAnd: rememberSplit(splitAnd)
of tkOr: rememberSplit(splitOr)
of tkIn, tkNotin:
if tok.tokType in {tkAnd, tkOr, tkIn, tkNotin}:
rememberSplit(splitIn)
wrSpace em
else: discard
else:
# keywords in backticks are not normalized:
wr(em, tok.ident.s, ltIdent)
@@ -367,22 +502,19 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
of tkColon:
wr(em, TokTypeToStr[tok.tokType], ltOther)
wrSpace em
of tkSemicolon, tkComma:
of tkSemiColon, tkComma:
wr(em, TokTypeToStr[tok.tokType], ltOther)
rememberSplit(splitComma)
wrSpace em
of tkParDotLe, tkParLe, tkBracketDotLe, tkBracketLe,
tkCurlyLe, tkCurlyDotLe, tkBracketLeColon:
if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker:
of openPars:
if tok.strongSpaceA > 0 and not em.endsInWhite and
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
wrSpace em
wr(em, TokTypeToStr[tok.tokType], ltOther)
wr(em, TokTypeToStr[tok.tokType], ltSomeParLe)
rememberSplit(splitParLe)
of tkParRi,
tkBracketRi, tkCurlyRi,
tkBracketDotRi,
tkCurlyDotRi,
tkParDotRi,
tkColonColon:
of closedPars:
wr(em, TokTypeToStr[tok.tokType], ltSomeParRi)
of tkColonColon:
wr(em, TokTypeToStr[tok.tokType], ltOther)
of tkDot:
lastTokWasTerse = true
@@ -392,8 +524,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
wr(em, TokTypeToStr[tok.tokType], ltOther)
if not em.inquote: wrSpace(em)
of tkOpr, tkDotDot:
if ((tok.strongSpaceA == 0 and tok.strongSpaceB == 0) or em.inquote) and
tok.ident.s notin ["<", ">", "<=", ">=", "==", "!="]:
if em.inquote or ((tok.strongSpaceA == 0 and tok.strongSpaceB == 0) and
tok.ident.s notin ["<", ">", "<=", ">=", "==", "!="]):
# bug #9504: remember to not spacify a keyword:
lastTokWasTerse = true
# if not surrounded by whitespace, don't produce any whitespace either:
@@ -413,10 +545,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
em.inquote = not em.inquote
of tkComment:
if not preventComment:
emitComment(em, tok)
emitComment(em, tok, dontIndent = false)
of tkIntLit..tkStrLit, tkRStrLit, tkTripleStrLit, tkGStrLit, tkGTripleStrLit, tkCharLit:
let lit = fileSection(em.config, em.fid, tok.offsetA, tok.offsetB)
softLinebreak(em, lit)
if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wrSpace(em)
em.lineSpan = countNewlines(lit)
if em.lineSpan > 0: calcCol(em, lit)
@@ -424,7 +555,6 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
of tkEof: discard
else:
let lit = if tok.ident != nil: tok.ident.s else: tok.literal
softLinebreak(em, lit)
if endsInAlpha(em): wrSpace(em)
wr em, lit, ltIdent
@@ -439,6 +569,11 @@ proc endsWith(em: Emitter; k: varargs[string]): bool =
if em.tokens[em.tokens.len - k.len + i] != k[i]: return false
return true
proc rfind(em: Emitter, t: string): int =
for i in 1..5:
if em.tokens[^i] == t:
return i
proc starWasExportMarker*(em: var Emitter) =
if em.endsWith(" ", "*", " "):
setLen(em.tokens, em.tokens.len-3)
@@ -449,11 +584,13 @@ proc starWasExportMarker*(em: var Emitter) =
proc commaWasSemicolon*(em: var Emitter) =
if em.semicolons == detectSemicolonKind:
em.semicolons = if em.endsWith(",", " "): dontTouch else: useSemicolon
if em.semicolons == useSemicolon and em.endsWith(",", " "):
em.tokens[em.tokens.len-2] = ";"
em.semicolons = if em.rfind(";") > 0: useSemicolon else: dontTouch
if em.semicolons == useSemicolon:
let commaPos = em.rfind(",")
if commaPos > 0:
em.tokens[^commaPos] = ";"
proc curlyRiWasPragma*(em: var Emitter) =
if em.endsWith("}"):
em.tokens[em.tokens.len-1] = ".}"
em.tokens[^1] = ".}"
inc em.col

View File

@@ -62,6 +62,7 @@ type
tkComma, tkSemiColon,
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot, tkBracketLeColon,
tkOpr, tkComment, tkAccent,
# these are fake tokens used by renderer.nim
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
TTokTypes* = set[TTokType]
@@ -134,7 +135,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
@@ -146,10 +147,6 @@ type
previousToken: TLineInfo
config*: ConfigRef
when defined(nimpretty):
var
gIndentationWidth*: int
proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
result = newLineInfo(L.fileIdx, tok.line, tok.col)
when defined(nimpretty):
@@ -173,7 +170,7 @@ proc isNimIdentifier*(s: string): bool =
inc(i)
result = true
proc tokToStr*(tok: TToken): string =
proc `$`*(tok: TToken): string =
case tok.tokType
of tkIntLit..tkInt64Lit: result = $tok.iNumber
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
@@ -188,11 +185,11 @@ proc tokToStr*(tok: TToken): string =
proc prettyTok*(tok: TToken): string =
if isKeyword(tok.tokType): result = "keyword " & tok.ident.s
else: result = tokToStr(tok)
else: result = $tok
proc printTok*(conf: ConfigRef; tok: TToken) =
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
TokTypeToStr[tok.tokType] & " " & tokToStr(tok))
TokTypeToStr[tok.tokType] & " " & $tok)
proc initToken*(L: var TToken) =
L.tokType = tkInvalid
@@ -223,7 +220,7 @@ proc fillToken(L: var TToken) =
proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache; config: ConfigRef) =
openBaseLexer(lex, inputstream)
lex.fileIdx = fileidx
lex.fileIdx = fileIdx
lex.indentAhead = -1
lex.currLineIndent = 0
inc(lex.lineNumber, inputstream.lineOffset)
@@ -308,11 +305,11 @@ template tokenEndPrevious(tok, pos) =
tok.offsetB = L.offsetBase + pos
template eatChar(L: var TLexer, t: var TToken, replacementChar: char) =
add(t.literal, replacementChar)
t.literal.add(replacementChar)
inc(L.bufpos)
template eatChar(L: var TLexer, t: var TToken) =
add(t.literal, L.buf[L.bufpos])
t.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
proc getNumber(L: var TLexer, result: var TToken) =
@@ -321,7 +318,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
result = 0
while true:
if L.buf[pos] in chars:
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
inc(result)
else:
@@ -332,14 +329,14 @@ proc getNumber(L: var TLexer, result: var TToken) =
"only single underscores may occur in a token and token may not " &
"end with an underscore: e.g. '1__1' and '1_' are invalid")
break
add(tok.literal, '_')
tok.literal.add('_')
inc(pos)
L.bufpos = pos
proc matchChars(L: var TLexer, tok: var TToken, chars: set[char]) =
var pos = L.bufpos # use registers for pos, buf
while L.buf[pos] in chars:
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
L.bufpos = pos
@@ -355,12 +352,12 @@ proc getNumber(L: var TLexer, result: var TToken) =
# We must verify +/- specifically so that we're not past the literal
if L.buf[L.bufpos] in {'+', '-'} and
L.buf[L.bufpos - 1] in {'e', 'E'}:
add(t.literal, L.buf[L.bufpos])
t.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
matchChars(L, t, literalishChars)
if L.buf[L.bufpos] in {'\'', 'f', 'F', 'd', 'D', 'i', 'I', 'u', 'U'}:
inc(L.bufpos)
add(t.literal, L.buf[L.bufpos])
t.literal.add(L.buf[L.bufpos])
matchChars(L, t, {'0'..'9'})
L.bufpos = msgPos
lexMessage(L, msgKind, msg % t.literal)
@@ -379,7 +376,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
result.literal = ""
result.base = base10
startpos = L.bufpos
tokenBegin(result, startPos)
tokenBegin(result, startpos)
# First stage: find out base, make verifications, build token literal string
# {'c', 'C'} is added for deprecation reasons to provide a clear error message
@@ -534,13 +531,13 @@ proc getNumber(L: var TLexer, result: var TToken) =
case result.tokType
of tkIntLit, tkInt64Lit: result.iNumber = xi
of tkInt8Lit: result.iNumber = BiggestInt(int8(toU8(int(xi))))
of tkInt16Lit: result.iNumber = BiggestInt(int16(toU16(int(xi))))
of tkInt32Lit: result.iNumber = BiggestInt(int32(toU32(int64(xi))))
of tkInt8Lit: result.iNumber = ashr(xi shl 56, 56)
of tkInt16Lit: result.iNumber = ashr(xi shl 48, 48)
of tkInt32Lit: result.iNumber = ashr(xi shl 32, 32)
of tkUIntLit, tkUInt64Lit: result.iNumber = xi
of tkUInt8Lit: result.iNumber = BiggestInt(cast[uint8](toU8(int(xi))))
of tkUInt16Lit: result.iNumber = BiggestInt(cast[uint16](toU16(int(xi))))
of tkUInt32Lit: result.iNumber = BiggestInt(cast[uint32](toU32(int64(xi))))
of tkUInt8Lit: result.iNumber = xi and 0xff
of tkUInt16Lit: result.iNumber = xi and 0xffff
of tkUInt32Lit: result.iNumber = xi and 0xffffffff
of tkFloat32Lit:
result.fNumber = (cast[PFloat32](addr(xi)))[]
# note: this code is endian neutral!
@@ -569,7 +566,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:
@@ -691,51 +688,51 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
if L.config.oldNewlines:
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\n not allowed in character literal")
add(tok.literal, L.config.target.tnl)
tok.literal.add(L.config.target.tnl)
else:
add(tok.literal, '\L')
tok.literal.add('\L')
inc(L.bufpos)
of 'p', 'P':
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\p not allowed in character literal")
add(tok.literal, L.config.target.tnl)
tok.literal.add(L.config.target.tnl)
inc(L.bufpos)
of 'r', 'R', 'c', 'C':
add(tok.literal, CR)
tok.literal.add(CR)
inc(L.bufpos)
of 'l', 'L':
add(tok.literal, LF)
tok.literal.add(LF)
inc(L.bufpos)
of 'f', 'F':
add(tok.literal, FF)
tok.literal.add(FF)
inc(L.bufpos)
of 'e', 'E':
add(tok.literal, ESC)
tok.literal.add(ESC)
inc(L.bufpos)
of 'a', 'A':
add(tok.literal, BEL)
tok.literal.add(BEL)
inc(L.bufpos)
of 'b', 'B':
add(tok.literal, BACKSPACE)
tok.literal.add(BACKSPACE)
inc(L.bufpos)
of 'v', 'V':
add(tok.literal, VT)
tok.literal.add(VT)
inc(L.bufpos)
of 't', 'T':
add(tok.literal, '\t')
tok.literal.add('\t')
inc(L.bufpos)
of '\'', '\"':
add(tok.literal, L.buf[L.bufpos])
tok.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
of '\\':
add(tok.literal, '\\')
tok.literal.add('\\')
inc(L.bufpos)
of 'x', 'X':
inc(L.bufpos)
var xi = 0
handleHexChar(L, xi, 1)
handleHexChar(L, xi, 2)
add(tok.literal, chr(xi))
tok.literal.add(chr(xi))
of 'u', 'U':
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\u not allowed in character literal")
@@ -765,14 +762,14 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
lexMessage(L, warnOctalEscape)
var xi = 0
handleDecChars(L, xi)
if (xi <= 255): add(tok.literal, chr(xi))
if (xi <= 255): tok.literal.add(chr(xi))
else: lexMessage(L, errGenerated, "invalid character constant")
else: lexMessage(L, errGenerated, "invalid character constant")
proc newString(s: cstring, len: int): string =
## XXX, how come there is no support for this?
result = newString(len)
for i in 0 ..< len:
for i in 0..<len:
result[i] = s[i]
proc handleCRLF(L: var TLexer, pos: int): int =
@@ -819,12 +816,12 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
tokenEndIgnore(tok, pos+2)
L.bufpos = pos + 3 # skip the three """
break
add(tok.literal, '\"')
tok.literal.add('\"')
inc(pos)
of CR, LF:
tokenEndIgnore(tok, pos)
pos = handleCRLF(L, pos)
add(tok.literal, "\n")
tok.literal.add("\n")
of nimlexbase.EndOfFile:
tokenEndIgnore(tok, pos)
var line2 = L.lineNumber
@@ -834,7 +831,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
L.bufpos = pos
break
else:
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
else:
# ordinary string literal
@@ -845,7 +842,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
if c == '\"':
if mode != normal and L.buf[pos+1] == '\"':
inc(pos, 2)
add(tok.literal, '"')
tok.literal.add('"')
else:
tokenEndIgnore(tok, pos)
inc(pos) # skip '"'
@@ -859,7 +856,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
getEscapedChar(L, tok)
pos = L.bufpos
else:
add(tok.literal, c)
tok.literal.add(c)
inc(pos)
L.bufpos = pos
@@ -868,7 +865,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
@@ -882,6 +881,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
var h: Hash = 0
var pos = L.bufpos
tokenBegin(tok, pos)
var suspicious = false
while true:
var c = L.buf[pos]
case c
@@ -892,21 +892,26 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h !& ord(c)
inc(pos)
suspicious = true
of '_':
if L.buf[pos+1] notin SymChars:
lexMessage(L, errGenerated, "invalid token: trailing underscore")
break
inc(pos)
suspicious = true
else: break
tokenEnd(tok, pos-1)
h = !$h
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
L.bufpos = pos
if (tok.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
(tok.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
tok.tokType = tkSymbol
else:
tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
if suspicious and {optStyleHint, optStyleError} * L.config.globalOptions != {}:
lintReport(L.config, getLineInfo(L), tok.ident.s.normalize, tok.ident.s)
L.bufpos = pos
proc endOperator(L: var TLexer, tok: var TToken, pos: int,
hash: Hash) {.inline.} =
@@ -943,15 +948,14 @@ proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
case tok.tokType
of tkOpr:
let L = tok.ident.s.len
let relevantChar = tok.ident.s[0]
# arrow like?
if L > 1 and tok.ident.s[L-1] == '>' and
tok.ident.s[L-2] in {'-', '~', '='}: return considerStrongSpaces(1)
if tok.ident.s.len > 1 and tok.ident.s[^1] == '>' and
tok.ident.s[^2] in {'-', '~', '='}: return considerStrongSpaces(1)
template considerAsgn(value: untyped) =
result = if tok.ident.s[L-1] == '=': 1 else: value
result = if tok.ident.s[^1] == '=': 1 else: value
case relevantChar
of '$', '^': considerAsgn(10)
@@ -1077,7 +1081,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
var lastBackslash = -1
while L.buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
if L.buf[pos] == '\\': lastBackslash = pos+1
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
tokenEndIgnore(tok, pos)
pos = handleCRLF(L, pos)
@@ -1119,7 +1123,7 @@ proc skip(L: var TLexer, tok: var TToken) =
inc(pos)
inc(tok.strongSpaceA)
of '\t':
if not L.allowTabs: lexMessagePos(L, errGenerated, pos, "tabulators are not allowed")
if not L.allowTabs: lexMessagePos(L, errGenerated, pos, "tabs are not allowed, use spaces instead")
inc(pos)
of CR, LF:
tokenEndPrevious(tok, pos)
@@ -1174,8 +1178,6 @@ proc skip(L: var TLexer, tok: var TToken) =
tok.commentOffsetB = L.offsetBase + pos - 1
tok.tokType = tkComment
tok.indent = commentIndent
if gIndentationWidth <= 0:
gIndentationWidth = tok.indent
proc rawGetTok*(L: var TLexer, tok: var TToken) =
template atTokenEnd() {.dirty.} =
@@ -1334,10 +1336,13 @@ proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
var tok: TToken
initToken(tok)
openLexer(lex, fileIdx, inputstream, cache, config)
while true:
var prevToken = tkEof
while tok.tokType != tkEof:
rawGetTok(lex, tok)
result = tok.indent
if result > 0 or tok.tokType == tkEof: break
if tok.indent > 0 and prevToken in {tkColon, tkEquals, tkType, tkConst, tkLet, tkVar, tkUsing}:
result = tok.indent
if result > 0: break
prevToken = tok.tokType
closeLexer(lex)
proc getPrecedence*(ident: PIdent): int =
@@ -1346,7 +1351,7 @@ proc getPrecedence*(ident: PIdent): int =
initToken(tok)
tok.ident = ident
tok.tokType =
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol) .. ord(tokKeywordHigh) - ord(tkSymbol):
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol)..ord(tokKeywordHigh) - ord(tkSymbol):
TTokType(tok.ident.id + ord(tkSymbol))
else: tkOpr
getPrecedence(tok, false)

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
## This module implements the '.liftLocals' pragma.
import
intsets, strutils, options, ast, astalgo, msgs,
strutils, options, ast, msgs,
idents, renderer, types, lowerings, lineinfos
from pragmas import getPragmaVal
@@ -30,10 +30,10 @@ proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode =
let field = addUniqueField(c.objType, s, c.cache)
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = c.objType
add(deref, newSymNode(c.partialParam, info))
deref.add(newSymNode(c.partialParam, info))
result = newNodeI(nkDotExpr, info)
add(result, deref)
add(result, newSymNode(field))
result.add(deref)
result.add(newSymNode(field))
result.typ = field.typ
proc liftLocals(n: PNode; i: int; c: var Ctx) =
@@ -44,12 +44,12 @@ proc liftLocals(n: PNode; i: int; c: var Ctx) =
n[i] = lookupOrAdd(c, it.sym, it.info)
of procDefs, nkTypeSection: discard
else:
for i in 0 ..< it.safeLen:
for i in 0..<it.safeLen:
liftLocals(it, i, c)
proc lookupParam(params, dest: PNode): PSym =
if dest.kind != nkIdent: return nil
for i in 1 ..< params.len:
for i in 1..<params.len:
if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
return params[i].sym

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
@@ -23,6 +23,7 @@ type
errGeneralParseError,
errNewSectionExpected,
errInvalidDirectiveX,
errProveInit,
errGenerated,
errUser,
warnCannotOpenFile,
@@ -33,12 +34,20 @@ type
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnUnusedImportX,
warnInheritFromException,
warnEachIdentIsTuple,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUnsafeSetLen,
warnUnsafeDefault,
warnProveInit, warnProveField, warnProveIndex,
warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnCaseTransition, warnUser,
warnInconsistentSpacing, warnCaseTransition, warnCycleCreated,
warnObservableStores,
warnUser,
hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintLineTooLong, hintXDeclaredButNotUsed,
hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
@@ -59,6 +68,7 @@ const
errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected",
errInvalidDirectiveX: "invalid directive: '$1'",
errProveInit: "Cannot prove that '$1' is initialized.",
errGenerated: "$1",
errUser: "$1",
warnCannotOpenFile: "cannot open '$1'",
@@ -78,10 +88,17 @@ 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'",
warnInheritFromException: "inherit from a more precise exception type like ValueError, " &
"IOError or OSError. If these don't suit, inherit from CatchableError or Defect.",
warnEachIdentIsTuple: "each identifier is a tuple",
warnUnsafeSetLen: "setLen can potentially expand the sequence, " &
"but the element type '$1' doesn't have a valid default value",
warnUnsafeDefault: "The '$1' type doesn't have a valid default value",
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",
warnProveIndex: "cannot prove index '$1' is valid",
warnStaticIndexCheck: "$1",
warnGcUnsafe: "not GC-safe: '$1'",
warnGcUnsafe2: "$1",
warnUninit: "'$1' might not have been initialized",
@@ -91,10 +108,13 @@ const
warnResultShadowed: "Special variable 'result' is shadowed.",
warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
warnCaseTransition: "Potential object case transition, instantiate new object instead",
warnCycleCreated: "$1",
warnObservableStores: "observable stores to '$1'",
warnUser: "$1",
hintSuccess: "operation successful: $#",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)",
hintCC: "CC: \'$1\'", # unused
# keep in sync with `testament.isSuccess`
hintSuccessX: "$loc LOC; $sec sec; $mem; $build build; proj: $project; out: $output",
hintCC: "CC: $1",
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintConvToBaseNotNeeded: "conversion to base object is not needed",
@@ -108,10 +128,10 @@ const
hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'",
hintConditionAlwaysFalse: "condition is always false: '$1'",
hintName: "name should be: '$1'",
hintName: "$1",
hintPattern: "$1",
hintExecuting: "$1",
hintLinking: "",
hintLinking: "$1",
hintDependency: "$1",
hintSource: "$1",
hintPerformance: "$1",
@@ -133,14 +153,19 @@ const
"LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored",
"TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"UnsafeCode", "UnusedImport", "InheritFromException",
"EachIdentIsTuple",
"UnsafeSetLen", "UnsafeDefault",
"ProveInit", "ProveField", "ProveIndex",
"IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "CaseTransition", "User"]
"Spacing", "CaseTransition", "CycleCreated",
"ObservableStores", "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",
@@ -193,7 +218,7 @@ type
# used for better error messages and
# embedding the original source in the
# generated code
dirtyfile*: AbsoluteFile # the file that is actually read into memory
dirtyFile*: AbsoluteFile # the file that is actually read into memory
# and parsed; usually "" but is used
# for 'nimsuggest'
hash*: string # the checksum of the file
@@ -221,7 +246,7 @@ type
TErrorOutputs* = set[TErrorOutput]
ERecoverableError* = object of ValueError
ESuggestDone* = object of Exception
ESuggestDone* = object of ValueError
proc `==`*(a, b: FileIndex): bool {.borrow.}
@@ -229,19 +254,17 @@ proc raiseRecoverableError*(msg: string) {.noinline.} =
raise newException(ERecoverableError, msg)
const
InvalidFileIDX* = FileIndex(-1)
proc unknownLineInfo*(): TLineInfo =
result.line = uint16(0)
result.col = int16(-1)
result.fileIndex = InvalidFileIDX
InvalidFileIdx* = FileIndex(-1)
unknownLineInfo* = TLineInfo(line: 0, col: -1, fileIndex: InvalidFileIdx)
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
@@ -259,7 +282,7 @@ type
proc initMsgConfig*(): MsgConfig =
result.msgContext = @[]
result.lastError = unknownLineInfo()
result.lastError = unknownLineInfo
result.filenameToIndexTbl = initTable[string, FileIndex]()
result.fileInfos = @[]
result.errorOutputs = {eStdOut, eStdErr}

View File

@@ -9,11 +9,9 @@
## This module implements the style checker.
import
strutils, os, intsets, strtabs
import strutils
import options, ast, astalgo, msgs, semdata, ropes, idents,
lineinfos, pathutils
import options, ast, msgs, idents, lineinfos, wordrecg
const
Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
@@ -22,33 +20,6 @@ proc identLen*(line: string, start: int): int =
while start+result < line.len and line[start+result] in Letters:
inc result
type
StyleCheck* {.pure.} = enum None, Warn, Auto
var
gOverWrite* = true
gStyleCheck*: StyleCheck
gCheckExtern*, gOnlyMainfile*: bool
proc overwriteFiles*(conf: ConfigRef) =
let doStrip = options.getConfigVar(conf, "pretty.strip").normalize == "on"
for i in 0 .. high(conf.m.fileInfos):
if conf.m.fileInfos[i].dirty and
(not gOnlyMainfile or FileIndex(i) == conf.projectMainIdx):
let newFile = if gOverWrite: conf.m.fileInfos[i].fullpath
else: conf.m.fileInfos[i].fullpath.changeFileExt(".pretty.nim")
try:
var f = open(newFile.string, fmWrite)
for line in conf.m.fileInfos[i].lines:
if doStrip:
f.write line.strip(leading = false, trailing = true)
else:
f.write line
f.write(conf.m.fileInfos[i], "\L")
f.close
except IOError:
rawMessage(conf, errGenerated, "cannot open file: " & newFile.string)
proc `=~`(s: string, a: openArray[string]): bool =
for x in a:
if s.startsWith(x): return true
@@ -66,10 +37,10 @@ proc beautifyName(s: string, k: TSymKind): string =
# Types should start with a capital unless builtins like 'int' etc.:
if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
"char", "byte", "bool", "openArray", "seq", "array", "void",
"pointer", "float", "csize", "cdouble", "cchar", "cschar",
"pointer", "float", "csize", "csize_t", "cdouble", "cchar", "cschar",
"cshort", "cu", "nil", "typedesc", "auto", "any",
"range", "openarray", "varargs", "set", "cfloat", "ref", "ptr",
"untyped", "typed", "static", "sink", "lent", "type"]:
"untyped", "typed", "static", "sink", "lent", "type", "owned"]:
result.add s[i]
else:
result.add toUpperAscii(s[i])
@@ -98,47 +69,25 @@ proc beautifyName(s: string, k: TSymKind): string =
result.add s[i]
inc i
proc differ*(line: string, a, b: int, x: string): bool =
let y = line[a..b]
result = cmpIgnoreStyle(y, x) == 0 and y != x
proc differ*(line: string, a, b: int, x: string): string =
proc substrEq(s: string, pos, last: int, substr: string): bool =
var i = 0
while i < substr.len and pos+i <= last and s[pos+i] == substr[i]:
inc i
return i == substr.len
proc replaceInFile(conf: ConfigRef; info: TLineInfo; newName: string) =
let line = conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1]
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in Letters: dec first
if first < 0: return
if line[first] == '`': inc first
let last = min(b, line.len)
let last = first+identLen(line, first)-1
if differ(line, first, last, newName):
# last-first+1 != newName.len or
var x = line.substr(0, first-1) & newName & line.substr(last+1)
system.shallowCopy(conf.m.fileInfos[info.fileIndex.int].lines[info.line.int-1], x)
conf.m.fileInfos[info.fileIndex.int].dirty = true
proc lintReport(conf: ConfigRef; info: TLineInfo, beau: string) =
if optStyleError in conf.globalOptions:
localError(conf, info, "name should be: '$1'" % beau)
else:
message(conf, info, hintName, beau)
result = ""
if not substrEq(line, a, b, x):
let y = line[a..b]
if cmpIgnoreStyle(y, x) == 0:
result = y
proc checkStyle(conf: ConfigRef; cache: IdentCache; info: TLineInfo, s: string, k: TSymKind; sym: PSym) =
let beau = beautifyName(s, k)
if s != beau:
if gStyleCheck == StyleCheck.Auto:
sym.name = getIdent(cache, beau)
replaceInFile(conf, info, beau)
else:
lintReport(conf, info, beau)
proc styleCheckDefImpl(conf: ConfigRef; cache: IdentCache; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are:
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
if k in {skType, skGenericParam} and sfAnon in s.flags: return
if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
checkStyle(conf, cache, info, s.name.s, k, s)
lintReport(conf, info, beau, s)
proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are:
@@ -146,35 +95,47 @@ proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
if k in {skType, skGenericParam} and sfAnon in s.flags: return
if s.typ != nil and s.typ.kind == tyTypeDesc: return
if {sfImportc, sfExportc} * s.flags != {}: return
if optStyleCheck notin s.options: return
let beau = beautifyName(s.name.s, k)
if s.name.s != beau:
lintReport(conf, info, beau)
lintReport(conf, info, beau, s.name.s)
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
if {optStyleHint, optStyleError} * conf.globalOptions != {}:
nep1CheckDefImpl(conf, info, s, k)
when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, cache, info, s, k)
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym) =
styleCheckDef(conf, info, s, s.kind)
template styleCheckDef*(conf: ConfigRef; s: PSym) =
styleCheckDef(conf, s.info, s, s.kind)
proc styleCheckUseImpl(conf: ConfigRef; info: TLineInfo; s: PSym) =
proc differs(conf: ConfigRef; info: TLineInfo; newName: string): string =
let line = sourceLine(conf, info)
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in Letters: dec first
if first < 0: return
if first+1 < line.len and line[first] == '`': inc first
let last = first+identLen(line, first)-1
result = differ(line, first, last, newName)
proc styleCheckUse*(conf: ConfigRef; info: TLineInfo; s: PSym) =
if info.fileIndex.int < 0: return
# we simply convert it to what it looks like in the definition
# for consistency
# operators stay as they are:
if s.kind in {skResult, skTemp} or s.name.s[0] notin Letters:
if s.kind == skTemp or s.name.s[0] notin Letters or sfAnon in s.flags:
return
if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
let newName = s.name.s
let oldName = differs(conf, info, newName)
if oldName.len > 0:
lintReport(conf, info, newName, oldName)
replaceInFile(conf, info, newName)
#if newName == "File": writeStackTrace()
template styleCheckUse*(info: TLineInfo; s: PSym) =
when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckUseImpl(conf, info, s)
proc checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
let wanted = canonPragmaSpelling(w)
if pragmaName != wanted:
lintReport(conf, info, wanted, pragmaName)

View File

@@ -10,11 +10,13 @@
## Low-level streams for high performance.
import
strutils, pathutils
pathutils
# support '-d:useGnuReadline' for backwards compatibility:
when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)):
import rdstdin
# support `useGnuReadline`, `useLinenoise` for backwards compatibility
const hasRstdin = (defined(nimUseLinenoise) or defined(useLinenoise) or defined(useGnuReadline)) and
not defined(windows)
when hasRstdin: import rdstdin
type
TLLRepl* = proc (s: PLLStream, buf: pointer, bufLen: int): int
@@ -97,7 +99,7 @@ proc continueLine(line: string, inTripleString: bool): bool {.inline.} =
proc countTriples(s: string): int =
var i = 0
while i < s.len:
while i+2 < s.len:
if s[i] == '"' and s[i+1] == '"' and s[i+2] == '"':
inc result
inc i, 2
@@ -109,12 +111,12 @@ proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
var line = newStringOfCap(120)
var triples = 0
while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line):
add(s.s, line)
add(s.s, "\n")
s.s.add(line)
s.s.add("\n")
inc triples, countTriples(line)
if not continueLine(line, (triples and 1) == 1): break
inc(s.lineOffset)
result = min(bufLen, len(s.s) - s.rd)
result = min(bufLen, s.s.len - s.rd)
if result > 0:
copyMem(buf, addr(s.s[s.rd]), result)
inc(s.rd, result)
@@ -124,7 +126,7 @@ proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int =
of llsNone:
result = 0
of llsString:
result = min(bufLen, len(s.s) - s.rd)
result = min(bufLen, s.s.len - s.rd)
if result > 0:
copyMem(buf, addr(s.s[0 + s.rd]), result)
inc(s.rd, result)
@@ -139,7 +141,7 @@ proc llStreamReadLine*(s: PLLStream, line: var string): bool =
of llsNone:
result = true
of llsString:
while s.rd < len(s.s):
while s.rd < s.s.len:
case s.s[s.rd]
of '\x0D':
inc(s.rd)
@@ -149,9 +151,9 @@ proc llStreamReadLine*(s: PLLStream, line: var string): bool =
inc(s.rd)
break
else:
add(line, s.s[s.rd])
line.add(s.s[s.rd])
inc(s.rd)
result = line.len > 0 or s.rd < len(s.s)
result = line.len > 0 or s.rd < s.s.len
of llsFile:
result = readLine(s.f, line)
of llsStdIn:
@@ -162,8 +164,8 @@ proc llStreamWrite*(s: PLLStream, data: string) =
of llsNone, llsStdIn:
discard
of llsString:
add(s.s, data)
inc(s.wr, len(data))
s.s.add(data)
inc(s.wr, data.len)
of llsFile:
write(s.f, data)
@@ -177,7 +179,7 @@ proc llStreamWrite*(s: PLLStream, data: char) =
of llsNone, llsStdIn:
discard
of llsString:
add(s.s, data)
s.s.add(data)
inc(s.wr)
of llsFile:
c = data
@@ -189,7 +191,7 @@ proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) =
discard
of llsString:
if buflen > 0:
setLen(s.s, len(s.s) + buflen)
setLen(s.s, s.s.len + buflen)
copyMem(addr(s.s[0 + s.wr]), buf, buflen)
inc(s.wr, buflen)
of llsFile:
@@ -204,7 +206,7 @@ proc llStreamReadAll*(s: PLLStream): string =
of llsString:
if s.rd == 0: result = s.s
else: result = substr(s.s, s.rd)
s.rd = len(s.s)
s.rd = s.s.len
of llsFile:
result = newString(bufSize)
var bytes = readBuffer(s.f, addr(result[0]), bufSize)

View File

@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, idents, semdata, types, msgs, options,
renderer, wordrecg, idgen, nimfix/prettybase, lineinfos, strutils
renderer, nimfix/prettybase, lineinfos, strutils
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)
@@ -36,11 +36,11 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
of nkAccQuoted:
case n.len
of 0: handleError(n, origin)
of 1: result = considerQuotedIdent(c, n.sons[0], origin)
of 1: result = considerQuotedIdent(c, n[0], origin)
else:
var id = ""
for i in 0..<n.len:
let x = n.sons[i]
let x = n[i]
case x.kind
of nkIdent: id.add(x.ident.s)
of nkSym: id.add(x.sym.name.s)
@@ -49,7 +49,7 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
result = getIdent(c.cache, id)
of nkOpenSymChoice, nkClosedSymChoice:
if n[0].kind == nkSym:
result = n.sons[0].sym.name
result = n[0].sym.name
else:
handleError(n, origin)
else:
@@ -100,16 +100,15 @@ proc searchInScopes*(c: PContext, s: PIdent): PSym =
if result != nil: return
result = nil
when declared(echo):
proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
var i = 0
for scope in walkScopes(c.currentScope):
echo "scope ", i
for h in 0 .. high(scope.symbols.data):
if scope.symbols.data[h] != nil:
echo scope.symbols.data[h].name.s
if i == limit: break
inc i
proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
var i = 0
for scope in walkScopes(c.currentScope):
echo "scope ", i
for h in 0..high(scope.symbols.data):
if scope.symbols.data[h] != nil:
echo scope.symbols.data[h].name.s
if i == limit: break
inc i
proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
for scope in walkScopes(c.currentScope):
@@ -124,7 +123,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
## creates an error symbol to avoid cascading errors (for IDE support)
var m = n
# ensure that 'considerQuotedIdent' can't fail:
if m.kind == nkDotExpr: m = m.sons[1]
if m.kind == nkDotExpr: m = m[1]
let ident = if m.kind in {nkIdent, nkSym, nkAccQuoted}:
considerQuotedIdent(c, m)
else:
@@ -233,7 +232,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))
@@ -326,29 +325,29 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
errorUseQualifier(c, n.info, n.sym)
of nkDotExpr:
result = nil
var m = qualifiedLookUp(c, n.sons[0], (flags*{checkUndeclared})+{checkModule})
var m = qualifiedLookUp(c, n[0], (flags*{checkUndeclared})+{checkModule})
if m != nil and m.kind == skModule:
var ident: PIdent = nil
if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident
elif n.sons[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n.sons[1])
if n[1].kind == nkIdent:
ident = n[1].ident
elif n[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n[1])
if ident != nil:
if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n, c.config)
else:
result = strTableGet(m.tab, ident).skipAlias(n, c.config)
if result == nil and checkUndeclared in flags:
fixSpelling(n.sons[1], ident, searchInScopes)
errorUndeclaredIdentifier(c, n.sons[1].info, ident.s)
result = errorSym(c, n.sons[1])
elif n.sons[1].kind == nkSym:
result = n.sons[1].sym
fixSpelling(n[1], ident, searchInScopes)
errorUndeclaredIdentifier(c, n[1].info, ident.s)
result = errorSym(c, n[1])
elif n[1].kind == nkSym:
result = n[1].sym
elif checkUndeclared in flags and
n.sons[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
localError(c.config, n.sons[1].info, "identifier expected, but got: " &
renderTree(n.sons[1]))
result = errorSym(c, n.sons[1])
n[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
localError(c.config, n[1].info, "identifier expected, but got: " &
renderTree(n[1]))
result = errorSym(c, n[1])
else:
result = nil
when false:
@@ -372,13 +371,13 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimDone
of nkDotExpr:
o.mode = oimOtherModule
o.m = qualifiedLookUp(c, n.sons[0], {checkUndeclared, checkModule})
o.m = qualifiedLookUp(c, n[0], {checkUndeclared, checkModule})
if o.m != nil and o.m.kind == skModule:
var ident: PIdent = nil
if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident
elif n.sons[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n.sons[1], n)
if n[1].kind == nkIdent:
ident = n[1].ident
elif n[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n[1], n)
if ident != nil:
if o.m == c.module:
# a module may access its private members:
@@ -388,12 +387,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else:
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n, c.config)
else:
noidentError(c.config, n.sons[1], n)
result = errorSym(c, n.sons[1])
noidentError(c.config, n[1], n)
result = errorSym(c, n[1])
of nkClosedSymChoice, nkOpenSymChoice:
o.mode = oimSymChoice
if n[0].kind == nkSym:
result = n.sons[0].sym
result = n[0].sym
else:
o.mode = oimDone
return nil
@@ -430,8 +429,8 @@ 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):
result = n.sons[o.symChoiceIndex].sym
if o.symChoiceIndex < n.len:
result = n[o.symChoiceIndex].sym
incl(o.inSymChoice, result.id)
inc o.symChoiceIndex
elif n.kind == nkOpenSymChoice:
@@ -439,19 +438,19 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoiceLocalLookup
o.scope = c.currentScope
result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
n[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
while result == nil:
o.scope = o.scope.parent
if o.scope == nil: break
result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
n[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
of oimSymChoiceLocalLookup:
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n, c.config)
while result == nil:
o.scope = o.scope.parent
if o.scope == nil: break
result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
n[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
when false:
if result != nil and result.kind == skStub: loadStub(result)

View File

@@ -14,44 +14,50 @@ const
import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs,
lineinfos
from trees import getMagic
proc newDeref*(n: PNode): PNode {.inline.} =
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
addSon(result, n)
result = newNodeIT(nkHiddenDeref, n.info, n.typ[0])
result.add n
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]))
addSon(result[0], tup[0])
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent}))
result.add newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent})[i])
result[0].add tup[0]
var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
lit.intVal = i
addSon(result[0], lit)
result[0].add lit
else:
result = newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(
abstractInst).sons[i])
addSon(result, copyTree(tup))
abstractInst)[i])
result.add copyTree(tup)
var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
lit.intVal = i
addSon(result, lit)
result.add lit
proc addVar*(father, v: PNode) =
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart.sons[0] = v
vpart.sons[1] = newNodeI(nkEmpty, v.info)
vpart.sons[2] = vpart[1]
addSon(father, vpart)
vpart[0] = v
vpart[1] = newNodeI(nkEmpty, v.info)
vpart[2] = vpart[1]
father.add vpart
proc newAsgnStmt(le, ri: PNode): PNode =
proc addVar*(father, v, value: PNode) =
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart[0] = v
vpart[1] = newNodeI(nkEmpty, v.info)
vpart[2] = value
father.add vpart
proc newAsgnStmt*(le, ri: PNode): PNode =
result = newNodeI(nkAsgn, le.info, 2)
result.sons[0] = le
result.sons[1] = ri
result[0] = le
result[1] = ri
proc newFastAsgnStmt(le, ri: PNode): PNode =
proc newFastAsgnStmt*(le, ri: PNode): PNode =
result = newNodeI(nkFastAsgn, le.info, 2)
result.sons[0] = le
result.sons[1] = ri
result[0] = le
result[1] = ri
proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
assert n.kind == nkVarTuple
@@ -64,13 +70,13 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var v = newNodeI(nkVarSection, value.info)
let tempAsNode = newSymNode(temp)
v.addVar(tempAsNode)
v.addVar(tempAsNode, value)
result.add(v)
result.add newAsgnStmt(tempAsNode, value)
for i in 0 .. n.len-3:
if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
result.add newAsgnStmt(n.sons[i], newTupleAccess(g, tempAsNode, i))
for i in 0..<n.len-2:
let val = newTupleAccess(g, tempAsNode, i)
if n[i].kind == nkSym: v.addVar(n[i], val)
else: result.add newAsgnStmt(n[i], val)
proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode =
## Turns (value) into (let tmp = value; tmp) so that 'value' can be re-used
@@ -90,10 +96,10 @@ proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode =
proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
result = newNodeI(nkBracketExpr, tup.info)
addSon(result, copyTree(tup))
result.add copyTree(tup)
var lit = newNodeI(nkIntLit, tup.info)
lit.intVal = i
addSon(result, lit)
result.add lit
proc newTryFinally*(body, final: PNode): PNode =
result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final))
@@ -107,31 +113,31 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
vpart.sons[0] = tempAsNode
vpart.sons[1] = newNodeI(nkEmpty, value.info)
vpart.sons[2] = value
addSon(v, vpart)
vpart[0] = tempAsNode
vpart[1] = newNodeI(nkEmpty, value.info)
vpart[2] = value
v.add vpart
result.add(v)
let lhs = n.sons[0]
for i in 0 .. lhs.len-1:
result.add newAsgnStmt(lhs.sons[i], newTupleAccessRaw(tempAsNode, i))
let lhs = n[0]
for i in 0..<lhs.len:
result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i))
proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result = newNodeI(nkStmtList, n.info)
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-(
var temp = newSym(skVar, getIdent(g.cache, genPrefix), owner, n.info, owner.options)
temp.typ = n.sons[1].typ
temp.typ = n[1].typ
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, n.info)
let tempAsNode = newSymNode(temp)
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart.sons[0] = tempAsNode
vpart.sons[1] = newNodeI(nkEmpty, v.info)
vpart.sons[2] = n[1]
addSon(v, vpart)
vpart[0] = tempAsNode
vpart[1] = newNodeI(nkEmpty, v.info)
vpart[2] = n[1]
v.add vpart
result.add(v)
result.add newFastAsgnStmt(n[1], n[2])
@@ -151,45 +157,53 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
s.typ = result
result.sym = s
template fieldCheck {.dirty.} =
when false:
if tfCheckedForDestructor in obj.flags:
echo "missed field ", field.name.s
writeStackTrace()
proc rawAddField*(obj: PType; field: PSym) =
assert field.kind == skField
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
field.position = obj.n.len
obj.n.add newSymNode(field)
propagateToOwner(obj, field.typ)
fieldCheck()
proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode =
# returns a[].field as a node
assert field.kind == skField
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
addSon(deref, a)
deref.typ = a.typ.skipTypes(abstractInst)[0]
deref.add a
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.add deref
result.add newSymNode(field)
result.typ = field.typ
proc rawDirectAccess*(obj, field: PSym): PNode =
# returns a.field as a node
assert field.kind == skField
result = newNodeI(nkDotExpr, field.info)
addSon(result, newSymNode obj)
addSon(result, newSymNode field)
result.add newSymNode(obj)
result.add newSymNode(field)
result.typ = field.typ
proc lookupInRecord(n: PNode, id: int): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = lookupInRecord(n.sons[i], id)
for i in 0..<n.len:
result = lookupInRecord(n[i], id)
if result != nil: return
of nkRecCase:
if n.sons[0].kind != nkSym: return
result = lookupInRecord(n.sons[0], id)
if n[0].kind != nkSym: return
result = lookupInRecord(n[0], id)
if result != nil: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = lookupInRecord(lastSon(n.sons[i]), id)
result = lookupInRecord(lastSon(n[i]), id)
if result != nil: return
else: discard
of nkSym:
@@ -205,8 +219,11 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) =
let t = skipIntLit(s.typ)
field.typ = t
assert t.kind != tyTyped
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
propagateToOwner(obj, t)
field.position = obj.n.len
field.flags = s.flags * {sfCursor}
obj.n.add newSymNode(field)
fieldCheck()
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} =
result = lookupInRecord(obj.n, s.id)
@@ -217,45 +234,46 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable
let t = skipIntLit(s.typ)
field.typ = t
assert t.kind != tyTyped
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
propagateToOwner(obj, t)
field.position = obj.n.len
obj.n.add newSymNode(field)
result = field
proc newDotExpr(obj, b: PSym): PNode =
proc newDotExpr*(obj, b: PSym): PNode =
result = newNodeI(nkDotExpr, obj.info)
let field = lookupInRecord(obj.typ.n, b.id)
assert field != nil, b.name.s
addSon(result, newSymNode(obj))
addSon(result, newSymNode(field))
result.add newSymNode(obj)
result.add newSymNode(field)
result.typ = field.typ
proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode =
# returns a[].b as a node
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
deref.typ = a.typ.skipTypes(abstractInst)[0]
var t = deref.typ.skipTypes(abstractInst)
var field: PSym
while true:
assert t.kind == tyObject
field = lookupInRecord(t.n, b)
if field != nil: break
t = t.sons[0]
t = t[0]
if t == nil: break
t = t.skipTypes(skipPtrs)
#if field == nil:
# echo "FIELD ", b
# debug deref.typ
assert field != nil
addSon(deref, a)
deref.add a
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.add deref
result.add newSymNode(field)
result.typ = field.typ
proc indirectAccess(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode =
proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode =
# returns a[].b as a node
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
deref.typ = a.typ.skipTypes(abstractInst)[0]
var t = deref.typ.skipTypes(abstractInst)
var field: PSym
let bb = getIdent(cache, b)
@@ -263,17 +281,17 @@ proc indirectAccess(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PN
assert t.kind == tyObject
field = getSymFromList(t.n, bb)
if field != nil: break
t = t.sons[0]
t = t[0]
if t == nil: break
t = t.skipTypes(skipPtrs)
#if field == nil:
# echo "FIELD ", b
# debug deref.typ
assert field != nil
addSon(deref, a)
deref.add a
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.add deref
result.add newSymNode(field)
result.typ = field.typ
proc getFieldFromObj*(t: PType; v: PSym): PSym =
@@ -283,7 +301,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
assert t.kind == tyObject
result = lookupInRecord(t.n, v.id)
if result != nil: break
t = t.sons[0]
t = t[0]
if t == nil: break
t = t.skipTypes(skipPtrs)
@@ -294,19 +312,19 @@ proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
result = indirectAccess(newSymNode(a), b, info)
proc genAddrOf*(n: PNode): PNode =
proc genAddrOf*(n: PNode, typeKind = tyPtr): PNode =
result = newNodeI(nkAddr, n.info, 1)
result.sons[0] = n
result.typ = newType(tyPtr, n.typ.owner)
result[0] = n
result.typ = newType(typeKind, n.typ.owner)
result.typ.rawAddSon(n.typ)
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
result = newNodeIT(k, n.info,
n.typ.skipTypes(abstractInst).sons[0])
n.typ.skipTypes(abstractInst)[0])
result.add n
proc callCodegenProc*(g: ModuleGraph; name: string;
info: TLineInfo = unknownLineInfo();
info: TLineInfo = unknownLineInfo;
arg1, arg2, arg3, optionalArgs: PNode = nil): PNode =
result = newNodeI(nkCall, info)
let sym = magicsys.getCompilerProc(g, name)
@@ -318,240 +336,9 @@ proc callCodegenProc*(g: ModuleGraph; name: string;
if arg2 != nil: result.add arg2
if arg3 != nil: result.add arg3
if optionalArgs != nil:
for i in 1..optionalArgs.len-3:
for i in 1..<optionalArgs.len-2:
result.add optionalArgs[i]
result.typ = sym.typ.sons[0]
proc callProc(a: PNode): PNode =
result = newNodeI(nkCall, a.info)
result.add a
result.typ = a.typ.sons[0]
# we have 4 cases to consider:
# - a void proc --> nothing to do
# - a proc returning GC'ed memory --> requires a flowVar
# - a proc returning non GC'ed memory --> pass as hidden 'var' parameter
# - not in a parallel environment --> requires a flowVar for memory safety
type
TSpawnResult* = enum
srVoid, srFlowVar, srByVar
TFlowVarKind = enum
fvInvalid # invalid type T for 'FlowVar[T]'
fvGC # FlowVar of a GC'ed type
fvBlob # FlowVar of a blob type
proc spawnResult*(t: PType; inParallel: bool): TSpawnResult =
if t.isEmptyType: srVoid
elif inParallel and not containsGarbageCollectedRef(t): srByVar
else: srFlowVar
proc flowVarKind(t: PType): TFlowVarKind =
if t.skipTypes(abstractInst).kind in {tyRef, tyString, tySequence}: fvGC
elif containsGarbageCollectedRef(t): fvInvalid
else: fvBlob
proc typeNeedsNoDeepCopy(t: PType): bool =
var t = t.skipTypes(abstractInst)
# for the tconvexhull example (and others) we're a bit lax here and pretend
# seqs and strings are *by value* only and 'shallow' doesn't exist!
if t.kind == tyString: return true
# note that seq[T] is fine, but 'var seq[T]' is not, so we need to skip 'var'
# for the stricter check and likewise we can skip 'seq' for a less
# strict check:
if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon
result = not containsGarbageCollectedRef(t)
proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym =
result = newSym(skLet, name, owner, varSection.info, owner.options)
result.flags.incl sfHoisted
result.typ = expr.typ
var varDef = newNodeI(nkIdentDefs, varSection.info, 3)
varDef.sons[0] = newSymNode(result)
varDef.sons[1] = newNodeI(nkEmpty, varSection.info)
varDef.sons[2] = expr
varSection.add varDef
proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType;
v: PNode; useShallowCopy=false): PSym =
result = newSym(skTemp, getIdent(g.cache, genPrefix), owner, varSection.info,
owner.options)
result.typ = typ
incl(result.flags, sfFromGeneric)
var vpart = newNodeI(nkIdentDefs, varSection.info, 3)
vpart.sons[0] = newSymNode(result)
vpart.sons[1] = newNodeI(nkEmpty, varSection.info)
vpart.sons[2] = if varInit.isNil: v else: vpart[1]
varSection.add vpart
if varInit != nil:
if useShallowCopy and typeNeedsNoDeepCopy(typ):
varInit.add newFastAsgnStmt(newSymNode(result), v)
else:
let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
deepCopyCall.sons[0] = newSymNode(getSysMagic(g, varSection.info, "deepCopy", mDeepCopy))
deepCopyCall.sons[1] = newSymNode(result)
deepCopyCall.sons[2] = v
varInit.add deepCopyCall
discard """
We generate roughly this:
proc f_wrapper(thread, args) =
barrierEnter(args.barrier) # for parallel statement
var a = args.a # thread transfer; deepCopy or shallowCopy or no copy
# depending on whether we're in a 'parallel' statement
var b = args.b
var fv = args.fv
fv.owner = thread # optional
nimArgsPassingDone() # signal parent that the work is done
#
args.fv.blob = f(a, b, ...)
nimFlowVarSignal(args.fv)
# - or -
f(a, b, ...)
barrierLeave(args.barrier) # for parallel statement
stmtList:
var scratchObj
scratchObj.a = a
scratchObj.b = b
nimSpawn(f_wrapper, addr scratchObj)
scratchObj.fv # optional
"""
proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
varSection, varInit, call, barrier, fv: PNode;
spawnKind: TSpawnResult): PSym =
var body = newNodeI(nkStmtList, f.info)
body.flags.incl nfTransf # do not transform further
var threadLocalBarrier: PSym
if barrier != nil:
var varSection2 = newNodeI(nkVarSection, barrier.info)
threadLocalBarrier = addLocalVar(g, varSection2, nil, argsParam.owner,
barrier.typ, barrier)
body.add varSection2
body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info,
threadLocalBarrier.newSymNode)
var threadLocalProm: PSym
if spawnKind == srByVar:
threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
elif fv != nil:
internalAssert g.config, fv.typ.kind == tyGenericInst
threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
body.add varSection
body.add varInit
if fv != nil and spawnKind != srByVar:
# generate:
# fv.owner = threadParam
body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
"owner", fv.info, g.cache), threadParam.newSymNode)
body.add callCodegenProc(g, "nimArgsPassingDone", threadParam.info,
threadParam.newSymNode)
if spawnKind == srByVar:
body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call)
elif fv != nil:
let fk = fv.typ.sons[1].flowVarKind
if fk == fvInvalid:
localError(g.config, f.info, "cannot create a flowVar of type: " &
typeToString(fv.typ.sons[1]))
body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
if fk == fvGC: "data" else: "blob", fv.info, g.cache), call)
if fk == fvGC:
let incRefCall = newNodeI(nkCall, fv.info, 2)
incRefCall.sons[0] = newSymNode(getSysMagic(g, fv.info, "GCref", mGCref))
incRefCall.sons[1] = indirectAccess(threadLocalProm.newSymNode,
"data", fv.info, g.cache)
body.add incRefCall
if barrier == nil:
# by now 'fv' is shared and thus might have beeen overwritten! we need
# to use the thread-local view instead:
body.add callCodegenProc(g, "nimFlowVarSignal", threadLocalProm.info,
threadLocalProm.newSymNode)
else:
body.add call
if barrier != nil:
body.add callCodegenProc(g, "barrierLeave", threadLocalBarrier.info,
threadLocalBarrier.newSymNode)
var params = newNodeI(nkFormalParams, f.info)
params.add newNodeI(nkEmpty, f.info)
params.add threadParam.newSymNode
params.add argsParam.newSymNode
var t = newType(tyProc, threadParam.owner)
t.rawAddSon nil
t.rawAddSon threadParam.typ
t.rawAddSon argsParam.typ
t.n = newNodeI(nkFormalParams, f.info)
t.n.add newNodeI(nkEffectList, f.info)
t.n.add threadParam.newSymNode
t.n.add argsParam.newSymNode
let name = (if f.kind == nkSym: f.sym.name.s else: genPrefix) & "Wrapper"
result = newSym(skProc, getIdent(g.cache, name), argsParam.owner, f.info,
argsParam.options)
let emptyNode = newNodeI(nkEmpty, f.info)
result.ast = newProcNode(nkProcDef, f.info, body = body,
params = params, name = newSymNode(result), pattern = emptyNode,
genericParams = emptyNode, pragmas = emptyNode,
exceptions = emptyNode)
result.typ = t
proc createCastExpr(argsParam: PSym; objType: PType): PNode =
result = newNodeI(nkCast, argsParam.info)
result.add newNodeI(nkEmpty, argsParam.info)
result.add newSymNode(argsParam)
result.typ = newType(tyPtr, objType.owner)
result.typ.rawAddSon(objType)
proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym,
castExpr, call,
varSection, varInit, result: PNode) =
let formals = n[0].typ.n
let tmpName = getIdent(g.cache, genPrefix)
for i in 1 ..< n.len:
# we pick n's type here, which hopefully is 'tyArray' and not
# 'tyOpenArray':
var argType = n[i].typ.skipTypes(abstractInst)
if i < formals.len and formals[i].typ.kind in {tyVar, tyLent}:
localError(g.config, n[i].info, "'spawn'ed function cannot have a 'var' parameter")
#elif containsTyRef(argType):
# localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
field.typ = argType
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
let temp = addLocalVar(g, varSection, varInit, objType.owner, argType,
indirectAccess(castExpr, field, n.info))
call.add(newSymNode(temp))
proc getRoot*(n: PNode): PSym =
## ``getRoot`` takes a *path* ``n``. A path is an lvalue expression
## like ``obj.x[i].y``. The *root* of a path is the symbol that can be
## determined as the owner; ``obj`` in the example.
case n.kind
of nkSym:
if n.sym.kind in {skVar, skResult, skTemp, skLet, skForVar}:
result = n.sym
of nkDotExpr, nkBracketExpr, nkHiddenDeref, nkDerefExpr,
nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
result = getRoot(n.sons[0])
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = getRoot(n.sons[1])
of nkCallKinds:
if getMagic(n) == mSlice: result = getRoot(n.sons[1])
else: discard
result.typ = sym.typ[0]
proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
result = nkIntLit.newIntNode(value)
@@ -559,212 +346,30 @@ 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)
result.sons[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
result.sons[1] = n
result[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
result[1] = n
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)
result.sons[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
result.sons[1] = n
result[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
result[1] = n
proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym;
castExpr, call,
varSection, varInit, result: PNode) =
let formals = n[0].typ.n
let tmpName = getIdent(g.cache, genPrefix)
# we need to copy the foreign scratch object fields into local variables
# for correctness: These are called 'threadLocal' here.
for i in 1 ..< n.len:
let n = n[i]
let argType = skipTypes(if i < formals.len: formals[i].typ else: n.typ,
abstractInst)
#if containsTyRef(argType):
# localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym =
result = newSym(skLet, name, owner, varSection.info, owner.options)
result.flags.incl sfHoisted
result.typ = expr.typ
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
var varDef = newNodeI(nkIdentDefs, varSection.info, 3)
varDef[0] = newSymNode(result)
varDef[1] = newNodeI(nkEmpty, varSection.info)
varDef[2] = expr
if argType.kind in {tyVarargs, tyOpenArray}:
# important special case: we always create a zero-copy slice:
let slice = newNodeI(nkCall, n.info, 4)
slice.typ = n.typ
slice.sons[0] = newSymNode(createMagic(g, "slice", mSlice))
slice.sons[0].typ = getSysType(g, n.info, tyInt) # fake type
var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
fieldB.typ = getSysType(g, n.info, tyInt)
objType.addField(fieldB, g.cache)
if getMagic(n) == mSlice:
let a = genAddrOf(n[1])
field.typ = a.typ
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
fieldA.typ = getSysType(g, n.info, tyInt)
objType.addField(fieldA, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3])
let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldA.typ,
indirectAccess(castExpr, fieldA, n.info),
useShallowCopy=true)
slice.sons[2] = threadLocal.newSymNode
else:
let a = genAddrOf(n)
field.typ = a.typ
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n))
slice.sons[2] = newIntLit(g, n.info, 0)
# the array itself does not need to go through a thread local variable:
slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info))
let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldB.typ,
indirectAccess(castExpr, fieldB, n.info),
useShallowCopy=true)
slice.sons[3] = threadLocal.newSymNode
call.add slice
elif (let size = computeSize(g.config, argType); size < 0 or size > 16) and
n.getRoot != nil:
# it is more efficient to pass a pointer instead:
let a = genAddrOf(n)
field.typ = a.typ
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
let threadLocal = addLocalVar(g, varSection,nil, objType.owner, field.typ,
indirectAccess(castExpr, field, n.info),
useShallowCopy=true)
call.add(genDeref(threadLocal.newSymNode))
else:
# boring case
field.typ = argType
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)
let threadLocal = addLocalVar(g, varSection, varInit,
objType.owner, field.typ,
indirectAccess(castExpr, field, n.info),
useShallowCopy=true)
call.add(threadLocal.newSymNode)
proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: PType;
barrier, dest: PNode = nil): PNode =
# if 'barrier' != nil, then it is in a 'parallel' section and we
# generate quite different code
let n = spawnExpr[^2]
let spawnKind = spawnResult(retType, barrier!=nil)
case spawnKind
of srVoid:
internalAssert g.config, dest == nil
result = newNodeI(nkStmtList, n.info)
of srFlowVar:
internalAssert g.config, dest == nil
result = newNodeIT(nkStmtListExpr, n.info, retType)
of srByVar:
if dest == nil: localError(g.config, n.info, "'spawn' must not be discarded")
result = newNodeI(nkStmtList, n.info)
if n.kind notin nkCallKinds:
localError(g.config, n.info, "'spawn' takes a call expression")
return
if optThreadAnalysis in g.config.globalOptions:
if {tfThread, tfNoSideEffect} * n[0].typ.flags == {}:
localError(g.config, n.info, "'spawn' takes a GC safe call expression")
var
threadParam = newSym(skParam, getIdent(g.cache, "thread"), owner, n.info, g.config.options)
argsParam = newSym(skParam, getIdent(g.cache, "args"), owner, n.info, g.config.options)
block:
let ptrType = getSysType(g, n.info, tyPointer)
threadParam.typ = ptrType
argsParam.typ = ptrType
argsParam.position = 1
var objType = createObj(g, owner, n.info)
incl(objType.flags, tfFinal)
let castExpr = createCastExpr(argsParam, objType)
var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), owner, n.info, g.config.options)
block:
scratchObj.typ = objType
incl(scratchObj.flags, sfFromGeneric)
var varSectionB = newNodeI(nkVarSection, n.info)
varSectionB.addVar(scratchObj.newSymNode)
result.add varSectionB
var call = newNodeIT(nkCall, n.info, n.typ)
var fn = n.sons[0]
# templates and macros are in fact valid here due to the nature of
# the transformation:
if fn.kind == nkClosure:
localError(g.config, n.info, "closure in spawn environment is not allowed")
if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro,
skFunc, skMethod, skConverter}):
# for indirect calls we pass the function pointer in the scratchObj
var argType = n[0].typ.skipTypes(abstractInst)
var field = newSym(skField, getIdent(g.cache, "fn"), owner, n.info, g.config.options)
field.typ = argType
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
fn = indirectAccess(castExpr, field, n.info)
elif fn.kind == nkSym and fn.sym.kind == skIterator:
localError(g.config, n.info, "iterator in spawn environment is not allowed")
elif fn.typ.callConv == ccClosure:
localError(g.config, n.info, "closure in spawn environment is not allowed")
call.add(fn)
var varSection = newNodeI(nkVarSection, n.info)
var varInit = newNodeI(nkStmtList, n.info)
if barrier.isNil:
setupArgsForConcurrency(g, n, objType, scratchObj, castExpr, call,
varSection, varInit, result)
else:
setupArgsForParallelism(g, n, objType, scratchObj, castExpr, call,
varSection, varInit, result)
var barrierAsExpr: PNode = nil
if barrier != nil:
let typ = newType(tyPtr, owner)
typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)
var field = newSym(skField, getIdent(g.cache, "barrier"), owner, n.info, g.config.options)
field.typ = typ
objType.addField(field, g.cache)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)
barrierAsExpr = indirectAccess(castExpr, field, n.info)
var fvField, fvAsExpr: PNode = nil
if spawnKind == srFlowVar:
var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
field.typ = retType
objType.addField(field, g.cache)
fvField = newDotExpr(scratchObj, field)
fvAsExpr = indirectAccess(castExpr, field, n.info)
# create flowVar:
result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))
if barrier == nil:
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info,
fvField)
elif spawnKind == srByVar:
var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
field.typ = newType(tyPtr, objType.owner)
field.typ.rawAddSon(retType)
objType.addField(field, g.cache)
fvAsExpr = indirectAccess(castExpr, field, n.info)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest))
let wrapper = createWrapperProc(g, fn, threadParam, argsParam,
varSection, varInit, call,
barrierAsExpr, fvAsExpr, spawnKind)
result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapper.info,
wrapper.newSymNode, genAddrOf(scratchObj.newSymNode), nil, spawnExpr)
if spawnKind == srFlowVar: result.add fvField
varSection.add varDef

View File

@@ -9,7 +9,7 @@
## This module implements helpers for the macro cache.
import lineinfos, ast, modulegraphs, vmdef, magicsys
import lineinfos, ast, modulegraphs, vmdef
proc recordInc*(c: PCtx; info: TLineInfo; key: string; by: BiggestInt) =
var recorded = newNodeI(nkCommentStmt, info)

View File

@@ -10,7 +10,7 @@
# Built-in types and compilerprocs are registered here.
import
ast, astalgo, hashes, msgs, platform, nversion, times, idents,
ast, astalgo, msgs, platform, idents,
modulegraphs, lineinfos
export createMagic
@@ -40,7 +40,7 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy
while r != nil:
if r.magic == m:
# prefer the tyInt variant:
if r.typ.sons[0] != nil and r.typ.sons[0].kind == tyInt: return r
if r.typ[0] != nil and r.typ[0].kind == tyInt: return r
result = r
r = nextIdentIter(ti, g.systemModule.tab)
if result != nil: return result
@@ -68,7 +68,7 @@ proc getSysType*(g: ModuleGraph; info: TLineInfo; kind: TTypeKind): PType =
of tyUInt64: result = sysTypeFromName("uint64")
of tyFloat: result = sysTypeFromName("float")
of tyFloat32: result = sysTypeFromName("float32")
of tyFloat64: return sysTypeFromName("float64")
of tyFloat64: result = sysTypeFromName("float64")
of tyFloat128: result = sysTypeFromName("float128")
of tyBool: result = sysTypeFromName("bool")
of tyChar: result = sysTypeFromName("char")
@@ -79,7 +79,9 @@ proc getSysType*(g: ModuleGraph; info: TLineInfo; kind: TTypeKind): PType =
else: internalError(g.config, "request for typekind: " & $kind)
g.sysTypes[kind] = result
if result.kind != kind:
internalError(g.config, "wanted: " & $kind & " got: " & $result.kind)
if kind == tyFloat64 and result.kind == tyFloat: discard # because of aliasing
else:
internalError(g.config, "wanted: " & $kind & " got: " & $result.kind)
if result == nil: internalError(g.config, "type not found: " & $kind)
proc resetSysTypes*(g: ModuleGraph) =
@@ -123,7 +125,7 @@ proc addSonSkipIntLit*(father, son: PType) =
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
let s = son.skipIntLit
add(father.sons, s)
father.sons.add(s)
propagateToOwner(father, s)
proc setIntLitType*(g: ModuleGraph; result: PNode) =
@@ -175,3 +177,28 @@ proc getNimScriptSymbol*(g: ModuleGraph; name: string): PSym =
strTableGet(g.exposed, getIdent(g.cache, name))
proc resetNimScriptSymbols*(g: ModuleGraph) = initStrTable(g.exposed)
proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym =
case t.kind
of tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64:
result = getSysMagic(g, info, "==", mEqI)
of tyEnum:
result = getSysMagic(g, info, "==", mEqEnum)
of tyBool:
result = getSysMagic(g, info, "==", mEqB)
of tyRef, tyPtr, tyPointer:
result = getSysMagic(g, info, "==", mEqRef)
of tyString:
result = getSysMagic(g, info, "==", mEqStr)
of tyChar:
result = getSysMagic(g, info, "==", mEqCh)
of tySet:
result = getSysMagic(g, info, "==", mEqSet)
of tyProc:
result = getSysMagic(g, info, "==", mEqProc)
else:
globalError(g.config, info,
"can't find magic equals operator for type kind " & $t.kind)

View File

@@ -13,22 +13,17 @@ when not defined(nimcore):
{.error: "nimcore MUST be defined for Nim's core tooling".}
import
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
os, condsyms, times,
wordrecg, sem, semdata, idents, passes, extccomp,
llstream, strutils, os, ast, lexer, syntaxes, options, msgs,
condsyms, times,
sem, idents, passes, extccomp,
cgen, json, nversion,
platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
parser, modules, ccgutils, sigmatch, ropes,
platform, nimconf, passaux, depends, vm, idgen,
modules,
modulegraphs, tables, rod, lineinfos, pathutils
when not defined(leanCompiler):
import jsgen, docgen, docgen2
from magicsys import resetSysTypes
proc codegenPass(g: ModuleGraph) =
registerPass g, cgenPass
proc semanticPasses(g: ModuleGraph) =
registerPass g, verbosePass
registerPass g, semPass
@@ -87,6 +82,16 @@ 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
if not extccomp.ccHasSaneOverflow(conf):
conf.symbols.defineSymbol("nimEmulateOverflowChecks")
compileProject(graph)
if graph.config.errorCounter > 0:
return # issue #9933
@@ -106,6 +111,7 @@ proc commandJsonScript(graph: ModuleGraph) =
when not defined(leanCompiler):
proc commandCompileToJS(graph: ModuleGraph) =
let conf = graph.config
conf.exc = excCpp
if conf.outDir.isEmpty:
conf.outDir = conf.projectPath
@@ -148,14 +154,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)
@@ -190,10 +188,12 @@ proc mainCommand*(graph: ModuleGraph) =
of "c", "cc", "compile", "compiletoc":
# compile means compileToC currently
conf.cmd = cmdCompileToC
if conf.exc == excNone: conf.exc = excSetjmp
defineSymbol(graph.config.symbols, "c")
commandCompileToC(graph)
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
if conf.exc == excNone: conf.exc = excCpp
defineSymbol(graph.config.symbols, "cpp")
commandCompileToC(graph)
of "objc", "compiletooc":
@@ -203,7 +203,7 @@ proc mainCommand*(graph: ModuleGraph) =
of "run":
conf.cmd = cmdRun
when hasTinyCBackend:
extccomp.setCC("tcc")
extccomp.setCC(conf, "tcc", unknownLineInfo)
commandCompileToC(graph)
else:
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
@@ -228,6 +228,12 @@ proc mainCommand*(graph: ModuleGraph) =
loadConfigs(DocConfig, cache, conf)
commandDoc(cache, conf)
of "doc2", "doc":
conf.setNoteDefaults(warnLockLevel, false) # issue #13218
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218
# because currently generates lots of false positives due to conflation
# of labels links in doc comments, eg for random.rand:
# ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
# ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
@@ -236,6 +242,7 @@ proc mainCommand*(graph: ModuleGraph) =
defineSymbol(conf.symbols, "nimdoc")
commandDoc2(graph, false)
of "rst2html":
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # similar to issue #13218
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
@@ -296,7 +303,9 @@ proc mainCommand*(graph: ModuleGraph) =
for s in definedSymbolNames(conf.symbols): definedSymbols.elems.add(%s)
var libpaths = newJArray()
var lazyPaths = newJArray()
for dir in conf.searchPaths: libpaths.elems.add(%dir.string)
for dir in conf.lazyPaths: lazyPaths.elems.add(%dir.string)
var hints = newJObject() # consider factoring with `listHints`
for a in hintMin..hintMax:
@@ -309,9 +318,13 @@ proc mainCommand*(graph: ModuleGraph) =
var dumpdata = %[
(key: "version", val: %VersionAsString),
(key: "nimExe", val: %(getAppFilename())),
(key: "prefixdir", val: %conf.getPrefixDir().string),
(key: "libpath", val: %conf.libpath.string),
(key: "project_path", val: %conf.projectFull.string),
(key: "defined_symbols", val: definedSymbols),
(key: "lib_paths", val: %libpaths),
(key: "lazyPaths", val: %lazyPaths),
(key: "outdir", val: %conf.outDir.string),
(key: "out", val: %conf.outFile.string),
(key: "nimcache", val: %getNimcacheDir(conf).string),
@@ -343,8 +356,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
@@ -356,16 +372,25 @@ proc mainCommand*(graph: ModuleGraph) =
if conf.errorCounter == 0 and
conf.cmd notin {cmdInterpret, cmdRun, cmdDump}:
when declared(system.getMaxMem):
let usedMem = formatSize(getMaxMem()) & " peakmem"
else:
let usedMem = formatSize(getTotalMem())
rawMessage(conf, hintSuccessX, [$conf.linesCompiled,
formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3),
usedMem,
if isDefined(conf, "danger"): "Dangerous Release Build"
elif isDefined(conf, "release"): "Release Build"
else: "Debug Build"])
let mem =
when declared(system.getMaxMem): formatSize(getMaxMem()) & " peakmem"
else: formatSize(getTotalMem()) & " totmem"
let loc = $conf.linesCompiled
let build = if isDefined(conf, "danger"): "Dangerous Release"
elif isDefined(conf, "release"): "Release"
else: "Debug"
let sec = formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3)
let project = if optListFullPaths in conf.globalOptions: $conf.projectFull else: $conf.projectName
var output = $conf.absOutFile
if optListFullPaths notin conf.globalOptions: output = output.AbsoluteFile.extractFilename
rawMessage(conf, hintSuccessX, [
"loc", loc,
"sec", sec,
"mem", mem,
"build", build,
"project", project,
"output", output,
])
when PrintRopeCacheStats:
echo "rope cache stats: "

View File

@@ -29,7 +29,7 @@ import ast, intsets, tables, options, lineinfos, hashes, idents,
incremental, btrees, md5
type
SigHash* = distinct Md5Digest
SigHash* = distinct MD5Digest
ModuleGraph* = ref object
modules*: seq[PSym] ## indexed by int32 fileIdx
@@ -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]
@@ -72,6 +72,10 @@ type
onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
globalDestructors*: seq[PNode]
proofEngine*: proc (graph: ModuleGraph; assumptions: seq[PNode]; toProve: PNode): (bool, string) {.nimcall.}
requirementsCheck*: proc (graph: ModuleGraph; assumptions: seq[PNode];
call, requirement: PNode): (bool, string) {.nimcall.}
compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {.nimcall.}
TPassContext* = object of RootObj # the pass's context
PPassContext* = ref TPassContext
@@ -98,7 +102,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])
@@ -163,8 +167,9 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
result = g.doStopCompile != nil and g.doStopCompile()
proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym =
result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo(), {})
result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo, {})
result.magic = m
result.flags = {sfNeverRaises}
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
result = ModuleGraph()
@@ -215,7 +220,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

@@ -8,7 +8,7 @@
#
import ast, renderer, strutils, msgs, options, idents, os, lineinfos,
pathutils, nimblecmd
pathutils
when false:
const
@@ -139,7 +139,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
result.add modname
of nkPrefix:
when false:
if n.sons[0].kind == nkIdent and n.sons[0].ident.s == "$":
if n[0].kind == nkIdent and n[0].ident.s == "$":
result = lookupPackage(n[1], nil)
else:
discard
@@ -149,7 +149,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths is deprecated")
result = renderTree(n, {renderNoComments}).replace(".", "/")
of nkImportAs:
result = getModuleName(conf, n.sons[0])
result = getModuleName(conf, n[0])
else:
localError(conf, n.info, "invalid module name: '$1'" % n.renderTree)
result = ""
@@ -162,6 +162,6 @@ proc checkModuleName*(conf: ConfigRef; n: PNode; doLocalError=true): FileIndex =
if doLocalError:
let m = if modulename.len > 0: modulename else: $n
localError(conf, n.info, "cannot open file: " & m)
result = InvalidFileIDX
result = InvalidFileIdx
else:
result = fileInfoIdx(conf, fullPath)

View File

@@ -10,8 +10,8 @@
## Implements the module handling, including the caching of modules.
import
ast, astalgo, magicsys, std / sha1, msgs, cgendata, sigmatch, options,
idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
ast, astalgo, magicsys, msgs, options,
idents, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
lineinfos, pathutils, tables
proc resetSystemArtifacts*(g: ModuleGraph) =
@@ -39,7 +39,8 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
# but starting with version 0.20 we now produce a fake Nimble package instead
# to resolve the conflicts:
let pck3 = fakePackageName(graph.config, filename)
packSym = newSym(skPackage, getIdent(graph.cache, pck3), nil, result.info)
# this makes the new `packSym`'s owner be the original `packSym`
packSym = newSym(skPackage, getIdent(graph.cache, pck3), packSym, result.info)
initStrTable(packSym.tab)
graph.packageSyms.strTableAdd(packSym)
@@ -50,22 +51,19 @@ 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)
proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
# We cannot call ``newSym`` here, because we have to circumvent the ID
# mechanism, which we do in order to assign each module a persistent ID.
new(result)
result.id = -1 # for better error checking
result.kind = skModule
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
result.name = getIdent(graph.cache, splitFile(filename).name)
result = PSym(kind: skModule, id: -1, # for better error checking
name: getIdent(graph.cache, splitFile(filename).name),
info: newLineInfo(fileIdx, 1, 1))
if not isNimIdentifier(result.name.s):
rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
result.info = newLineInfo(fileIdx, 1, 1)
partialInitModule(result, graph, fileIdx, filename)
proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): PSym =
@@ -77,8 +75,6 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
if result == nil:
result = newModule(graph, fileIdx)
result.flags = result.flags + flags
if sfMainModule in result.flags:
graph.config.mainPackageId = result.owner.id
result.id = id
registerModule(graph, result)
else:
@@ -96,7 +92,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil)
graph.markClientsDirty(fileIdx)
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym {.procvar.} =
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
# this is called by the semantic checking phase
assert graph.config != nil
result = compileModule(graph, fileIdx, {})
@@ -111,7 +107,7 @@ proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym {.proc
if s.owner.id == graph.config.mainPackageId or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode {.procvar.} =
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
result = syntaxes.parseFile(fileIdx, graph.cache, graph.config)
graph.addDep(s, fileIdx)
graph.addIncludeDep(s.position.FileIndex, fileIdx)
@@ -133,12 +129,12 @@ proc wantMainModule*(conf: ConfigRef) =
"command expects a filename")
conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIDX) =
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
connectCallbacks(graph)
let conf = graph.config
wantMainModule(conf)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIDX: conf.projectMainIdx else: projectFileIdx
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})

View File

@@ -8,7 +8,7 @@
#
import
options, strutils, os, tables, ropes, platform, terminal, macros,
options, strutils, os, tables, ropes, terminal, macros,
lineinfos, pathutils
proc toCChar*(c: char; result: var string) =
@@ -26,13 +26,13 @@ proc makeCString*(s: string): Rope =
const MaxLineLength = 64
result = nil
var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
add(res, "\"")
for i in 0 ..< len(s):
res.add("\"")
for i in 0..<s.len:
if (i + 1) mod MaxLineLength == 0:
add(res, "\"\L\"")
res.add("\"\L\"")
toCChar(s[i], res)
add(res, '\"')
add(result, rope(res))
res.add('\"')
result.add(rope(res))
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
@@ -40,9 +40,8 @@ proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
#shallow(result.fullPath)
result.projPath = projPath
#shallow(result.projPath)
let fileName = fullPath.extractFilename
result.shortName = fileName.changeFileExt("")
result.quotedName = fileName.makeCString
result.shortName = fullPath.extractFilename
result.quotedName = result.shortName.makeCString
result.quotedFullName = fullPath.string.makeCString
result.lines = @[]
when defined(nimpretty):
@@ -82,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
@@ -96,14 +96,20 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
result.fileIndex = fileInfoIdx
result.line = uint16(line)
result.col = int16(col)
if line < int high(uint16):
result.line = uint16(line)
else:
result.line = high(uint16)
if col < int high(int16):
result.col = int16(col)
else:
result.col = -1
proc newLineInfo*(conf: ConfigRef; filename: AbsoluteFile, line, col: int): TLineInfo {.inline.} =
result = newLineInfo(fileInfoIdx(conf, filename), line, col)
proc concat(strings: openarray[string]): string =
proc concat(strings: openArray[string]): string =
var totalLen = 0
for s in strings: totalLen += s.len
result = newStringOfCap totalLen
@@ -147,26 +153,32 @@ proc pushInfoContext*(conf: ConfigRef; info: TLineInfo; detail: string = "") =
conf.m.msgContext.add((info, detail))
proc popInfoContext*(conf: ConfigRef) =
setLen(conf.m.msgContext, len(conf.m.msgContext) - 1)
setLen(conf.m.msgContext, conf.m.msgContext.len - 1)
proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
let L = conf.m.msgContext.len
let i = if index < 0: L + index else: index
if i >=% L: result = unknownLineInfo()
let i = if index < 0: conf.m.msgContext.len + index else: index
if i >=% conf.m.msgContext.len: 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:
if optListFullPaths in conf.globalOptions:
conf.m.fileInfos[fileIdx.int32].fullPath.string
else:
conf.m.fileInfos[fileIdx.int32].projPath.string
conf.m.fileInfos[fileIdx.int32].shortName
proc toProjPath*(conf: ConfigRef; fileIdx: FileIndex): string =
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
@@ -183,7 +195,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:
@@ -192,22 +204,28 @@ proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile
template toFilename*(conf: ConfigRef; info: TLineInfo): string =
toFilename(conf, info.fileIndex)
template toProjPath*(conf: ConfigRef; info: TLineInfo): string =
toProjPath(conf, info.fileIndex)
template toFullPath*(conf: ConfigRef; info: TLineInfo): string =
toFullPath(conf, info.fileIndex)
template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string =
string toFullPathConsiderDirty(conf, info.fileIndex)
proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
if info.fileIndex.int32 < 0:
result = "???"
return
let absPath = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
if optListFullPaths in conf.globalOptions:
result = absPath
else:
let relPath = conf.m.fileInfos[info.fileIndex.int32].projPath.string
result = if relPath.count("..") > 2: absPath else: relPath
proc toMsgFilename*(conf: ConfigRef; info: FileIndex): string =
let
absPath = toFullPath(conf, info)
relPath = toProjPath(conf, info)
result = if (optListFullPaths in conf.globalOptions) or
(relPath.len > absPath.len) or
(relPath.count("..") > 2):
absPath
else:
relPath
template toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
toMsgFilename(conf, info.fileIndex)
proc toLinenumber*(info: TLineInfo): int {.inline.} =
result = int info.line
@@ -215,12 +233,9 @@ proc toLinenumber*(info: TLineInfo): int {.inline.} =
proc toColumn*(info: TLineInfo): int {.inline.} =
result = info.col
proc toFileLine*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
result = toFilename(conf, info) & ":" & $info.line
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
# consider calling `helpers.lineInfoToString` instead
result = toFilename(conf, info) & "(" & $info.line & ", " &
result = toMsgFilename(conf, info) & "(" & $info.line & ", " &
$(info.col + ColOffset) & ")"
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
@@ -318,14 +333,14 @@ proc getMessageStr(msg: TMsgKind, arg: string): string =
type
TErrorHandling = enum doNothing, doAbort, doRaise
proc log*(s: string) {.procvar.} =
proc log*(s: string) =
var f: File
if open(f, getHomeDir() / "nimsuggest.log", fmAppend):
f.writeLine(s)
close(f)
proc quit(conf: ConfigRef; msg: TMsgKind) {.gcsafe.} =
if defined(debug) or msg == errInternal or hintStackTrace in conf.notes:
if defined(debug) or msg == errInternal or conf.hasHint(hintStackTrace):
{.gcsafe.}:
if stackTraceAvailable() and isNil(conf.writelnHook):
writeStackTrace()
@@ -359,12 +374,12 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
const instantiationFrom = "template/generic instantiation from here"
const instantiationOfFrom = "template/generic instantiation of `$1` from here"
var info = lastinfo
for i in 0 ..< len(conf.m.msgContext):
for i in 0..<conf.m.msgContext.len:
let context = conf.m.msgContext[i]
if context.info != lastinfo and context.info != info:
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, context.info, instantiationFrom,
Severity.Error)
Severity.Hint)
else:
let message = if context.detail == "":
instantiationFrom
@@ -390,22 +405,20 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
case msg
of errMin..errMax:
sev = Severity.Error
writeContext(conf, unknownLineInfo())
writeContext(conf, unknownLineInfo)
title = ErrorTitle
color = ErrorColor
of warnMin..warnMax:
sev = Severity.Warning
if optWarns notin conf.options: return
if msg notin conf.notes: return
writeContext(conf, unknownLineInfo())
if not conf.hasWarn(msg): return
writeContext(conf, unknownLineInfo)
title = WarningTitle
color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
if optHints notin conf.options: return
if msg notin conf.notes: return
if not conf.hasHint(msg): return
title = HintTitle
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
@@ -413,7 +426,7 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
let s = msgKindToString(msg) % args
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, unknownLineInfo(),
conf.structuredErrorHook(conf, unknownLineInfo,
s & (if kind.len > 0: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg):
@@ -452,7 +465,8 @@ proc sourceLine*(conf: ConfigRef; i: TLineInfo): string =
proc writeSurroundingSrc(conf: ConfigRef; info: TLineInfo) =
const indent = " "
msgWriteln(conf, indent & $sourceLine(conf, info))
msgWriteln(conf, indent & spaces(info.col) & '^')
if info.col >= 0:
msgWriteln(conf, indent & spaces(info.col) & '^')
proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): string =
let title = case msg
@@ -484,7 +498,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
conf.m.lastError = info
of warnMin..warnMax:
sev = Severity.Warning
ignoreMsg = optWarns notin conf.options or msg notin conf.notes
ignoreMsg = not conf.hasWarn(msg)
if not ignoreMsg: writeContext(conf, info)
title = WarningTitle
color = WarningColor
@@ -492,7 +506,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
ignoreMsg = optHints notin conf.options or msg notin conf.notes
ignoreMsg = not conf.hasHint(msg)
title = HintTitle
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
@@ -510,7 +524,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
KindColor, `%`(KindFormat, kind))
else:
styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s)
if hintSource in conf.notes:
if conf.hasHint(hintSource):
conf.writeSurroundingSrc(info)
handleError(conf, msg, eh, s)
@@ -532,7 +546,7 @@ proc localError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
proc localError*(conf: ConfigRef; info: TLineInfo, arg: string) =
liMessage(conf, info, errGenerated, arg, doNothing)
proc localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openarray[string]) =
proc localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openArray[string]) =
localError(conf, info, format % params)
proc message*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
@@ -545,7 +559,7 @@ proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
proc internalError*(conf: ConfigRef; errMsg: string) =
if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
writeContext(conf, unknownLineInfo())
writeContext(conf, unknownLineInfo)
rawMessage(conf, errInternal, errMsg)
template assertNotNil*(conf: ConfigRef; e): untyped =
@@ -556,8 +570,9 @@ template internalAssert*(conf: ConfigRef, e: bool) =
if not e: internalError(conf, $instantiationInfo())
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
assert i.fileIndex.int32 >= 0
if optExcessiveStackTrace in conf.globalOptions:
if i.fileIndex.int32 < 0:
result = makeCString "???"
elif optExcessiveStackTrace in conf.globalOptions:
result = conf.m.fileInfos[i.fileIndex.int32].quotedFullName
else:
result = conf.m.fileInfos[i.fileIndex.int32].quotedName
@@ -577,3 +592,10 @@ proc listHints*(conf: ConfigRef) =
if hint in conf.notes: "x" else: " ",
lineinfos.HintsToStr[ord(hint) - ord(hintMin)]
])
proc lintReport*(conf: ConfigRef; info: TLineInfo, beau, got: string) =
let m = "'$2' should be: '$1'" % [beau, got]
if optStyleError in conf.globalOptions:
localError(conf, info, m)
else:
message(conf, info, hintName, m)

View File

@@ -17,6 +17,8 @@ type
enabled: bool
f: File
buf: string
filename: AbsoluteFile
syms: seq[PSym]
proc doWrite(f: var NdiFile; s: PSym; conf: ConfigRef) =
f.buf.setLen 0
@@ -28,13 +30,20 @@ proc doWrite(f: var NdiFile; s: PSym; conf: ConfigRef) =
f.f.writeLine("\t", toFullPath(conf, s.info), "\t", f.buf)
template writeMangledName*(f: NdiFile; s: PSym; conf: ConfigRef) =
if f.enabled: doWrite(f, s, conf)
if f.enabled: f.syms.add s
proc open*(f: var NdiFile; filename: AbsoluteFile; conf: ConfigRef) =
f.enabled = not filename.isEmpty
if f.enabled:
f.f = open(filename.string, fmWrite, 8000)
f.filename = filename
f.buf = newStringOfCap(20)
proc close*(f: var NdiFile) =
if f.enabled: close(f.f)
proc close*(f: var NdiFile, conf: ConfigRef) =
if f.enabled:
f.f = open(f.filename.string, fmWrite, 8000)
doAssert f.f != nil, f.filename.string
for s in f.syms:
doWrite(f, s, conf)
close(f.f)
f.syms.reset
f.filename.reset

View File

@@ -7,16 +7,18 @@ define:nimcore
#define:nimIncremental
#import:"$projectpath/testability"
#define:staticSqlite
@if windows:
cincludes: "$lib/wrappers/libffi/common"
@end
define:useStdoutAsStdmsg
define:nimOldCaseObjects
@if nimHasStyleChecks:
styleCheck:error
@end
#define:useNodeIds
#gc:markAndSweep
@if nimHasWarningCaseTransition:
warning[CaseTransition]:off
@end

View File

@@ -19,9 +19,9 @@ when defined(i386) and defined(windows) and defined(vcc):
{.link: "../icons/nim-i386-windows-vcc.res".}
import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt,
scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper,
commands, options, msgs,
extccomp, strutils, os, main, parseopt,
idents, lineinfos, cmdlinehelper,
pathutils
include nodejs
@@ -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:
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
@@ -73,12 +93,12 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
self.processCmdLineAndProjectPath(conf)
if not self.loadConfigsAndRunMainCommand(cache, conf): return
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
if conf.hasHint(hintGCStats): echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter != 0: return
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.run(conf.arguments)
tccgen.run(conf, conf.arguments)
if optRun in conf.globalOptions:
var ex = quoteShell conf.absOutFile
if conf.cmd == cmdCompileToJS:

View File

@@ -48,7 +48,7 @@ proc `<`*(ver: Version, ver2: Version): bool =
# Handling for normal versions such as "0.1.0" or "1.0".
var sVer = string(ver).split('.')
var sVer2 = string(ver2).split('.')
for i in 0..max(sVer.len, sVer2.len)-1:
for i in 0..<max(sVer.len, sVer2.len):
var sVerI = 0
if i < sVer.len:
discard parseInt(sVer[i], sVerI)
@@ -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
@@ -82,7 +83,7 @@ proc getPathVersion*(p: string): tuple[name, version: string] =
result.name = p
return
result.name = p[0 .. sepIdx - 1]
result.name = p[0..sepIdx - 1]
result.version = p.substr(sepIdx + 1)
proc addPackage(conf: ConfigRef; packages: StringTableRef, p: string; info: TLineInfo) =
@@ -129,6 +130,10 @@ proc addPathRec(conf: ConfigRef; dir: string, info: TLineInfo) =
proc nimblePath*(conf: ConfigRef; path: AbsoluteDir, info: TLineInfo) =
addPathRec(conf, path.string, info)
addNimblePath(conf, path.string, info)
let i = conf.nimblePaths.find(path)
if i != -1:
conf.nimblePaths.delete(i)
conf.nimblePaths.insert(path, 0)
when isMainModule:
proc v(s: string): Version = s.newVersion
@@ -142,16 +147,16 @@ when isMainModule:
let conf = newConfigRef()
var rr = newStringTable()
addPackage conf, rr, "irc-#a111", unknownLineInfo()
addPackage conf, rr, "irc-#head", unknownLineInfo()
addPackage conf, rr, "irc-0.1.0", unknownLineInfo()
#addPackage conf, rr, "irc", unknownLineInfo()
#addPackage conf, rr, "another", unknownLineInfo()
addPackage conf, rr, "another-0.1", unknownLineInfo()
addPackage conf, rr, "irc-#a111", unknownLineInfo
addPackage conf, rr, "irc-#head", unknownLineInfo
addPackage conf, rr, "irc-0.1.0", unknownLineInfo
#addPackage conf, rr, "irc", unknownLineInfo
#addPackage conf, rr, "another", unknownLineInfo
addPackage conf, rr, "another-0.1", unknownLineInfo
addPackage conf, rr, "ab-0.1.3", unknownLineInfo()
addPackage conf, rr, "ab-0.1", unknownLineInfo()
addPackage conf, rr, "justone-1.0", unknownLineInfo()
addPackage conf, rr, "ab-0.1.3", unknownLineInfo
addPackage conf, rr, "ab-0.1", unknownLineInfo
addPackage conf, rr, "justone-1.0", unknownLineInfo
doAssert toSeq(rr.chosen) ==
@["irc-#head", "another-0.1", "ab-0.1.3", "justone-1.0"]

View File

@@ -10,8 +10,8 @@
# This module handles the reading of the config file.
import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
options, idents, wordrecg, strtabs, lineinfos, pathutils
llstream, commands, os, strutils, msgs, lexer,
options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig
# ---------------- configuration file parser -----------------------------
# we use Nim's scanner here to save space and work
@@ -114,7 +114,7 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
ppGetTok(L, tok) # skip @
case whichKeyword(tok.ident)
of wIf:
setLen(condStack, len(condStack) + 1)
setLen(condStack, condStack.len + 1)
let res = evalppIf(L, tok, config)
condStack[high(condStack)] = res
if not res: jumpToDirective(L, tok, jdElseEndif, config, condStack)
@@ -123,31 +123,31 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
of wEnd: doEnd(L, tok, condStack)
of wWrite:
ppGetTok(L, tok)
msgs.msgWriteln(config, strtabs.`%`(tokToStr(tok), config.configVars,
msgs.msgWriteln(config, strtabs.`%`($tok, config.configVars,
{useEnvironment, useKey}))
ppGetTok(L, tok)
else:
case tok.ident.s.normalize
of "putenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
var key = $tok
ppGetTok(L, tok)
os.putEnv(key, tokToStr(tok))
os.putEnv(key, $tok)
ppGetTok(L, tok)
of "prependenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
var key = $tok
ppGetTok(L, tok)
os.putEnv(key, tokToStr(tok) & os.getEnv(key))
os.putEnv(key, $tok & os.getEnv(key))
ppGetTok(L, tok)
of "appendenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
var key = $tok
ppGetTok(L, tok)
os.putEnv(key, os.getEnv(key) & tokToStr(tok))
os.putEnv(key, os.getEnv(key) & $tok)
ppGetTok(L, tok)
else:
lexMessage(L, errGenerated, "invalid directive: '$1'" % tokToStr(tok))
lexMessage(L, errGenerated, "invalid directive: '$1'" % $tok)
proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
ppGetTok(L, tok)
@@ -156,44 +156,51 @@ proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var s
proc checkSymbol(L: TLexer, tok: TToken) =
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
lexMessage(L, errGenerated, "expected identifier, but got: " & tokToStr(tok))
lexMessage(L, errGenerated, "expected identifier, but got: " & $tok)
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 = tokToStr(tok)
var s = $tok
confTok(L, tok, config, condStack) # skip symbol
var val = ""
while tok.tokType == tkDot:
add(s, '.')
s.add('.')
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(s, tokToStr(tok))
s.add($tok)
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketLe:
# BUGFIX: val, not s!
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(val, '[')
add(val, tokToStr(tok))
val.add('[')
val.add($tok)
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketRi: confTok(L, tok, config, condStack)
else: lexMessage(L, errGenerated, "expected closing ']'")
add(val, ']')
val.add(']')
let percent = tok.ident != nil and tok.ident.s == "%="
if tok.tokType in {tkColon, tkEquals} or percent:
if len(val) > 0: add(val, ':')
if val.len > 0: val.add(':')
confTok(L, tok, config, condStack) # skip ':' or '=' or '%'
checkSymbol(L, tok)
add(val, tokToStr(tok))
val.add($tok)
confTok(L, tok, config, condStack) # skip symbol
if tok.tokType in {tkColon, tkEquals}:
val.add($tok) # add the :
confTok(L, tok, config, condStack) # skip symbol
checkSymbol(L, tok)
val.add($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)
add(val, tokToStr(tok))
val.add($tok)
confTok(L, tok, config, condStack)
if percent:
processSwitch(s, strtabs.`%`(val, config.configVars,
@@ -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
@@ -215,7 +222,7 @@ proc readConfigFile(filename: AbsoluteFile; cache: IdentCache;
var condStack: seq[bool] = @[]
confTok(L, tok, config, condStack) # read in the first token
while tok.tokType != tkEof: parseAssignment(L, tok, config, condStack)
if len(condStack) > 0: lexMessage(L, errGenerated, "expected @end")
if condStack.len > 0: lexMessage(L, errGenerated, "expected @end")
closeLexer(L)
return true
@@ -239,19 +246,34 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
template readConfigFile(path) =
let configPath = path
if readConfigFile(configPath, cache, conf):
add(configFiles, configPath)
configFiles.add(configPath)
template runNimScriptIfExists(path: AbsoluteFile) =
let p = path # eval once
if fileExists(p):
configFiles.add(p)
runNimScript(cache, p, freshDefines = false, conf)
if optSkipSystemConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg))
if cfg == DefaultConfig:
runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims))
if optSkipUserConfigFile notin conf.globalOptions:
readConfigFile(getUserConfigPath(cfg))
if cfg == DefaultConfig:
runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
let pd = if not conf.projectPath.isEmpty: conf.projectPath else: AbsoluteDir(getCurrentDir())
if optSkipParentConfigFiles notin conf.globalOptions:
for dir in parentDirs(pd.string, fromRoot=true, inclusive=false):
readConfigFile(AbsoluteDir(dir) / cfg)
if cfg == DefaultConfig:
runNimScriptIfExists(AbsoluteDir(dir) / DefaultConfigNims)
if optSkipProjConfigFile notin conf.globalOptions:
readConfigFile(pd / cfg)
@@ -262,6 +284,20 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
projectConfig = changeFileExt(conf.projectFull, "nim.cfg")
readConfigFile(projectConfig)
if cfg == DefaultConfig:
runNimScriptIfExists(pd / DefaultConfigNims)
for filename in configFiles:
# delayed to here so that `hintConf` is honored
rawMessage(conf, hintConf, filename.string)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
if conf.command != "nimsuggest":
runNimScriptIfExists(scriptFile)
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile)
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard

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

@@ -8,9 +8,7 @@
#
import strutils except Letters
import lexbase, streams
import ".." / [ast, msgs, lineinfos, idents, options, linter]
from os import splitFile
proc replaceDeprecated*(conf: ConfigRef; info: TLineInfo; oldSym, newSym: PIdent) =
let line = sourceLine(conf, info)

View File

@@ -157,7 +157,7 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
result = ""
var i = L.lineStart
while not (L.buf[i] in {CR, LF, EndOfFile}):
add(result, L.buf[i])
result.add(L.buf[i])
inc(i)
result.add("\n")
if marker:

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