mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 10:53:40 +00:00
Compare commits
368 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d274b56256 | ||
|
|
dd6833297f | ||
|
|
e885d89f63 | ||
|
|
2b53216152 | ||
|
|
d33e112766 | ||
|
|
e7e8f437c4 | ||
|
|
789b1bcbb6 | ||
|
|
251bdc1d5a | ||
|
|
b41226001c | ||
|
|
a4fdaa88cc | ||
|
|
ab47707586 | ||
|
|
2f4900615a | ||
|
|
8fa2c0b532 | ||
|
|
e2e663a143 | ||
|
|
ac89eead8a | ||
|
|
6f4bacff67 | ||
|
|
1e5dd9022b | ||
|
|
8cde6ba6bc | ||
|
|
eefca1b81f | ||
|
|
1972005439 | ||
|
|
25d89269eb | ||
|
|
836b95c896 | ||
|
|
415689323c | ||
|
|
e1702ae1e6 | ||
|
|
f2b16c490d | ||
|
|
b024a45163 | ||
|
|
d0232f0e5b | ||
|
|
4341b06f65 | ||
|
|
f7a13f62d6 | ||
|
|
68aeb4c1a6 | ||
|
|
4e3eb7414c | ||
|
|
d30c6419a0 | ||
|
|
15f0b48676 | ||
|
|
497af2c0d9 | ||
|
|
004fc23a3f | ||
|
|
14960fa754 | ||
|
|
d81edcacc6 | ||
|
|
ec0cec3170 | ||
|
|
b1b5e3ab10 | ||
|
|
05c0419658 | ||
|
|
a8426fc789 | ||
|
|
63cca93ea9 | ||
|
|
06f02bb771 | ||
|
|
33888a7384 | ||
|
|
19001c070b | ||
|
|
c61eb5df32 | ||
|
|
b9f243eb2a | ||
|
|
85bc8326ac | ||
|
|
b2b878f4d6 | ||
|
|
61c1142667 | ||
|
|
8c100a37b9 | ||
|
|
2c73e84436 | ||
|
|
0455d24d55 | ||
|
|
a4401054cc | ||
|
|
278ecad973 | ||
|
|
2ecae20c43 | ||
|
|
832b8c5034 | ||
|
|
927978345b | ||
|
|
4680ab61c0 | ||
|
|
e4a2c2d474 | ||
|
|
8bfc396a4d | ||
|
|
ef4ac5a0d2 | ||
|
|
82680a12a7 | ||
|
|
42ac50e988 | ||
|
|
ee0a470294 | ||
|
|
15ae9323e8 | ||
|
|
465fd06d50 | ||
|
|
2f32b450d3 | ||
|
|
efaa6777a4 | ||
|
|
8e6136dd59 | ||
|
|
b10f0e7bca | ||
|
|
02e8aa9660 | ||
|
|
bb839029d5 | ||
|
|
dc4cc2dca5 | ||
|
|
ef7d7f2459 | ||
|
|
98cebad7de | ||
|
|
26bcf18f91 | ||
|
|
26acc97864 | ||
|
|
a77ffdb7ea | ||
|
|
152dab0983 | ||
|
|
ded8b0e541 | ||
|
|
00775f6880 | ||
|
|
e78ef57c93 | ||
|
|
1807de38e5 | ||
|
|
c8aeea9d62 | ||
|
|
810d5e91e4 | ||
|
|
0978276ed9 | ||
|
|
e1929deac7 | ||
|
|
065f568470 | ||
|
|
cb6ce80cb8 | ||
|
|
e649ddd09b | ||
|
|
abe3b0eb64 | ||
|
|
c322faaf38 | ||
|
|
5a995ffc53 | ||
|
|
83dabb69ae | ||
|
|
c3f03cfa5d | ||
|
|
a7024f49af | ||
|
|
1275763284 | ||
|
|
49844415ce | ||
|
|
eae29e8eaf | ||
|
|
7d32425a57 | ||
|
|
82319ef00d | ||
|
|
8cdd8867c0 | ||
|
|
86e93eb293 | ||
|
|
84ac003519 | ||
|
|
4dfe420c2f | ||
|
|
51df9ff1c7 | ||
|
|
12a0f88a52 | ||
|
|
afbcba909b | ||
|
|
400e0260b8 | ||
|
|
7c3c61f2f1 | ||
|
|
a262a87bbe | ||
|
|
2c01c9c4c8 | ||
|
|
b0bd4320a0 | ||
|
|
d7a966c4eb | ||
|
|
d14e8e8dcc | ||
|
|
e93eaac223 | ||
|
|
7f6e800caf | ||
|
|
a8b5ad845c | ||
|
|
4c8934305c | ||
|
|
c4a0d4c5e3 | ||
|
|
731eabc930 | ||
|
|
3e83d73f27 | ||
|
|
7b811deeff | ||
|
|
7a50d66346 | ||
|
|
4c76f9f152 | ||
|
|
6773ffa63d | ||
|
|
2beefb9aa0 | ||
|
|
0d6795a771 | ||
|
|
8f9dd5b349 | ||
|
|
6454472938 | ||
|
|
488e18f90d | ||
|
|
590d397852 | ||
|
|
d6d36093b1 | ||
|
|
207237cec2 | ||
|
|
c870ff5946 | ||
|
|
c2c9fbd745 | ||
|
|
f0bfc0bd3f | ||
|
|
9c17a32e0e | ||
|
|
ef3f343ec2 | ||
|
|
fe791c67b4 | ||
|
|
9a49451124 | ||
|
|
340b5a1676 | ||
|
|
0c915b5e47 | ||
|
|
516db3bac3 | ||
|
|
f019e999d4 | ||
|
|
30e9f23ec0 | ||
|
|
b2c5d7b4ff | ||
|
|
2ef71c0a46 | ||
|
|
8e8231f9d6 | ||
|
|
42eeab5fd1 | ||
|
|
cda77c1520 | ||
|
|
551225d888 | ||
|
|
ed0dce7292 | ||
|
|
b936bfd01a | ||
|
|
27e548140b | ||
|
|
801c0f0369 | ||
|
|
4b0636fba0 | ||
|
|
28180e47a9 | ||
|
|
6b302bb71b | ||
|
|
d0287748fe | ||
|
|
7b09fd70ab | ||
|
|
33bfe5b12c | ||
|
|
772ed5eff2 | ||
|
|
891329cd4b | ||
|
|
486cb09ec2 | ||
|
|
1830a3b505 | ||
|
|
22ae0bef63 | ||
|
|
56a901f9e1 | ||
|
|
33cd883e27 | ||
|
|
cb894c7094 | ||
|
|
520881af9a | ||
|
|
0c3892c3c7 | ||
|
|
6319b00ef7 | ||
|
|
4b723c0f53 | ||
|
|
6ea6225523 | ||
|
|
f7c4fb0014 | ||
|
|
15f54de5c4 | ||
|
|
2bd1aa186e | ||
|
|
1563cb2f6e | ||
|
|
927fa890ec | ||
|
|
851e515bba | ||
|
|
4a38092ac1 | ||
|
|
ce44cf03cc | ||
|
|
08261cb9e3 | ||
|
|
5d34e81f23 | ||
|
|
23c4bbedcb | ||
|
|
b3c178c202 | ||
|
|
aac54b9c7f | ||
|
|
d7869a8009 | ||
|
|
5d303762f1 | ||
|
|
bc3bee5469 | ||
|
|
07c7a8a526 | ||
|
|
dc8ac66873 | ||
|
|
4f6b59de96 | ||
|
|
2c5b367001 | ||
|
|
15e3813d96 | ||
|
|
d102b2f54c | ||
|
|
a95399143f | ||
|
|
342b74ef70 | ||
|
|
7bdfeb7819 | ||
|
|
a93f6e7acc | ||
|
|
9b9ae8a487 | ||
|
|
5853303be0 | ||
|
|
40a9c33eff | ||
|
|
a9135095f0 | ||
|
|
ada815e459 | ||
|
|
9a32905d89 | ||
|
|
9888a29c3d | ||
|
|
bcbeff3632 | ||
|
|
92e5573b20 | ||
|
|
955040f0f1 | ||
|
|
b098546da0 | ||
|
|
ae92eac060 | ||
|
|
58656aa5bb | ||
|
|
4306d8fb36 | ||
|
|
c7d5b8c83d | ||
|
|
5ec8b60942 | ||
|
|
9df195ef58 | ||
|
|
1869826668 | ||
|
|
0bcd7062c6 | ||
|
|
39a27783fc | ||
|
|
35cae73aa5 | ||
|
|
fcf1df6e56 | ||
|
|
526a32e169 | ||
|
|
19bcb43a0e | ||
|
|
bd4f76a2e3 | ||
|
|
e49d52eb61 | ||
|
|
bbd5086bc3 | ||
|
|
53e1d57419 | ||
|
|
61d682e733 | ||
|
|
ef634cc251 | ||
|
|
faaf271928 | ||
|
|
ac37eed5a2 | ||
|
|
dc5c88ca79 | ||
|
|
23d64be860 | ||
|
|
a9223d4cdd | ||
|
|
77ad8b81e4 | ||
|
|
a61bbf7d8d | ||
|
|
fdbec969d8 | ||
|
|
fa96e56ad0 | ||
|
|
81d32cf7e5 | ||
|
|
7a5314c571 | ||
|
|
19898e1225 | ||
|
|
4da7dbffc5 | ||
|
|
ea475a4e98 | ||
|
|
b812431f83 | ||
|
|
610516e027 | ||
|
|
3d9b6cfebc | ||
|
|
5ddaf3e1fb | ||
|
|
609388e33f | ||
|
|
5d2bab7558 | ||
|
|
c17baaefbc | ||
|
|
3e31f55aed | ||
|
|
c55930f2e6 | ||
|
|
78b86b7942 | ||
|
|
0ff4b2ba7e | ||
|
|
4b5cecd902 | ||
|
|
a3ef5df680 | ||
|
|
1a92edeb89 | ||
|
|
908fc2a22e | ||
|
|
7ff43d07b2 | ||
|
|
9338aa2497 | ||
|
|
c989542339 | ||
|
|
d39147219a | ||
|
|
69aabdab80 | ||
|
|
32d4bf3525 | ||
|
|
4f64c9fae5 | ||
|
|
99f8793502 | ||
|
|
742e9d65ad | ||
|
|
502ac4ed5e | ||
|
|
0992854941 | ||
|
|
7806ec525e | ||
|
|
cd592ed85b | ||
|
|
93c8427fca | ||
|
|
ebd88725f9 | ||
|
|
0213c7313b | ||
|
|
7e3da693f5 | ||
|
|
faacd63bf6 | ||
|
|
e5475768ba | ||
|
|
1ef945668d | ||
|
|
c658de24b0 | ||
|
|
1cbdc1573a | ||
|
|
f90620fb32 | ||
|
|
d584dd5b99 | ||
|
|
23c117a950 | ||
|
|
373c909300 | ||
|
|
0d0c249074 | ||
|
|
f91867aa31 | ||
|
|
a59ad20062 | ||
|
|
a0073d2d4c | ||
|
|
c7c6b13a32 | ||
|
|
ff39f6e260 | ||
|
|
2859069dbe | ||
|
|
5933aece9b | ||
|
|
040d23e799 | ||
|
|
7772ca303c | ||
|
|
1b143f5e79 | ||
|
|
eb5358dcdb | ||
|
|
a8611c665f | ||
|
|
fe46c8b5f1 | ||
|
|
92d6fb86c6 | ||
|
|
309ec7167e | ||
|
|
6976d18519 | ||
|
|
bec4900165 | ||
|
|
270a5a372d | ||
|
|
ade85ee91f | ||
|
|
0a1049881e | ||
|
|
c6fc3b2eae | ||
|
|
f8b71f7075 | ||
|
|
3aaa12dbe5 | ||
|
|
528ef6c218 | ||
|
|
cde83d90aa | ||
|
|
7313b70a6a | ||
|
|
036d894e6a | ||
|
|
77b696c2c9 | ||
|
|
a78ee8ae84 | ||
|
|
15157d06c3 | ||
|
|
997ccc5889 | ||
|
|
46fb855425 | ||
|
|
b0f4a9b845 | ||
|
|
6ff61766da | ||
|
|
b7c66ce860 | ||
|
|
83a9c3ba31 | ||
|
|
b21eb1ed36 | ||
|
|
b423ab138f | ||
|
|
fce89cb60a | ||
|
|
f2f15e9726 | ||
|
|
b2edc3468c | ||
|
|
f7cfc46ae1 | ||
|
|
dbbafd320c | ||
|
|
5fed1c05ce | ||
|
|
539bced70d | ||
|
|
b155864967 | ||
|
|
9d51197aa4 | ||
|
|
a55b90827e | ||
|
|
efaaa38eef | ||
|
|
12d2901e89 | ||
|
|
e01e543fce | ||
|
|
2e0db988e7 | ||
|
|
cc984217a9 | ||
|
|
24a7584299 | ||
|
|
4c510d5577 | ||
|
|
2f730afe9e | ||
|
|
2bda4a30a6 | ||
|
|
f755e452d2 | ||
|
|
cfdac6666f | ||
|
|
ee703c5db4 | ||
|
|
7ba2659f73 | ||
|
|
c80e2c1736 | ||
|
|
cd2b093d07 | ||
|
|
ee65767d44 | ||
|
|
f50bcf82c3 | ||
|
|
dde556665a | ||
|
|
8d5a275189 | ||
|
|
83a2515af7 | ||
|
|
3ecb369ca1 | ||
|
|
582468da1c | ||
|
|
141b76e365 | ||
|
|
41d9918591 | ||
|
|
6621e1a3ea | ||
|
|
490c4226a5 | ||
|
|
4d8108046b | ||
|
|
d634587423 | ||
|
|
5e2b9341f3 | ||
|
|
1a45da9150 | ||
|
|
62701cd3b9 | ||
|
|
c239db4817 |
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -2,7 +2,7 @@
|
||||
name: Feature request
|
||||
about: Do you want to suggest a new feature? Use this template.
|
||||
title: ''
|
||||
labels: ''
|
||||
labels: ["Feature"]
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
94
changelog.md
94
changelog.md
@@ -3,15 +3,102 @@
|
||||
|
||||
## Changes affecting backward compatibility
|
||||
|
||||
- The `Math.trunc` polyfill for targeting Internet Explorer was
|
||||
previously emitted for every JavaScript output file except if
|
||||
the symbol `nodejs` was defined via `-d:nodejs`. Now, it is only
|
||||
emitted if the symbol `nimJsMathTruncPolyfill` is defined. If you are
|
||||
targeting Internet Explorer, you may choose to enable this option
|
||||
or define your own `Math.trunc` polyfill using the [`emit` pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-emit-pragma). Nim uses
|
||||
`Math.trunc` for the division and modulo operators for integers.
|
||||
|
||||
- Deprecated `std/sums`.
|
||||
|
||||
- Optional parameters in combination with `: body` syntax (RFC #405) are now opt-in via
|
||||
`experimental:flexibleOptionalParams`.
|
||||
|
||||
- `std/sharedstrings` module is removed.
|
||||
- Constants `colors.colPaleVioletRed` and `colors.colMediumPurple` changed to match the CSS color standard.
|
||||
|
||||
- `addr` is now available for all addressable locations, `unsafeAddr` is deprecated and
|
||||
becomes an alias for `addr`.
|
||||
|
||||
- io is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/syncio`.
|
||||
|
||||
- The `gc:v2` option is removed.
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Changes:"
|
||||
- `macros.parseExpr` and `macros.parseStmt` now accept an optional.
|
||||
filename argument for more informative errors.
|
||||
- Module `colors` expanded with missing colors from the CSS color standard.
|
||||
- Fixed `lists.SinglyLinkedList` being broken after removing the last node ([#19353](https://github.com/nim-lang/Nim/pull/19353)).
|
||||
- `md5` now works at compile time and in JavaScript.
|
||||
- `std/smtp` sends `ehlo` first. If the mail server does not understand, it sends `helo` as a fallback.
|
||||
- Changed mimedb to use an `OrderedTable` instead of `OrderedTableRef`, to use it in a const.
|
||||
- `strutils.find` now use and default to `last=-1` for whole string searches, making limiting it to just the first char (`last=0`) valid.
|
||||
|
||||
[//]: # "Additions:"
|
||||
- Added `IsoWeekRange`, a range type to represent the number of weeks in an ISO week-based year.
|
||||
- Added `IsoYear`, a distinct int type to prevent bugs from confusing the week-based year and the regular year.
|
||||
- Added `initDateTime` in `times` to create a datetime from a weekday, and ISO 8601 week number and week-based year.
|
||||
- Added `getIsoWeekAndYear` in `times` to get an ISO week number along with the corresponding ISO week-based year from a datetime.
|
||||
- Added `getIsoWeeksInYear` in `times` to return the number of weeks in an ISO week-based year.
|
||||
- Added `std/oserrors` for OS error reporting. Added `std/envvars` for environment variables handling.
|
||||
- Added `sep` parameter in `std/uri` to specify the query separator.
|
||||
- Added [`Array.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift) for JavaScript targets.
|
||||
- Added [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask) for JavaScript targets.
|
||||
|
||||
[//]: # "Deprecations:"
|
||||
- Deprecated `selfExe` for Nimscript.
|
||||
|
||||
[//]: # "Removals:"
|
||||
- Removed deprecated `oids.oidToString`.
|
||||
- Removed define `nimExperimentalAsyncjsThen` for `std/asyncjs.then` and `std/jsfetch`.
|
||||
- Removed deprecated `jsre.test` and `jsre.toString`.
|
||||
- Removed deprecated `math.c_frexp`.
|
||||
- Removed deprecated `` httpcore.`==` ``.
|
||||
- Removed deprecated `std/dom_extensions`.
|
||||
- Removed deprecated `std/posix.CMSG_SPACE` and `std/posix.CMSG_LEN` that takes wrong argument types.
|
||||
- Removed deprecated `osproc.poDemon`, symbol with typo.
|
||||
|
||||
## Language changes
|
||||
|
||||
- Pragma macros on type definitions can now return `nnkTypeSection` nodes as well as `nnkTypeDef`,
|
||||
allowing multiple type definitions to be injected in place of the original type definition.
|
||||
|
||||
```nim
|
||||
import macros
|
||||
|
||||
macro multiply(amount: static int, s: untyped): untyped =
|
||||
let name = $s[0].basename
|
||||
result = newNimNode(nnkTypeSection)
|
||||
for i in 1 .. amount:
|
||||
result.add(newTree(nnkTypeDef, ident(name & $i), s[1], s[2]))
|
||||
|
||||
type
|
||||
Foo = object
|
||||
Bar {.multiply: 3.} = object
|
||||
x, y, z: int
|
||||
Baz = object
|
||||
|
||||
# becomes
|
||||
|
||||
type
|
||||
Foo = object
|
||||
Bar1 = object
|
||||
x, y, z: int
|
||||
Bar2 = object
|
||||
x, y, z: int
|
||||
Bar3 = object
|
||||
x, y, z: int
|
||||
Baz = object
|
||||
```
|
||||
- [Case statement macros](manual.html#macros-case-statement-macros) are no longer experimental,
|
||||
meaning you no longer need to enable the experimental switch `caseStmtMacros` to use them.
|
||||
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
|
||||
for the right-hand side of type definitions in type sections. Previously
|
||||
they would error with "invalid indentation".
|
||||
|
||||
## Compiler changes
|
||||
|
||||
@@ -21,5 +108,12 @@
|
||||
|
||||
## Tool changes
|
||||
|
||||
- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the
|
||||
reality better. (Nim moved away from all techniques based on "tracing".)
|
||||
|
||||
- Nim now supports Nimble version 0.14 which added support for lock-files. This is done by
|
||||
a simple configuration change setting that you can do yourself too. In `$nim/config/nim.cfg`
|
||||
replace `pkgs` by `pkgs2`.
|
||||
|
||||
- There is a new switch `--nimMainPrefix:prefix` to influence the `NimMain` that the
|
||||
compiler produces. This is particularly useful for generating static libraries.
|
||||
|
||||
33
changelogs/changelog.md
Normal file
33
changelogs/changelog.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# v1.xx.x - yyyy-mm-dd
|
||||
|
||||
## Changes affecting backward compatibility
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
- `std/sharedlist` and `std/sharedtables` are now deprecated, see RFC [#433](https://github.com/nim-lang/RFCs/issues/433).
|
||||
|
||||
### New compile flag (`-d:nimNoGetRandom`) when building `std/sysrand` to remove dependency on linux `getrandom` syscall
|
||||
|
||||
This compile flag only affects linux builds and is necessary if either compiling on a linux kernel version < 3.17, or if code built will be executing on kernel < 3.17.
|
||||
|
||||
On linux kernels < 3.17 (such as kernel 3.10 in RHEL7 and CentOS7), the `getrandom` syscall was not yet introduced. Without this, the `std/sysrand` module will not build properly, and if code is built on a kernel >= 3.17 without the flag, any usage of the `std/sysrand` module will fail to execute on a kernel < 3.17 (since it attempts to perform a syscall to `getrandom`, which isn't present in the current kernel). A compile flag has been added to force the `std/sysrand` module to use /dev/urandom (available since linux kernel 1.3.30), rather than the `getrandom` syscall. This allows for use of a cryptographically secure PRNG, regardless of kernel support for the `getrandom` syscall.
|
||||
|
||||
When building for RHEL7/CentOS7 for example, the entire build process for nim from a source package would then be:
|
||||
```sh
|
||||
$ yum install devtoolset-8 # Install GCC version 8 vs the standard 4.8.5 on RHEL7/CentOS7. Alternatively use -d:nimEmulateOverflowChecks. See issue #13692 for details
|
||||
$ scl enable devtoolset-8 bash # Run bash shell with default toolchain of gcc 8
|
||||
$ sh build.sh # per unix install instructions
|
||||
$ bin/nim c koch # per unix install instructions
|
||||
$ ./koch boot -d:release # per unix install instructions
|
||||
$ ./koch tools -d:nimNoGetRandom # pass the nimNoGetRandom flag to compile std/sysrand without support for getrandom syscall
|
||||
```
|
||||
|
||||
This is necessary to pass when building nim on kernel versions < 3.17 in particular to avoid an error of "SYS_getrandom undeclared" during the build process for stdlib (sysrand in particular).
|
||||
|
||||
## Language changes
|
||||
|
||||
|
||||
## Compiler changes
|
||||
|
||||
|
||||
## Tool changes
|
||||
@@ -282,7 +282,7 @@
|
||||
- Removed the deprecated `asyncdispatch.newAsyncNativeSocket`.
|
||||
- Removed the deprecated `dom.releaseEvents` and `dom.captureEvents`.
|
||||
|
||||
- Removed `sharedlists.initSharedList`, was deprecated and produces undefined behaviour.
|
||||
- Removed `sharedlist.initSharedList`, was deprecated and produces undefined behaviour.
|
||||
|
||||
- There is a new experimental feature called "strictFuncs" which makes the definition of
|
||||
`.noSideEffect` stricter. [See here](manual_experimental.html#stricts-funcs)
|
||||
|
||||
@@ -76,6 +76,8 @@ _nimBuildCsourcesIfNeeded(){
|
||||
makeX=gmake
|
||||
elif [ "$unamestr" = 'CROSSOS' ]; then
|
||||
makeX=gmake
|
||||
elif [ "$unamestr" = 'SunOS' ]; then
|
||||
makeX=gmake
|
||||
else
|
||||
makeX=make
|
||||
fi
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
import
|
||||
ast, astalgo, types, trees, intsets
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
TAnalysisResult* = enum
|
||||
arNo, arMaybe, arYes
|
||||
|
||||
@@ -13,6 +13,9 @@ import
|
||||
lineinfos, hashes, options, ropes, idents, int128, tables
|
||||
from strutils import toLowerAscii
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
export int128
|
||||
|
||||
type
|
||||
@@ -501,7 +504,7 @@ type
|
||||
nfHasComment # node has a comment
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 43)
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45)
|
||||
tfVarargs, # procedure has C styled varargs
|
||||
# tyArray type represeting a varargs list
|
||||
tfNoSideEffect, # procedure type does not allow side effects
|
||||
@@ -673,7 +676,7 @@ type
|
||||
mSwap, mIsNil, mArrToSeq,
|
||||
mNewString, mNewStringOfCap, mParseBiggestFloat,
|
||||
mMove, mWasMoved, mDestroy, mTrace,
|
||||
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mReset,
|
||||
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mAccessTypeField, mReset,
|
||||
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
|
||||
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
|
||||
mOrdinal, mIterableType,
|
||||
@@ -1105,21 +1108,6 @@ proc getPIdent*(a: PNode): PIdent {.inline.} =
|
||||
of nkIdent: a.ident
|
||||
else: nil
|
||||
|
||||
proc getnimblePkg*(a: PSym): PSym =
|
||||
result = a
|
||||
while result != nil:
|
||||
case result.kind
|
||||
of skModule:
|
||||
result = result.owner
|
||||
assert result.kind == skPackage
|
||||
of skPackage:
|
||||
if result.owner == nil:
|
||||
break
|
||||
else:
|
||||
result = result.owner
|
||||
else:
|
||||
assert false, $result.kind
|
||||
|
||||
const
|
||||
moduleShift = when defined(cpu32): 20 else: 24
|
||||
|
||||
@@ -1164,13 +1152,7 @@ when false:
|
||||
assert dest.ItemId.item <= src.ItemId.item
|
||||
dest = src
|
||||
|
||||
proc getnimblePkgId*(a: PSym): int =
|
||||
let b = a.getnimblePkg
|
||||
result = if b == nil: -1 else: b.id
|
||||
|
||||
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
|
||||
#var
|
||||
# gMainPackageId*: int
|
||||
|
||||
proc isCallExpr*(n: PNode): bool =
|
||||
result = n.kind in nkCallKinds
|
||||
@@ -1524,7 +1506,7 @@ proc assignType*(dest, src: PType) =
|
||||
# this fixes 'type TLock = TSysLock':
|
||||
if src.sym != nil:
|
||||
if dest.sym != nil:
|
||||
dest.sym.flags.incl src.sym.flags-{sfExported}
|
||||
dest.sym.flags.incl src.sym.flags-{sfUsed, sfExported}
|
||||
if dest.sym.annex == nil: dest.sym.annex = src.sym.annex
|
||||
mergeLoc(dest.sym.loc, src.sym.loc)
|
||||
else:
|
||||
@@ -2101,3 +2083,11 @@ proc skipAddr*(n: PNode): PNode {.inline.} =
|
||||
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
|
||||
assert n.kind == nkTypeClassTy
|
||||
result = n[0].kind == nkEmpty
|
||||
|
||||
const
|
||||
nodesToIgnoreSet* = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||
nkTypeSection, nkProcDef, nkConverterDef,
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt}
|
||||
|
||||
@@ -15,6 +15,9 @@ import
|
||||
ast, hashes, intsets, strutils, options, lineinfos, ropes, idents, rodutils,
|
||||
msgs
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc hashNode*(p: RootRef): Hash
|
||||
proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
|
||||
# Convert a tree into its YAML representation; this is used by the
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
# this unit handles Nim sets; it implements bit sets
|
||||
# the code here should be reused in the Nim standard library
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
ElemType = byte
|
||||
TBitSet* = seq[ElemType] # we use byte here to avoid issues with
|
||||
@@ -23,53 +26,40 @@ const
|
||||
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)
|
||||
proc bitSetDiff*(x: var TBitSet, y: TBitSet)
|
||||
proc bitSetSymDiff*(x: var TBitSet, y: TBitSet)
|
||||
proc bitSetIntersect*(x: var TBitSet, y: TBitSet)
|
||||
proc bitSetIncl*(x: var TBitSet, elem: BiggestInt)
|
||||
proc bitSetExcl*(x: var TBitSet, elem: BiggestInt)
|
||||
proc bitSetIn*(x: TBitSet, e: BiggestInt): bool
|
||||
proc bitSetEquals*(x, y: TBitSet): bool
|
||||
proc bitSetContains*(x, y: TBitSet): bool
|
||||
proc bitSetCard*(x: TBitSet): BiggestInt
|
||||
# implementation
|
||||
|
||||
proc bitSetIn(x: TBitSet, e: BiggestInt): bool =
|
||||
proc bitSetIn*(x: TBitSet, e: BiggestInt): bool =
|
||||
result = (x[int(e.divElemSize)] and (One shl e.modElemSize)) != Zero
|
||||
|
||||
proc bitSetIncl(x: var TBitSet, elem: BiggestInt) =
|
||||
proc bitSetIncl*(x: var TBitSet, elem: BiggestInt) =
|
||||
assert(elem >= 0)
|
||||
x[int(elem.divElemSize)] = x[int(elem.divElemSize)] or
|
||||
(One shl elem.modElemSize)
|
||||
|
||||
proc bitSetExcl(x: var TBitSet, elem: BiggestInt) =
|
||||
proc bitSetExcl*(x: var TBitSet, elem: BiggestInt) =
|
||||
x[int(elem.divElemSize)] = x[int(elem.divElemSize)] and
|
||||
not(One shl elem.modElemSize)
|
||||
|
||||
proc bitSetInit(b: var TBitSet, length: int) =
|
||||
proc bitSetInit*(b: var TBitSet, length: int) =
|
||||
newSeq(b, length)
|
||||
|
||||
proc bitSetUnion(x: var TBitSet, y: TBitSet) =
|
||||
proc bitSetUnion*(x: var TBitSet, y: TBitSet) =
|
||||
for i in 0..high(x): x[i] = x[i] or y[i]
|
||||
|
||||
proc bitSetDiff(x: var TBitSet, y: TBitSet) =
|
||||
proc bitSetDiff*(x: var TBitSet, y: TBitSet) =
|
||||
for i in 0..high(x): x[i] = x[i] and not y[i]
|
||||
|
||||
proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
|
||||
proc bitSetSymDiff*(x: var TBitSet, y: TBitSet) =
|
||||
for i in 0..high(x): x[i] = x[i] xor y[i]
|
||||
|
||||
proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
|
||||
proc bitSetIntersect*(x: var TBitSet, y: TBitSet) =
|
||||
for i in 0..high(x): x[i] = x[i] and y[i]
|
||||
|
||||
proc bitSetEquals(x, y: TBitSet): bool =
|
||||
proc bitSetEquals*(x, y: TBitSet): bool =
|
||||
for i in 0..high(x):
|
||||
if x[i] != y[i]:
|
||||
return false
|
||||
result = true
|
||||
|
||||
proc bitSetContains(x, y: TBitSet): bool =
|
||||
proc bitSetContains*(x, y: TBitSet): bool =
|
||||
for i in 0..high(x):
|
||||
if (x[i] and not y[i]) != Zero:
|
||||
return false
|
||||
@@ -96,6 +86,6 @@ const populationCount: array[uint8, uint8] = block:
|
||||
|
||||
arr
|
||||
|
||||
proc bitSetCard(x: TBitSet): BiggestInt =
|
||||
proc bitSetCard*(x: TBitSet): BiggestInt =
|
||||
for it in x:
|
||||
result.inc int(populationCount[it])
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
## BTree implementation with few features, but good enough for the
|
||||
## Nim compiler's needs.
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
M = 512 # max children per B-tree node = M-1
|
||||
# (must be even and greater than 2)
|
||||
|
||||
@@ -21,7 +21,7 @@ proc canRaiseDisp(p: BProc; n: PNode): bool =
|
||||
# we have to be *very* conservative:
|
||||
result = canRaiseConservative(n)
|
||||
|
||||
proc preventNrvo(p: BProc; le, ri: PNode): bool =
|
||||
proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
|
||||
proc locationEscapes(p: BProc; le: PNode; inTryStmt: bool): bool =
|
||||
var n = le
|
||||
while true:
|
||||
@@ -54,6 +54,11 @@ proc preventNrvo(p: BProc; le, ri: PNode): bool =
|
||||
if canRaise(ri[0]) and
|
||||
locationEscapes(p, le, p.nestedTryStmts.len > 0):
|
||||
message(p.config, le.info, warnObservableStores, $le)
|
||||
# bug #19613 prevent dangerous aliasing too:
|
||||
if dest != nil and dest != le:
|
||||
for i in 1..<ri.len:
|
||||
let r = ri[i]
|
||||
if isPartOf(dest, r) != arNo: return true
|
||||
|
||||
proc hasNoInit(call: PNode): bool {.inline.} =
|
||||
result = call[0].kind == nkSym and sfNoInit in call[0].sym.flags
|
||||
@@ -76,10 +81,10 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
if typ[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ[0]):
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
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 preventNrvo(p, le, ri):
|
||||
if d.k in {locTemp, locNone} or not preventNrvo(p, d.lode, le, ri):
|
||||
# Great, we can use 'd':
|
||||
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
|
||||
elif d.k notin {locTemp} and not hasNoInit(ri):
|
||||
@@ -214,7 +219,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||
else:
|
||||
var a: TLoc
|
||||
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
|
||||
case skipTypes(a.t, abstractVar).kind
|
||||
case skipTypes(a.t, abstractVar+{tyStatic}).kind
|
||||
of tyOpenArray, tyVarargs:
|
||||
if reifiedOpenArray(n):
|
||||
if a.t.kind in {tyVar, tyLent}:
|
||||
@@ -376,8 +381,8 @@ proc genParams(p: BProc, ri: PNode, typ: PType): Rope =
|
||||
if not needTmp[i - 1]:
|
||||
needTmp[i - 1] = potentialAlias(n, potentialWrites)
|
||||
getPotentialWrites(ri[i], false, potentialWrites)
|
||||
if ri[i].kind == nkHiddenAddr:
|
||||
# Optimization: don't use a temp, if we would only take the adress anyway
|
||||
if ri[i].kind in {nkHiddenAddr, nkAddr}:
|
||||
# Optimization: don't use a temp, if we would only take the address anyway
|
||||
needTmp[i - 1] = false
|
||||
|
||||
for i in 1..<ri.len:
|
||||
@@ -439,10 +444,10 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
let rawProc = getClosureType(p.module, typ, clHalf)
|
||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
||||
if typ[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ[0]):
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
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 preventNrvo(p, le, ri):
|
||||
if d.k in {locTemp, locNone} or not preventNrvo(p, d.lode, le, ri):
|
||||
# Great, we can use 'd':
|
||||
if d.k == locNone:
|
||||
getTemp(p, typ[0], d, needsInit=true)
|
||||
@@ -737,7 +742,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
pl.add(~": ")
|
||||
pl.add(genArg(p, ri[i], param, ri))
|
||||
if typ[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ[0]):
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
if ri.len > 1: pl.add(~" ")
|
||||
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||
if d.k in {locTemp, locNone}:
|
||||
|
||||
@@ -584,13 +584,23 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
else:
|
||||
# we handle div by zero here so that we know that the compilerproc's
|
||||
# result is only for overflows.
|
||||
var needsOverflowCheck = true
|
||||
if m in {mDivI, mModI}:
|
||||
linefmt(p, cpsStmts, "if ($1 == 0){ #raiseDivByZero(); $2}$n",
|
||||
[rdLoc(b), raiseInstr(p)])
|
||||
|
||||
let res = binaryArithOverflowRaw(p, t, a, b,
|
||||
if t.kind == tyInt64: prc64[m] else: prc[m])
|
||||
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
|
||||
var canBeZero = true
|
||||
if e[2].kind in {nkIntLit..nkUInt64Lit}:
|
||||
canBeZero = e[2].intVal == 0
|
||||
if e[2].kind in {nkIntLit..nkInt64Lit}:
|
||||
needsOverflowCheck = e[2].intVal == -1
|
||||
if canBeZero:
|
||||
linefmt(p, cpsStmts, "if ($1 == 0){ #raiseDivByZero(); $2}$n",
|
||||
[rdLoc(b), raiseInstr(p)])
|
||||
if needsOverflowCheck:
|
||||
let res = binaryArithOverflowRaw(p, t, a, b,
|
||||
if t.kind == tyInt64: prc64[m] else: prc[m])
|
||||
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
|
||||
else:
|
||||
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
|
||||
putIntoDest(p, d, e, res)
|
||||
|
||||
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
var
|
||||
@@ -978,12 +988,12 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
|
||||
if reifiedOpenArray(arr.lode):
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($2-$1 != -1 && " &
|
||||
"((NU)($1) >= (NU)($3.Field1) || (NU)($2) >= (NU)($3.Field1))){ #raiseIndexError(); $4}$n",
|
||||
"($1 < 0 || $1 >= $3.Field1 || $2 < 0 || $2 >= $3.Field1)){ #raiseIndexError4($1, $2, $3.Field1); $4}$n",
|
||||
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p)])
|
||||
else:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($2-$1 != -1 && " &
|
||||
"((NU)($1) >= (NU)($3Len_0) || (NU)($2) >= (NU)($3Len_0))){ #raiseIndexError(); $4}$n",
|
||||
"if ($2-$1 != -1 && ($1 < 0 || $1 >= $3Len_0 || $2 < 0 || $2 >= $3Len_0))" &
|
||||
"{ #raiseIndexError4($1, $2, $3Len_0); $4}$n",
|
||||
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p)])
|
||||
of tyArray:
|
||||
let first = intLiteral(firstOrd(p.config, ty))
|
||||
@@ -994,7 +1004,7 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
|
||||
of tySequence, tyString:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($2-$1 != -1 && " &
|
||||
"((NU)($1) >= (NU)$3 || (NU)($2) >= (NU)$3)){ #raiseIndexError(); $4}$n",
|
||||
"($1 < 0 || $1 >= $3 || $2 < 0 || $2 >= $3)){ #raiseIndexError4($1, $2, $3); $4}$n",
|
||||
[rdLoc(a), rdLoc(b), lenExpr(p, arr), raiseInstr(p)])
|
||||
else: discard
|
||||
|
||||
@@ -1005,14 +1015,14 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
if not reifiedOpenArray(x):
|
||||
# emit range check:
|
||||
if optBoundsCheck in p.options:
|
||||
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)){ #raiseIndexError2($1,$2Len_0-1); $3}$n",
|
||||
linefmt(p, cpsStmts, "if ($1 < 0 || $1 >= $2Len_0){ #raiseIndexError2($1,$2Len_0-1); $3}$n",
|
||||
[rdCharLoc(b), rdLoc(a), raiseInstr(p)]) # BUGFIX: ``>=`` and not ``>``!
|
||||
inheritLocation(d, a)
|
||||
putIntoDest(p, d, n,
|
||||
ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
|
||||
else:
|
||||
if optBoundsCheck in p.options:
|
||||
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2.Field1)){ #raiseIndexError2($1,$2.Field1-1); $3}$n",
|
||||
linefmt(p, cpsStmts, "if ($1 < 0 || $1 >= $2.Field1){ #raiseIndexError2($1,$2.Field1-1); $3}$n",
|
||||
[rdCharLoc(b), rdLoc(a), raiseInstr(p)]) # BUGFIX: ``>=`` and not ``>``!
|
||||
inheritLocation(d, a)
|
||||
putIntoDest(p, d, n,
|
||||
@@ -1027,7 +1037,7 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check:
|
||||
if optBoundsCheck in p.options:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ((NU)($1) >= (NU)$2){ #raiseIndexError2($1,$2-1); $3}$n",
|
||||
"if ($1 < 0 || $1 >= $2){ #raiseIndexError2($1,$2-1); $3}$n",
|
||||
[rdCharLoc(b), lenExpr(p, a), raiseInstr(p)])
|
||||
if d.k == locNone: d.storage = OnHeap
|
||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||
@@ -1605,8 +1615,11 @@ proc genNewFinalize(p: BProc, e: PNode) =
|
||||
|
||||
proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
result = ropecg(p.module, "#isObj($1.m_type, $2)",
|
||||
[a, genTypeInfo2Name(p.module, dest)])
|
||||
let ti = genTypeInfo2Name(p.module, dest)
|
||||
inc p.module.labels
|
||||
let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope
|
||||
p.module.s[cfsVars].addf("static TNimTypeV2* $#[2];$n", [cache])
|
||||
result = ropecg(p.module, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache])
|
||||
else:
|
||||
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
|
||||
# have to call it here first:
|
||||
@@ -1741,6 +1754,13 @@ proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
|
||||
# use the dynamic type stored at offset 0:
|
||||
putIntoDest(p, d, e, rdMType(p, a, nilCheck))
|
||||
|
||||
proc genAccessTypeField(p: BProc; e: PNode; d: var TLoc) =
|
||||
var a: TLoc
|
||||
initLocExpr(p, e[1], a)
|
||||
var nilCheck = Rope(nil)
|
||||
# use the dynamic type stored at offset 0:
|
||||
putIntoDest(p, d, e, rdMType(p, a, nilCheck))
|
||||
|
||||
template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
||||
var a: TLoc
|
||||
initLocExpr(p, n[1], a)
|
||||
@@ -2449,6 +2469,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mMove: genMove(p, e, d)
|
||||
of mDestroy: genDestroy(p, e)
|
||||
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
|
||||
of mAccessTypeField: genAccessTypeField(p, e, d)
|
||||
of mSlice: genSlice(p, e, d)
|
||||
of mTrace: discard "no code to generate"
|
||||
else:
|
||||
@@ -2924,7 +2945,21 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt:
|
||||
discard
|
||||
of nkPragma: genPragma(p, n)
|
||||
of nkPragmaBlock: expr(p, n.lastSon, d)
|
||||
of nkPragmaBlock:
|
||||
var inUncheckedAssignSection = 0
|
||||
let pragmaList = n[0]
|
||||
for pi in pragmaList:
|
||||
if whichPragma(pi) == wCast:
|
||||
case whichPragma(pi[1])
|
||||
of wUncheckedAssign:
|
||||
inUncheckedAssignSection = 1
|
||||
else:
|
||||
discard
|
||||
|
||||
inc p.inUncheckedAssignSection, inUncheckedAssignSection
|
||||
expr(p, n.lastSon, d)
|
||||
dec p.inUncheckedAssignSection, inUncheckedAssignSection
|
||||
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
|
||||
if n[genericParamsPos].kind == nkEmpty:
|
||||
var prc = n[namePos].sym
|
||||
|
||||
@@ -16,7 +16,7 @@ const
|
||||
# above X strings a hash-switch for strings is generated
|
||||
|
||||
proc getTraverseProc(p: BProc, v: PSym): Rope =
|
||||
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcV2, gcRefc} and
|
||||
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcRefc} and
|
||||
optOwnedRefs notin p.config.globalOptions and
|
||||
containsGarbageCollectedRef(v.loc.t):
|
||||
# we register a specialized marked proc here; this has the advantage
|
||||
@@ -32,13 +32,20 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) =
|
||||
"$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc])
|
||||
|
||||
proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
|
||||
if n.kind == nkEmpty: return false
|
||||
if isInvalidReturnType(conf, n.typ):
|
||||
# var v = f()
|
||||
# is transformed into: var v; f(addr v)
|
||||
# where 'f' **does not** initialize the result!
|
||||
return false
|
||||
result = true
|
||||
if n.kind == nkEmpty:
|
||||
result = false
|
||||
elif n.kind in nkCallKinds and n[0] != nil and n[0].typ != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc:
|
||||
if isInvalidReturnType(conf, n[0].typ, true):
|
||||
# var v = f()
|
||||
# is transformed into: var v; f(addr v)
|
||||
# where 'f' **does not** initialize the result!
|
||||
result = false
|
||||
else:
|
||||
result = true
|
||||
elif isInvalidReturnType(conf, n.typ, false):
|
||||
result = false
|
||||
else:
|
||||
result = true
|
||||
|
||||
proc inExceptBlockLen(p: BProc): int =
|
||||
for x in p.nestedTryStmts:
|
||||
@@ -1356,8 +1363,19 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimSigSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimBuiltinSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = __builtin_setjmp($1.context);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimRawSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
|
||||
if isDefined(p.config, "mswindows"):
|
||||
# The Windows `_setjmp()` takes two arguments, with the second being an
|
||||
# undocumented buffer used by the SEH mechanism for stack unwinding.
|
||||
# Mingw-w64 has been trying to get it right for years, but it's still
|
||||
# prone to stack corruption during unwinding, so we disable that by setting
|
||||
# it to NULL.
|
||||
# More details: https://github.com/status-im/nimbus-eth2/issues/3121
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context, 0);$n", [safePoint])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||
lineCg(p, cpsStmts, "if ($1.status == 0) {$n", [safePoint])
|
||||
@@ -1548,7 +1566,7 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||
initLocExpr(p, e[0], a)
|
||||
getTemp(p, a.t, tmp)
|
||||
expr(p, e[1], tmp)
|
||||
if optTinyRtti notin p.config.globalOptions:
|
||||
if optTinyRtti notin p.config.globalOptions and p.inUncheckedAssignSection == 0:
|
||||
let field = dotExpr[1].sym
|
||||
genDiscriminantCheck(p, a, tmp, dotExpr[0].typ, field)
|
||||
message(p.config, e.info, warnCaseTransition)
|
||||
|
||||
@@ -39,7 +39,7 @@ proc mangleName(m: BModule; s: PSym): Rope =
|
||||
result = s.loc.r
|
||||
if result == nil:
|
||||
result = s.name.s.mangle.rope
|
||||
result.add "_"
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_"
|
||||
result.add rope s.itemId.item
|
||||
@@ -215,12 +215,19 @@ proc isObjLackingTypeField(typ: PType): bool {.inline.} =
|
||||
result = (typ.kind == tyObject) and ((tfFinal in typ.flags) and
|
||||
(typ[0] == nil) or isPureObject(typ))
|
||||
|
||||
proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool =
|
||||
proc isInvalidReturnType(conf: ConfigRef; typ: PType, isProc = true): bool =
|
||||
# Arrays and sets cannot be returned by a C procedure, because C is
|
||||
# such a poor programming language.
|
||||
# We exclude records with refs too. This enhances efficiency and
|
||||
# is necessary for proper code generation of assignments.
|
||||
if rettype == nil: result = true
|
||||
var rettype = typ
|
||||
var isAllowedCall = true
|
||||
if isProc:
|
||||
rettype = rettype[0]
|
||||
isAllowedCall = typ.callConv in {ccClosure, ccInline, ccNimCall}
|
||||
if rettype == nil or (isAllowedCall and
|
||||
getSize(conf, rettype) > conf.target.floatSize*3):
|
||||
result = true
|
||||
else:
|
||||
case mapType(conf, rettype, skResult)
|
||||
of ctArray:
|
||||
@@ -256,11 +263,11 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) =
|
||||
# see `testCodegenABICheck` for example error message it generates
|
||||
|
||||
|
||||
proc fillResult(conf: ConfigRef; param: PNode) =
|
||||
proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) =
|
||||
fillLoc(param.sym.loc, locParam, param, ~"Result",
|
||||
OnStack)
|
||||
let t = param.sym.typ
|
||||
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, t):
|
||||
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, proctype):
|
||||
incl(param.sym.loc.flags, lfIndirect)
|
||||
param.sym.loc.storage = OnUnknown
|
||||
|
||||
@@ -425,7 +432,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
check: var IntSet, declareEnvironment=true;
|
||||
weakDep=false) =
|
||||
params = nil
|
||||
if t[0] == nil or isInvalidReturnType(m.config, t[0]):
|
||||
if t[0] == nil or isInvalidReturnType(m.config, t):
|
||||
rettype = ~"void"
|
||||
else:
|
||||
rettype = getTypeDescAux(m, t[0], check, skResult)
|
||||
@@ -460,12 +467,17 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
params.addf(", NI $1Len_$2", [param.loc.r, j.rope])
|
||||
inc(j)
|
||||
arr = arr[0].skipTypes({tySink})
|
||||
if t[0] != nil and isInvalidReturnType(m.config, t[0]):
|
||||
if t[0] != nil and isInvalidReturnType(m.config, t):
|
||||
var arr = t[0]
|
||||
if params != nil: params.add(", ")
|
||||
if mapReturnType(m.config, t[0]) != ctArray:
|
||||
params.add(getTypeDescWeak(m, arr, check, skResult))
|
||||
params.add("*")
|
||||
if isHeaderFile in m.flags:
|
||||
# still generates types for `--header`
|
||||
params.add(getTypeDescAux(m, arr, check, skResult))
|
||||
params.add("*")
|
||||
else:
|
||||
params.add(getTypeDescWeak(m, arr, check, skResult))
|
||||
params.add("*")
|
||||
else:
|
||||
params.add(getTypeDescAux(m, arr, check, skResult))
|
||||
params.addf(" Result", [])
|
||||
@@ -582,7 +594,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||
|
||||
if typ.kind == tyObject:
|
||||
if typ[0] == nil:
|
||||
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
|
||||
if lacksMTypeField(typ):
|
||||
appcg(m, result, " {$n", [])
|
||||
else:
|
||||
if optTinyRtti in m.config.globalOptions:
|
||||
@@ -1471,12 +1483,12 @@ proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
genTupleInfo(m, x, x, result, info)
|
||||
of tySequence:
|
||||
genTypeInfoAux(m, t, t, result, info)
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcV2, gcGo}:
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
|
||||
let markerProc = genTraverseProc(m, origType, sig)
|
||||
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
|
||||
of tyRef:
|
||||
genTypeInfoAux(m, t, t, result, info)
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcV2, gcGo}:
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
|
||||
let markerProc = genTraverseProc(m, origType, sig)
|
||||
m.s[cfsTypeInit3].addf("$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
|
||||
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
|
||||
|
||||
@@ -13,6 +13,9 @@ import
|
||||
ast, types, hashes, strutils, msgs, wordrecg,
|
||||
platform, trees, options, cgendata
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
|
||||
case n.kind
|
||||
of nkStmtList:
|
||||
|
||||
@@ -15,7 +15,10 @@ import
|
||||
ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth,
|
||||
rodutils, renderer, cgendata, aliases,
|
||||
lowerings, tables, sets, ndi, lineinfos, pathutils, transf,
|
||||
injectdestructors, astmsgs
|
||||
injectdestructors, astmsgs, modulepaths
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when not defined(leanCompiler):
|
||||
import spawn, semparallel
|
||||
@@ -48,8 +51,13 @@ proc addForwardedProc(m: BModule, prc: PSym) =
|
||||
m.g.forwardedProcs.add(prc)
|
||||
|
||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.modules[ms]
|
||||
# TODO fixme
|
||||
if m.config.symbolFiles == v2Sf:
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.modules[ms]
|
||||
else:
|
||||
var ms = getModule(s)
|
||||
result = m.g.modules[ms.position]
|
||||
|
||||
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) =
|
||||
result.k = k
|
||||
@@ -154,6 +162,11 @@ macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||
inc(i)
|
||||
result.add newCall(formatValue, resVar, args[num])
|
||||
inc(num)
|
||||
of '^':
|
||||
flushStrLit()
|
||||
inc(i)
|
||||
result.add newCall(formatValue, resVar, args[^1])
|
||||
inc(num)
|
||||
of '0'..'9':
|
||||
var j = 0
|
||||
while true:
|
||||
@@ -363,7 +376,8 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
|
||||
else:
|
||||
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfoV1(p.module, t, a.lode.info)])
|
||||
of frEmbedded:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
# inheritance in C++ does not allow struct initialization: bug #18410
|
||||
if not p.module.compileToCpp and optTinyRtti in p.config.globalOptions:
|
||||
var tmp: TLoc
|
||||
if mode == constructRefObj:
|
||||
let objType = t.skipTypes(abstractInst+{tyRef})
|
||||
@@ -442,8 +456,14 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
|
||||
if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}:
|
||||
linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
|
||||
elif not isComplexValueType(typ):
|
||||
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
|
||||
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
|
||||
if containsGarbageCollectedRef(loc.t):
|
||||
var nilLoc: TLoc
|
||||
initLoc(nilLoc, locTemp, loc.lode, OnStack)
|
||||
nilLoc.r = rope("NIM_NIL")
|
||||
genRefAssign(p, loc, nilLoc)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
|
||||
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
|
||||
else:
|
||||
if not isTemp or containsGarbageCollectedRef(loc.t):
|
||||
# don't use nimZeroMem for temporary values for performance if we can
|
||||
@@ -864,7 +884,7 @@ proc containsResult(n: PNode): bool =
|
||||
if containsResult(n[i]): return true
|
||||
|
||||
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
|
||||
nkMacroDef, nkMixinStmt, nkBindStmt} +
|
||||
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
|
||||
declarativeDefs
|
||||
|
||||
proc easyResultAsgn(n: PNode): PNode =
|
||||
@@ -1022,7 +1042,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
internalError(m.config, prc.info, "proc has no result symbol")
|
||||
let resNode = prc.ast[resultPos]
|
||||
let res = resNode.sym # get result symbol
|
||||
if not isInvalidReturnType(m.config, prc.typ[0]):
|
||||
if not isInvalidReturnType(m.config, prc.typ):
|
||||
if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
|
||||
if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil):
|
||||
var decl = localVarDecl(p, resNode)
|
||||
@@ -1036,7 +1056,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
initLocalVar(p, res, immediateAsgn=false)
|
||||
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
|
||||
else:
|
||||
fillResult(p.config, resNode)
|
||||
fillResult(p.config, resNode, prc.typ)
|
||||
assignParam(p, res, prc.typ[0])
|
||||
# We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)'
|
||||
# to 'unsureAsgn(result, x)'
|
||||
@@ -1044,9 +1064,11 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
# the 'unsureAsgn' is a nop. If it points to a global variable the
|
||||
# global is either 'nil' or points to valid memory and so the RC operation
|
||||
# succeeds without touching not-initialized memory.
|
||||
if sfNoInit in prc.flags: discard
|
||||
if sfNoInit in prc.flags and p.config.selectedGC notin {gcArc, gcOrc}: discard
|
||||
elif allPathsAsgnResult(procBody) == InitSkippable: discard
|
||||
else:
|
||||
if sfNoInit in prc.flags and p.config.selectedGC in {gcArc, gcOrc}:
|
||||
message(m.config, resNode.info, warnNoInitIgnored, "")
|
||||
resetLoc(p, res.loc)
|
||||
if skipTypes(res.typ, abstractInst).kind == tyArray:
|
||||
#incl(res.loc.flags, lfIndirect)
|
||||
@@ -1285,17 +1307,19 @@ proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope =
|
||||
if conf.hcrOn: result.add("#define NIM_HOT_CODE_RELOADING\L")
|
||||
addNimDefines(result, conf)
|
||||
|
||||
proc getSomeNameForModule(m: PSym): Rope =
|
||||
assert m.kind == skModule
|
||||
assert m.owner.kind == skPackage
|
||||
if {sfSystemModule, sfMainModule} * m.flags == {}:
|
||||
result = m.owner.name.s.mangle.rope
|
||||
result.add "_"
|
||||
result.add m.name.s.mangle
|
||||
proc getSomeNameForModule(conf: ConfigRef, filename: AbsoluteFile): Rope =
|
||||
## Returns a mangled module name.
|
||||
result.add mangleModuleName(conf, filename).mangle
|
||||
|
||||
proc getSomeNameForModule(m: BModule): Rope =
|
||||
## Returns a mangled module name.
|
||||
assert m.module.kind == skModule
|
||||
assert m.module.owner.kind == skPackage
|
||||
result.add mangleModuleName(m.g.config, m.filename).mangle
|
||||
|
||||
proc getSomeInitName(m: BModule, suffix: string): Rope =
|
||||
if not m.hcrOn:
|
||||
result = getSomeNameForModule(m.module)
|
||||
result = getSomeNameForModule(m)
|
||||
result.add suffix
|
||||
|
||||
proc getInitName(m: BModule): Rope =
|
||||
@@ -1346,20 +1370,29 @@ proc genMainProc(m: BModule) =
|
||||
# The use of a volatile function pointer to call Pre/NimMainInner
|
||||
# prevents inlining of the NimMainInner function and dependent
|
||||
# functions, which might otherwise merge their stack frames.
|
||||
PreMainBody = "$N" &
|
||||
|
||||
PreMainVolatileBody =
|
||||
"\tvoid (*volatile inner)(void);$N" &
|
||||
"\tinner = PreMainInner;$N" &
|
||||
"$1" &
|
||||
"\t(*inner)();$N"
|
||||
|
||||
PreMainNonVolatileBody =
|
||||
"$1" &
|
||||
"\tPreMainInner();$N"
|
||||
|
||||
PreMainBodyStart = "$N" &
|
||||
"N_LIB_PRIVATE void PreMainInner(void) {$N" &
|
||||
"$2" &
|
||||
"}$N$N" &
|
||||
PosixCmdLine &
|
||||
"N_LIB_PRIVATE void PreMain(void) {$N" &
|
||||
"\tvoid (*volatile inner)(void);$N" &
|
||||
"\tinner = PreMainInner;$N" &
|
||||
"$1" &
|
||||
"\t(*inner)();$N" &
|
||||
"N_LIB_PRIVATE void PreMain(void) {$N"
|
||||
|
||||
PreMainBodyEnd =
|
||||
"}$N$N"
|
||||
|
||||
MainProcs =
|
||||
"\tNimMain();$N"
|
||||
"\t$^NimMain();$N"
|
||||
|
||||
MainProcsWithResult =
|
||||
MainProcs & ("\treturn $1nim_program_result;$N")
|
||||
@@ -1368,17 +1401,32 @@ proc genMainProc(m: BModule) =
|
||||
"$1" &
|
||||
"}$N$N"
|
||||
|
||||
NimMainProc =
|
||||
"N_CDECL(void, NimMain)(void) {$N" &
|
||||
"\tvoid (*volatile inner)(void);$N" &
|
||||
"$4" &
|
||||
"\tinner = NimMainInner;$N" &
|
||||
"$2" &
|
||||
"\t(*inner)();$N" &
|
||||
NimMainVolatileBody =
|
||||
"\tvoid (*volatile inner)(void);$N" &
|
||||
"$4" &
|
||||
"\tinner = NimMainInner;$N" &
|
||||
"$2" &
|
||||
"\t(*inner)();$N"
|
||||
|
||||
NimMainNonVolatileBody =
|
||||
"$4" &
|
||||
"$2" &
|
||||
"\tNimMainInner();$N"
|
||||
|
||||
NimMainProcStart =
|
||||
"N_CDECL(void, $5NimMain)(void) {$N"
|
||||
|
||||
NimMainProcEnd =
|
||||
"}$N$N"
|
||||
|
||||
NimMainProc = NimMainProcStart & NimMainVolatileBody & NimMainProcEnd
|
||||
|
||||
NimSlimMainProc = NimMainProcStart & NimMainNonVolatileBody & NimMainProcEnd
|
||||
|
||||
NimMainBody = NimMainInner & NimMainProc
|
||||
|
||||
NimSlimMainBody = NimMainInner & NimSlimMainProc
|
||||
|
||||
PosixCMain =
|
||||
"int main(int argc, char** args, char** env) {$N" &
|
||||
"\tcmdLine = args;$N" &
|
||||
@@ -1439,38 +1487,45 @@ proc genMainProc(m: BModule) =
|
||||
m.includeHeader("<libc/component.h>")
|
||||
|
||||
let initStackBottomCall =
|
||||
if m.config.target.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope
|
||||
if m.config.target.targetOS == osStandalone or m.config.selectedGC in {gcNone, gcArc, gcOrc}: "".rope
|
||||
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", [])
|
||||
inc(m.labels)
|
||||
appcg(m, m.s[cfsProcs], PreMainBody, [m.g.mainDatInit, m.g.otherModsInit])
|
||||
if m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
|
||||
appcg(m, m.s[cfsProcs], PreMainBodyStart & PreMainVolatileBody & PreMainBodyEnd, [m.g.mainDatInit, m.g.otherModsInit])
|
||||
else:
|
||||
appcg(m, m.s[cfsProcs], PreMainBodyStart & PreMainNonVolatileBody & PreMainBodyEnd, [m.g.mainDatInit, m.g.otherModsInit])
|
||||
|
||||
if m.config.target.targetOS == osWindows and
|
||||
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
if optGenGuiApp in m.config.globalOptions:
|
||||
const nimMain = WinNimMain
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
else:
|
||||
const nimMain = WinNimDllMain
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
elif m.config.target.targetOS == osGenode:
|
||||
const nimMain = GenodeNimMain
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
elif optGenDynLib in m.config.globalOptions:
|
||||
const nimMain = PosixNimDllMain
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
elif m.config.target.targetOS == osStandalone:
|
||||
const nimMain = NimMainBody
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
else:
|
||||
const nimMain = NimMainBody
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
|
||||
|
||||
if m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
|
||||
const nimMain = NimMainBody
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
else:
|
||||
const nimMain = NimSlimMainBody
|
||||
appcg(m, m.s[cfsProcs], nimMain,
|
||||
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
|
||||
|
||||
if optNoMain notin m.config.globalOptions:
|
||||
if m.config.cppCustomNamespace.len > 0:
|
||||
@@ -1480,23 +1535,22 @@ proc genMainProc(m: BModule) =
|
||||
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
if optGenGuiApp in m.config.globalOptions:
|
||||
const otherMain = WinCMain
|
||||
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: ""])
|
||||
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: "", m.config.nimMainPrefix])
|
||||
else:
|
||||
const otherMain = WinCDllMain
|
||||
appcg(m, m.s[cfsProcs], otherMain, [])
|
||||
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
|
||||
elif m.config.target.targetOS == osGenode:
|
||||
const otherMain = ComponentConstruct
|
||||
appcg(m, m.s[cfsProcs], otherMain, [])
|
||||
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
|
||||
elif optGenDynLib in m.config.globalOptions:
|
||||
const otherMain = PosixCDllMain
|
||||
appcg(m, m.s[cfsProcs], otherMain, [])
|
||||
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
|
||||
elif m.config.target.targetOS == osStandalone:
|
||||
const otherMain = StandaloneCMain
|
||||
appcg(m, m.s[cfsProcs], otherMain, [])
|
||||
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
|
||||
else:
|
||||
const otherMain = PosixCMain
|
||||
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: ""])
|
||||
|
||||
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: "", m.config.nimMainPrefix])
|
||||
|
||||
if m.config.cppCustomNamespace.len > 0:
|
||||
m.s[cfsProcs].add openNamespaceNim(m.config.cppCustomNamespace)
|
||||
@@ -1504,11 +1558,11 @@ proc genMainProc(m: BModule) =
|
||||
proc registerInitProcs*(g: BModuleList; m: PSym; flags: set[ModuleBackendFlag]) =
|
||||
## Called from the IC backend.
|
||||
if HasDatInitProc in flags:
|
||||
let datInit = getSomeNameForModule(m) & "DatInit000"
|
||||
let datInit = getSomeNameForModule(g.config, g.config.toFullPath(m.info.fileIndex).AbsoluteFile) & "DatInit000"
|
||||
g.mainModProcs.addf("N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [datInit])
|
||||
g.mainDatInit.addf("\t$1();$N", [datInit])
|
||||
if HasModuleInitProc in flags:
|
||||
let init = getSomeNameForModule(m) & "Init000"
|
||||
let init = getSomeNameForModule(g.config, g.config.toFullPath(m.info.fileIndex).AbsoluteFile) & "Init000"
|
||||
g.mainModProcs.addf("N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [init])
|
||||
let initCall = "\t$1();$N" % [init]
|
||||
if sfMainModule in m.flags:
|
||||
@@ -1878,7 +1932,7 @@ proc writeHeader(m: BModule) =
|
||||
|
||||
if optGenDynLib in m.config.globalOptions:
|
||||
result.add("N_LIB_IMPORT ")
|
||||
result.addf("N_CDECL(void, NimMain)(void);$n", [])
|
||||
result.addf("N_CDECL(void, $1NimMain)(void);$n", [rope m.config.nimMainPrefix])
|
||||
if m.config.cppCustomNamespace.len > 0: result.add closeNamespaceNim()
|
||||
result.addf("#endif /* $1 */$n", [guard])
|
||||
if not writeRope(result, m.filename):
|
||||
@@ -1889,7 +1943,7 @@ proc getCFile(m: BModule): AbsoluteFile =
|
||||
if m.compileToCpp: ".nim.cpp"
|
||||
elif m.config.backend == backendObjc or sfCompileToObjc in m.module.flags: ".nim.m"
|
||||
else: ".nim.c"
|
||||
result = changeFileExt(completeCfilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
|
||||
result = changeFileExt(completeCfilePath(m.config, mangleModuleName(m.config, m.cfilename).AbsoluteFile), ext)
|
||||
|
||||
when false:
|
||||
proc myOpenCached(graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext =
|
||||
@@ -2042,7 +2096,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||
discard cgsym(m, "rawWrite")
|
||||
|
||||
# raise dependencies on behalf of genMainProc
|
||||
if m.config.target.targetOS != osStandalone and m.config.selectedGC != gcNone:
|
||||
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
|
||||
discard cgsym(m, "initStackBottomWith")
|
||||
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
|
||||
discard cgsym(m, "initThreadVarsEmulation")
|
||||
|
||||
@@ -99,6 +99,7 @@ type
|
||||
withinTryWithExcept*: int # required for goto based exception handling
|
||||
withinBlockLeaveActions*: int # complex to explain
|
||||
sigConflicts*: CountTable[string]
|
||||
inUncheckedAssignSection*: int
|
||||
|
||||
TTypeSeq* = seq[PType]
|
||||
TypeCache* = Table[SigHash, Rope]
|
||||
|
||||
@@ -13,6 +13,10 @@ import
|
||||
intsets, options, ast, msgs, idents, renderer, types, magicsys,
|
||||
sempass2, strutils, modulegraphs, lineinfos
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
|
||||
proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
|
||||
var dest = skipTypes(d, abstractPtrs)
|
||||
var source = skipTypes(n.typ, abstractPtrs)
|
||||
|
||||
@@ -133,6 +133,9 @@ import
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
|
||||
tables, options
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
Ctx = object
|
||||
g: ModuleGraph
|
||||
@@ -1351,13 +1354,15 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode =
|
||||
case n.kind
|
||||
of nkTryStmt:
|
||||
let f = n.lastSon
|
||||
var didAddSomething = false
|
||||
if f.kind == nkFinally:
|
||||
c.finallys.add f.lastSon
|
||||
didAddSomething = true
|
||||
|
||||
for i in 0 ..< n.len:
|
||||
result[i] = preprocess(c, n[i])
|
||||
|
||||
if f.kind == nkFinally:
|
||||
if didAddSomething:
|
||||
discard c.finallys.pop()
|
||||
|
||||
of nkWhileStmt, nkBlockStmt:
|
||||
@@ -1384,7 +1389,7 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode =
|
||||
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, idgen: c.idgen)
|
||||
result.add freshVars(preprocess(c, c.finallys[i]), vars)
|
||||
result.add freshVars(copyTree(c.finallys[i]), vars)
|
||||
c.idgen = vars.idgen
|
||||
result.add n
|
||||
of nkSkip: discard
|
||||
|
||||
@@ -64,7 +64,8 @@ proc loadConfigsAndProcessCmdLine*(self: NimProg, cache: IdentCache; conf: Confi
|
||||
if conf.cmd == cmdNimscript: return false
|
||||
# now process command line arguments again, because some options in the
|
||||
# command line can overwrite the config file's settings
|
||||
extccomp.initVars(conf)
|
||||
if conf.backend != backendJs: # bug #19059
|
||||
extccomp.initVars(conf)
|
||||
self.processCmdLine(passCmd2, "", conf)
|
||||
if conf.cmd == cmdNone:
|
||||
rawMessage(conf, errGenerated, "command missing")
|
||||
|
||||
@@ -31,6 +31,9 @@ import
|
||||
|
||||
from ast import setUseIc, eqTypeFlags, tfGcSafe, tfNoSideEffect
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
# but some have deps to imported modules. Yay.
|
||||
bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
|
||||
bootSwitch(usedFFI, hasFFI, "-d:nimHasLibFFI")
|
||||
@@ -113,7 +116,7 @@ const
|
||||
errInvalidCmdLineOption = "invalid command line option: '$1'"
|
||||
errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found"
|
||||
errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found"
|
||||
errOffHintsError = "'off', 'hint' or 'error' expected, but '$1' found"
|
||||
errOffHintsError = "'off', 'hint', 'error' or 'usages' expected, but '$1' found"
|
||||
|
||||
proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) =
|
||||
if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-")
|
||||
@@ -238,7 +241,7 @@ const
|
||||
errNoneBoehmRefcExpectedButXFound = "'arc', 'orc', 'markAndSweep', 'boehm', 'go', 'none', 'regions', 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"
|
||||
errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found"
|
||||
|
||||
template warningOptionNoop(switch: string) =
|
||||
warningDeprecated(conf, info, "'$#' is deprecated, now a noop" % switch)
|
||||
@@ -248,7 +251,7 @@ template deprecatedAlias(oldName, newName: string) =
|
||||
|
||||
proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
|
||||
case switch.normalize
|
||||
of "gc":
|
||||
of "gc", "mm":
|
||||
case arg.normalize
|
||||
of "boehm": result = conf.selectedGC == gcBoehm
|
||||
of "refc": result = conf.selectedGC == gcRefc
|
||||
@@ -259,7 +262,6 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
|
||||
of "go": result = conf.selectedGC == gcGo
|
||||
of "none": result = conf.selectedGC == gcNone
|
||||
of "stack", "regions": result = conf.selectedGC == gcRegions
|
||||
of "v2", "generational": warningOptionNoop(arg)
|
||||
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
||||
of "opt":
|
||||
case arg.normalize
|
||||
@@ -332,6 +334,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
||||
result = contains(conf.options, optTrMacros)
|
||||
of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
|
||||
of "nilseqs", "nilchecks", "taintmode": warningOptionNoop(switch)
|
||||
of "panics": result = contains(conf.globalOptions, optPanics)
|
||||
else: invalidCmdLineOption(conf, passCmd1, switch, info)
|
||||
|
||||
proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
|
||||
@@ -497,6 +500,75 @@ proc specialDefine(conf: ConfigRef, key: string; pass: TCmdLinePass) =
|
||||
optOverflowCheck, optAssert, optStackTrace, optLineTrace, optLineDir}
|
||||
conf.globalOptions.excl {optCDebug}
|
||||
|
||||
proc registerArcOrc(pass: TCmdLinePass, conf: ConfigRef, isOrc: bool) =
|
||||
if isOrc:
|
||||
conf.selectedGC = gcOrc
|
||||
defineSymbol(conf.symbols, "gcorc")
|
||||
else:
|
||||
conf.selectedGC = gcArc
|
||||
defineSymbol(conf.symbols, "gcarc")
|
||||
|
||||
defineSymbol(conf.symbols, "gcdestructors")
|
||||
incl conf.globalOptions, optSeqDestructors
|
||||
incl conf.globalOptions, optTinyRtti
|
||||
if pass in {passCmd2, passPP}:
|
||||
defineSymbol(conf.symbols, "nimSeqsV2")
|
||||
defineSymbol(conf.symbols, "nimV2")
|
||||
if conf.exc == excNone and conf.backend != backendCpp:
|
||||
conf.exc = excGoto
|
||||
|
||||
proc unregisterArcOrc(conf: ConfigRef) =
|
||||
undefSymbol(conf.symbols, "gcdestructors")
|
||||
undefSymbol(conf.symbols, "gcarc")
|
||||
undefSymbol(conf.symbols, "gcorc")
|
||||
undefSymbol(conf.symbols, "nimSeqsV2")
|
||||
undefSymbol(conf.symbols, "nimV2")
|
||||
excl conf.globalOptions, optSeqDestructors
|
||||
excl conf.globalOptions, optTinyRtti
|
||||
|
||||
proc processMemoryManagementOption(switch, arg: string, pass: TCmdLinePass,
|
||||
info: TLineInfo; conf: ConfigRef) =
|
||||
if conf.backend == backendJs: return # for: bug #16033
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
case arg.normalize
|
||||
of "boehm":
|
||||
unregisterArcOrc(conf)
|
||||
conf.selectedGC = gcBoehm
|
||||
defineSymbol(conf.symbols, "boehmgc")
|
||||
incl conf.globalOptions, optTlsEmulation # Boehm GC doesn't scan the real TLS
|
||||
of "refc":
|
||||
unregisterArcOrc(conf)
|
||||
conf.selectedGC = gcRefc
|
||||
of "markandsweep":
|
||||
unregisterArcOrc(conf)
|
||||
conf.selectedGC = gcMarkAndSweep
|
||||
defineSymbol(conf.symbols, "gcmarkandsweep")
|
||||
of "destructors", "arc":
|
||||
registerArcOrc(pass, conf, false)
|
||||
of "orc":
|
||||
registerArcOrc(pass, conf, true)
|
||||
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":
|
||||
unregisterArcOrc(conf)
|
||||
conf.selectedGC = gcGo
|
||||
defineSymbol(conf.symbols, "gogc")
|
||||
of "none":
|
||||
unregisterArcOrc(conf)
|
||||
conf.selectedGC = gcNone
|
||||
defineSymbol(conf.symbols, "nogc")
|
||||
of "stack", "regions":
|
||||
unregisterArcOrc(conf)
|
||||
conf.selectedGC = gcRegions
|
||||
defineSymbol(conf.symbols, "gcregions")
|
||||
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
||||
|
||||
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
conf: ConfigRef) =
|
||||
var
|
||||
@@ -597,59 +669,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "project":
|
||||
processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
|
||||
of "gc":
|
||||
if conf.backend == backendJs: return # for: bug #16033
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
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 "markandsweep":
|
||||
conf.selectedGC = gcMarkAndSweep
|
||||
defineSymbol(conf.symbols, "gcmarkandsweep")
|
||||
of "destructors", "arc":
|
||||
conf.selectedGC = gcArc
|
||||
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")
|
||||
if conf.exc == excNone and conf.backend != backendCpp:
|
||||
conf.exc = excGoto
|
||||
of "orc":
|
||||
conf.selectedGC = gcOrc
|
||||
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")
|
||||
if conf.exc == excNone and conf.backend != backendCpp:
|
||||
conf.exc = excGoto
|
||||
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")
|
||||
of "v2": warningOptionNoop(arg)
|
||||
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
||||
warningDeprecated(conf, info, "`gc:option` is deprecated; use `mm:option` instead")
|
||||
processMemoryManagementOption(switch, arg, pass, info, conf)
|
||||
of "mm":
|
||||
processMemoryManagementOption(switch, arg, pass, info, conf)
|
||||
of "warnings", "w":
|
||||
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
|
||||
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
|
||||
@@ -717,7 +740,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
|
||||
of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
|
||||
of "threads":
|
||||
if conf.backend == backendJs: discard
|
||||
if conf.backend == backendJs or conf.cmd == cmdNimscript: discard
|
||||
else: processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
|
||||
#if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
|
||||
of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
|
||||
@@ -885,8 +908,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
splitSwitch(conf, arg, key, val, pass, info)
|
||||
os.putEnv(key, val)
|
||||
of "cc":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
setCC(conf, arg, info)
|
||||
if conf.backend != backendJs: # bug #19330
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
setCC(conf, arg, info)
|
||||
of "track":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
track(conf, arg, info)
|
||||
@@ -1027,6 +1051,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
defineSymbol(conf.symbols, "NimMajor", "1")
|
||||
defineSymbol(conf.symbols, "NimMinor", "2")
|
||||
conf.globalOptions.incl optNimV12Emulation
|
||||
of "1.6":
|
||||
defineSymbol(conf.symbols, "NimMajor", "1")
|
||||
defineSymbol(conf.symbols, "NimMinor", "6")
|
||||
conf.globalOptions.incl optNimV16Emulation
|
||||
else:
|
||||
localError(conf, info, "unknown Nim version; currently supported values are: `1.0`, `1.2`")
|
||||
# always be compatible with 1.x.100:
|
||||
@@ -1052,6 +1080,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
|
||||
handleStdinInput(conf)
|
||||
of "nilseqs", "nilchecks", "mainmodule", "m", "symbol", "taintmode", "cs", "deadcodeelim": warningOptionNoop(switch)
|
||||
of "nimmainprefix": conf.nimMainPrefix = arg
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
|
||||
else: invalidCmdLineOption(conf, pass, switch, info)
|
||||
@@ -1088,6 +1117,8 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
||||
else:
|
||||
if pass == passCmd1: config.commandArgs.add p.key
|
||||
if argsCount == 1:
|
||||
if p.key.endsWith(".nims"):
|
||||
incl(config.globalOptions, optWasNimscript)
|
||||
# support UNIX style filenames everywhere for portable build scripts:
|
||||
if config.projectName.len == 0:
|
||||
config.projectName = unixToNativePath(p.key)
|
||||
|
||||
@@ -15,6 +15,9 @@ import ast, astalgo, semdata, lookups, lineinfos, idents, msgs, renderer, types,
|
||||
|
||||
from magicsys import addSonSkipIntLit
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
logBindings = false
|
||||
|
||||
|
||||
@@ -138,3 +138,5 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasHintAll")
|
||||
defineSymbol("nimHasTrace")
|
||||
defineSymbol("nimHasEffectsOf")
|
||||
|
||||
defineSymbol("nimHasEnforceNoRaises")
|
||||
|
||||
@@ -54,3 +54,19 @@ proc isCompilerDebug*(): bool =
|
||||
{.undef(nimCompilerDebug).}
|
||||
echo 'x'
|
||||
conf0.isDefined("nimCompilerDebug")
|
||||
|
||||
proc enteringDebugSection*() {.exportc, dynlib.} =
|
||||
## Provides a way for native debuggers to enable breakpoints, watchpoints, etc
|
||||
## when code of interest is being compiled.
|
||||
##
|
||||
## Set your debugger to break on entering `nimCompilerIsEnteringDebugSection`
|
||||
## and then execute a desired command.
|
||||
discard
|
||||
|
||||
proc exitingDebugSection*() {.exportc, dynlib.} =
|
||||
## Provides a way for native debuggers to disable breakpoints, watchpoints, etc
|
||||
## when code of interest is no longer being compiled.
|
||||
##
|
||||
## Set your debugger to break on entering `exitingDebugSection`
|
||||
## and then execute a desired command.
|
||||
discard
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
import ast, intsets, lineinfos, renderer
|
||||
import std/private/asciitables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
InstrKind* = enum
|
||||
goto, fork, def, use
|
||||
@@ -605,11 +608,11 @@ proc aliases*(obj, field: PNode): AliasKind =
|
||||
var n = n
|
||||
while true:
|
||||
case n.kind
|
||||
of PathKinds0 - {nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}:
|
||||
of PathKinds0 - {nkDotExpr, nkBracketExpr}:
|
||||
n = n[0]
|
||||
of PathKinds1:
|
||||
n = n[1]
|
||||
of nkDotExpr, nkCheckedFieldExpr, nkBracketExpr:
|
||||
of nkDotExpr, nkBracketExpr:
|
||||
result.add n
|
||||
n = n[0]
|
||||
of nkSym:
|
||||
@@ -642,8 +645,6 @@ proc aliases*(obj, field: PNode): AliasKind =
|
||||
if currFieldPath.sym != currObjPath.sym: return no
|
||||
of nkDotExpr:
|
||||
if currFieldPath[1].sym != currObjPath[1].sym: return no
|
||||
of nkCheckedFieldExpr:
|
||||
if currFieldPath[0][1].sym != currObjPath[0][1].sym: return no
|
||||
of nkBracketExpr:
|
||||
if currFieldPath[1].kind in nkLiterals and currObjPath[1].kind in nkLiterals:
|
||||
if currFieldPath[1].intVal != currObjPath[1].intVal:
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
import
|
||||
ast, strutils, strtabs, algorithm, sequtils, options, msgs, os, idents,
|
||||
wordrecg, syntaxes, renderer, lexer,
|
||||
packages/docutils/rst, packages/docutils/rstgen,
|
||||
packages/docutils/[rst, rstgen, dochelpers],
|
||||
json, xmltree, trees, types,
|
||||
typesrenderer, astalgo, lineinfos, intsets,
|
||||
pathutils, tables, nimpaths, renderverbatim, osproc
|
||||
pathutils, tables, nimpaths, renderverbatim, osproc, packages
|
||||
import packages/docutils/rstast except FileIndex, TLineInfo
|
||||
|
||||
from uri import encodeUrl
|
||||
@@ -44,8 +44,14 @@ type
|
||||
## runnableExamples).
|
||||
substitutions: seq[string] ## Variable names in `doc.item`...
|
||||
sortName: string ## The string used for sorting in output
|
||||
info: rstast.TLineInfo ## place where symbol was defined (for messages)
|
||||
anchor: string ## e.g. HTML anchor
|
||||
name: string ## short name of the symbol, not unique
|
||||
## (includes backticks ` if present)
|
||||
detailedName: string ## longer name like `proc search(x: int): int`
|
||||
ModSection = object ## Section like Procs, Types, etc.
|
||||
secItems: seq[Item] ## Pre-processed items.
|
||||
secItems: Table[string, seq[Item]]
|
||||
## Map basic name -> pre-processed items.
|
||||
finalMarkup: string ## The items, after RST pass 2 and rendering.
|
||||
ModSections = array[TSymKind, ModSection]
|
||||
TocItem = object ## HTML TOC item
|
||||
@@ -91,12 +97,22 @@ type
|
||||
thisDir*: AbsoluteDir
|
||||
exampleGroups: OrderedTable[string, ExampleGroup]
|
||||
wroteSupportFiles*: bool
|
||||
nimToRstFid: Table[lineinfos.FileIndex, rstast.FileIndex]
|
||||
## map Nim FileIndex -> RST one, it's needed because we keep them separate
|
||||
|
||||
PDoc* = ref TDocumentor ## Alias to type less.
|
||||
|
||||
proc add(dest: var ItemPre, rst: PRstNode) = dest.add ItemFragment(isRst: true, rst: rst)
|
||||
proc add(dest: var ItemPre, str: string) = dest.add ItemFragment(isRst: false, str: str)
|
||||
|
||||
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
|
||||
let invalid = rstast.FileIndex(-1)
|
||||
result = d.nimToRstFid.getOrDefault(info.fileIndex, default = invalid)
|
||||
if result == invalid:
|
||||
let fname = toFullPath(d.conf, info)
|
||||
result = addFilename(d.sharedState, fname)
|
||||
d.nimToRstFid[info.fileIndex] = result
|
||||
|
||||
proc cmpDecimalsIgnoreCase(a, b: string): int =
|
||||
## For sorting with correct handling of cases like 'uint8' and 'uint16'.
|
||||
## Also handles leading zeros well (however note that leading zeros are
|
||||
@@ -216,13 +232,16 @@ template declareClosures =
|
||||
of meExpected: k = errXExpected
|
||||
of meGridTableNotImplemented: k = errRstGridTableNotImplemented
|
||||
of meMarkdownIllformedTable: k = errRstMarkdownIllformedTable
|
||||
of meIllformedTable: k = errRstIllformedTable
|
||||
of meNewSectionExpected: k = errRstNewSectionExpected
|
||||
of meGeneralParseError: k = errRstGeneralParseError
|
||||
of meInvalidDirective: k = errRstInvalidDirectiveX
|
||||
of meInvalidField: k = errRstInvalidField
|
||||
of meFootnoteMismatch: k = errRstFootnoteMismatch
|
||||
of meSandboxedDirective: k = errRstSandboxedDirective
|
||||
of mwRedefinitionOfLabel: k = warnRstRedefinitionOfLabel
|
||||
of mwUnknownSubstitution: k = warnRstUnknownSubstitutionX
|
||||
of mwAmbiguousLink: k = warnRstAmbiguousLink
|
||||
of mwBrokenLink: k = warnRstBrokenLink
|
||||
of mwUnsupportedLanguage: k = warnRstLanguageXNotSupported
|
||||
of mwUnsupportedField: k = warnRstFieldXNotSupported
|
||||
@@ -236,7 +255,7 @@ template declareClosures =
|
||||
result = getCurrentDir() / s
|
||||
if not fileExists(result): result = ""
|
||||
|
||||
proc parseRst(text, filename: string,
|
||||
proc parseRst(text: string,
|
||||
line, column: int,
|
||||
conf: ConfigRef, sharedState: PRstSharedState): PRstNode =
|
||||
declareClosures()
|
||||
@@ -265,7 +284,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||
result.cache = cache
|
||||
result.outDir = conf.outDir.string
|
||||
result.isPureRst = isPureRst
|
||||
var options= {roSupportRawDirective, roSupportMarkdown, roPreferMarkdown}
|
||||
var options= {roSupportRawDirective, roSupportMarkdown, roPreferMarkdown, roSandboxDisabled}
|
||||
if not isPureRst: options.incl roNimFile
|
||||
result.sharedState = newRstSharedState(
|
||||
options, filename.string,
|
||||
@@ -352,7 +371,8 @@ proc getVarIdx(varnames: openArray[string], id: string): int =
|
||||
|
||||
proc genComment(d: PDoc, n: PNode): PRstNode =
|
||||
if n.comment.len > 0:
|
||||
result = parseRst(n.comment, toFullPath(d.conf, n.info),
|
||||
d.sharedState.currFileIdx = addRstFileIndex(d, n.info)
|
||||
result = parseRst(n.comment,
|
||||
toLinenumber(n.info),
|
||||
toColumn(n.info) + DocColOffset,
|
||||
d.conf, d.sharedState)
|
||||
@@ -394,9 +414,6 @@ proc getPlainDocstring(n: PNode): string =
|
||||
result = getPlainDocstring(n[i])
|
||||
if result.len > 0: return
|
||||
|
||||
proc belongsToPackage(conf: ConfigRef; module: PSym): bool =
|
||||
result = module.kind == skModule and module.getnimblePkgId == conf.mainPackageId
|
||||
|
||||
proc externalDep(d: PDoc; module: PSym): string =
|
||||
if optWholeProject in d.conf.globalOptions or d.conf.docRoot.len > 0:
|
||||
let full = AbsoluteFile toFullPath(d.conf, FileIndex module.position)
|
||||
@@ -452,7 +469,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var string;
|
||||
"\\spanIdentifier{$1}", [escLit, procLink])
|
||||
elif s != nil and s.kind in {skType, skVar, skLet, skConst} and
|
||||
sfExported in s.flags and s.owner != nil and
|
||||
belongsToPackage(d.conf, s.owner) and d.target == outHtml:
|
||||
belongsToProjectPackage(d.conf, s.owner) and d.target == outHtml:
|
||||
let external = externalDep(d, s.owner)
|
||||
result.addf "<a href=\"$1#$2\"><span class=\"Identifier\">$3</span></a>",
|
||||
[changeFileExt(external, "html"), literal,
|
||||
@@ -885,6 +902,64 @@ proc genSeeSrc(d: PDoc, path: string, line: int): string =
|
||||
"path", path.string, "line", $line, "url", gitUrl,
|
||||
"commit", commit, "devel", develBranch]])
|
||||
|
||||
proc symbolPriority(k: TSymKind): int =
|
||||
result = case k
|
||||
of skMacro: -3
|
||||
of skTemplate: -2
|
||||
of skIterator: -1
|
||||
else: 0 # including skProc which have higher priority
|
||||
# documentation itself has even higher priority 1
|
||||
|
||||
proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
|
||||
## Converts symbol info (names/types/parameters) in `n` into format
|
||||
## `LangSymbol` convenient for ``rst.nim``/``dochelpers.nim``.
|
||||
result.name = baseName.nimIdentNormalize
|
||||
result.symKind = k.toHumanStr
|
||||
if k in routineKinds:
|
||||
var
|
||||
paramTypes: seq[string]
|
||||
renderParamTypes(paramTypes, n[paramsPos], toNormalize=true)
|
||||
let paramNames = renderParamNames(n[paramsPos], toNormalize=true)
|
||||
# In some rare cases (system.typeof) parameter type is not set for default:
|
||||
doAssert paramTypes.len <= paramNames.len
|
||||
for i in 0 ..< paramNames.len:
|
||||
if i < paramTypes.len:
|
||||
result.parameters.add (paramNames[i], paramTypes[i])
|
||||
else:
|
||||
result.parameters.add (paramNames[i], "")
|
||||
result.parametersProvided = true
|
||||
|
||||
result.outType = renderOutType(n[paramsPos], toNormalize=true)
|
||||
|
||||
if k in {skProc, skFunc, skType, skIterator}:
|
||||
# Obtain `result.generics`
|
||||
# Use `n[miscPos]` since n[genericParamsPos] does not contain constraints
|
||||
var genNode: PNode = nil
|
||||
if k == skType:
|
||||
genNode = n[1] # FIXME: what is index 1?
|
||||
else:
|
||||
if n[miscPos].kind != nkEmpty:
|
||||
genNode = n[miscPos][1] # FIXME: what is index 1?
|
||||
if genNode != nil:
|
||||
var literal = ""
|
||||
var r: TSrcGen
|
||||
initTokRender(r, genNode, {renderNoBody, renderNoComments,
|
||||
renderNoPragmas, renderNoProcDefs})
|
||||
var kind = tkEof
|
||||
while true:
|
||||
getNextTok(r, kind, literal)
|
||||
if kind == tkEof:
|
||||
break
|
||||
if kind != tkSpaces:
|
||||
result.generics.add(literal.nimIdentNormalize)
|
||||
|
||||
if k == skType:
|
||||
case n[2].kind
|
||||
of nkEnumTy: result.symTypeKind = "enum"
|
||||
of nkObjectTy: result.symTypeKind = "object"
|
||||
of nkTupleTy: result.symTypeKind = "tuple"
|
||||
else: discard
|
||||
|
||||
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
if (docFlags != kForceExport) and not isVisible(d, nameNode): return
|
||||
let
|
||||
@@ -915,6 +990,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
inc(d.id)
|
||||
let
|
||||
plainNameEsc = esc(d.target, plainName.strip)
|
||||
detailedName = k.toHumanStr & " " & (
|
||||
if k in routineKinds: plainName else: name)
|
||||
uniqueName = if k in routineKinds: plainNameEsc else: name
|
||||
sortName = if k in routineKinds: plainName.strip else: name
|
||||
cleanPlainSymbol = renderPlainSymbolName(nameNode)
|
||||
@@ -923,20 +1000,32 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
symbolOrId = d.newUniquePlainSymbol(complexSymbol)
|
||||
symbolOrIdEnc = encodeUrl(symbolOrId, usePlus = false)
|
||||
deprecationMsg = genDeprecationMsg(d, pragmaNode)
|
||||
rstLangSymbol = toLangSymbol(k, n, cleanPlainSymbol)
|
||||
|
||||
# we generate anchors automatically for subsequent use in doc comments
|
||||
let lineinfo = rstast.TLineInfo(
|
||||
line: nameNode.info.line, col: nameNode.info.col,
|
||||
fileIndex: addRstFileIndex(d, nameNode.info))
|
||||
addAnchorNim(d.sharedState, refn = symbolOrId, tooltip = detailedName,
|
||||
rstLangSymbol, priority = symbolPriority(k), info = lineinfo)
|
||||
|
||||
nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments,
|
||||
renderDocComments, renderSyms}, symbolOrIdEnc)
|
||||
|
||||
let seeSrc = genSeeSrc(d, toFullPath(d.conf, n.info), n.info.line.int)
|
||||
|
||||
d.section[k].secItems.add Item(
|
||||
d.section[k].secItems.mgetOrPut(cleanPlainSymbol, newSeq[Item]()).add Item(
|
||||
descRst: comm,
|
||||
sortName: sortName,
|
||||
info: lineinfo,
|
||||
anchor: symbolOrId,
|
||||
detailedName: detailedName,
|
||||
name: name,
|
||||
substitutions: @[
|
||||
"name", name, "uniqueName", uniqueName,
|
||||
"uniqueName", uniqueName,
|
||||
"header", result, "itemID", $d.id,
|
||||
"header_plain", plainNameEsc, "itemSym", cleanPlainSymbol,
|
||||
"itemSymOrID", symbolOrId, "itemSymEnc", plainSymbolEnc,
|
||||
"itemSymEnc", plainSymbolEnc,
|
||||
"itemSymOrIDEnc", symbolOrIdEnc, "seeSrc", seeSrc,
|
||||
"deprecationMsg", deprecationMsg])
|
||||
|
||||
@@ -1040,7 +1129,7 @@ proc traceDeps(d: PDoc, it: PNode) =
|
||||
for x in it[2]:
|
||||
a[2] = x
|
||||
traceDeps(d, a)
|
||||
elif it.kind == nkSym and belongsToPackage(d.conf, it.sym):
|
||||
elif it.kind == nkSym and belongsToProjectPackage(d.conf, it.sym):
|
||||
let external = externalDep(d, it.sym)
|
||||
if d.section[k].finalMarkup != "": d.section[k].finalMarkup.add(", ")
|
||||
dispA(d.conf, d.section[k].finalMarkup,
|
||||
@@ -1050,7 +1139,7 @@ proc traceDeps(d: PDoc, it: PNode) =
|
||||
|
||||
proc exportSym(d: PDoc; s: PSym) =
|
||||
const k = exportSection
|
||||
if s.kind == skModule and belongsToPackage(d.conf, s):
|
||||
if s.kind == skModule and belongsToProjectPackage(d.conf, s):
|
||||
let external = externalDep(d, s)
|
||||
if d.section[k].finalMarkup != "": d.section[k].finalMarkup.add(", ")
|
||||
dispA(d.conf, d.section[k].finalMarkup,
|
||||
@@ -1059,7 +1148,7 @@ proc exportSym(d: PDoc; s: PSym) =
|
||||
changeFileExt(external, "html")])
|
||||
elif s.kind != skModule and s.owner != nil:
|
||||
let module = originatingModule(s)
|
||||
if belongsToPackage(d.conf, module):
|
||||
if belongsToProjectPackage(d.conf, module):
|
||||
let
|
||||
complexSymbol = complexName(s.kind, s.ast, s.name.s)
|
||||
symbolOrId = d.newUniquePlainSymbol(complexSymbol)
|
||||
@@ -1184,6 +1273,11 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
|
||||
if comm.len != 0: d.modDescPre.add(comm)
|
||||
else: discard
|
||||
|
||||
proc overloadGroupName(s: string, k: TSymKind): string =
|
||||
## Turns a name like `f` into anchor `f-procs-all`
|
||||
#s & " " & k.toHumanStr & "s all"
|
||||
s & "-" & k.toHumanStr & "s-all"
|
||||
|
||||
proc finishGenerateDoc*(d: var PDoc) =
|
||||
## Perform 2nd RST pass for resolution of links/footnotes/headings...
|
||||
# copy file map `filenames` to ``rstgen.nim`` for its warnings
|
||||
@@ -1197,6 +1291,22 @@ proc finishGenerateDoc*(d: var PDoc) =
|
||||
break
|
||||
preparePass2(d.sharedState, firstRst)
|
||||
|
||||
# add anchors to overload groups before RST resolution
|
||||
for k in TSymKind:
|
||||
if k in routineKinds:
|
||||
for plainName, overloadChoices in d.section[k].secItems:
|
||||
if overloadChoices.len > 1:
|
||||
let refn = overloadGroupName(plainName, k)
|
||||
let tooltip = "$1 ($2 overloads)" % [
|
||||
k.toHumanStr & " " & plainName, $overloadChoices.len]
|
||||
addAnchorNim(d.sharedState, refn, tooltip,
|
||||
LangSymbol(symKind: k.toHumanStr,
|
||||
name: nimIdentBackticksNormalize(plainName),
|
||||
isGroup: true),
|
||||
priority = symbolPriority(k),
|
||||
# select index `0` just to have any meaningful warning:
|
||||
info = overloadChoices[0].info)
|
||||
|
||||
# Finalize fragments of ``.nim`` or ``.rst`` file
|
||||
proc renderItemPre(d: PDoc, fragments: ItemPre, result: var string) =
|
||||
for f in fragments:
|
||||
@@ -1207,14 +1317,33 @@ proc finishGenerateDoc*(d: var PDoc) =
|
||||
of false: result &= f.str
|
||||
proc cmp(x, y: Item): int = cmpDecimalsIgnoreCase(x.sortName, y.sortName)
|
||||
for k in TSymKind:
|
||||
for item in d.section[k].secItems.sorted(cmp):
|
||||
var itemDesc: string
|
||||
renderItemPre(d, item.descRst, itemDesc)
|
||||
d.section[k].finalMarkup.add(
|
||||
getConfigVar(d.conf, "doc.item") % (
|
||||
item.substitutions & @["desc", itemDesc]))
|
||||
itemDesc = ""
|
||||
d.section[k].secItems.setLen 0
|
||||
# add symbols to section for each `k`, while optionally wrapping
|
||||
# overloadable items with the same basic name by ``doc.item2``
|
||||
let overloadableNames = toSeq(keys(d.section[k].secItems))
|
||||
for plainName in overloadableNames.sorted(cmpDecimalsIgnoreCase):
|
||||
var overloadChoices = d.section[k].secItems[plainName]
|
||||
overloadChoices.sort(cmp)
|
||||
var nameContent = ""
|
||||
for item in overloadChoices:
|
||||
var itemDesc: string
|
||||
renderItemPre(d, item.descRst, itemDesc)
|
||||
nameContent.add(
|
||||
getConfigVar(d.conf, "doc.item") % (
|
||||
item.substitutions & @[
|
||||
"desc", itemDesc,
|
||||
"name", item.name,
|
||||
"itemSymOrID", item.anchor]))
|
||||
if k in routineKinds:
|
||||
let plainNameEsc1 = esc(d.target, plainName.strip)
|
||||
let plainNameEsc2 = esc(d.target, plainName.strip, escMode=emUrl)
|
||||
d.section[k].finalMarkup.add(
|
||||
getConfigVar(d.conf, "doc.item2") % (
|
||||
@["header_plain", plainNameEsc1,
|
||||
"overloadGroupName", overloadGroupName(plainNameEsc2, k),
|
||||
"content", nameContent]))
|
||||
else:
|
||||
d.section[k].finalMarkup.add(nameContent)
|
||||
d.section[k].secItems.clear
|
||||
renderItemPre(d, d.modDescPre, d.modDescFinal)
|
||||
d.modDescPre.setLen 0
|
||||
d.hasToc = d.hasToc or d.sharedState.hasToc
|
||||
@@ -1368,7 +1497,10 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
|
||||
# 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 = presentationPath(d.conf, AbsoluteFile d.filename).changeFileExt(HtmlExt).string.nativeToUnixPath
|
||||
let external = AbsoluteFile(d.destFile)
|
||||
.relativeTo(d.conf.outDir, '/')
|
||||
.changeFileExt(HtmlExt)
|
||||
.string
|
||||
setIndexTerm(d[], external, "", title)
|
||||
else:
|
||||
# Modules get an automatic title for the HTML, but no entry in the index.
|
||||
@@ -1442,7 +1574,11 @@ proc writeOutput*(d: PDoc, useWarning = false, groupedToc = false) =
|
||||
outfile.string)
|
||||
if not d.wroteSupportFiles: # nimdoc.css + dochack.js
|
||||
let nimr = $d.conf.getPrefixDir()
|
||||
copyFile(docCss.interp(nimr = nimr), $d.conf.outDir / nimdocOutCss)
|
||||
case d.target
|
||||
of outHtml:
|
||||
copyFile(docCss.interp(nimr = nimr), $d.conf.outDir / nimdocOutCss)
|
||||
of outLatex:
|
||||
copyFile(docCls.interp(nimr = nimr), $d.conf.outDir / nimdocOutCls)
|
||||
if optGenIndex in d.conf.globalOptions:
|
||||
let docHackJs2 = getDocHacksJs(nimr, nim = getAppFilename())
|
||||
copyFile(docHackJs2, $d.conf.outDir / docHackJs2.lastPathPart)
|
||||
@@ -1493,7 +1629,7 @@ proc commandRstAux(cache: IdentCache, conf: ConfigRef;
|
||||
filename: AbsoluteFile, outExt: string) =
|
||||
var filen = addFileExt(filename, "txt")
|
||||
var d = newDocumentor(filen, cache, conf, outExt, isPureRst = true)
|
||||
let rst = parseRst(readFile(filen.string), filen.string,
|
||||
let rst = parseRst(readFile(filen.string),
|
||||
line=LineRstInit, column=ColRstInit,
|
||||
conf, d.sharedState)
|
||||
d.modDescPre = @[ItemFragment(isRst: true, rst: rst)]
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# semantic checking.
|
||||
|
||||
import
|
||||
options, ast, msgs, passes, docgen, lineinfos, pathutils
|
||||
options, ast, msgs, passes, docgen, lineinfos, pathutils, packages
|
||||
|
||||
from modulegraphs import ModuleGraph, PPassContext
|
||||
|
||||
@@ -23,7 +23,7 @@ type
|
||||
PGen = ref TGen
|
||||
|
||||
proc shouldProcess(g: PGen): bool =
|
||||
(optWholeProject in g.doc.conf.globalOptions and g.module.getnimblePkgId == g.doc.conf.mainPackageId) or
|
||||
(optWholeProject in g.doc.conf.globalOptions and g.doc.conf.belongsToProjectPackage(g.module)) or
|
||||
sfMainModule in g.module.flags or g.config.projectMainIdx == g.module.info.fileIndex
|
||||
|
||||
template closeImpl(body: untyped) {.dirty.} =
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
|
||||
import ast, idents, lineinfos, modulegraphs, magicsys
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
|
||||
proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
|
||||
result = newSym(skProc, getIdent(g.cache, "$"), nextSymId idgen, t.owner, info)
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
import ast, renderer, options, strutils, types
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
ErrorKind* = enum ## expand as you need.
|
||||
RawTypeMismatchError
|
||||
|
||||
@@ -12,10 +12,13 @@
|
||||
# from a lineinfos file, to provide generalized procedures to compile
|
||||
# nim files.
|
||||
|
||||
import ropes, platform, condsyms, options, msgs, lineinfos, pathutils
|
||||
import ropes, platform, condsyms, options, msgs, lineinfos, pathutils, modulepaths
|
||||
|
||||
import std/[os, strutils, osproc, sha1, streams, sequtils, times, strtabs, json, jsonutils, sugar]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
type
|
||||
TInfoCCProp* = enum # properties of the C compiler:
|
||||
hasSwitchRange, # CC allows ranges in switch statements (GNU C)
|
||||
@@ -367,6 +370,7 @@ proc initVars*(conf: ConfigRef) =
|
||||
|
||||
proc completeCfilePath*(conf: ConfigRef; cfile: AbsoluteFile,
|
||||
createSubDir: bool = true): AbsoluteFile =
|
||||
## Generate the absolute file path to the generated modules.
|
||||
result = completeGeneratedFilePath(conf, cfile, createSubDir)
|
||||
|
||||
proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
|
||||
@@ -377,7 +381,7 @@ 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
|
||||
let key = completeCfilePath(conf, mangleModuleName(conf, nimfile).AbsoluteFile).string
|
||||
var value = conf.cfileSpecificOptions.getOrDefault(key)
|
||||
if strutils.find(value, option, 0) < 0:
|
||||
addOpt(value, option)
|
||||
@@ -430,7 +434,13 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
|
||||
# really: Cross compilation from Linux to Linux for example is entirely
|
||||
# reasonable.
|
||||
# `optGenMapping` is included here for niminst.
|
||||
result = conf.globalOptions * {optGenScript, optGenMapping} != {}
|
||||
# We use absolute paths for vcc / cl, see issue #19883.
|
||||
let options =
|
||||
if conf.cCompiler == ccVcc:
|
||||
{optGenMapping}
|
||||
else:
|
||||
{optGenScript, optGenMapping}
|
||||
result = conf.globalOptions * options != {}
|
||||
|
||||
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
|
||||
result = conf.compileOptions
|
||||
@@ -634,7 +644,7 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
|
||||
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
||||
if conf.backend == backendJs: return false # pre-existing behavior, but not sure it's good
|
||||
|
||||
let hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
|
||||
let hashFile = toGeneratedFile(conf, conf.mangleModuleName(cfile.cname).AbsoluteFile, "sha1")
|
||||
let currentHash = footprint(conf, cfile)
|
||||
var f: File
|
||||
if open(f, hashFile.string, fmRead):
|
||||
@@ -649,8 +659,10 @@ proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
|
||||
close(f)
|
||||
|
||||
proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
|
||||
# we want to generate the hash file unconditionally
|
||||
let extFileChanged = externalFileChanged(conf, c)
|
||||
if optForceFullMake notin conf.globalOptions and fileExists(c.obj) and
|
||||
not externalFileChanged(conf, c):
|
||||
not extFileChanged:
|
||||
c.flags.incl CfileFlag.Cached
|
||||
else:
|
||||
# make sure Nim keeps recompiling the external file on reruns
|
||||
@@ -840,9 +852,9 @@ proc hcrLinkTargetName(conf: ConfigRef, objFile: string, isMain = false): Absolu
|
||||
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)
|
||||
result = MsgKindToStr[hintCC] % (demangleModuleName(path.splitFile.name) & ": " & compileCmd)
|
||||
else:
|
||||
result = MsgKindToStr[hintCC] % demanglePackageName(path.splitFile.name)
|
||||
result = MsgKindToStr[hintCC] % demangleModuleName(path.splitFile.name)
|
||||
|
||||
proc callCCompiler*(conf: ConfigRef) =
|
||||
var
|
||||
@@ -915,7 +927,7 @@ proc callCCompiler*(conf: ConfigRef) =
|
||||
objfiles.add(' ')
|
||||
objfiles.add(quoteShell(objFile))
|
||||
let mainOutput = if optGenScript notin conf.globalOptions: conf.prepareToWriteOutput
|
||||
else: AbsoluteFile(conf.projectName)
|
||||
else: AbsoluteFile(conf.outFile)
|
||||
|
||||
linkCmd = getLinkCmd(conf, mainOutput, objfiles, removeStaticFile = true)
|
||||
extraCmds = getExtraCmds(conf, mainOutput)
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
import msgs, std / sha1, os, osproc, streams, options,
|
||||
lineinfos, pathutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
proc readOutput(p: Process): (string, int) =
|
||||
result[0] = ""
|
||||
var output = p.outputStream
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
|
||||
saturate, modulegraphs, options, lineinfos, int128
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
||||
mEqStr, mEqSet, mEqCString}
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
# This include implements the high level optimization pass.
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc hlo(c: PContext, n: PNode): PNode
|
||||
|
||||
proc evalPattern(c: PContext, n, orig: PNode): PNode =
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
import hashes, rodfiles
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
LitId* = distinct uint32
|
||||
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
|
||||
import std/packedsets, algorithm, tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import ".."/[ast, options, lineinfos, modulegraphs, cgendata, cgen,
|
||||
pathutils, extccomp, msgs]
|
||||
pathutils, extccomp, msgs, modulepaths]
|
||||
|
||||
import packed_ast, ic, dce, rodfiles
|
||||
|
||||
@@ -61,7 +64,8 @@ proc addFileToLink(config: ConfigRef; m: PSym) =
|
||||
if config.backend == backendCpp: ".nim.cpp"
|
||||
elif config.backend == backendObjc: ".nim.m"
|
||||
else: ".nim.c"
|
||||
let cfile = changeFileExt(completeCfilePath(config, withPackageName(config, filename)), ext)
|
||||
let cfile = changeFileExt(completeCfilePath(config,
|
||||
mangleModuleName(config, filename).AbsoluteFile), ext)
|
||||
let objFile = completeCfilePath(config, toObjFile(config, cfile))
|
||||
if fileExists(objFile):
|
||||
var cf = Cfile(nimname: m.name.s, cname: cfile,
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
## Dead code elimination (=DCE) for IC.
|
||||
|
||||
import std/[intsets, tables]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import ".." / [ast, options, lineinfos, types]
|
||||
|
||||
import packed_ast, ic, bitabs
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
import hashes, tables, intsets, std/sha1
|
||||
import packed_ast, bitabs, rodfiles
|
||||
import ".." / [ast, idents, lineinfos, msgs, ropes, options,
|
||||
pathutils, condsyms]
|
||||
pathutils, condsyms, packages, modulepaths]
|
||||
#import ".." / [renderer, astalgo]
|
||||
from os import removeFile, isAbsolute
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
type
|
||||
PackedConfig* = object
|
||||
backend: TBackend
|
||||
@@ -548,6 +551,10 @@ proc loadError(err: RodFileError; filename: AbsoluteFile; config: ConfigRef;) =
|
||||
rawMessage(config, warnCannotOpenFile, filename.string & " reason: " & $err)
|
||||
#echo "Error: ", $err, " loading file: ", filename.string
|
||||
|
||||
proc toRodFile*(conf: ConfigRef; f: AbsoluteFile; ext = RodExt): AbsoluteFile =
|
||||
result = changeFileExt(completeGeneratedFilePath(conf,
|
||||
mangleModuleName(conf, f).AbsoluteFile), ext)
|
||||
|
||||
proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef;
|
||||
ignoreConfig = false): RodFileError =
|
||||
var f = rodfiles.open(filename.string)
|
||||
@@ -927,17 +934,6 @@ proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; t
|
||||
result = g[si].types[t.item]
|
||||
assert result.itemId.item > 0
|
||||
|
||||
proc newPackage(config: ConfigRef; cache: IdentCache; fileIdx: FileIndex): PSym =
|
||||
let filename = AbsoluteFile toFullPath(config, fileIdx)
|
||||
let name = getIdent(cache, splitFile(filename).name)
|
||||
let info = newLineInfo(fileIdx, 1, 1)
|
||||
let
|
||||
pck = getPackageName(config, filename.string)
|
||||
pck2 = if pck.len > 0: pck else: "unknown"
|
||||
pack = getIdent(cache, pck2)
|
||||
result = newSym(skPackage, getIdent(cache, pck2),
|
||||
ItemId(module: PackageModuleId, item: int32(fileIdx)), nil, info)
|
||||
|
||||
proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache;
|
||||
fileIdx: FileIndex; m: var LoadedModule) =
|
||||
m.iface = initTable[PIdent, seq[PackedItemId]]()
|
||||
@@ -965,7 +961,7 @@ proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCa
|
||||
name: getIdent(cache, splitFile(filename).name),
|
||||
info: newLineInfo(fileIdx, 1, 1),
|
||||
position: int(fileIdx))
|
||||
m.module.owner = newPackage(conf, cache, fileIdx)
|
||||
m.module.owner = getPackage(conf, cache, fileIdx)
|
||||
m.module.flags = m.fromDisk.moduleFlags
|
||||
|
||||
proc loadToReplayNodes(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
## The set must cover a complete Nim project.
|
||||
|
||||
import sets
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import ".." / [ast, modulegraphs]
|
||||
import packed_ast, bitabs, ic
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ import sets
|
||||
from os import nil
|
||||
from std/private/miscdollars import toLocation
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import ".." / [ast, modulegraphs, msgs, options]
|
||||
import packed_ast, bitabs, ic
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ import hashes, tables, strtabs
|
||||
import bitabs
|
||||
import ".." / [ast, options]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
SymId* = distinct int32
|
||||
ModuleId* = distinct int32
|
||||
|
||||
@@ -16,6 +16,9 @@ import ".." / [ast, modulegraphs, trees, extccomp, btrees,
|
||||
|
||||
import tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import packed_ast, ic, bitabs
|
||||
|
||||
proc replayStateChanges*(module: PSym; g: ModuleGraph) =
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
from typetraits import supportsCopyMem
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
## Overview
|
||||
## ========
|
||||
## `RodFile` represents a Rod File (versioned binary format), and the
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
import
|
||||
hashes, wordrecg
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
PIdent* = ref TIdent
|
||||
TIdent*{.acyclic.} = object
|
||||
|
||||
@@ -15,6 +15,9 @@ import
|
||||
modulegraphs, wordrecg, tables
|
||||
from strutils import `%`
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc readExceptSet*(c: PContext, n: PNode): IntSet =
|
||||
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
|
||||
result = initIntSet()
|
||||
@@ -185,11 +188,13 @@ template addUnnamedIt(c: PContext, fromMod: PSym; filter: untyped) {.dirty.} =
|
||||
for it in mitems c.graph.ifaces[fromMod.position].converters:
|
||||
if filter:
|
||||
loadPackedSym(c.graph, it)
|
||||
addConverter(c, it)
|
||||
if sfExported in it.sym.flags:
|
||||
addConverter(c, it)
|
||||
for it in mitems c.graph.ifaces[fromMod.position].patterns:
|
||||
if filter:
|
||||
loadPackedSym(c.graph, it)
|
||||
addPattern(c, it)
|
||||
if sfExported in it.sym.flags:
|
||||
addPattern(c, it)
|
||||
for it in mitems c.graph.ifaces[fromMod.position].pureEnums:
|
||||
if filter:
|
||||
loadPackedSym(c.graph, it)
|
||||
@@ -197,7 +202,7 @@ template addUnnamedIt(c: PContext, fromMod: PSym; filter: untyped) {.dirty.} =
|
||||
|
||||
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
|
||||
c.addImport ImportedModule(m: fromMod, mode: importExcept, exceptSet: exceptSet)
|
||||
addUnnamedIt(c, fromMod, it.sym.id notin exceptSet)
|
||||
addUnnamedIt(c, fromMod, it.sym.name.id notin exceptSet)
|
||||
|
||||
proc importAllSymbols*(c: PContext, fromMod: PSym) =
|
||||
c.addImport ImportedModule(m: fromMod, mode: importAll)
|
||||
|
||||
@@ -19,6 +19,9 @@ import
|
||||
lineinfos, parampatterns, sighashes, liftdestructors, optimizer,
|
||||
varpartitions
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
from trees import exprStructuralEquivalent, getRoot
|
||||
|
||||
type
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
from math import trunc
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
Int128* = object
|
||||
udata: array[4, uint32]
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
import
|
||||
ast, types, renderer, intsets
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc canAlias(arg, ret: PType; marker: var IntSet): bool
|
||||
|
||||
proc canAliasN(arg: PType; n: PNode; marker: var IntSet): bool =
|
||||
@@ -71,12 +74,23 @@ proc isValueOnlyType(t: PType): bool =
|
||||
|
||||
proc canAlias*(arg, ret: PType): bool =
|
||||
if isValueOnlyType(arg):
|
||||
# can alias only with unsafeAddr(arg.x) and we don't care if it is not safe
|
||||
# can alias only with addr(arg.x) and we don't care if it is not safe
|
||||
result = false
|
||||
else:
|
||||
var marker = initIntSet()
|
||||
result = canAlias(arg, ret, marker)
|
||||
|
||||
proc containsVariable(n: PNode): bool =
|
||||
case n.kind
|
||||
of nodesToIgnoreSet:
|
||||
result = false
|
||||
of nkSym:
|
||||
result = n.sym.kind in {skForVar, skParam, skVar, skLet, skConst, skResult, skTemp}
|
||||
else:
|
||||
for ch in n:
|
||||
if containsVariable(ch): return true
|
||||
result = false
|
||||
|
||||
proc checkIsolate*(n: PNode): bool =
|
||||
if types.containsTyRef(n.typ):
|
||||
# XXX Maybe require that 'n.typ' is acyclic. This is not much
|
||||
@@ -96,7 +110,11 @@ proc checkIsolate*(n: PNode): bool =
|
||||
else:
|
||||
let argType = n[i].typ
|
||||
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
|
||||
if argType.canAlias(n.typ):
|
||||
if argType.canAlias(n.typ) or containsVariable(n[i]):
|
||||
# bug #19013: Alias information is not enough, we need to check for potential
|
||||
# "overlaps". I claim the problem can only happen by reading again from a location
|
||||
# that materialized which is only possible if a variable that contains a `ref`
|
||||
# is involved.
|
||||
return false
|
||||
result = true
|
||||
of nkIfStmt, nkIfExpr:
|
||||
|
||||
@@ -178,7 +178,7 @@ const
|
||||
proc mapType(typ: PType): TJSTypeKind =
|
||||
let t = skipTypes(typ, abstractInst)
|
||||
case t.kind
|
||||
of tyVar, tyRef, tyPtr, tyLent:
|
||||
of tyVar, tyRef, tyPtr:
|
||||
if skipTypes(t.lastSon, abstractInst).kind in MappedToObject:
|
||||
result = etyObject
|
||||
else:
|
||||
@@ -186,7 +186,8 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||
of tyPointer:
|
||||
# treat a tyPointer like a typed pointer to an array of bytes
|
||||
result = etyBaseIndex
|
||||
of tyRange, tyDistinct, tyOrdinal, tyProxy:
|
||||
of tyRange, tyDistinct, tyOrdinal, tyProxy, tyLent:
|
||||
# tyLent is no-op as JS has pass-by-reference semantics
|
||||
result = mapType(t[0])
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
|
||||
of tyBool: result = etyBool
|
||||
@@ -770,9 +771,6 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if catchBranchesExist:
|
||||
p.body.add("++excHandler;\L")
|
||||
var tmpFramePtr = rope"F"
|
||||
if optStackTrace notin p.options:
|
||||
tmpFramePtr = p.getTemp(true)
|
||||
line(p, tmpFramePtr & " = framePtr;\L")
|
||||
lineF(p, "try {$n", [])
|
||||
var a: TCompRes
|
||||
gen(p, n[0], a)
|
||||
@@ -781,7 +779,8 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if catchBranchesExist:
|
||||
p.body.addf("--excHandler;$n} catch (EXCEPTION) {$n var prevJSError = lastJSError;$n" &
|
||||
" lastJSError = EXCEPTION;$n --excHandler;$n", [])
|
||||
line(p, "framePtr = $1;$n" % [tmpFramePtr])
|
||||
if hasFrameInfo(p):
|
||||
line(p, "framePtr = $1;$n" % [tmpFramePtr])
|
||||
while i < n.len and n[i].kind == nkExceptBranch:
|
||||
if n[i].len == 1:
|
||||
# general except section:
|
||||
@@ -840,7 +839,8 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
line(p, "}\L")
|
||||
lineF(p, "lastJSError = prevJSError;$n")
|
||||
line(p, "} finally {\L")
|
||||
line(p, "framePtr = $1;$n" % [tmpFramePtr])
|
||||
if hasFrameInfo(p):
|
||||
line(p, "framePtr = $1;$n" % [tmpFramePtr])
|
||||
if i < n.len and n[i].kind == nkFinally:
|
||||
genStmt(p, n[i][0])
|
||||
line(p, "}\L")
|
||||
@@ -1060,14 +1060,14 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||
xtyp = etySeq
|
||||
case xtyp
|
||||
of etySeq:
|
||||
if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
if x.typ.kind in {tyVar, tyLent} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
else:
|
||||
useMagic(p, "nimCopy")
|
||||
lineF(p, "$1 = nimCopy(null, $2, $3);$n",
|
||||
[a.rdLoc, b.res, genTypeInfo(p, y.typ)])
|
||||
of etyObject:
|
||||
if x.typ.kind in {tyVar} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
if x.typ.kind in {tyVar, tyLent} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
else:
|
||||
useMagic(p, "nimCopy")
|
||||
@@ -1092,10 +1092,18 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
elif a.typ == etyBaseIndex:
|
||||
# array indexing may not map to var type
|
||||
if b.address != nil:
|
||||
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
||||
else:
|
||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||
else:
|
||||
internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
|
||||
else:
|
||||
elif b.address != nil:
|
||||
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
||||
else:
|
||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||
else:
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
|
||||
@@ -1288,75 +1296,89 @@ template isIndirect(x: PSym): bool =
|
||||
v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator,
|
||||
skConst, skTemp, skLet})
|
||||
|
||||
proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
case n[0].kind
|
||||
of nkSym:
|
||||
let s = n[0].sym
|
||||
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
|
||||
case s.kind
|
||||
of skParam:
|
||||
r.res = s.loc.r
|
||||
r.address = nil
|
||||
r.typ = etyNone
|
||||
of skVar, skLet, skResult:
|
||||
r.kind = resExpr
|
||||
let jsType = mapType(p, n.typ)
|
||||
if jsType == etyObject:
|
||||
# make addr() a no-op:
|
||||
r.typ = etyNone
|
||||
if isIndirect(s):
|
||||
r.res = s.loc.r & "[0]"
|
||||
else:
|
||||
r.res = s.loc.r
|
||||
r.address = nil
|
||||
elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex:
|
||||
# for ease of code generation, we do not distinguish between
|
||||
# sfAddrTaken and sfGlobal.
|
||||
r.typ = etyBaseIndex
|
||||
r.address = s.loc.r
|
||||
r.res = rope("0")
|
||||
proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
|
||||
let s = n.sym
|
||||
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
|
||||
case s.kind
|
||||
of skParam:
|
||||
r.res = s.loc.r
|
||||
r.address = nil
|
||||
r.typ = etyNone
|
||||
of skVar, skLet, skResult:
|
||||
r.kind = resExpr
|
||||
let jsType = mapType(p):
|
||||
if typ.isNil:
|
||||
n.typ
|
||||
else:
|
||||
# 'var openArray' for instance produces an 'addr' but this is harmless:
|
||||
gen(p, n[0], r)
|
||||
#internalError(p.config, n.info, "genAddr: 4 " & renderTree(n))
|
||||
else: internalError(p.config, n.info, $("genAddr: 2", s.kind))
|
||||
of nkCheckedFieldExpr:
|
||||
genCheckedFieldOp(p, n[0], n.typ, r)
|
||||
of nkDotExpr:
|
||||
if mapType(p, n.typ) == etyBaseIndex:
|
||||
genFieldAddr(p, n[0], r)
|
||||
typ
|
||||
if jsType == etyObject:
|
||||
# make addr() a no-op:
|
||||
r.typ = etyNone
|
||||
if isIndirect(s):
|
||||
r.res = s.loc.r & "[0]"
|
||||
else:
|
||||
r.res = s.loc.r
|
||||
r.address = nil
|
||||
elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex:
|
||||
# for ease of code generation, we do not distinguish between
|
||||
# sfAddrTaken and sfGlobal.
|
||||
r.typ = etyBaseIndex
|
||||
r.address = s.loc.r
|
||||
r.res = rope("0")
|
||||
else:
|
||||
genFieldAccess(p, n[0], r)
|
||||
of nkBracketExpr:
|
||||
var ty = skipTypes(n[0].typ, abstractVarRange)
|
||||
if ty.kind in MappedToObject:
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
let kindOfIndexedExpr = skipTypes(n[0][0].typ, abstractVarRange).kind
|
||||
case kindOfIndexedExpr
|
||||
of tyArray, tyOpenArray, tySequence, tyString, tyCstring, tyVarargs:
|
||||
genArrayAddr(p, n[0], r)
|
||||
of tyTuple:
|
||||
genFieldAddr(p, n[0], r)
|
||||
else: internalError(p.config, n[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
|
||||
of nkObjDownConv:
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenDeref:
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenAddr:
|
||||
gen(p, n[0], r)
|
||||
of nkStmtListExpr:
|
||||
if n.len == 1: gen(p, n[0], r)
|
||||
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
|
||||
of nkCallKinds:
|
||||
if n[0].typ.kind == tyOpenArray:
|
||||
# 'var openArray' for instance produces an 'addr' but this is harmless:
|
||||
# namely toOpenArray(a, 1, 3)
|
||||
gen(p, n, r)
|
||||
#internalError(p.config, n.info, "genAddr: 4 " & renderTree(n))
|
||||
else: internalError(p.config, n.info, $("genAddr: 2", s.kind))
|
||||
|
||||
proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if n.kind == nkSym:
|
||||
genSymAddr(p, n, nil, r)
|
||||
else:
|
||||
case n[0].kind
|
||||
of nkSym:
|
||||
genSymAddr(p, n[0], n.typ, r)
|
||||
of nkCheckedFieldExpr:
|
||||
genCheckedFieldOp(p, n[0], n.typ, r)
|
||||
of nkDotExpr:
|
||||
if mapType(p, n.typ) == etyBaseIndex:
|
||||
genFieldAddr(p, n[0], r)
|
||||
else:
|
||||
genFieldAccess(p, n[0], r)
|
||||
of nkBracketExpr:
|
||||
var ty = skipTypes(n[0].typ, abstractVarRange)
|
||||
if ty.kind in MappedToObject:
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
let kindOfIndexedExpr = skipTypes(n[0][0].typ, abstractVarRange).kind
|
||||
case kindOfIndexedExpr
|
||||
of tyArray, tyOpenArray, tySequence, tyString, tyCstring, tyVarargs:
|
||||
genArrayAddr(p, n[0], r)
|
||||
of tyTuple:
|
||||
genFieldAddr(p, n[0], r)
|
||||
of tyGenericBody:
|
||||
genAddr(p, n[^1], r)
|
||||
else: internalError(p.config, n[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
|
||||
of nkObjDownConv:
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenDeref:
|
||||
gen(p, n[0], r)
|
||||
of nkHiddenAddr:
|
||||
gen(p, n[0], r)
|
||||
of nkConv:
|
||||
genAddr(p, n[0], r)
|
||||
of nkStmtListExpr:
|
||||
if n.len == 1: gen(p, n[0], r)
|
||||
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
|
||||
of nkCallKinds:
|
||||
if n[0].typ.kind == tyOpenArray:
|
||||
# 'var openArray' for instance produces an 'addr' but this is harmless:
|
||||
# namely toOpenArray(a, 1, 3)
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
|
||||
else:
|
||||
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
|
||||
else:
|
||||
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
|
||||
|
||||
proc attachProc(p: PProc; content: Rope; s: PSym) =
|
||||
p.g.code.add(content)
|
||||
@@ -1442,13 +1464,17 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||
else:
|
||||
if s.loc.r == nil:
|
||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||
r.res = s.loc.r
|
||||
if mapType(p, s.typ) == etyBaseIndex:
|
||||
r.address = s.loc.r
|
||||
r.res = s.loc.r & "_Idx"
|
||||
else:
|
||||
r.res = s.loc.r
|
||||
r.kind = resVal
|
||||
|
||||
proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let it = n[0]
|
||||
let t = mapType(p, it.typ)
|
||||
if t == etyObject:
|
||||
if t == etyObject or it.typ.kind == tyLent:
|
||||
gen(p, it, r)
|
||||
else:
|
||||
var a: TCompRes
|
||||
@@ -1689,7 +1715,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
result = putToSeq("0", indirect)
|
||||
of tyFloat..tyFloat128:
|
||||
result = putToSeq("0.0", indirect)
|
||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
|
||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
|
||||
result = createVar(p, lastSon(typ), indirect)
|
||||
of tySet:
|
||||
result = putToSeq("{}", indirect)
|
||||
@@ -1731,7 +1757,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
createObjInitList(p, t, initIntSet(), initList)
|
||||
result = ("({$1})") % [initList]
|
||||
if indirect: result = "[$1]" % [result]
|
||||
of tyVar, tyPtr, tyLent, tyRef, tyPointer:
|
||||
of tyVar, tyPtr, tyRef, tyPointer:
|
||||
if mapType(p, t) == etyBaseIndex:
|
||||
result = putToSeq("[null, 0]", indirect)
|
||||
else:
|
||||
@@ -2366,6 +2392,7 @@ proc optionalLine(p: Rope): Rope =
|
||||
return p & "\L"
|
||||
|
||||
proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||
## Generate a JS procedure ('function').
|
||||
var
|
||||
resultSym: PSym
|
||||
a: TCompRes
|
||||
@@ -2380,16 +2407,17 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||
if prc.typ[0] != nil and sfPure notin prc.flags:
|
||||
resultSym = prc.ast[resultPos].sym
|
||||
let mname = mangleName(p.module, resultSym)
|
||||
if not isIndirect(resultSym) and
|
||||
let returnAddress = not isIndirect(resultSym) and
|
||||
resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and
|
||||
mapType(p, resultSym.typ) == etyBaseIndex:
|
||||
mapType(p, resultSym.typ) == etyBaseIndex
|
||||
if returnAddress:
|
||||
resultAsgn = p.indentLine(("var $# = null;$n") % [mname])
|
||||
resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])
|
||||
else:
|
||||
let resVar = createVar(p, resultSym.typ, isIndirect(resultSym))
|
||||
resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar])
|
||||
gen(p, prc.ast[resultPos], a)
|
||||
if mapType(p, resultSym.typ) == etyBaseIndex:
|
||||
if returnAddress:
|
||||
returnStmt = "return [$#, $#];$n" % [a.address, a.res]
|
||||
else:
|
||||
returnStmt = "return $#;$n" % [a.res]
|
||||
@@ -2565,8 +2593,15 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkObjConstr: genObjConstr(p, n, r)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||
of nkAddr, nkHiddenAddr:
|
||||
genAddr(p, n, r)
|
||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
||||
if n.typ.kind in {tyLent}:
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
genAddr(p, n, r)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
if n.typ.kind in {tyLent}:
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
genDeref(p, n, r)
|
||||
of nkBracketExpr: genArrayAccess(p, n, r)
|
||||
of nkDotExpr: genFieldAccess(p, n, r)
|
||||
of nkCheckedFieldExpr: genCheckedFieldOp(p, n, nil, r)
|
||||
@@ -2639,6 +2674,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
else: internalError(p.config, n.info, "gen: unknown node type: " & $n.kind)
|
||||
|
||||
proc newModule(g: ModuleGraph; module: PSym): BModule =
|
||||
## Create a new JS backend module node.
|
||||
new(result)
|
||||
result.module = module
|
||||
result.sigConflicts = initCountTable[SigHash]()
|
||||
@@ -2650,6 +2686,7 @@ proc newModule(g: ModuleGraph; module: PSym): BModule =
|
||||
PGlobals(g.backend).inSystem = true
|
||||
|
||||
proc genHeader(): Rope =
|
||||
## Generate the JS header.
|
||||
result = rope("""/* Generated by the Nim Compiler v$1 */
|
||||
var framePtr = null;
|
||||
var excHandler = 0;
|
||||
@@ -2680,6 +2717,8 @@ proc addHcrInitGuards(p: PProc, n: PNode,
|
||||
genStmt(p, n)
|
||||
|
||||
proc genModule(p: PProc, n: PNode) =
|
||||
## Generate the JS module code.
|
||||
## Called for each top level node in a Nim module.
|
||||
if optStackTrace in p.options:
|
||||
p.body.add(frameCreate(p,
|
||||
makeJSString("module " & p.module.module.name.s),
|
||||
@@ -2708,6 +2747,7 @@ proc genModule(p: PProc, n: PNode) =
|
||||
p.body.add(frameDestroy(p))
|
||||
|
||||
proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
## Generate JS code for a node.
|
||||
result = n
|
||||
let m = BModule(b)
|
||||
if passes.skipCodegen(m.config, n): return n
|
||||
@@ -2720,6 +2760,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
p.g.code.add(p.body)
|
||||
|
||||
proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
|
||||
## Combine source code from all nodes.
|
||||
let globals = PGlobals(graph.backend)
|
||||
for prc in globals.forwarded:
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
@@ -2745,26 +2786,41 @@ proc getClassName(t: PType): Rope =
|
||||
else: result = rope(s.name.s)
|
||||
|
||||
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||
result = myProcess(b, n)
|
||||
## Finalize JS code generation of a Nim module.
|
||||
## Param `n` may contain nodes returned from the last module close call.
|
||||
var m = BModule(b)
|
||||
if sfMainModule in m.module.flags:
|
||||
for destructorCall in graph.globalDestructors:
|
||||
n.add destructorCall
|
||||
# Add global destructors to the module.
|
||||
# This must come before the last call to `myProcess`.
|
||||
for i in countdown(high(graph.globalDestructors), 0):
|
||||
n.add graph.globalDestructors[i]
|
||||
# Process any nodes left over from the last call to `myClose`.
|
||||
result = myProcess(b, n)
|
||||
# Some codegen is different (such as no stacktraces; see `initProcOptions`)
|
||||
# when `std/system` is being processed.
|
||||
if sfSystemModule in m.module.flags:
|
||||
PGlobals(graph.backend).inSystem = false
|
||||
# Check if codegen should continue before any files are generated.
|
||||
# It may bail early is if too many errors have been raised.
|
||||
if passes.skipCodegen(m.config, n): return n
|
||||
# Nim modules are compiled into a single JS file.
|
||||
# If this is the main module, then this is the final call to `myClose`.
|
||||
if sfMainModule in m.module.flags:
|
||||
var code = genHeader() & wholeCode(graph, m)
|
||||
let outFile = m.config.prepareToWriteOutput()
|
||||
|
||||
# Generate an optional source map.
|
||||
if optSourcemap in m.config.globalOptions:
|
||||
var map: SourceMap
|
||||
(code, map) = genSourceMap($(code), outFile.string)
|
||||
writeFile(outFile.string & ".map", $(%map))
|
||||
discard writeRopeIfNotEqual(code, outFile)
|
||||
|
||||
# Check if the generated JS code matches the output file, or else
|
||||
# write it to the file.
|
||||
if not equalsFile(code, outFile):
|
||||
if not writeRope(code, outFile):
|
||||
rawMessage(m.config, errCannotOpenFile, outFile.string)
|
||||
|
||||
proc myOpen(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext =
|
||||
## Create the JS backend pass context `BModule` for a Nim module.
|
||||
result = newModule(graph, s)
|
||||
result.idgen = idgen
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ import
|
||||
idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos,
|
||||
transf, liftdestructors, typeallowed
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
discard """
|
||||
The basic approach is that captured vars need to be put on the heap and
|
||||
that the calling chain needs to be explicitly modelled. Things to consider:
|
||||
@@ -272,16 +275,11 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PN
|
||||
proc freshVarForClosureIter*(g: ModuleGraph; s: PSym; idgen: IdGenerator; owner: PSym): PNode =
|
||||
let envParam = getHiddenParam(g, owner)
|
||||
let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
addField(obj, s, g.cache, idgen)
|
||||
let field = addField(obj, s, g.cache, idgen)
|
||||
|
||||
var access = newSymNode(envParam)
|
||||
assert obj.kind == tyObject
|
||||
let field = getFieldFromObj(obj, s)
|
||||
if field != nil:
|
||||
result = rawIndirectAccess(access, field, s.info)
|
||||
else:
|
||||
localError(g.config, s.info, "internal error: cannot generate fresh variable")
|
||||
result = access
|
||||
result = rawIndirectAccess(access, field, s.info)
|
||||
|
||||
# ------------------ new stuff -------------------------------------------
|
||||
|
||||
@@ -290,7 +288,8 @@ proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
|
||||
if illegalCapture(s):
|
||||
localError(g.config, n.info,
|
||||
("'$1' is of type <$2> which cannot be captured as it would violate memory" &
|
||||
" safety, declared here: $3; using '-d:nimNoLentIterators' helps in some cases") %
|
||||
" safety, declared here: $3; using '-d:nimNoLentIterators' helps in some cases." &
|
||||
" Consider using a <ref $2> which can be captured.") %
|
||||
[s.name.s, typeToString(s.typ), g.config$s.info])
|
||||
elif not (owner.typ.callConv == ccClosure or owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags):
|
||||
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
|
||||
@@ -449,7 +448,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
if s.name.id == getIdent(c.graph.cache, ":state").id:
|
||||
obj.n[0].sym.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
|
||||
else:
|
||||
addField(obj, s, c.graph.cache, c.idgen)
|
||||
discard addField(obj, s, c.graph.cache, c.idgen)
|
||||
# direct or indirect dependency:
|
||||
elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s):
|
||||
discard """
|
||||
@@ -471,7 +470,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
|
||||
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
addField(obj, s, c.graph.cache, c.idgen)
|
||||
discard addField(obj, s, c.graph.cache, c.idgen)
|
||||
# create required upFields:
|
||||
var w = owner.skipGenericOwner
|
||||
if isInnerProc(w) or owner.isIterator:
|
||||
|
||||
@@ -19,6 +19,9 @@ import
|
||||
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream,
|
||||
wordrecg, lineinfos, pathutils, parseutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
MaxLineLength* = 80 # lines longer than this lead to a warning
|
||||
numChars*: set[char] = {'0'..'9', 'a'..'z', 'A'..'Z'}
|
||||
|
||||
@@ -15,6 +15,9 @@ import modulegraphs, lineinfos, idents, ast, renderer, semdata,
|
||||
|
||||
from trees import isCaseObj
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
TLiftCtx = object
|
||||
g: ModuleGraph
|
||||
@@ -941,6 +944,12 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfGeneratedOp
|
||||
|
||||
proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xx = genBuiltin(c, mAccessTypeField, "accessTypeField", x)
|
||||
let yy = genBuiltin(c, mAccessTypeField, "accessTypeField", y)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ = xx.typ
|
||||
body.add newAsgnStmt(xx, yy)
|
||||
|
||||
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator): PSym =
|
||||
@@ -980,6 +989,10 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
fillStrOp(a, typ, result.ast[bodyPos], d, src)
|
||||
else:
|
||||
fillBody(a, typ, result.ast[bodyPos], d, src)
|
||||
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy} and not lacksMTypeField(typ):
|
||||
# bug #19205: Do not forget to also copy the hidden type field:
|
||||
genTypeFieldCopy(a, typ, result.ast[bodyPos], d, src)
|
||||
|
||||
if not a.canRaise: incl result.flags, sfNeverRaises
|
||||
completePartialOp(g, idgen.module, typ, kind, result)
|
||||
|
||||
|
||||
@@ -34,11 +34,13 @@ type
|
||||
errXExpected,
|
||||
errRstGridTableNotImplemented,
|
||||
errRstMarkdownIllformedTable,
|
||||
errRstIllformedTable,
|
||||
errRstNewSectionExpected,
|
||||
errRstGeneralParseError,
|
||||
errRstInvalidDirectiveX,
|
||||
errRstInvalidField,
|
||||
errRstFootnoteMismatch,
|
||||
errRstSandboxedDirective,
|
||||
errProveInit, # deadcode
|
||||
errGenerated,
|
||||
errUser,
|
||||
@@ -50,6 +52,7 @@ type
|
||||
warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
|
||||
warnRstRedefinitionOfLabel = "RedefinitionOfLabel",
|
||||
warnRstUnknownSubstitutionX = "UnknownSubstitutionX",
|
||||
warnRstAmbiguousLink = "AmbiguousLink",
|
||||
warnRstBrokenLink = "BrokenLink",
|
||||
warnRstLanguageXNotSupported = "LanguageXNotSupported",
|
||||
warnRstFieldXNotSupported = "FieldXNotSupported",
|
||||
@@ -75,6 +78,7 @@ type
|
||||
warnAnyEnumConv = "AnyEnumConv",
|
||||
warnHoleEnumConv = "HoleEnumConv",
|
||||
warnCstringConv = "CStringConv",
|
||||
warnNoInitIgnored = "NoInitIgnored"
|
||||
warnEffect = "Effect",
|
||||
warnUser = "User",
|
||||
# hints
|
||||
@@ -104,11 +108,13 @@ const
|
||||
errXExpected: "'$1' expected",
|
||||
errRstGridTableNotImplemented: "grid table is not implemented",
|
||||
errRstMarkdownIllformedTable: "illformed delimiter row of a markdown table",
|
||||
errRstIllformedTable: "Illformed table: $1",
|
||||
errRstNewSectionExpected: "new section expected $1",
|
||||
errRstGeneralParseError: "general parse error",
|
||||
errRstInvalidDirectiveX: "invalid directive: '$1'",
|
||||
errRstInvalidField: "invalid field: $1",
|
||||
errRstFootnoteMismatch: "number of footnotes and their references don't match: $1",
|
||||
errRstSandboxedDirective: "disabled directive: '$1'",
|
||||
errProveInit: "Cannot prove that '$1' is initialized.", # deadcode
|
||||
errGenerated: "$1",
|
||||
errUser: "$1",
|
||||
@@ -123,6 +129,7 @@ const
|
||||
warnUnknownMagic: "unknown magic '$1' might crash the compiler",
|
||||
warnRstRedefinitionOfLabel: "redefinition of label '$1'",
|
||||
warnRstUnknownSubstitutionX: "unknown substitution '$1'",
|
||||
warnRstAmbiguousLink: "ambiguous doc link $1",
|
||||
warnRstBrokenLink: "broken link '$1'",
|
||||
warnRstLanguageXNotSupported: "language '$1' not supported",
|
||||
warnRstFieldXNotSupported: "field '$1' not supported",
|
||||
@@ -164,6 +171,7 @@ const
|
||||
warnAnyEnumConv: "$1",
|
||||
warnHoleEnumConv: "$1",
|
||||
warnCstringConv: "$1",
|
||||
warnNoInitIgnored: "noinit pragma is ignored",
|
||||
warnEffect: "$1",
|
||||
warnUser: "$1",
|
||||
hintSuccess: "operation successful: $#",
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
import
|
||||
pathutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
# support `useGnuReadline`, `useLinenoise` for backwards compatibility
|
||||
const hasRstdin = (defined(nimUseLinenoise) or defined(useLinenoise) or defined(useGnuReadline)) and
|
||||
not defined(windows)
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
|
||||
# This module implements lookup helpers.
|
||||
import std/[algorithm, strutils]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, idents, semdata, types, msgs, options,
|
||||
renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs
|
||||
|
||||
@@ -15,6 +15,9 @@ const
|
||||
import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs,
|
||||
lineinfos
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc newDeref*(n: PNode): PNode {.inline.} =
|
||||
result = newNodeIT(nkHiddenDeref, n.info, n.typ[0])
|
||||
result.add n
|
||||
@@ -71,14 +74,20 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: P
|
||||
let value = n.lastSon
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId(idgen),
|
||||
owner, value.info, g.config.options)
|
||||
temp.typ = skipTypes(value.typ, abstractInst)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
var tempAsNode: PNode
|
||||
let avoidTemp = value.kind == nkSym
|
||||
if avoidTemp:
|
||||
tempAsNode = value
|
||||
else:
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId(idgen),
|
||||
owner, value.info, g.config.options)
|
||||
temp.typ = skipTypes(value.typ, abstractInst)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
tempAsNode = newSymNode(temp)
|
||||
|
||||
var v = newNodeI(nkVarSection, value.info)
|
||||
let tempAsNode = newSymNode(temp)
|
||||
v.addVar(tempAsNode, value)
|
||||
if not avoidTemp:
|
||||
v.addVar(tempAsNode, value)
|
||||
result.add(v)
|
||||
|
||||
for i in 0..<n.len-2:
|
||||
@@ -221,7 +230,7 @@ proc lookupInRecord(n: PNode, id: ItemId): PSym =
|
||||
if n.sym.itemId.module == id.module and n.sym.itemId.item == -abs(id.item): result = n.sym
|
||||
else: discard
|
||||
|
||||
proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator) =
|
||||
proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym =
|
||||
# because of 'gensym' support, we have to mangle the name with its ID.
|
||||
# This is hacky but the clean solution is much more complex than it looks.
|
||||
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len),
|
||||
@@ -235,6 +244,7 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator) =
|
||||
field.flags = s.flags * {sfCursor}
|
||||
obj.n.add newSymNode(field)
|
||||
fieldCheck()
|
||||
result = field
|
||||
|
||||
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} =
|
||||
result = lookupInRecord(obj.n, s.itemId)
|
||||
|
||||
@@ -22,6 +22,10 @@ import
|
||||
modules,
|
||||
modulegraphs, lineinfos, pathutils, vmprofiler
|
||||
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
import ic / [cbackend, integrity, navigator]
|
||||
from ic / ic import rodViewer
|
||||
|
||||
@@ -58,6 +62,11 @@ proc commandCheck(graph: ModuleGraph) =
|
||||
let conf = graph.config
|
||||
conf.setErrorMaxHighMaybe
|
||||
defineSymbol(conf.symbols, "nimcheck")
|
||||
if optWasNimscript in conf.globalOptions:
|
||||
defineSymbol(conf.symbols, "nimscript")
|
||||
defineSymbol(conf.symbols, "nimconfig")
|
||||
elif conf.backend == backendJs:
|
||||
setTarget(conf.target, osJS, cpuJS)
|
||||
semanticPasses(graph) # use an empty backend for semantic checking only
|
||||
compileProject(graph)
|
||||
|
||||
@@ -363,7 +372,8 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
msgWriteln(conf, "-- end of list --", {msgStdout, msgSkipHook})
|
||||
|
||||
for it in conf.searchPaths: msgWriteln(conf, it.string)
|
||||
of cmdCheck: commandCheck(graph)
|
||||
of cmdCheck:
|
||||
commandCheck(graph)
|
||||
of cmdParse:
|
||||
wantMainModule(conf)
|
||||
discard parseFile(conf.projectMainIdx, cache, conf)
|
||||
|
||||
297
compiler/md5_old.nim
Normal file
297
compiler/md5_old.nim
Normal file
@@ -0,0 +1,297 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# `std/md5` without VM and JavaScript support, to circumvent a bug with
|
||||
# openarrays on Nim < 1.4.
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
type
|
||||
MD5State = array[0..3, uint32]
|
||||
MD5Block = array[0..15, uint32]
|
||||
MD5CBits = array[0..7, uint8]
|
||||
MD5Digest* = array[0..15, uint8]
|
||||
## MD5 checksum of a string, obtained with the `toMD5 proc <#toMD5,string>`_.
|
||||
MD5Buffer = array[0..63, uint8]
|
||||
MD5Context* {.final.} = object
|
||||
state: MD5State
|
||||
count: array[0..1, uint32]
|
||||
buffer: MD5Buffer
|
||||
|
||||
const
|
||||
padding: array[0..63, uint8] = [
|
||||
0x80'u8, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
]
|
||||
|
||||
proc F(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = (x and y) or ((not x) and z)
|
||||
|
||||
proc G(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = (x and z) or (y and (not z))
|
||||
|
||||
proc H(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = x xor y xor z
|
||||
|
||||
proc I(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = y xor (x or (not z))
|
||||
|
||||
proc rot(x: var uint32, n: uint8) {.inline.} =
|
||||
x = (x shl n) or (x shr (32'u32 - n))
|
||||
|
||||
proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + F(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a + b
|
||||
|
||||
proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + G(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a + b
|
||||
|
||||
proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + H(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a + b
|
||||
|
||||
proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + I(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a + b
|
||||
|
||||
proc encode(dest: var MD5Block, src: openArray[uint8]) =
|
||||
var j = 0
|
||||
for i in 0..high(dest):
|
||||
dest[i] = uint32(ord(src[j])) or
|
||||
uint32(ord(src[j+1])) shl 8 or
|
||||
uint32(ord(src[j+2])) shl 16 or
|
||||
uint32(ord(src[j+3])) shl 24
|
||||
inc(j, 4)
|
||||
|
||||
proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
|
||||
var i = 0
|
||||
for j in 0..high(src):
|
||||
dest[i] = uint8(src[j] and 0xff'u32)
|
||||
dest[i+1] = uint8(src[j] shr 8 and 0xff'u32)
|
||||
dest[i+2] = uint8(src[j] shr 16 and 0xff'u32)
|
||||
dest[i+3] = uint8(src[j] shr 24 and 0xff'u32)
|
||||
inc(i, 4)
|
||||
|
||||
template slice(s: string | cstring, a, b): openArray[uint8] =
|
||||
s.toOpenArrayByte(a, b)
|
||||
|
||||
template slice(s: openArray[uint8], a, b): openArray[uint8] =
|
||||
s.toOpenArray(a, b)
|
||||
|
||||
proc transform(buffer: openArray[uint8], state: var MD5State) =
|
||||
var
|
||||
myBlock: MD5Block
|
||||
encode(myBlock, buffer)
|
||||
var a = state[0]
|
||||
var b = state[1]
|
||||
var c = state[2]
|
||||
var d = state[3]
|
||||
FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32)
|
||||
FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32)
|
||||
FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32)
|
||||
FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32)
|
||||
FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32)
|
||||
FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32)
|
||||
FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32)
|
||||
FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32)
|
||||
FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32)
|
||||
FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32)
|
||||
FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32)
|
||||
FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32)
|
||||
FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32)
|
||||
FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32)
|
||||
FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32)
|
||||
FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32)
|
||||
GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32)
|
||||
GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32)
|
||||
GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32)
|
||||
GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32)
|
||||
GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32)
|
||||
GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32)
|
||||
GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32)
|
||||
GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32)
|
||||
GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32)
|
||||
GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32)
|
||||
GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32)
|
||||
GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32)
|
||||
GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32)
|
||||
GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32)
|
||||
GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32)
|
||||
GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32)
|
||||
HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32)
|
||||
HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32)
|
||||
HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32)
|
||||
HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32)
|
||||
HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32)
|
||||
HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32)
|
||||
HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32)
|
||||
HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32)
|
||||
HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32)
|
||||
HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32)
|
||||
HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32)
|
||||
HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32)
|
||||
HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32)
|
||||
HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32)
|
||||
HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32)
|
||||
HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32)
|
||||
II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32)
|
||||
II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32)
|
||||
II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32)
|
||||
II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32)
|
||||
II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32)
|
||||
II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32)
|
||||
II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32)
|
||||
II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32)
|
||||
II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32)
|
||||
II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32)
|
||||
II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32)
|
||||
II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32)
|
||||
II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32)
|
||||
II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32)
|
||||
II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32)
|
||||
II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32)
|
||||
state[0] = state[0] + a
|
||||
state[1] = state[1] + b
|
||||
state[2] = state[2] + c
|
||||
state[3] = state[3] + d
|
||||
|
||||
proc md5Init*(c: var MD5Context) {.raises: [], tags: [], gcsafe.}
|
||||
proc md5Update*(c: var MD5Context, input: openArray[uint8]) {.raises: [],
|
||||
tags: [], gcsafe.}
|
||||
proc md5Final*(c: var MD5Context, digest: var MD5Digest) {.raises: [], tags: [], gcsafe.}
|
||||
|
||||
proc md5Update*(c: var MD5Context, input: cstring, len: int) {.raises: [],
|
||||
tags: [], gcsafe.} =
|
||||
## Updates the `MD5Context` with the `input` data of length `len`.
|
||||
##
|
||||
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
|
||||
## function explicitly.
|
||||
md5Update(c, input.slice(0, len - 1))
|
||||
|
||||
|
||||
proc toMD5*(s: string): MD5Digest =
|
||||
## Computes the `MD5Digest` value for a string `s`.
|
||||
##
|
||||
## **See also:**
|
||||
## * `getMD5 proc <#getMD5,string>`_ which returns a string representation
|
||||
## of the `MD5Digest`
|
||||
## * `$ proc <#$,MD5Digest>`_ for converting MD5Digest to string
|
||||
runnableExamples:
|
||||
assert $toMD5("abc") == "900150983cd24fb0d6963f7d28e17f72"
|
||||
|
||||
var c: MD5Context
|
||||
md5Init(c)
|
||||
md5Update(c, s.slice(0, s.len - 1))
|
||||
md5Final(c, result)
|
||||
|
||||
proc `$`*(d: MD5Digest): string =
|
||||
## Converts a `MD5Digest` value into its string representation.
|
||||
const digits = "0123456789abcdef"
|
||||
result = ""
|
||||
for i in 0..15:
|
||||
add(result, digits[(d[i].int shr 4) and 0xF])
|
||||
add(result, digits[d[i].int and 0xF])
|
||||
|
||||
proc getMD5*(s: string): string =
|
||||
## Computes an MD5 value of `s` and returns its string representation.
|
||||
##
|
||||
## **See also:**
|
||||
## * `toMD5 proc <#toMD5,string>`_ which returns the `MD5Digest` of a string
|
||||
runnableExamples:
|
||||
assert getMD5("abc") == "900150983cd24fb0d6963f7d28e17f72"
|
||||
|
||||
var
|
||||
c: MD5Context
|
||||
d: MD5Digest
|
||||
md5Init(c)
|
||||
md5Update(c, s.slice(0, s.len - 1))
|
||||
md5Final(c, d)
|
||||
result = $d
|
||||
|
||||
proc `==`*(D1, D2: MD5Digest): bool =
|
||||
## Checks if two `MD5Digest` values are identical.
|
||||
for i in 0..15:
|
||||
if D1[i] != D2[i]: return false
|
||||
return true
|
||||
|
||||
|
||||
proc clearBuffer(c: var MD5Context) {.inline.} =
|
||||
zeroMem(addr(c.buffer), sizeof(MD5Buffer))
|
||||
|
||||
proc md5Init*(c: var MD5Context) =
|
||||
## Initializes an `MD5Context`.
|
||||
##
|
||||
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
|
||||
## function explicitly.
|
||||
c.state[0] = 0x67452301'u32
|
||||
c.state[1] = 0xEFCDAB89'u32
|
||||
c.state[2] = 0x98BADCFE'u32
|
||||
c.state[3] = 0x10325476'u32
|
||||
c.count[0] = 0'u32
|
||||
c.count[1] = 0'u32
|
||||
clearBuffer(c)
|
||||
|
||||
proc writeBuffer(c: var MD5Context, index: int,
|
||||
input: openArray[uint8], inputIndex, len: int) {.inline.} =
|
||||
copyMem(addr(c.buffer[index]), unsafeAddr(input[inputIndex]), len)
|
||||
|
||||
proc md5Update*(c: var MD5Context, input: openArray[uint8]) =
|
||||
## Updates the `MD5Context` with the `input` data.
|
||||
##
|
||||
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
|
||||
## function explicitly.
|
||||
var Index = int((c.count[0] shr 3) and 0x3F)
|
||||
c.count[0] = c.count[0] + (uint32(input.len) shl 3)
|
||||
if c.count[0] < (uint32(input.len) shl 3): c.count[1] = c.count[1] + 1'u32
|
||||
c.count[1] = c.count[1] + (uint32(input.len) shr 29)
|
||||
var PartLen = 64 - Index
|
||||
if input.len >= PartLen:
|
||||
writeBuffer(c, Index, input, 0, PartLen)
|
||||
transform(c.buffer, c.state)
|
||||
var i = PartLen
|
||||
while i + 63 < input.len:
|
||||
transform(input.slice(i, i + 63), c.state)
|
||||
inc(i, 64)
|
||||
if i < input.len:
|
||||
writeBuffer(c, 0, input, i, input.len - i)
|
||||
elif input.len > 0:
|
||||
writeBuffer(c, Index, input, 0, input.len)
|
||||
|
||||
proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
|
||||
## Finishes the `MD5Context` and stores the result in `digest`.
|
||||
##
|
||||
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
|
||||
## function explicitly.
|
||||
var
|
||||
Bits: MD5CBits
|
||||
PadLen: int
|
||||
decode(Bits, c.count)
|
||||
var Index = int((c.count[0] shr 3) and 0x3F)
|
||||
if Index < 56: PadLen = 56 - Index
|
||||
else: PadLen = 120 - Index
|
||||
md5Update(c, padding.slice(0, PadLen - 1))
|
||||
md5Update(c, Bits)
|
||||
decode(digest, c.state)
|
||||
clearBuffer(c)
|
||||
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.pop.} #{.push styleChecks: off.}
|
||||
@@ -11,10 +11,13 @@
|
||||
## represents a complete Nim project. Single modules can either be kept in RAM
|
||||
## or stored in a rod-file.
|
||||
|
||||
import intsets, tables, hashes, md5
|
||||
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils
|
||||
import intsets, tables, hashes, md5_old, sequtils
|
||||
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils, packages
|
||||
import ic / [packed_ast, ic]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
SigHash* = distinct MD5Digest
|
||||
|
||||
@@ -64,7 +67,6 @@ type
|
||||
|
||||
startupPackedConfig*: PackedConfig
|
||||
packageSyms*: TStrTable
|
||||
modulesPerPackage*: Table[ItemId, TStrTable]
|
||||
deps*: IntSet # the dependency graph or potentially its transitive closure.
|
||||
importDeps*: Table[FileIndex, seq[FileIndex]] # explicit import module dependencies
|
||||
suggestMode*: bool # whether we are in nimsuggest mode or not.
|
||||
@@ -81,6 +83,8 @@ type
|
||||
doStopCompile*: proc(): bool {.closure.}
|
||||
usageSym*: PSym # for nimsuggest
|
||||
owners*: seq[PSym]
|
||||
suggestSymbols*: Table[FileIndex, seq[tuple[sym: PSym, info: TLineInfo]]]
|
||||
suggestErrors*: Table[FileIndex, seq[Suggest]]
|
||||
methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization!
|
||||
systemModule*: PSym
|
||||
sysTypes*: array[TTypeKind, PType]
|
||||
@@ -383,9 +387,19 @@ when defined(nimfind):
|
||||
c.graph.onDefinitionResolveForward(c.graph, s, info)
|
||||
|
||||
else:
|
||||
template onUse*(info: TLineInfo; s: PSym) = discard
|
||||
template onDef*(info: TLineInfo; s: PSym) = discard
|
||||
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
|
||||
when defined(nimsuggest):
|
||||
template onUse*(info: TLineInfo; s: PSym) = discard
|
||||
|
||||
template onDef*(info: TLineInfo; s: PSym) =
|
||||
let c = getPContext()
|
||||
if c.graph.config.suggestVersion == 3:
|
||||
suggestSym(c.graph, info, s, c.graph.usageSym)
|
||||
|
||||
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
|
||||
else:
|
||||
template onUse*(info: TLineInfo; s: PSym) = discard
|
||||
template onDef*(info: TLineInfo; s: PSym) = discard
|
||||
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
|
||||
|
||||
proc stopCompile*(g: ModuleGraph): bool {.inline.} =
|
||||
result = g.doStopCompile != nil and g.doStopCompile()
|
||||
@@ -432,8 +446,7 @@ proc initOperators*(g: ModuleGraph): Operators =
|
||||
result.opNot = createMagic(g, "not", mNot)
|
||||
result.opContains = createMagic(g, "contains", mInSet)
|
||||
|
||||
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result = ModuleGraph()
|
||||
proc initModuleGraphFields(result: ModuleGraph) =
|
||||
# A module ID of -1 means that the symbol is not attached to a module at all,
|
||||
# but to the module graph:
|
||||
result.idgen = IdGenerator(module: -1'i32, symId: 0'i32, typeId: 0'i32)
|
||||
@@ -443,9 +456,9 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result.ifaces = @[]
|
||||
result.importStack = @[]
|
||||
result.inclToMod = initTable[FileIndex, FileIndex]()
|
||||
result.config = config
|
||||
result.cache = cache
|
||||
result.owners = @[]
|
||||
result.suggestSymbols = initTable[FileIndex, seq[tuple[sym: PSym, info: TLineInfo]]]()
|
||||
result.suggestErrors = initTable[FileIndex, seq[Suggest]]()
|
||||
result.methods = @[]
|
||||
initStrTable(result.compilerprocs)
|
||||
initStrTable(result.exposed)
|
||||
@@ -459,6 +472,12 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result.operators = initOperators(result)
|
||||
result.emittedTypeInfo = initTable[string, FileIndex]()
|
||||
|
||||
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result = ModuleGraph()
|
||||
result.config = config
|
||||
result.cache = cache
|
||||
initModuleGraphFields(result)
|
||||
|
||||
proc resetAllModules*(g: ModuleGraph) =
|
||||
initStrTable(g.packageSyms)
|
||||
g.deps = initIntSet()
|
||||
@@ -470,6 +489,7 @@ proc resetAllModules*(g: ModuleGraph) =
|
||||
g.methods = @[]
|
||||
initStrTable(g.compilerprocs)
|
||||
initStrTable(g.exposed)
|
||||
initModuleGraphFields(g)
|
||||
|
||||
proc getModule*(g: ModuleGraph; fileIdx: FileIndex): PSym =
|
||||
if fileIdx.int32 >= 0:
|
||||
@@ -548,7 +568,19 @@ proc transitiveClosure(g: var IntSet; n: int) =
|
||||
|
||||
proc markDirty*(g: ModuleGraph; fileIdx: FileIndex) =
|
||||
let m = g.getModule fileIdx
|
||||
if m != nil: incl m.flags, sfDirty
|
||||
if m != nil:
|
||||
g.suggestSymbols.del(fileIdx)
|
||||
g.suggestErrors.del(fileIdx)
|
||||
incl m.flags, sfDirty
|
||||
|
||||
proc unmarkAllDirty*(g: ModuleGraph) =
|
||||
for i in 0i32..<g.ifaces.len.int32:
|
||||
let m = g.ifaces[i].module
|
||||
if m != nil:
|
||||
m.flags.excl sfDirty
|
||||
|
||||
proc isDirty*(g: ModuleGraph; m: PSym): bool =
|
||||
result = g.suggestMode and sfDirty in m.flags
|
||||
|
||||
proc markClientsDirty*(g: ModuleGraph; fileIdx: FileIndex) =
|
||||
# we need to mark its dependent modules D as dirty right away because after
|
||||
@@ -560,12 +592,26 @@ proc markClientsDirty*(g: ModuleGraph; fileIdx: FileIndex) =
|
||||
|
||||
# every module that *depends* on this file is also dirty:
|
||||
for i in 0i32..<g.ifaces.len.int32:
|
||||
let m = g.ifaces[i].module
|
||||
if m != nil and g.deps.contains(i.dependsOn(fileIdx.int)):
|
||||
incl m.flags, sfDirty
|
||||
if g.deps.contains(i.dependsOn(fileIdx.int)):
|
||||
g.markDirty(FileIndex(i))
|
||||
|
||||
proc isDirty*(g: ModuleGraph; m: PSym): bool =
|
||||
result = g.suggestMode and sfDirty in m.flags
|
||||
proc needsCompilation*(g: ModuleGraph): bool =
|
||||
# every module that *depends* on this file is also dirty:
|
||||
for i in 0i32..<g.ifaces.len.int32:
|
||||
let m = g.ifaces[i].module
|
||||
if m != nil:
|
||||
if sfDirty in m.flags:
|
||||
return true
|
||||
|
||||
proc needsCompilation*(g: ModuleGraph, fileIdx: FileIndex): bool =
|
||||
let module = g.getModule(fileIdx)
|
||||
if module != nil and g.isDirty(module):
|
||||
return true
|
||||
|
||||
for i in 0i32..<g.ifaces.len.int32:
|
||||
let m = g.ifaces[i].module
|
||||
if m != nil and g.isDirty(m) and g.deps.contains(fileIdx.int32.dependsOn(i)):
|
||||
return true
|
||||
|
||||
proc getBody*(g: ModuleGraph; s: PSym): PNode {.inline.} =
|
||||
result = s.ast[bodyPos]
|
||||
@@ -594,3 +640,28 @@ proc onProcessing*(graph: ModuleGraph, fileIdx: FileIndex, moduleStatus: string,
|
||||
let fromModule2 = if fromModule != nil: $fromModule.name.s else: "(toplevel)"
|
||||
let mode = if isNimscript: "(nims) " else: ""
|
||||
rawMessage(conf, hintProcessing, "$#$# $#: $#: $#" % [mode, indent, fromModule2, moduleStatus, path])
|
||||
|
||||
proc getPackage*(graph: ModuleGraph; fileIdx: FileIndex): PSym =
|
||||
## Returns a package symbol for yet to be defined module for fileIdx.
|
||||
## The package symbol is added to the graph if it doesn't exist.
|
||||
let pkgSym = getPackage(graph.config, graph.cache, fileIdx)
|
||||
# check if the package is already in the graph
|
||||
result = graph.packageSyms.strTableGet(pkgSym.name)
|
||||
if result == nil:
|
||||
# the package isn't in the graph, so create and add it
|
||||
result = pkgSym
|
||||
graph.packageSyms.strTableAdd(pkgSym)
|
||||
|
||||
func belongsToStdlib*(graph: ModuleGraph, sym: PSym): bool =
|
||||
## Check if symbol belongs to the 'stdlib' package.
|
||||
sym.getPackageSymbol.getPackageId == graph.systemModule.getPackageId
|
||||
|
||||
iterator suggestSymbolsIter*(g: ModuleGraph): tuple[sym: PSym, info: TLineInfo] =
|
||||
for xs in g.suggestSymbols.values:
|
||||
for x in xs.deduplicate:
|
||||
yield x
|
||||
|
||||
iterator suggestErrorsIter*(g: ModuleGraph): Suggest =
|
||||
for xs in g.suggestErrors.values:
|
||||
for x in xs:
|
||||
yield x
|
||||
|
||||
@@ -10,100 +10,6 @@
|
||||
import ast, renderer, strutils, msgs, options, idents, os, lineinfos,
|
||||
pathutils
|
||||
|
||||
when false:
|
||||
const
|
||||
considerParentDirs = not defined(noParentProjects)
|
||||
considerNimbleDirs = not defined(noNimbleDirs)
|
||||
|
||||
proc findInNimbleDir(pkg, subdir, dir: string): string =
|
||||
var best = ""
|
||||
var bestv = ""
|
||||
for k, p in os.walkDir(dir, relative=true):
|
||||
if k == pcDir and p.len > pkg.len+1 and
|
||||
p[pkg.len] == '-' and p.startsWith(pkg):
|
||||
let (_, a, _) = getPathVersionChecksum(p)
|
||||
if bestv.len == 0 or bestv < a:
|
||||
bestv = a
|
||||
best = dir / p
|
||||
|
||||
if best.len > 0:
|
||||
var f: File
|
||||
if open(f, best / changeFileExt(pkg, ".nimble-link")):
|
||||
# the second line contains what we're interested in, see:
|
||||
# https://github.com/nim-lang/nimble#nimble-link
|
||||
var override = ""
|
||||
discard readLine(f, override)
|
||||
discard readLine(f, override)
|
||||
close(f)
|
||||
if not override.isAbsolute():
|
||||
best = best / override
|
||||
else:
|
||||
best = override
|
||||
let f = if subdir.len == 0: pkg else: subdir
|
||||
let res = addFileExt(best / f, "nim")
|
||||
if best.len > 0 and fileExists(res):
|
||||
result = res
|
||||
|
||||
when false:
|
||||
proc resolveDollar(project, source, pkg, subdir: string; info: TLineInfo): string =
|
||||
template attempt(a) =
|
||||
let x = addFileExt(a, "nim")
|
||||
if fileExists(x): return x
|
||||
|
||||
case pkg
|
||||
of "stdlib":
|
||||
if subdir.len == 0:
|
||||
return options.libpath
|
||||
else:
|
||||
for candidate in stdlibDirs:
|
||||
attempt(options.libpath / candidate / subdir)
|
||||
of "root":
|
||||
let root = project.splitFile.dir
|
||||
if subdir.len == 0:
|
||||
return root
|
||||
else:
|
||||
attempt(root / subdir)
|
||||
else:
|
||||
when considerParentDirs:
|
||||
var p = parentDir(source.splitFile.dir)
|
||||
# support 'import $karax':
|
||||
let f = if subdir.len == 0: pkg else: subdir
|
||||
|
||||
while p.len > 0:
|
||||
let dir = p / pkg
|
||||
if dirExists(dir):
|
||||
attempt(dir / f)
|
||||
# 2nd attempt: try to use 'karax/karax'
|
||||
attempt(dir / pkg / f)
|
||||
# 3rd attempt: try to use 'karax/src/karax'
|
||||
attempt(dir / "src" / f)
|
||||
attempt(dir / "src" / pkg / f)
|
||||
p = parentDir(p)
|
||||
|
||||
when considerNimbleDirs:
|
||||
if not options.gNoNimblePath:
|
||||
var nimbleDir = getEnv("NIMBLE_DIR")
|
||||
if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
|
||||
result = findInNimbleDir(pkg, subdir, nimbleDir / "pkgs")
|
||||
if result.len > 0: return result
|
||||
when not defined(windows):
|
||||
result = findInNimbleDir(pkg, subdir, "/opt/nimble/pkgs")
|
||||
if result.len > 0: return result
|
||||
|
||||
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
||||
resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
||||
|
||||
proc lookupPackage(pkg, subdir: PNode): string =
|
||||
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
||||
case pkg.kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
result = scriptableImport(pkg.strVal, sub, pkg.info)
|
||||
of nkIdent:
|
||||
result = scriptableImport(pkg.ident.s, sub, pkg.info)
|
||||
else:
|
||||
localError(pkg.info, "package name must be an identifier or string literal")
|
||||
result = ""
|
||||
|
||||
proc getModuleName*(conf: ConfigRef; n: PNode): string =
|
||||
# This returns a short relative module name without the nim extension
|
||||
# e.g. like "system", "importer" or "somepath/module"
|
||||
@@ -163,3 +69,18 @@ proc checkModuleName*(conf: ConfigRef; n: PNode; doLocalError=true): FileIndex =
|
||||
result = InvalidFileIdx
|
||||
else:
|
||||
result = fileInfoIdx(conf, fullPath)
|
||||
|
||||
proc mangleModuleName*(conf: ConfigRef; path: AbsoluteFile): string =
|
||||
## Mangle a relative module path to avoid path and symbol collisions.
|
||||
##
|
||||
## Used by backends that need to generate intermediary files from Nim modules.
|
||||
## This is needed because the compiler uses a flat cache file hierarchy.
|
||||
##
|
||||
## Example:
|
||||
## `foo-#head/../bar` becomes `@foo-@hhead@s..@sbar`
|
||||
"@m" & relativeTo(path, conf.projectPath).string.multiReplace(
|
||||
{$os.DirSep: "@s", $os.AltSep: "@s", "#": "@h", "@": "@@", ":": "@c"})
|
||||
|
||||
proc demangleModuleName*(path: string): string =
|
||||
## Demangle a relative module path.
|
||||
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
import
|
||||
ast, astalgo, magicsys, msgs, options,
|
||||
idents, lexer, passes, syntaxes, llstream, modulegraphs,
|
||||
lineinfos, pathutils, tables
|
||||
lineinfos, pathutils, tables, packages
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
import ic / replayer
|
||||
|
||||
@@ -22,56 +25,11 @@ proc resetSystemArtifacts*(g: ModuleGraph) =
|
||||
template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
|
||||
getIdent(graph.cache, splitFile(filename).name)
|
||||
|
||||
template packageId(): untyped {.dirty.} = ItemId(module: PackageModuleId, item: int32(fileIdx))
|
||||
|
||||
proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym =
|
||||
## returns package symbol (skPackage) for yet to be defined module for fileIdx
|
||||
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
|
||||
let name = getModuleIdent(graph, filename)
|
||||
let info = newLineInfo(fileIdx, 1, 1)
|
||||
let
|
||||
pck = getPackageName(graph.config, filename.string)
|
||||
pck2 = if pck.len > 0: pck else: "unknown"
|
||||
pack = getIdent(graph.cache, pck2)
|
||||
result = graph.packageSyms.strTableGet(pack)
|
||||
if result == nil:
|
||||
result = newSym(skPackage, getIdent(graph.cache, pck2), packageId(), nil, info)
|
||||
#initStrTable(packSym.tab)
|
||||
graph.packageSyms.strTableAdd(result)
|
||||
else:
|
||||
let modules = graph.modulesPerPackage.getOrDefault(result.itemId)
|
||||
let existing = if modules.data.len > 0: strTableGet(modules, name) else: nil
|
||||
if existing != nil and existing.info.fileIndex != info.fileIndex:
|
||||
when false:
|
||||
# we used to produce an error:
|
||||
localError(graph.config, info,
|
||||
"module names need to be unique per Nimble package; module clashes with " &
|
||||
toFullPath(graph.config, existing.info.fileIndex))
|
||||
else:
|
||||
# but starting with version 0.20 we now produce a fake Nimble package instead
|
||||
# to resolve the conflicts:
|
||||
let pck3 = fakePackageName(graph.config, filename)
|
||||
# this makes the new `result`'s owner be the original `result`
|
||||
result = newSym(skPackage, getIdent(graph.cache, pck3), packageId(), result, info)
|
||||
#initStrTable(packSym.tab)
|
||||
graph.packageSyms.strTableAdd(result)
|
||||
|
||||
proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
|
||||
let packSym = getPackage(graph, fileIdx)
|
||||
result.owner = packSym
|
||||
result.position = int fileIdx
|
||||
|
||||
#initStrTable(result.tab(graph))
|
||||
when false:
|
||||
strTableAdd(result.tab, result) # a module knows itself
|
||||
# This is now implemented via
|
||||
# c.moduleScope.addSym(module) # a module knows itself
|
||||
# in sem.nim, around line 527
|
||||
|
||||
if graph.modulesPerPackage.getOrDefault(packSym.itemId).data.len == 0:
|
||||
graph.modulesPerPackage[packSym.itemId] = newStrTable()
|
||||
graph.modulesPerPackage[packSym.itemId].strTableAdd(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
|
||||
@@ -133,7 +91,7 @@ proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
|
||||
# localError(result.info, errAttemptToRedefine, result.name.s)
|
||||
# restore the notes for outer module:
|
||||
graph.config.notes =
|
||||
if s.getnimblePkgId == graph.config.mainPackageId or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
|
||||
if graph.config.belongsToProjectPackage(s) or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
|
||||
else: graph.config.foreignPackageNotes
|
||||
|
||||
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
|
||||
@@ -168,7 +126,7 @@ proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
|
||||
conf.projectMainIdx2 = projectFile
|
||||
|
||||
let packSym = getPackage(graph, projectFile)
|
||||
graph.config.mainPackageId = packSym.getnimblePkgId
|
||||
graph.config.mainPackageId = packSym.getPackageId
|
||||
graph.importStack.add projectFile
|
||||
|
||||
if projectFile == systemFileIdx:
|
||||
|
||||
@@ -12,6 +12,10 @@ import
|
||||
std/private/miscdollars,
|
||||
options, ropes, lineinfos, pathutils, strutils2
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
|
||||
type InstantiationInfo* = typeof(instantiationInfo())
|
||||
template instLoc*(): InstantiationInfo = instantiationInfo(-2, fullPaths = true)
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
import ast, msgs, ropes, options, pathutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
type
|
||||
NdiFile* = object
|
||||
enabled: bool
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
import ast, renderer, intsets, tables, msgs, options, lineinfos, strformat, idents, treetab, hashes
|
||||
import sequtils, strutils, sets
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
# IMPORTANT: notes not up to date, i'll update this comment again
|
||||
#
|
||||
# notes:
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#
|
||||
|
||||
import std/[os, strutils, parseopt]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when defined(windows) and not defined(nimKochBootstrap):
|
||||
# remove workaround pending bootstrap >= 1.5.1
|
||||
# refs https://github.com/nim-lang/Nim/issues/18334#issuecomment-867114536
|
||||
@@ -116,7 +120,8 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
|
||||
if cmdPrefix.len > 0: cmdPrefix.add " "
|
||||
# without the `cmdPrefix.len > 0` check, on windows you'd get a cryptic:
|
||||
# `The parameter is incorrect`
|
||||
execExternalProgram(conf, cmdPrefix & output.quoteShell & ' ' & conf.arguments)
|
||||
let cmd = cmdPrefix & output.quoteShell & ' ' & conf.arguments
|
||||
execExternalProgram(conf, cmd.strip(leading=false,trailing=true))
|
||||
of cmdDocLike, cmdRst2html, cmdRst2tex: # bugfix(cmdRst2tex was missing)
|
||||
if conf.arguments.len > 0:
|
||||
# reserved for future use
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
import parseutils, strutils, os, options, msgs, sequtils, lineinfos, pathutils,
|
||||
std/sha1, tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
proc addPath*(conf: ConfigRef; path: AbsoluteDir, info: TLineInfo) =
|
||||
if not conf.searchPaths.contains(path):
|
||||
conf.searchPaths.insert(path, 0)
|
||||
|
||||
@@ -13,6 +13,9 @@ import
|
||||
llstream, commands, os, strutils, msgs, lexer, ast,
|
||||
options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
# ---------------- configuration file parser -----------------------------
|
||||
# we use Nim's lexer here to save space and work
|
||||
|
||||
@@ -298,7 +301,7 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen:
|
||||
if conf.cmd == cmdNimscript:
|
||||
showHintConf()
|
||||
conf.configFiles.setLen 0
|
||||
if conf.cmd != cmdIdeTools:
|
||||
if conf.cmd notin {cmdIdeTools, cmdCheck, cmdDump}:
|
||||
if conf.cmd == cmdNimscript:
|
||||
runNimScriptIfExists(conf.projectFull, isMain = true)
|
||||
else:
|
||||
@@ -308,5 +311,6 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen:
|
||||
runNimScriptIfExists(scriptFile, isMain = true)
|
||||
else:
|
||||
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
|
||||
# `nim check foo.nims' means to check the syntax of the NimScript file
|
||||
discard
|
||||
showHintConf()
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
import
|
||||
llstream, strutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
Lrz* = ' '
|
||||
Apo* = '\''
|
||||
|
||||
@@ -19,13 +19,19 @@ Unstable API
|
||||
|
||||
import os, strutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
|
||||
const
|
||||
docCss* = "$nimr/doc/nimdoc.css"
|
||||
docCls* = "$nimr/doc/nimdoc.cls"
|
||||
docHackNim* = "$nimr/tools/dochack/dochack.nim"
|
||||
docHackJs* = docHackNim.changeFileExt("js")
|
||||
docHackJsFname* = docHackJs.lastPathPart
|
||||
theindexFname* = "theindex.html"
|
||||
nimdocOutCss* = "nimdoc.out.css"
|
||||
nimdocOutCls* = "nimdoc.cls"
|
||||
# `out` to make it easier to use with gitignore in user's repos
|
||||
htmldocsDirname* = "htmldocs"
|
||||
dotdotMangle* = "_._" ## refs #13223
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
import
|
||||
ast, astalgo, lineinfos, bitsets, types, options
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc inSet*(s: PNode, elem: PNode): bool =
|
||||
assert s.kind == nkCurly
|
||||
if s.kind != nkCurly:
|
||||
|
||||
@@ -127,11 +127,11 @@ proc analyse(c: var Con; b: var BasicBlock; n: PNode) =
|
||||
for i in 0 ..< n.len:
|
||||
analyse(c, b, n[i])
|
||||
else:
|
||||
#[ Test tmatrix.test3:
|
||||
#[ Test destructor/tmatrix.test3:
|
||||
Prevent this from being elided. We should probably
|
||||
find a better solution...
|
||||
|
||||
`=sink`(b, - (
|
||||
`=sink`(b, -
|
||||
let blitTmp = b;
|
||||
wasMoved(b);
|
||||
blitTmp + a)
|
||||
|
||||
@@ -14,12 +14,17 @@ import
|
||||
from terminal import isatty
|
||||
from times import utc, fromUnix, local, getTime, format, DateTime
|
||||
from std/private/globs import nativeToUnixPath
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
|
||||
const
|
||||
hasTinyCBackend* = defined(tinyc)
|
||||
useEffectSystem* = true
|
||||
useWriteTracking* = false
|
||||
hasFFI* = defined(nimHasLibFFI)
|
||||
copyrightYear* = "2021"
|
||||
copyrightYear* = "2022"
|
||||
|
||||
nimEnableCovariance* = defined(nimEnableCovariance)
|
||||
|
||||
@@ -96,6 +101,7 @@ type # please make sure we have under 32 options
|
||||
optPanics # turn panics (sysFatal) into a process termination
|
||||
optNimV1Emulation # emulate Nim v1.0
|
||||
optNimV12Emulation # emulate Nim v1.2
|
||||
optNimV16Emulation # emulate Nim v1.6
|
||||
optSourcemap
|
||||
optProfileVM # enable VM profiler
|
||||
optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
|
||||
@@ -177,14 +183,14 @@ type
|
||||
gcMarkAndSweep = "markAndSweep"
|
||||
gcHooks = "hooks"
|
||||
gcRefc = "refc"
|
||||
gcV2 = "v2"
|
||||
gcGo = "go"
|
||||
# gcRefc and the GCs that follow it use a write barrier,
|
||||
# as far as usesWriteBarrier() is concerned
|
||||
|
||||
IdeCmd* = enum
|
||||
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
|
||||
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject
|
||||
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
|
||||
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
|
||||
ideRecompile, ideChanged
|
||||
|
||||
Feature* = enum ## experimental features; DO NOT RENAME THESE!
|
||||
implicitDeref,
|
||||
@@ -195,7 +201,7 @@ type
|
||||
notnil,
|
||||
dynamicBindSym,
|
||||
forLoopMacros, # not experimental anymore; remains here for backwards compatibility
|
||||
caseStmtMacros,
|
||||
caseStmtMacros, # ditto
|
||||
codeReordering,
|
||||
compiletimeFFI,
|
||||
## This requires building nim with `-d:nimHasLibFFI`
|
||||
@@ -207,7 +213,8 @@ type
|
||||
strictNotNil,
|
||||
overloadableEnums,
|
||||
strictEffects,
|
||||
unicodeOperators
|
||||
unicodeOperators,
|
||||
flexibleOptionalParams
|
||||
|
||||
LegacyFeature* = enum
|
||||
allowSemcheckedAstModification,
|
||||
@@ -389,6 +396,7 @@ type
|
||||
structuredErrorHook*: proc (config: ConfigRef; info: TLineInfo; msg: string;
|
||||
severity: Severity) {.closure, gcsafe.}
|
||||
cppCustomNamespace*: string
|
||||
nimMainPrefix*: string
|
||||
vmProfileData*: ProfileData
|
||||
|
||||
proc parseNimVersion*(a: string): NimVer =
|
||||
@@ -595,7 +603,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||
osQnx, osAtari, osAix,
|
||||
osHaiku, osVxWorks, osSolaris, osNetbsd,
|
||||
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
|
||||
osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos}
|
||||
osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr}
|
||||
of "linux":
|
||||
result = conf.target.targetOS in {osLinux, osAndroid}
|
||||
of "bsd":
|
||||
@@ -615,6 +623,8 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||
result = conf.target.targetOS == osNintendoSwitch
|
||||
of "freertos", "lwip":
|
||||
result = conf.target.targetOS == osFreeRTOS
|
||||
of "zephyr":
|
||||
result = conf.target.targetOS == osZephyr
|
||||
of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian
|
||||
of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian
|
||||
of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
|
||||
@@ -797,6 +807,8 @@ proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
|
||||
|
||||
proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
|
||||
createSubDir: bool = true): AbsoluteFile =
|
||||
## Return an absolute path of a generated intermediary file.
|
||||
## Optionally creates the cache directory if `createSubDir` is `true`.
|
||||
let subdir = getNimcacheDir(conf)
|
||||
if createSubDir:
|
||||
try:
|
||||
@@ -804,11 +816,6 @@ proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
|
||||
except OSError:
|
||||
conf.quitOrRaise "cannot create directory: " & subdir.string
|
||||
result = subdir / RelativeFile f.string.splitPath.tail
|
||||
#echo "completeGeneratedFilePath(", f, ") = ", result
|
||||
|
||||
proc toRodFile*(conf: ConfigRef; f: AbsoluteFile; ext = RodExt): AbsoluteFile =
|
||||
result = changeFileExt(completeGeneratedFilePath(conf,
|
||||
withPackageName(conf, f)), ext)
|
||||
|
||||
proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
|
||||
for it in conf.searchPaths:
|
||||
@@ -987,12 +994,16 @@ proc parseIdeCmd*(s: string): IdeCmd =
|
||||
of "use": ideUse
|
||||
of "dus": ideDus
|
||||
of "chk": ideChk
|
||||
of "chkFile": ideChkFile
|
||||
of "mod": ideMod
|
||||
of "highlight": ideHighlight
|
||||
of "outline": ideOutline
|
||||
of "known": ideKnown
|
||||
of "msg": ideMsg
|
||||
of "project": ideProject
|
||||
of "globalSymbols": ideGlobalSymbols
|
||||
of "recompile": ideRecompile
|
||||
of "changed": ideChanged
|
||||
else: ideNone
|
||||
|
||||
proc `$`*(c: IdeCmd): string =
|
||||
@@ -1003,6 +1014,7 @@ proc `$`*(c: IdeCmd): string =
|
||||
of ideUse: "use"
|
||||
of ideDus: "dus"
|
||||
of ideChk: "chk"
|
||||
of ideChkFile: "chkFile"
|
||||
of ideMod: "mod"
|
||||
of ideNone: "none"
|
||||
of ideHighlight: "highlight"
|
||||
@@ -1010,6 +1022,9 @@ proc `$`*(c: IdeCmd): string =
|
||||
of ideKnown: "known"
|
||||
of ideMsg: "msg"
|
||||
of ideProject: "project"
|
||||
of ideGlobalSymbols: "globalSymbols"
|
||||
of ideRecompile: "recompile"
|
||||
of ideChanged: "changed"
|
||||
|
||||
proc floatInt64Align*(conf: ConfigRef): int16 =
|
||||
## Returns either 4 or 8 depending on reasons.
|
||||
|
||||
@@ -37,24 +37,7 @@ proc getNimbleFile*(conf: ConfigRef; path: string): string =
|
||||
proc getPackageName*(conf: ConfigRef; path: string): string =
|
||||
## returns nimble package name, e.g.: `cligen`
|
||||
let path = getNimbleFile(conf, path)
|
||||
result = path.splitFile.name
|
||||
|
||||
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
|
||||
# Convert `path` so that 2 modules with same name
|
||||
# in different directory get different name and they can be
|
||||
# placed in a directory.
|
||||
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
|
||||
result = "@m" & relativeTo(path, conf.projectPath).string.multiReplace(
|
||||
{$os.DirSep: "@s", $os.AltSep: "@s", "#": "@h", "@": "@@", ":": "@c"})
|
||||
|
||||
proc demanglePackageName*(path: string): string =
|
||||
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
|
||||
|
||||
proc withPackageName*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
|
||||
let x = getPackageName(conf, path.string)
|
||||
let (p, file, ext) = path.splitFile
|
||||
if x == "stdlib":
|
||||
# Hot code reloading now relies on 'stdlib_system' names etc.
|
||||
result = p / RelativeFile((x & '_' & file) & ext)
|
||||
if path.len > 0:
|
||||
return path.splitFile.name
|
||||
else:
|
||||
result = p / RelativeFile(fakePackageName(conf, path))
|
||||
return "unknown"
|
||||
|
||||
49
compiler/packages.nim
Normal file
49
compiler/packages.nim
Normal file
@@ -0,0 +1,49 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2022 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Package related procs.
|
||||
##
|
||||
## See Also:
|
||||
## * `packagehandling` for package path handling
|
||||
## * `modulegraphs.getPackage`
|
||||
## * `modulegraphs.belongsToStdlib`
|
||||
|
||||
import "." / [options, ast, lineinfos, idents, pathutils, msgs]
|
||||
|
||||
proc getPackage*(conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex): PSym =
|
||||
## Return a new package symbol.
|
||||
##
|
||||
## See Also:
|
||||
## * `modulegraphs.getPackage`
|
||||
let
|
||||
filename = AbsoluteFile toFullPath(conf, fileIdx)
|
||||
name = getIdent(cache, splitFile(filename).name)
|
||||
info = newLineInfo(fileIdx, 1, 1)
|
||||
pkgName = getPackageName(conf, filename.string)
|
||||
pkgIdent = getIdent(cache, pkgName)
|
||||
newSym(skPackage, pkgIdent, ItemId(module: PackageModuleId, item: int32(fileIdx)), nil, info)
|
||||
|
||||
func getPackageSymbol*(sym: PSym): PSym =
|
||||
## Return the owning package symbol.
|
||||
assert sym != nil
|
||||
result = sym
|
||||
while result.kind != skPackage:
|
||||
result = result.owner
|
||||
assert result != nil, repr(sym.info)
|
||||
|
||||
func getPackageId*(sym: PSym): int =
|
||||
## Return the owning package ID.
|
||||
sym.getPackageSymbol.id
|
||||
|
||||
func belongsToProjectPackage*(conf: ConfigRef, sym: PSym): bool =
|
||||
## Return whether the symbol belongs to the project's package.
|
||||
##
|
||||
## See Also:
|
||||
## * `modulegraphs.belongsToStdlib`
|
||||
conf.mainPackageId == sym.getPackageId
|
||||
@@ -143,8 +143,11 @@ proc checkForSideEffects*(n: PNode): TSideEffectAnalysis =
|
||||
let s = op.sym
|
||||
if sfSideEffect in s.flags:
|
||||
return seSideEffect
|
||||
# assume no side effect:
|
||||
result = seNoSideEffect
|
||||
elif tfNoSideEffect in op.typ.flags:
|
||||
result = seNoSideEffect
|
||||
else:
|
||||
# assume side effect:
|
||||
result = seSideEffect
|
||||
elif tfNoSideEffect in op.typ.flags:
|
||||
# indirect call without side effects:
|
||||
result = seNoSideEffect
|
||||
@@ -176,6 +179,7 @@ type
|
||||
arLocalLValue, # is an l-value, but local var; must not escape
|
||||
# its stack frame!
|
||||
arDiscriminant, # is a discriminant
|
||||
arAddressableConst, # an addressable const
|
||||
arLentValue, # lent value
|
||||
arStrange # it is a strange beast like 'typedesc[var T]'
|
||||
|
||||
@@ -209,7 +213,7 @@ proc exprRoot*(n: PNode): PSym =
|
||||
else:
|
||||
break
|
||||
|
||||
proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult =
|
||||
proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
## 'owner' can be nil!
|
||||
result = arNone
|
||||
case n.kind
|
||||
@@ -217,20 +221,20 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||
if n.typ != nil and n.typ.kind in {tyVar}:
|
||||
result = arLValue
|
||||
of nkSym:
|
||||
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
|
||||
else: {skVar, skResult, skTemp}
|
||||
if n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and n.sym.kind == skParam:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and n.sym.kind == skConst and dontInlineConstant(n, n.sym.ast):
|
||||
result = arLValue
|
||||
const kinds = {skVar, skResult, skTemp, skParam, skLet, skForVar}
|
||||
if n.sym.kind == skParam:
|
||||
result = if n.sym.typ.kind in {tyVar, tySink}: arLValue else: arAddressableConst
|
||||
elif n.sym.kind == skConst and dontInlineConstant(n, n.sym.ast):
|
||||
result = arAddressableConst
|
||||
elif n.sym.kind in kinds:
|
||||
if owner != nil and owner == n.sym.owner and
|
||||
sfGlobal notin n.sym.flags:
|
||||
result = arLocalLValue
|
||||
if n.sym.kind in {skParam, skLet, skForVar}:
|
||||
result = arAddressableConst
|
||||
else:
|
||||
result = arLValue
|
||||
if owner != nil and owner == n.sym.owner and
|
||||
sfGlobal notin n.sym.flags:
|
||||
result = arLocalLValue
|
||||
else:
|
||||
result = arLValue
|
||||
elif n.sym.kind == skType:
|
||||
let t = n.sym.typ.skipTypes({tyTypeDesc})
|
||||
if t.kind in {tyVar}: result = arStrange
|
||||
@@ -238,10 +242,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and t.kind == tyLent:
|
||||
result = arLValue
|
||||
elif t.kind == tyLent:
|
||||
result = arAddressableConst
|
||||
else:
|
||||
result = isAssignable(owner, n[0], isUnsafeAddr)
|
||||
result = isAssignable(owner, n[0])
|
||||
if result != arNone and n[1].kind == nkSym and
|
||||
sfDiscriminant in n[1].sym.flags:
|
||||
result = arDiscriminant
|
||||
@@ -249,23 +253,23 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and t.kind == tyLent:
|
||||
result = arLValue
|
||||
elif t.kind == tyLent:
|
||||
result = arAddressableConst
|
||||
else:
|
||||
result = isAssignable(owner, n[0], isUnsafeAddr)
|
||||
result = isAssignable(owner, n[0])
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
# Object and tuple conversions are still addressable, so we skip them
|
||||
# XXX why is 'tyOpenArray' allowed here?
|
||||
if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in
|
||||
{tyOpenArray, tyTuple, tyObject}:
|
||||
result = isAssignable(owner, n[1], isUnsafeAddr)
|
||||
result = isAssignable(owner, n[1])
|
||||
elif compareTypes(n.typ, n[1].typ, dcEqIgnoreDistinct):
|
||||
# types that are equal modulo distinction preserve l-value:
|
||||
result = isAssignable(owner, n[1], isUnsafeAddr)
|
||||
result = isAssignable(owner, n[1])
|
||||
of nkHiddenDeref:
|
||||
let n0 = n[0]
|
||||
if n0.typ.kind == tyLent:
|
||||
if isUnsafeAddr or (n0.kind == nkSym and n0.sym.kind == skResult):
|
||||
if n0.kind == nkSym and n0.sym.kind == skResult:
|
||||
result = arLValue
|
||||
else:
|
||||
result = arLentValue
|
||||
@@ -274,18 +278,19 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||
of nkDerefExpr, nkHiddenAddr:
|
||||
result = arLValue
|
||||
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
||||
result = isAssignable(owner, n[0], isUnsafeAddr)
|
||||
result = isAssignable(owner, n[0])
|
||||
of nkCallKinds:
|
||||
# builtin slice keeps lvalue-ness:
|
||||
if getMagic(n) in {mArrGet, mSlice}:
|
||||
result = isAssignable(owner, n[1], isUnsafeAddr)
|
||||
elif n.typ != nil and n.typ.kind in {tyVar}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and n.typ != nil and n.typ.kind == tyLent:
|
||||
result = arLValue
|
||||
result = isAssignable(owner, n[1])
|
||||
elif n.typ != nil:
|
||||
case n.typ.kind
|
||||
of tyVar: result = arLValue
|
||||
of tyLent: result = arLentValue
|
||||
else: discard
|
||||
of nkStmtList, nkStmtListExpr:
|
||||
if n.typ != nil:
|
||||
result = isAssignable(owner, n.lastSon, isUnsafeAddr)
|
||||
result = isAssignable(owner, n.lastSon)
|
||||
of nkVarTy:
|
||||
# XXX: The fact that this is here is a bit of a hack.
|
||||
# The goal is to allow the use of checks such as "foo(var T)"
|
||||
|
||||
@@ -36,6 +36,9 @@ import
|
||||
when defined(nimpretty):
|
||||
import layouter
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
Parser* = object # A Parser object represents a file that
|
||||
# is being parsed
|
||||
@@ -582,10 +585,10 @@ proc parsePar(p: var Parser): PNode =
|
||||
#| | 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
|
||||
#| | 'when' | 'var' | 'mixin'
|
||||
#| par = '(' optInd
|
||||
#| ( &parKeyw (ifExpr \ complexOrSimpleStmt) ^+ ';'
|
||||
#| | ';' (ifExpr \ complexOrSimpleStmt) ^+ ';'
|
||||
#| ( &parKeyw (ifExpr / complexOrSimpleStmt) ^+ ';'
|
||||
#| | ';' (ifExpr / complexOrSimpleStmt) ^+ ';'
|
||||
#| | pragmaStmt
|
||||
#| | simpleExpr ( ('=' expr (';' (ifExpr \ complexOrSimpleStmt) ^+ ';' )? )
|
||||
#| | simpleExpr ( ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
|
||||
#| | (':' expr (',' exprColonEqExpr ^+ ',' )? ) ) )
|
||||
#| optPar ')'
|
||||
#
|
||||
@@ -811,7 +814,7 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
#| | DOTLIKEOP optInd symbol generalizedLit?
|
||||
#| | '[' optInd exprColonEqExprList optPar ']'
|
||||
#| | '{' optInd exprColonEqExprList optPar '}'
|
||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
|
||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr (comma expr)* # command syntax
|
||||
result = r
|
||||
|
||||
# progress guaranteed
|
||||
@@ -821,14 +824,14 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
of tkParLe:
|
||||
# progress guaranteed
|
||||
if p.tok.strongSpaceA > 0:
|
||||
# inside type sections, expressions such as `ref (int, bar)`
|
||||
# are parsed as a nkCommand with a single tuple argument (nkPar)
|
||||
result = commandExpr(p, result, mode)
|
||||
# type sections allow full command syntax
|
||||
if mode == pmTypeDef:
|
||||
result = newNodeP(nkCommand, p)
|
||||
result.add r
|
||||
result.add primary(p, pmNormal)
|
||||
else:
|
||||
result = commandExpr(p, result, mode)
|
||||
var isFirstParam = false
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, mode))
|
||||
break
|
||||
result = namedParams(p, result, nkCall, tkParRi)
|
||||
if result.len > 1 and result[1].kind == nkExprColonExpr:
|
||||
@@ -869,9 +872,18 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
# actually parsing {.push hints:off.} as {.push(hints:off).} is a sweet
|
||||
# solution, but pragmas.nim can't handle that
|
||||
result = commandExpr(p, result, mode)
|
||||
if mode == pmTypeDef:
|
||||
var isFirstParam = false
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, mode))
|
||||
break
|
||||
else:
|
||||
break
|
||||
# type sections allow post-expr blocks
|
||||
if mode == pmTypeDef:
|
||||
result = postExprBlocks(p, result)
|
||||
|
||||
proc parseOperators(p: var Parser, headNode: PNode,
|
||||
limit: int, mode: PrimaryMode): PNode =
|
||||
@@ -1110,11 +1122,14 @@ proc optPragmas(p: var Parser): PNode =
|
||||
|
||||
proc parseDoBlock(p: var Parser; info: TLineInfo): PNode =
|
||||
#| doBlock = 'do' paramListArrow pragma? colcom stmt
|
||||
let params = parseParamList(p, retColon=false)
|
||||
var params = parseParamList(p, retColon=false)
|
||||
let pragmas = optPragmas(p)
|
||||
colcom(p, result)
|
||||
result = parseStmt(p)
|
||||
if params.kind != nkEmpty:
|
||||
if params.kind != nkEmpty or pragmas.kind != nkEmpty:
|
||||
if params.kind == nkEmpty:
|
||||
params = newNodeP(nkFormalParams, p)
|
||||
params.add(p.emptyNode) # return type
|
||||
result = newProcNode(nkDo, info,
|
||||
body = result, params = params, name = p.emptyNode, pattern = p.emptyNode,
|
||||
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
|
||||
@@ -1146,7 +1161,7 @@ proc isExprStart(p: Parser): bool =
|
||||
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkFor,
|
||||
tkProc, tkFunc, tkIterator, tkBind, tkBuiltInMagics,
|
||||
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCustomLit, tkVar, tkRef, tkPtr,
|
||||
tkTuple, tkObject, tkWhen, tkCase, tkOut:
|
||||
tkTuple, tkObject, tkWhen, tkCase, tkOut, tkTry, tkBlock:
|
||||
result = true
|
||||
else: result = false
|
||||
|
||||
@@ -1339,7 +1354,8 @@ proc parseTypeDesc(p: var Parser): PNode =
|
||||
result = binaryNot(p, result)
|
||||
|
||||
proc parseTypeDefAux(p: var Parser): PNode =
|
||||
#| typeDefAux = simpleExpr ('not' expr)?
|
||||
#| typeDefAux = simpleExpr ('not' expr
|
||||
#| | postExprBlocks)?
|
||||
result = simpleExpr(p, pmTypeDef)
|
||||
result = binaryNot(p, result)
|
||||
|
||||
@@ -1381,7 +1397,10 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
if stmtList[0].kind == nkStmtList: stmtList = stmtList[0]
|
||||
|
||||
stmtList.flags.incl nfBlockArg
|
||||
if openingParams.kind != nkEmpty:
|
||||
if openingParams.kind != nkEmpty or openingPragmas.kind != nkEmpty:
|
||||
if openingParams.kind == nkEmpty:
|
||||
openingParams = newNodeP(nkFormalParams, p)
|
||||
openingParams.add(p.emptyNode) # return type
|
||||
result.add newProcNode(nkDo, stmtList.info, body = stmtList,
|
||||
params = openingParams,
|
||||
name = p.emptyNode, pattern = p.emptyNode,
|
||||
@@ -1877,7 +1896,7 @@ proc parseEnum(p: var Parser): PNode =
|
||||
|
||||
var symPragma = a
|
||||
var pragma: PNode
|
||||
if p.tok.tokType == tkCurlyDotLe:
|
||||
if (p.tok.indent < 0 or p.tok.indent >= p.currInd) and p.tok.tokType == tkCurlyDotLe:
|
||||
pragma = optPragmas(p)
|
||||
symPragma = newNodeP(nkPragmaExpr, p)
|
||||
symPragma.add(a)
|
||||
@@ -2374,6 +2393,10 @@ proc parseAll(p: var Parser): PNode =
|
||||
if p.tok.indent != 0:
|
||||
parMessage(p, errInvalidIndentation)
|
||||
|
||||
proc checkFirstLineIndentation*(p: var Parser) =
|
||||
if p.tok.indent != 0 and p.tok.strongSpaceA > 0:
|
||||
parMessage(p, errInvalidIndentation)
|
||||
|
||||
proc parseTopLevelStmt(p: var Parser): PNode =
|
||||
## Implements an iterator which, when called repeatedly, returns the next
|
||||
## top-level statement or emptyNode if end of stream.
|
||||
|
||||
@@ -14,7 +14,10 @@ import
|
||||
options, ast, llstream, msgs,
|
||||
idents,
|
||||
syntaxes, modulegraphs, reorder,
|
||||
lineinfos, pathutils
|
||||
lineinfos, pathutils, std/sha1, packages
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
type
|
||||
TPassData* = tuple[input: PNode, closeOutput: PNode]
|
||||
@@ -101,7 +104,7 @@ const
|
||||
|
||||
proc prepareConfigNotes(graph: ModuleGraph; module: PSym) =
|
||||
# don't be verbose unless the module belongs to the main package:
|
||||
if module.getnimblePkgId == graph.config.mainPackageId:
|
||||
if graph.config.belongsToProjectPackage(module):
|
||||
graph.config.notes = graph.config.mainPackageNotes
|
||||
else:
|
||||
if graph.config.mainPackageNotes == {}: graph.config.mainPackageNotes = graph.config.notes
|
||||
@@ -111,12 +114,6 @@ proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
|
||||
result = true
|
||||
#module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange")
|
||||
|
||||
proc partOfStdlib(x: PSym): bool =
|
||||
var it = x.owner
|
||||
while it != nil and it.kind == skPackage and it.owner != nil:
|
||||
it = it.owner
|
||||
result = it != nil and it.name.s == "stdlib"
|
||||
|
||||
proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
|
||||
stream: PLLStream): bool {.discardable.} =
|
||||
if graph.stopCompile(): return true
|
||||
@@ -135,10 +132,15 @@ proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
|
||||
return false
|
||||
else:
|
||||
s = stream
|
||||
|
||||
when defined(nimsuggest):
|
||||
let filename = toFullPathConsiderDirty(graph.config, fileIdx).string
|
||||
msgs.setHash(graph.config, fileIdx, $sha1.secureHashFile(filename))
|
||||
|
||||
while true:
|
||||
openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
if not partOfStdlib(module) or module.name.s == "distros":
|
||||
if not belongsToStdlib(graph, module) or (belongsToStdlib(graph, module) and module.name.s == "distros"):
|
||||
# XXX what about caching? no processing then? what if I change the
|
||||
# modules to include between compilation runs? we'd need to track that
|
||||
# in ROD files. I think we should enable this feature only
|
||||
@@ -147,6 +149,7 @@ proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
|
||||
processImplicits graph, graph.config.implicitImports, nkImportStmt, a, module
|
||||
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module
|
||||
|
||||
checkFirstLineIndentation(p)
|
||||
while true:
|
||||
if graph.stopCompile(): break
|
||||
var n = parseTopLevelStmt(p)
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
|
||||
import os, pathnorm
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
type
|
||||
AbsoluteFile* = distinct string
|
||||
AbsoluteDir* = distinct string
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
import
|
||||
ast, types, semdata, sigmatch, idents, aliases, parampatterns, trees
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
TPatternContext = object
|
||||
owner: PSym
|
||||
|
||||
@@ -16,13 +16,17 @@
|
||||
import
|
||||
strutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
|
||||
type
|
||||
TSystemOS* = enum # Also add OS in initialization section and alias
|
||||
# conditionals to condsyms (end of module).
|
||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osCrossos, osAix, osPalmos, osQnx,
|
||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
|
||||
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osAny
|
||||
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osZephyr, osAny
|
||||
|
||||
type
|
||||
TInfoOSProp* = enum
|
||||
@@ -185,6 +189,10 @@ const
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospPosix}),
|
||||
(name: "Zephyr", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospPosix}),
|
||||
(name: "Any", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
@@ -197,7 +205,8 @@ type
|
||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||
cpuPowerpc64el, cpuSparc, cpuVm, cpuHppa, cpuIa64, cpuAmd64, cpuMips,
|
||||
cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430,
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32,
|
||||
cpuE2k, cpuLoongArch64
|
||||
|
||||
type
|
||||
TInfoCPU* = tuple[name: string, intSize: int, endian: Endianness,
|
||||
@@ -232,7 +241,9 @@ const
|
||||
(name: "riscv32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "esp", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "wasm32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32)]
|
||||
(name: "wasm32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
|
||||
(name: "e2k", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "loongarch64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)]
|
||||
|
||||
type
|
||||
Target* = object
|
||||
|
||||
@@ -14,6 +14,9 @@ import
|
||||
wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees,
|
||||
types, lookups, lineinfos, pathutils, linter
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
from ic / ic import addCompilerProc
|
||||
|
||||
const
|
||||
@@ -31,7 +34,7 @@ const
|
||||
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
|
||||
wGensym, wInject, wRaises, wEffectsOf, wTags, wLocks, wDelegator, wGcSafe,
|
||||
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy,
|
||||
wRequires, wEnsures}
|
||||
wRequires, wEnsures, wEnforceNoRaises}
|
||||
converterPragmas* = procPragmas
|
||||
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
|
||||
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
||||
@@ -44,18 +47,21 @@ const
|
||||
wDiscardable, wGensym, wInject, wRaises, wEffectsOf,
|
||||
wTags, wLocks, wGcSafe, wRequires, wEnsures}
|
||||
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNoSideEffect}
|
||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
|
||||
wBoundChecks, wOverflowChecks, wNilChecks, wStaticBoundchecks,
|
||||
wStyleChecks, wAssertions,
|
||||
wWarnings, wHints,
|
||||
wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError,
|
||||
stmtPragmas* = {
|
||||
wHint, wWarning, wError,
|
||||
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
|
||||
wPassl, wPassc, wLocalPassc,
|
||||
wDeadCodeElimUnused, # deprecated, always on
|
||||
wDeprecated,
|
||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||
wExperimental, wThis, wUsed, wInvariant, wAssume, wAssert}
|
||||
stmtPragmasTopLevel* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
|
||||
wBoundChecks, wOverflowChecks, wNilChecks, wStaticBoundchecks,
|
||||
wStyleChecks, wAssertions,
|
||||
wWarnings, wHints,
|
||||
wLineDir, wStackTrace, wLineTrace, wOptimization,
|
||||
wFloatChecks, wInfChecks, wNanChecks}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv,
|
||||
wNoSideEffect, wSideEffect, wNoreturn, wNosinks, wDynlib, wHeader,
|
||||
wThread, wAsmNoStackFrame,
|
||||
@@ -635,12 +641,13 @@ proc pragmaLine(c: PContext, n: PNode) =
|
||||
n.info = getInfoContext(c.config, -1)
|
||||
|
||||
proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
## Create and add a new custom pragma `{.pragma: name.}` node to the module's context.
|
||||
let it = n[i]
|
||||
if it.kind notin nkPragmaCallKinds and it.safeLen == 2: invalidPragma(c, n)
|
||||
elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent:
|
||||
invalidPragma(c, n)
|
||||
|
||||
var userPragma = newSym(skTemplate, it[1].ident, nextSymId(c.idgen), nil, it.info, c.config.options)
|
||||
var userPragma = newSym(skTemplate, it[1].ident, nextSymId(c.idgen), c.module, it.info, c.config.options)
|
||||
userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
|
||||
strTableAdd(c.userPragmas, userPragma)
|
||||
|
||||
@@ -650,7 +657,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
|
||||
x.typ = makeTypeFromExpr(c, x)
|
||||
else:
|
||||
var t = skipTypes(c.semTypeNode(c, x, nil), skipPtrs)
|
||||
if t.kind != tyObject and not t.isMetaType:
|
||||
if t.kind notin {tyObject, tyOr}:
|
||||
localError(c.config, x.info, errGenerated, "invalid type for raises/tags list")
|
||||
x.typ = t
|
||||
|
||||
@@ -1237,6 +1244,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
pragmaProposition(c, it)
|
||||
of wEnsures:
|
||||
pragmaEnsures(c, it)
|
||||
of wEnforceNoRaises:
|
||||
sym.flags.incl sfNeverRaises
|
||||
else: invalidPragma(c, it)
|
||||
elif comesFromPush and whichKeyword(ident) != wInvalid:
|
||||
discard "ignore the .push pragma; it doesn't apply"
|
||||
|
||||
@@ -17,6 +17,9 @@ when defined(nimHasUsed):
|
||||
import
|
||||
lexer, options, idents, strutils, ast, msgs, lineinfos
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
type
|
||||
TRenderFlag* = enum
|
||||
renderNone, renderNoBody, renderNoComments, renderDocComments,
|
||||
@@ -162,6 +165,7 @@ proc putNL(g: var TSrcGen) =
|
||||
proc optNL(g: var TSrcGen, indent: int) =
|
||||
g.pendingNL = indent
|
||||
g.lineLen = indent
|
||||
g.col = g.indent
|
||||
when defined(nimpretty): g.pendingNewlineCount = 0
|
||||
|
||||
proc optNL(g: var TSrcGen) =
|
||||
@@ -170,6 +174,7 @@ proc optNL(g: var TSrcGen) =
|
||||
proc optNL(g: var TSrcGen; a, b: PNode) =
|
||||
g.pendingNL = g.indent
|
||||
g.lineLen = g.indent
|
||||
g.col = g.indent
|
||||
when defined(nimpretty): g.pendingNewlineCount = lineDiff(a, b)
|
||||
|
||||
proc indentNL(g: var TSrcGen) =
|
||||
|
||||
@@ -4,6 +4,9 @@ import
|
||||
msgs, modulegraphs, syntaxes, options, modulepaths,
|
||||
lineinfos
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
DepN = ref object
|
||||
pnode: PNode
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
## Serialization utilities for the compiler.
|
||||
import strutils, math
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
# bcc on windows doesn't have C99 functions
|
||||
when defined(windows) and defined(bcc):
|
||||
{.emit: """#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
|
||||
@@ -60,6 +60,10 @@ import
|
||||
|
||||
from pathutils import AbsoluteFile
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[assertions, syncio]
|
||||
|
||||
|
||||
type
|
||||
FormatStr* = string # later we may change it to CString for better
|
||||
# performance of the code generator (assignments
|
||||
@@ -329,10 +333,3 @@ proc equalsFile*(r: Rope, filename: AbsoluteFile): bool =
|
||||
if result:
|
||||
result = equalsFile(r, f)
|
||||
close(f)
|
||||
|
||||
proc writeRopeIfNotEqual*(r: Rope, filename: AbsoluteFile): bool =
|
||||
# returns true if overwritten
|
||||
if not equalsFile(r, filename):
|
||||
result = writeRope(r, filename)
|
||||
else:
|
||||
result = false
|
||||
|
||||
@@ -16,6 +16,9 @@ import
|
||||
os, times, osproc, wordrecg, strtabs, modulegraphs,
|
||||
pathutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
# we support 'cmpIgnoreStyle' natively for efficiency:
|
||||
from strutils import cmpIgnoreStyle, contains
|
||||
|
||||
|
||||
@@ -703,7 +703,16 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||
call.add(newIdentNode(fn.name, fn.info))
|
||||
for i in 1..<fn.typ.n.len:
|
||||
let param = fn.typ.n[i]
|
||||
let t = skipTypes(param.typ, abstractVar-{tyTypeDesc, tyDistinct})
|
||||
const desiredTypes = abstractVar + {tyCompositeTypeClass} - {tyTypeDesc, tyDistinct}
|
||||
#[.
|
||||
# We only want the type not any modifiers such as `ptr`, `var`, `ref` ...
|
||||
# tyCompositeTypeClass is here for
|
||||
# when using something like:
|
||||
type Foo[T] = distinct int
|
||||
proc `$`(f: Foo): string {.borrow.}
|
||||
# We want to skip the `Foo` to get `int`
|
||||
]#
|
||||
let t = skipTypes(param.typ, desiredTypes)
|
||||
if t.kind == tyDistinct or param.typ.kind == tyDistinct: hasDistinct = true
|
||||
var x: PType
|
||||
if param.typ.kind == tyVar:
|
||||
@@ -721,4 +730,4 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||
result = nil
|
||||
elif result.magic in {mArrPut, mArrGet}:
|
||||
# cannot borrow these magics for now
|
||||
result = nil
|
||||
result = nil
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
import tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import
|
||||
intsets, options, ast, astalgo, msgs, idents, renderer,
|
||||
magicsys, vmdef, modulegraphs, lineinfos, sets, pathutils
|
||||
|
||||
@@ -645,13 +645,13 @@ proc fixAbstractType(c: PContext, n: PNode) =
|
||||
skipTypes(it.typ, abstractVar).kind notin {tyOpenArray, tyVarargs}:
|
||||
if skipTypes(it[1].typ, abstractVar).kind in
|
||||
{tyNil, tyTuple, tySet} or it[1].isArrayConstr:
|
||||
var s = skipTypes(it.typ, abstractVar)
|
||||
var s = skipTypes(it.typ, abstractVar + tyUserTypeClasses)
|
||||
if s.kind != tyUntyped:
|
||||
changeType(c, it[1], s, check=true)
|
||||
n[i] = it[1]
|
||||
|
||||
proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult =
|
||||
result = parampatterns.isAssignable(c.p.owner, n, isUnsafeAddr)
|
||||
proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
||||
result = parampatterns.isAssignable(c.p.owner, n)
|
||||
|
||||
proc isUnresolvedSym(s: PSym): bool =
|
||||
result = s.kind == skGenericParam
|
||||
@@ -1188,7 +1188,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
let s = getGenSym(c, sym)
|
||||
case s.kind
|
||||
of skConst:
|
||||
markUsed(c, n.info, s)
|
||||
if n.kind != nkDotExpr: # dotExpr is already checked by builtinFieldAccess
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
let typ = skipTypes(s.typ, abstractInst-{tyTypeDesc})
|
||||
case typ.kind
|
||||
@@ -1249,7 +1250,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if s.magic == mNimvm:
|
||||
localError(c.config, n.info, "illegal context for 'nimvm' magic")
|
||||
|
||||
markUsed(c, n.info, s)
|
||||
if n.kind != nkDotExpr: # dotExpr is already checked by builtinFieldAccess
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
# We cannot check for access to outer vars for example because it's still
|
||||
@@ -1270,7 +1272,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
n.typ = s.typ
|
||||
return n
|
||||
of skType:
|
||||
markUsed(c, n.info, s)
|
||||
if n.kind != nkDotExpr: # dotExpr is already checked by builtinFieldAccess
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
|
||||
return s.typ.n
|
||||
@@ -1414,7 +1417,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass:
|
||||
ty = ty.lastSon
|
||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink})
|
||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink, tyStatic})
|
||||
while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct, tyGenericInst, tyAlias})
|
||||
var check: PNode = nil
|
||||
if ty.kind == tyObject:
|
||||
@@ -1433,8 +1436,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# is the access to a public field or in the same module or in a friend?
|
||||
markUsed(c, n[1].info, f)
|
||||
onUse(n[1].info, f)
|
||||
let info = n[1].info
|
||||
n[0] = makeDeref(n[0])
|
||||
n[1] = newSymNode(f) # we now have the correct field
|
||||
n[1].info = info # preserve the original info
|
||||
n.typ = f.typ
|
||||
if check == nil:
|
||||
result = n
|
||||
@@ -1658,9 +1663,11 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
|
||||
# `proc fun(a: var int): var int = a`
|
||||
discard
|
||||
else: discard
|
||||
let valid = isAssignable(c, n, isLent)
|
||||
let valid = isAssignable(c, n)
|
||||
if valid != arLValue:
|
||||
if valid == arLocalLValue:
|
||||
if valid in {arAddressableConst, arLentValue} and isLent:
|
||||
discard "ok"
|
||||
elif valid == arLocalLValue:
|
||||
localError(c.config, n.info, errXStackEscape % renderTree(n, {renderNoComments}))
|
||||
else:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
@@ -1784,7 +1791,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
if le == nil:
|
||||
localError(c.config, a.info, "expression has no type")
|
||||
elif (skipTypes(le, {tyGenericInst, tyAlias, tySink}).kind notin {tyVar} and
|
||||
isAssignable(c, a) in {arNone, arLentValue}) or (
|
||||
isAssignable(c, a) in {arNone, arLentValue, arAddressableConst}) or (
|
||||
skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs} and views notin c.features):
|
||||
# Direct assignment to a discriminant is allowed!
|
||||
localError(c.config, a.info, errXCannotBeAssignedTo %
|
||||
@@ -2267,7 +2274,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
markUsed(c, n.info, s)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result[0] = newSymNode(s, n[0].info)
|
||||
result[1] = semAddrArg(c, n[1], s.name.s == "unsafeAddr")
|
||||
result[1] = semAddrArg(c, n[1])
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
of mTypeOf:
|
||||
markUsed(c, n.info, s)
|
||||
@@ -2767,6 +2774,12 @@ proc enumFieldSymChoice(c: PContext, n: PNode, s: PSym): PNode =
|
||||
onUse(info, a)
|
||||
a = nextOverloadIter(o, c, n)
|
||||
|
||||
proc semPragmaStmt(c: PContext; n: PNode) =
|
||||
if c.p.owner.kind == skModule:
|
||||
pragma(c, c.p.owner, n, stmtPragmas+stmtPragmasTopLevel, true)
|
||||
else:
|
||||
pragma(c, c.p.owner, n, stmtPragmas, true)
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
when defined(nimCompilerStacktraceHints):
|
||||
setFrameMsg c.config$n.info & " " & $n.kind
|
||||
@@ -2856,7 +2869,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkBind:
|
||||
message(c.config, n.info, warnDeprecated, "bind is deprecated")
|
||||
result = semExpr(c, n[0], flags)
|
||||
of nkTypeOfExpr, nkTupleTy, nkTupleClassTy, nkRefTy..nkEnumTy, nkStaticTy:
|
||||
of nkTypeOfExpr..nkTupleClassTy, nkStaticTy, nkRefTy..nkEnumTy:
|
||||
if c.matchedConcept != nil and n.len == 1:
|
||||
let modifier = n.modifierTypeKindOfNode
|
||||
if modifier != tyNone:
|
||||
@@ -3015,7 +3028,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkUsingStmt: result = semUsing(c, n)
|
||||
of nkAsmStmt: result = semAsm(c, n)
|
||||
of nkYieldStmt: result = semYield(c, n)
|
||||
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas, true)
|
||||
of nkPragma: semPragmaStmt(c, n)
|
||||
of nkIteratorDef: result = semIterator(c, n)
|
||||
of nkProcDef: result = semProc(c, n)
|
||||
of nkFuncDef: result = semFunc(c, n)
|
||||
|
||||
@@ -17,6 +17,9 @@ import
|
||||
|
||||
from system/memory import nimCStrLen
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
proc errorType*(g: ModuleGraph): PType =
|
||||
## creates a type representing an error state
|
||||
result = newType(tyError, nextTypeId(g.idgen), g.owners[^1])
|
||||
@@ -133,7 +136,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
of mCard: result = newIntNodeT(toInt128(nimsets.cardSet(g.config, a)), n, idgen, g)
|
||||
of mBitnotI:
|
||||
if n.typ.isUnsigned:
|
||||
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, idgen, g)
|
||||
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(getSize(g.config, n.typ))), n, idgen, g)
|
||||
else:
|
||||
result = newIntNodeT(bitnot(getInt(a)), n, idgen, g)
|
||||
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, idgen, g)
|
||||
@@ -248,23 +251,23 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, idgen, g)
|
||||
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, idgen, g)
|
||||
of mAddU:
|
||||
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
|
||||
let val = maskBytes(getInt(a) + getInt(b), int(getSize(g.config, n.typ)))
|
||||
result = newIntNodeT(val, n, idgen, g)
|
||||
of mSubU:
|
||||
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
|
||||
let val = maskBytes(getInt(a) - getInt(b), int(getSize(g.config, n.typ)))
|
||||
result = newIntNodeT(val, n, idgen, g)
|
||||
# echo "subU: ", val, " n: ", n, " result: ", val
|
||||
of mMulU:
|
||||
let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size))
|
||||
let val = maskBytes(getInt(a) * getInt(b), int(getSize(g.config, n.typ)))
|
||||
result = newIntNodeT(val, n, idgen, g)
|
||||
of mModU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
|
||||
let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA mod argB, n, idgen, g)
|
||||
of mDivU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
|
||||
let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA div argB, n, idgen, g)
|
||||
of mLeSet: result = newIntNodeT(toInt128(ord(containsSets(g.config, a, b))), n, idgen, g)
|
||||
@@ -292,13 +295,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
else: result = newStrNodeT("true", n, g)
|
||||
of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
|
||||
of mCStrToStr, mCharToStr:
|
||||
if a.kind == nkBracket:
|
||||
var s = ""
|
||||
for b in a.sons:
|
||||
s.add b.getStrOrChar
|
||||
result = newStrNodeT(s, n, g)
|
||||
else:
|
||||
result = newStrNodeT(getStrOrChar(a), n, g)
|
||||
result = newStrNodeT(getStrOrChar(a), n, g)
|
||||
of mStrToStr: result = newStrNodeT(getStrOrChar(a), n, g)
|
||||
of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
|
||||
of mArrToSeq:
|
||||
@@ -412,7 +409,7 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
rangeCheck(n, getInt(result), g)
|
||||
of tyFloat..tyFloat64:
|
||||
case srcTyp.kind
|
||||
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
|
||||
result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
|
||||
else:
|
||||
result = a
|
||||
|
||||
@@ -145,7 +145,11 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) =
|
||||
if sfGenSym in param.flags:
|
||||
idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym)
|
||||
freshGenSyms(c, b, result, orig, symMap)
|
||||
b = semProcBody(c, b)
|
||||
|
||||
if sfBorrow notin orig.flags:
|
||||
# We do not want to generate a body for generic borrowed procs.
|
||||
# As body is a sym to the borrowed proc.
|
||||
b = semProcBody(c, b)
|
||||
result.ast[bodyPos] = hloBody(c, b)
|
||||
excl(result.flags, sfForward)
|
||||
trackProc(c, result, result.ast[bodyPos])
|
||||
|
||||
@@ -10,17 +10,12 @@
|
||||
# This include file implements the semantic checking for magics.
|
||||
# included from sem.nim
|
||||
|
||||
proc semAddrArg(c: PContext; n: PNode; isUnsafeAddr = false): PNode =
|
||||
proc semAddrArg(c: PContext; n: PNode): PNode =
|
||||
let x = semExprWithType(c, n)
|
||||
if x.kind == nkSym:
|
||||
x.sym.flags.incl(sfAddrTaken)
|
||||
if isAssignable(c, x, isUnsafeAddr) notin {arLValue, arLocalLValue}:
|
||||
# Do not suggest the use of unsafeAddr if this expression already is a
|
||||
# unsafeAddr
|
||||
if isUnsafeAddr:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
else:
|
||||
localError(c.config, n.info, errExprHasNoAddress & "; maybe use 'unsafeAddr'")
|
||||
if isAssignable(c, x) notin {arLValue, arLocalLValue, arAddressableConst, arLentValue}:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result = x
|
||||
|
||||
proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
@@ -471,7 +466,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
of mAddr:
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = n
|
||||
result[1] = semAddrArg(c, n[1], n[0].sym.name.s == "unsafeAddr")
|
||||
result[1] = semAddrArg(c, n[1])
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
of mTypeOf:
|
||||
result = semTypeOf(c, n)
|
||||
|
||||
@@ -366,10 +366,9 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
|
||||
if objType.kind == tyObject:
|
||||
var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info))
|
||||
let initResult = semConstructTypeAux(c, constrCtx, {})
|
||||
assert constrCtx.missingFields.len > 0
|
||||
localError(c.config, info,
|
||||
"The $1 type doesn't have a default value. The following fields must " &
|
||||
"be initialized: $2." % [typeToString(t), listSymbolNames(constrCtx.missingFields)])
|
||||
if constrCtx.missingFields.len > 0:
|
||||
localError(c.config, info,
|
||||
"The $1 type doesn't have a default value. The following fields must be initialized: $2." % [typeToString(t), listSymbolNames(constrCtx.missingFields)])
|
||||
elif objType.kind == tyDistinct:
|
||||
localError(c.config, info,
|
||||
"The $1 distinct type doesn't have a default value." % typeToString(t))
|
||||
|
||||
@@ -12,6 +12,9 @@ import
|
||||
wordrecg, strutils, options, guards, lineinfos, semfold, semdata,
|
||||
modulegraphs, varpartitions, typeallowed, nilcheck, errorhandling, tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when defined(useDfa):
|
||||
import dfa
|
||||
|
||||
@@ -851,11 +854,15 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
elif isIndirectCall(tracked, a):
|
||||
assumeTheWorst(tracked, n, op)
|
||||
gcsafeAndSideeffectCheck()
|
||||
else:
|
||||
if strictEffects in tracked.c.features and a.kind == nkSym and
|
||||
a.sym.kind in routineKinds:
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
else:
|
||||
mergeRaises(tracked, effectList[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList[tagEffects], n)
|
||||
gcsafeAndSideeffectCheck()
|
||||
if a.kind != nkSym or a.sym.magic notin {mNBindSym, mFinished}:
|
||||
if a.kind != nkSym or a.sym.magic notin {mNBindSym, mFinished, mExpandToAst, mQuoteAst}:
|
||||
for i in 1..<n.len:
|
||||
trackOperandForIndirectCall(tracked, n[i], op, i, a)
|
||||
if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
|
||||
@@ -880,7 +887,7 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
optStaticBoundsCheck in tracked.currOptions:
|
||||
checkBounds(tracked, n[1], n[2])
|
||||
|
||||
if a.kind != nkSym or a.sym.magic != mRunnableExamples:
|
||||
if a.kind != nkSym or a.sym.magic notin {mRunnableExamples, mNBindSym, mExpandToAst, mQuoteAst}:
|
||||
for i in 0..<n.safeLen:
|
||||
track(tracked, n[i])
|
||||
|
||||
@@ -1047,7 +1054,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
addAsgnFact(tracked.guards, n[0], n[1])
|
||||
notNilCheck(tracked, n[1], n[0].typ)
|
||||
when false: cstringCheck(tracked, n)
|
||||
if tracked.owner.kind != skMacro:
|
||||
if tracked.owner.kind != skMacro and n[0].typ.kind notin {tyOpenArray, tyVarargs}:
|
||||
createTypeBoundOps(tracked, n[0].typ, n.info)
|
||||
if n[0].kind != nkSym or not isLocalVar(tracked, n[0].sym):
|
||||
checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n[1])
|
||||
|
||||
@@ -140,7 +140,9 @@ proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
|
||||
n[0] = result
|
||||
elif result.typ.kind != tyError and c.config.cmd != cmdInteractive:
|
||||
var n = result
|
||||
while n.kind in skipForDiscardable: n = n.lastSon
|
||||
while n.kind in skipForDiscardable:
|
||||
if n.kind == nkTryStmt: n = n[0]
|
||||
else: n = n.lastSon
|
||||
var s = "expression '" & $n & "' is of type '" &
|
||||
result.typ.typeToString & "' and has to be used (or discarded)"
|
||||
if result.info.line != n.info.line or
|
||||
@@ -306,7 +308,7 @@ proc identWithin(n: PNode, s: PIdent): bool =
|
||||
if identWithin(n[i], s): return true
|
||||
result = n.kind == nkSym and n.sym.name.id == s.id
|
||||
|
||||
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
|
||||
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind, reportToNimsuggest = true): PSym =
|
||||
if isTopLevel(c):
|
||||
result = semIdentWithPragma(c, kind, n, {sfExported})
|
||||
incl(result.flags, sfGlobal)
|
||||
@@ -330,7 +332,8 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
|
||||
discard
|
||||
result = n.info
|
||||
let info = getLineInfo(n)
|
||||
suggestSym(c.graph, info, result, c.graph.usageSym)
|
||||
if reportToNimsuggest:
|
||||
suggestSym(c.graph, info, result, c.graph.usageSym)
|
||||
|
||||
proc checkNilable(c: PContext; v: PSym) =
|
||||
if {sfGlobal, sfImportc} * v.flags == {sfGlobal} and v.typ.requiresInit:
|
||||
@@ -341,8 +344,12 @@ proc checkNilable(c: PContext; v: PSym) =
|
||||
|
||||
#include liftdestructors
|
||||
|
||||
proc addToVarSection(c: PContext; result: PNode; orig, identDefs: PNode) =
|
||||
let value = identDefs[^1]
|
||||
proc addToVarSection(c: PContext; result: var PNode; n: PNode) =
|
||||
if result.kind != nkStmtList:
|
||||
result = makeStmtList(result)
|
||||
result.add n
|
||||
|
||||
proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
|
||||
if result.kind == nkStmtList:
|
||||
let o = copyNode(orig)
|
||||
o.add identDefs
|
||||
@@ -445,55 +452,115 @@ proc setVarType(c: PContext; v: PSym, typ: PType) =
|
||||
"; new type is: " & typeToString(typ, preferDesc))
|
||||
v.typ = typ
|
||||
|
||||
proc semLowerLetVarCustomPragma(c: PContext, a: PNode, n: PNode): PNode =
|
||||
var b = a[0]
|
||||
if b.kind == nkPragmaExpr:
|
||||
if b[1].len != 1:
|
||||
# we could in future support pragmas w args e.g.: `var foo {.bar:"goo".} = expr`
|
||||
return nil
|
||||
let nodePragma = b[1][0]
|
||||
# see: `singlePragma`
|
||||
proc isPossibleMacroPragma(c: PContext, it: PNode, key: PNode): bool =
|
||||
# make sure it's not a normal pragma, and calls an identifier
|
||||
# considerQuotedIdent below will fail on non-identifiers
|
||||
result = whichPragma(it) == wInvalid and key.kind in nkIdentKinds
|
||||
if result:
|
||||
# make sure it's not a user pragma
|
||||
let ident = considerQuotedIdent(c, key)
|
||||
result = strTableGet(c.userPragmas, ident) == nil
|
||||
if result:
|
||||
# make sure it's not a custom pragma
|
||||
var amb = false
|
||||
let sym = searchInScopes(c, ident, amb)
|
||||
result = sym == nil or sfCustomPragma notin sym.flags
|
||||
|
||||
var amb = false
|
||||
var sym: PSym = nil
|
||||
case nodePragma.kind
|
||||
of nkIdent, nkAccQuoted:
|
||||
let ident = considerQuotedIdent(c, nodePragma)
|
||||
var userPragma = strTableGet(c.userPragmas, ident)
|
||||
if userPragma != nil: return nil
|
||||
let w = nodePragma.whichPragma
|
||||
if n.kind == nkVarSection and w in varPragmas or
|
||||
n.kind == nkLetSection and w in letPragmas or
|
||||
n.kind == nkConstSection and w in constPragmas:
|
||||
return nil
|
||||
sym = searchInScopes(c, ident, amb)
|
||||
# XXX what if amb is true?
|
||||
# CHECKME: should that test also apply to `nkSym` case?
|
||||
if sym == nil or sfCustomPragma in sym.flags: return nil
|
||||
of nkSym:
|
||||
sym = nodePragma.sym
|
||||
else:
|
||||
return nil
|
||||
# skip if not in scope; skip `template myAttr() {.pragma.}`
|
||||
proc copyExcept(n: PNode, i: int): PNode =
|
||||
result = copyNode(n)
|
||||
for j in 0..<n.len:
|
||||
if j != i: result.add(n[j])
|
||||
|
||||
let lhs = b[0]
|
||||
let clash = strTableGet(c.currentScope.symbols, lhs.ident)
|
||||
if clash != nil:
|
||||
# refs https://github.com/nim-lang/Nim/issues/8275
|
||||
wrongRedefinition(c, lhs.info, lhs.ident.s, clash.info)
|
||||
proc semVarMacroPragma(c: PContext, a: PNode, n: PNode): PNode =
|
||||
# Mirrored with semProcAnnotation
|
||||
result = nil
|
||||
# a, b {.prag.}: int = 3 not allowed
|
||||
const lhsPos = 0
|
||||
if a.len == 3 and a[lhsPos].kind == nkPragmaExpr:
|
||||
var b = a[lhsPos]
|
||||
const
|
||||
namePos = 0
|
||||
pragmaPos = 1
|
||||
let pragmas = b[pragmaPos]
|
||||
for i in 0 ..< pragmas.len:
|
||||
let it = pragmas[i]
|
||||
let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
|
||||
|
||||
result = newTree(nkCall)
|
||||
result.add nodePragma
|
||||
result.add lhs
|
||||
if a[1].kind != nkEmpty:
|
||||
result.add a[1]
|
||||
else:
|
||||
result.add newNodeIT(nkNilLit, a.info, c.graph.sysTypes[tyNil])
|
||||
result.add a[2]
|
||||
result.info = a.info
|
||||
let ret = newNodeI(nkStmtList, a.info)
|
||||
ret.add result
|
||||
result = semExprNoType(c, ret)
|
||||
when false:
|
||||
let lhs = b[0]
|
||||
let clash = strTableGet(c.currentScope.symbols, lhs.ident)
|
||||
if clash != nil:
|
||||
# refs https://github.com/nim-lang/Nim/issues/8275
|
||||
wrongRedefinition(c, lhs.info, lhs.ident.s, clash.info)
|
||||
|
||||
if isPossibleMacroPragma(c, it, key):
|
||||
# we transform ``var p {.m, rest.}`` into ``m(do: var p {.rest.})`` and
|
||||
# let the semantic checker deal with it:
|
||||
var x = newNodeI(nkCall, key.info)
|
||||
x.add(key)
|
||||
|
||||
if it.kind in nkPragmaCallKinds and it.len > 1:
|
||||
# pass pragma arguments to the macro too:
|
||||
for i in 1..<it.len:
|
||||
x.add(it[i])
|
||||
|
||||
# Drop the pragma from the list, this prevents getting caught in endless
|
||||
# recursion when the nkCall is semanticized
|
||||
let oldExpr = a[lhsPos]
|
||||
let newPragmas = copyExcept(pragmas, i)
|
||||
if newPragmas.kind != nkEmpty and newPragmas.len == 0:
|
||||
a[lhsPos] = oldExpr[namePos]
|
||||
else:
|
||||
a[lhsPos] = copyNode(oldExpr)
|
||||
a[lhsPos].add(oldExpr[namePos])
|
||||
a[lhsPos].add(newPragmas)
|
||||
|
||||
var unarySection = newNodeI(n.kind, a.info)
|
||||
unarySection.add(a)
|
||||
x.add(unarySection)
|
||||
|
||||
# recursion assures that this works for multiple macro annotations too:
|
||||
var r = semOverloadedCall(c, x, x, {skMacro, skTemplate}, {efNoUndeclared})
|
||||
if r == nil:
|
||||
# Restore the old list of pragmas since we couldn't process this
|
||||
a[lhsPos] = oldExpr
|
||||
# No matching macro was found but there's always the possibility this may
|
||||
# be a .pragma. template instead
|
||||
continue
|
||||
|
||||
doAssert r[0].kind == nkSym
|
||||
let m = r[0].sym
|
||||
case m.kind
|
||||
of skMacro: result = semMacroExpr(c, r, r, m, {})
|
||||
of skTemplate: result = semTemplateExpr(c, r, m, {})
|
||||
else:
|
||||
a[lhsPos] = oldExpr
|
||||
continue
|
||||
|
||||
doAssert result != nil
|
||||
|
||||
# since a macro pragma can set pragmas, we process these here again.
|
||||
# This is required for SqueakNim-like export pragmas.
|
||||
if false and result.kind in {nkVarSection, nkLetSection, nkConstSection}:
|
||||
var validPragmas: TSpecialWords
|
||||
case result.kind
|
||||
of nkVarSection:
|
||||
validPragmas = varPragmas
|
||||
of nkLetSection:
|
||||
validPragmas = letPragmas
|
||||
of nkConstSection:
|
||||
validPragmas = constPragmas
|
||||
else:
|
||||
# unreachable
|
||||
discard
|
||||
for defs in result:
|
||||
for i in 0 ..< defs.len - 2:
|
||||
let ex = defs[i]
|
||||
if ex.kind == nkPragmaExpr and
|
||||
ex[namePos].kind == nkSym and
|
||||
ex[pragmaPos].kind != nkEmpty:
|
||||
pragma(c, defs[lhsPos][namePos].sym, defs[lhsPos][pragmaPos], validPragmas)
|
||||
return result
|
||||
|
||||
proc errorSymChoiceUseQualifier(c: PContext; n: PNode) =
|
||||
assert n.kind in nkSymChoices
|
||||
@@ -508,10 +575,6 @@ proc errorSymChoiceUseQualifier(c: PContext; n: PNode) =
|
||||
localError(c.config, n.info, errGenerated, err)
|
||||
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if n.len == 1:
|
||||
result = semLowerLetVarCustomPragma(c, n[0], n)
|
||||
if result != nil: return result
|
||||
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
@@ -521,6 +584,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if a.kind notin {nkIdentDefs, nkVarTuple}: illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
|
||||
b = semVarMacroPragma(c, a, n)
|
||||
if b != nil:
|
||||
addToVarSection(c, result, b)
|
||||
continue
|
||||
|
||||
var typ: PType = nil
|
||||
if a[^2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a[^2], nil)
|
||||
@@ -595,7 +663,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if a.kind != nkVarTuple: typ else: tup[j])
|
||||
addToVarSection(c, result, n, a)
|
||||
continue
|
||||
var v = semIdentDef(c, a[j], symkind)
|
||||
var v = semIdentDef(c, a[j], symkind, false)
|
||||
styleCheckDef(c.config, v)
|
||||
onDef(a[j].info, v)
|
||||
if sfGenSym notin v.flags:
|
||||
@@ -660,9 +728,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
|
||||
message(c.config, v.info, hintGlobalVar)
|
||||
|
||||
suggestSym(c.graph, v.info, v, c.graph.usageSym)
|
||||
|
||||
proc semConst(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
inc c.inStaticContext
|
||||
var b: PNode
|
||||
for i in 0..<n.len:
|
||||
var a = n[i]
|
||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||
@@ -670,6 +741,11 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
|
||||
b = semVarMacroPragma(c, a, n)
|
||||
if b != nil:
|
||||
addToVarSection(c, result, b)
|
||||
continue
|
||||
|
||||
var typ: PType = nil
|
||||
if a[^2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a[^2], nil)
|
||||
@@ -704,7 +780,6 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
typFlags.incl taConcept
|
||||
typeAllowedCheck(c, a.info, typ, skConst, typFlags)
|
||||
|
||||
var b: PNode
|
||||
if a.kind == nkVarTuple:
|
||||
if typ.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
@@ -735,7 +810,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
v.ast = if def[j].kind != nkExprColonExpr: def[j]
|
||||
else: def[j][1]
|
||||
b[j] = newSymNode(v)
|
||||
result.add b
|
||||
addToVarSection(c, result, n, b)
|
||||
dec c.inStaticContext
|
||||
|
||||
include semfields
|
||||
@@ -987,10 +1062,10 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
else:
|
||||
popCaseContext(c)
|
||||
closeScope(c)
|
||||
if caseStmtMacros in c.features:
|
||||
result = handleCaseStmtMacro(c, n, flags)
|
||||
if result != nil:
|
||||
return result
|
||||
#if caseStmtMacros in c.features:
|
||||
result = handleCaseStmtMacro(c, n, flags)
|
||||
if result != nil:
|
||||
return result
|
||||
localError(c.config, n[0].info, errSelectorMustBeOfCertainTypes)
|
||||
return
|
||||
for i in 1..<n.len:
|
||||
@@ -1112,7 +1187,12 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) =
|
||||
if name.kind == nkPragmaExpr:
|
||||
let rewritten = applyTypeSectionPragmas(c, name[1], typeDef)
|
||||
if rewritten != nil:
|
||||
typeSection[i] = rewritten
|
||||
case rewritten.kind
|
||||
of nkTypeDef:
|
||||
typeSection[i] = rewritten
|
||||
of nkTypeSection:
|
||||
typeSection.sons[i .. i] = rewritten.sons
|
||||
else: illFormedAst(rewritten, c.config)
|
||||
typeDefLeftSidePass(c, typeSection, i)
|
||||
return
|
||||
pragma(c, s, name[1], typePragmas)
|
||||
@@ -1143,16 +1223,19 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) =
|
||||
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
||||
# process the symbols on the left side for the whole type section, before
|
||||
# we even look at the type definitions on the right
|
||||
for i in 0..<n.len:
|
||||
var i = 0
|
||||
while i < n.len: # n may grow due to type pragma macros
|
||||
var a = n[i]
|
||||
when defined(nimsuggest):
|
||||
if c.config.cmd == cmdIdeTools:
|
||||
inc c.inTypeContext
|
||||
suggestStmt(c, a)
|
||||
dec c.inTypeContext
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind != nkTypeDef: illFormedAst(a, c.config)
|
||||
typeDefLeftSidePass(c, n, i)
|
||||
case a.kind
|
||||
of nkCommentStmt: discard
|
||||
of nkTypeDef: typeDefLeftSidePass(c, n, i)
|
||||
else: illFormedAst(a, c.config)
|
||||
inc i
|
||||
|
||||
proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
|
||||
var body = genericType[^1]
|
||||
@@ -1511,77 +1594,61 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) =
|
||||
n.add newSymNode(c.p.resultSym)
|
||||
addParamOrResult(c, c.p.resultSym, owner)
|
||||
|
||||
proc copyExcept(n: PNode, i: int): PNode =
|
||||
result = copyNode(n)
|
||||
for j in 0..<n.len:
|
||||
if j != i: result.add(n[j])
|
||||
|
||||
proc semProcAnnotation(c: PContext, prc: PNode;
|
||||
validPragmas: TSpecialWords): PNode =
|
||||
# Mirrored with semVarMacroPragma
|
||||
var n = prc[pragmasPos]
|
||||
if n == nil or n.kind == nkEmpty: return
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
|
||||
|
||||
if whichPragma(it) != wInvalid:
|
||||
# Not a custom pragma
|
||||
continue
|
||||
else:
|
||||
let ident = considerQuotedIdent(c, key)
|
||||
if strTableGet(c.userPragmas, ident) != nil:
|
||||
continue # User defined pragma
|
||||
if isPossibleMacroPragma(c, it, key):
|
||||
# we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
|
||||
# let the semantic checker deal with it:
|
||||
var x = newNodeI(nkCall, key.info)
|
||||
x.add(key)
|
||||
|
||||
if it.kind in nkPragmaCallKinds and it.len > 1:
|
||||
# pass pragma arguments to the macro too:
|
||||
for i in 1..<it.len:
|
||||
x.add(it[i])
|
||||
|
||||
# Drop the pragma from the list, this prevents getting caught in endless
|
||||
# recursion when the nkCall is semanticized
|
||||
prc[pragmasPos] = copyExcept(n, i)
|
||||
if prc[pragmasPos].kind != nkEmpty and prc[pragmasPos].len == 0:
|
||||
prc[pragmasPos] = c.graph.emptyNode
|
||||
|
||||
x.add(prc)
|
||||
|
||||
# recursion assures that this works for multiple macro annotations too:
|
||||
var r = semOverloadedCall(c, x, x, {skMacro, skTemplate}, {efNoUndeclared})
|
||||
if r == nil:
|
||||
# Restore the old list of pragmas since we couldn't process this
|
||||
prc[pragmasPos] = n
|
||||
# No matching macro was found but there's always the possibility this may
|
||||
# be a .pragma. template instead
|
||||
continue
|
||||
|
||||
doAssert r[0].kind == nkSym
|
||||
let m = r[0].sym
|
||||
case m.kind
|
||||
of skMacro: result = semMacroExpr(c, r, r, m, {})
|
||||
of skTemplate: result = semTemplateExpr(c, r, m, {})
|
||||
else:
|
||||
var amb = false
|
||||
let sym = searchInScopes(c, ident, amb)
|
||||
if sym != nil and sfCustomPragma in sym.flags:
|
||||
continue # User custom pragma
|
||||
prc[pragmasPos] = n
|
||||
continue
|
||||
|
||||
# we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
|
||||
# let the semantic checker deal with it:
|
||||
var x = newNodeI(nkCall, key.info)
|
||||
x.add(key)
|
||||
doAssert result != nil
|
||||
|
||||
if it.kind in nkPragmaCallKinds and it.len > 1:
|
||||
# pass pragma arguments to the macro too:
|
||||
for i in 1..<it.len:
|
||||
x.add(it[i])
|
||||
# since a proc annotation can set pragmas, we process these here again.
|
||||
# This is required for SqueakNim-like export pragmas.
|
||||
if false and result.kind in procDefs and result[namePos].kind == nkSym and
|
||||
result[pragmasPos].kind != nkEmpty:
|
||||
pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
|
||||
|
||||
# Drop the pragma from the list, this prevents getting caught in endless
|
||||
# recursion when the nkCall is semanticized
|
||||
prc[pragmasPos] = copyExcept(n, i)
|
||||
if prc[pragmasPos].kind != nkEmpty and prc[pragmasPos].len == 0:
|
||||
prc[pragmasPos] = c.graph.emptyNode
|
||||
|
||||
x.add(prc)
|
||||
|
||||
# recursion assures that this works for multiple macro annotations too:
|
||||
var r = semOverloadedCall(c, x, x, {skMacro, skTemplate}, {efNoUndeclared})
|
||||
if r == nil:
|
||||
# Restore the old list of pragmas since we couldn't process this
|
||||
prc[pragmasPos] = n
|
||||
# No matching macro was found but there's always the possibility this may
|
||||
# be a .pragma. template instead
|
||||
continue
|
||||
|
||||
doAssert r[0].kind == nkSym
|
||||
let m = r[0].sym
|
||||
case m.kind
|
||||
of skMacro: result = semMacroExpr(c, r, r, m, {})
|
||||
of skTemplate: result = semTemplateExpr(c, r, m, {})
|
||||
else:
|
||||
prc[pragmasPos] = n
|
||||
continue
|
||||
|
||||
doAssert result != nil
|
||||
|
||||
# since a proc annotation can set pragmas, we process these here again.
|
||||
# This is required for SqueakNim-like export pragmas.
|
||||
if result.kind in procDefs and result[namePos].kind == nkSym and
|
||||
result[pragmasPos].kind != nkEmpty:
|
||||
pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
|
||||
|
||||
return
|
||||
return result
|
||||
|
||||
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} =
|
||||
## used for resolving 'auto' in lambdas based on their callsite
|
||||
@@ -2075,6 +2142,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
incl(s.flags, sfWasForwarded)
|
||||
elif sfBorrow in s.flags: semBorrow(c, n, s)
|
||||
sideEffectsCheck(c, s)
|
||||
|
||||
closeScope(c) # close scope for parameters
|
||||
# c.currentScope = oldScope
|
||||
popOwner(c)
|
||||
|
||||
@@ -270,7 +270,8 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode =
|
||||
# Issue #12832
|
||||
when defined(nimsuggest):
|
||||
suggestSym(c.graph, n.info, s, c.graph.usageSym, false)
|
||||
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||
# field access (dot expr) will be handled by builtinFieldAccess
|
||||
if not isField and {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||
styleCheckUse(c.config, n.info, s)
|
||||
|
||||
proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
|
||||
@@ -602,7 +603,12 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||
for i in 0..<n.len:
|
||||
result[i] = semTemplBodyDirty(c, n[i])
|
||||
|
||||
# in semstmts.nim:
|
||||
proc semProcAnnotation(c: PContext, prc: PNode; validPragmas: TSpecialWords): PNode
|
||||
|
||||
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
result = semProcAnnotation(c, n, templatePragmas)
|
||||
if result != nil: return result
|
||||
result = n
|
||||
var s: PSym
|
||||
if isTopLevel(c):
|
||||
|
||||
@@ -1993,8 +1993,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkStmtListType: result = semStmtListType(c, n, prev)
|
||||
of nkBlockType: result = semBlockType(c, n, prev)
|
||||
else:
|
||||
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
result = semTypeExpr(c, n, prev)
|
||||
when false:
|
||||
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
n.typ = result
|
||||
dec c.inTypeContext
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ import ast, astalgo, msgs, types, magicsys, semdata, renderer, options,
|
||||
|
||||
from concepts import makeTypeDesc
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const tfInstClearedFlags = {tfHasMeta, tfUnresolved}
|
||||
|
||||
proc checkPartialConstructedType(conf: ConfigRef; info: TLineInfo, t: PType) =
|
||||
|
||||
@@ -9,10 +9,14 @@
|
||||
|
||||
## Computes hash values for routine (proc, method etc) signatures.
|
||||
|
||||
import ast, tables, ropes, md5, modulegraphs
|
||||
import ast, tables, ropes, md5_old, modulegraphs
|
||||
from hashes import Hash
|
||||
import types
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
|
||||
proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
|
||||
proc `&=`(c: var MD5Context, ch: char) =
|
||||
# XXX suspicious code here; relies on ch being zero terminated?
|
||||
|
||||
@@ -15,6 +15,9 @@ import
|
||||
magicsys, idents, lexer, options, parampatterns, strutils, trees,
|
||||
linter, lineinfos, lowerings, modulegraphs, concepts
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
MismatchKind* = enum
|
||||
kUnknown, kAlreadyGiven, kUnknownNamedParam, kTypeMismatch, kVarNeeded,
|
||||
@@ -1634,6 +1637,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
bindConcreteTypeToUserTypeClass(matched, a)
|
||||
if doBind: put(c, f, matched)
|
||||
result = isGeneric
|
||||
elif a.len > 0 and a.lastSon == f:
|
||||
# Needed for checking `Y` == `Addable` in the following
|
||||
#[
|
||||
type
|
||||
Addable = concept a, type A
|
||||
a + a is A
|
||||
MyType[T: Addable; Y: static T] = object
|
||||
]#
|
||||
result = isGeneric
|
||||
else:
|
||||
result = isNone
|
||||
|
||||
@@ -1679,7 +1691,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
var aa = a
|
||||
while aa.kind in {tyTypeDesc, tyGenericParam} and aa.len > 0:
|
||||
aa = lastSon(aa)
|
||||
if aa.kind == tyGenericParam:
|
||||
if aa.kind in {tyGenericParam} + tyTypeClasses:
|
||||
# If the constraint is a genericParam or typeClass this isGeneric
|
||||
return isGeneric
|
||||
result = typeRel(c, f.base, aa, flags)
|
||||
if result > isGeneric: result = isGeneric
|
||||
@@ -1739,11 +1752,22 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let prev = PType(idTableGet(c.bindings, f))
|
||||
if prev == nil:
|
||||
if aOrig.kind == tyStatic:
|
||||
if f.base.kind != tyNone:
|
||||
if f.base.kind notin {tyNone, tyGenericParam}:
|
||||
result = typeRel(c, f.base, a, flags)
|
||||
if result != isNone and f.n != nil:
|
||||
if not exprStructuralEquivalent(f.n, aOrig.n):
|
||||
result = isNone
|
||||
elif f.base.kind == tyGenericParam:
|
||||
# Handling things like `type A[T; Y: static T] = object`
|
||||
if f.base.len > 0: # There is a constraint, handle it
|
||||
result = typeRel(c, f.base.lastSon, a, flags)
|
||||
else:
|
||||
# No constraint
|
||||
if tfGenericTypeParam in f.flags:
|
||||
result = isGeneric
|
||||
else:
|
||||
# for things like `proc fun[T](a: static[T])`
|
||||
result = typeRel(c, f.base, a, flags)
|
||||
else:
|
||||
result = isGeneric
|
||||
if result != isNone: put(c, f, aOrig)
|
||||
@@ -1993,7 +2017,6 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
arg = argSemantized
|
||||
a = a
|
||||
c = m.c
|
||||
|
||||
if tfHasStatic in fMaybeStatic.flags:
|
||||
# XXX: When implicit statics are the default
|
||||
# this will be done earlier - we just have to
|
||||
@@ -2461,7 +2484,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
if m.callee.n[f].kind != nkSym:
|
||||
internalError(c.config, n[a].info, "matches")
|
||||
noMatch()
|
||||
if a >= firstArgBlock: f = max(f, m.callee.n.len - (n.len - a))
|
||||
if flexibleOptionalParams in c.features and a >= firstArgBlock:
|
||||
f = max(f, m.callee.n.len - (n.len - a))
|
||||
formal = m.callee.n[f].sym
|
||||
m.firstMismatch.kind = kTypeMismatch
|
||||
if containsOrIncl(marker, formal.position) and container.isNil:
|
||||
|
||||
@@ -40,15 +40,15 @@ proc inc(arg: var OffsetAccum; value: int) =
|
||||
else:
|
||||
arg.offset += value
|
||||
|
||||
proc alignmentMax(a,b: int): int =
|
||||
proc alignmentMax(a, b: int): int =
|
||||
if unlikely(a == szIllegalRecursion or b == szIllegalRecursion): raiseIllegalTypeRecursion()
|
||||
if a == szUnknownSize or b == szUnknownSize:
|
||||
szUnknownSize
|
||||
else:
|
||||
max(a,b)
|
||||
max(a, b)
|
||||
|
||||
proc align(arg: var OffsetAccum; value: int) =
|
||||
if unlikely(value == szIllegalRecursion): raiseIllegalTypeRecursion()
|
||||
if unlikely(value == szIllegalRecursion): raiseIllegalTypeRecursion()
|
||||
if value == szUnknownSize or arg.maxAlign == szUnknownSize or arg.offset == szUnknownSize:
|
||||
arg.maxAlign = szUnknownSize
|
||||
arg.offset = szUnknownSize
|
||||
@@ -112,7 +112,7 @@ proc setOffsetsToUnknown(n: PNode) =
|
||||
for i in 0..<n.safeLen:
|
||||
setOffsetsToUnknown(n[i])
|
||||
|
||||
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, accum: var OffsetAccum) =
|
||||
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; packed: bool; accum: var OffsetAccum) =
|
||||
## ``offset`` is the offset within the object, after the node has been written, no padding bytes added
|
||||
## ``align`` maximum alignment from all sub nodes
|
||||
assert n != nil
|
||||
@@ -196,6 +196,11 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; packed: bo
|
||||
accum.offset = szUnknownSize
|
||||
|
||||
proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
template setSize(typ, s) =
|
||||
typ.size = s
|
||||
typ.align = s
|
||||
typ.paddingAtEnd = 0
|
||||
|
||||
## computes and sets ``size`` and ``align`` members of ``typ``
|
||||
assert typ != nil
|
||||
let hasSize = typ.size != szUncomputedSize
|
||||
@@ -258,14 +263,14 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
|
||||
of tyArray:
|
||||
computeSizeAlign(conf, typ[1])
|
||||
let elemSize = typ[1].size
|
||||
let elemSize = typ[1].size
|
||||
let len = lengthOrd(conf, typ[0])
|
||||
if elemSize < 0:
|
||||
typ.size = elemSize
|
||||
typ.align = int16(elemSize)
|
||||
elif len < 0:
|
||||
typ.size = szUnknownSize
|
||||
typ.align = szUnknownSize
|
||||
typ.align = szUnknownSize
|
||||
else:
|
||||
typ.size = toInt64Checked(len * int32(elemSize), szTooBigSize)
|
||||
typ.align = typ[1].align
|
||||
@@ -375,10 +380,8 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
|
||||
localError(conf, info, "union type may not have an object header")
|
||||
accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
|
||||
elif tfPacked in typ.flags:
|
||||
computeUnionObjectOffsetsFoldFunction(conf, typ.n, true, accum)
|
||||
else:
|
||||
computeUnionObjectOffsetsFoldFunction(conf, typ.n, false, accum)
|
||||
computeUnionObjectOffsetsFoldFunction(conf, typ.n, tfPacked in typ.flags, accum)
|
||||
elif tfPacked in typ.flags:
|
||||
accum.maxAlign = 1
|
||||
computeObjectOffsetsFoldFunction(conf, typ.n, true, accum)
|
||||
@@ -445,6 +448,16 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
typ.size = szUnknownSize
|
||||
typ.align = szUnknownSize
|
||||
typ.paddingAtEnd = szUnknownSize
|
||||
of tyInt, tyUInt:
|
||||
setSize typ, conf.target.intSize.int16
|
||||
of tyBool, tyChar, tyUInt8, tyInt8:
|
||||
setSize typ, 1
|
||||
of tyInt16, tyUInt16:
|
||||
setSize typ, 2
|
||||
of tyInt32, tyUInt32:
|
||||
setSize typ, 4
|
||||
of tyInt64, tyUInt64:
|
||||
setSize typ, 8
|
||||
else:
|
||||
typ.size = szUnknownSize
|
||||
typ.align = szUnknownSize
|
||||
@@ -482,7 +495,7 @@ template foldOffsetOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
## Returns an int literal node of the given offsetof expression in `n`.
|
||||
## Falls back to `fallback`, if the `offsetof` expression can't be processed.
|
||||
let config = conf
|
||||
let node : PNode = n
|
||||
let node = n
|
||||
var dotExpr: PNode
|
||||
block findDotExpr:
|
||||
if node[1].kind == nkDotExpr:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user