mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 11:23:40 +00:00
Compare commits
579 Commits
pr_16253
...
version-1-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a598a4945 | ||
|
|
5360d076f3 | ||
|
|
71467ecd86 | ||
|
|
ec324ad073 | ||
|
|
9ce81868a8 | ||
|
|
d993aff496 | ||
|
|
786bbff1ae | ||
|
|
fda43d1f0a | ||
|
|
6789859503 | ||
|
|
d9b1477b81 | ||
|
|
3864066408 | ||
|
|
53424c0036 | ||
|
|
6a63df181f | ||
|
|
b7b3f87719 | ||
|
|
8ebb4dc30a | ||
|
|
19fdbfc173 | ||
|
|
8f9fde0615 | ||
|
|
e6ee956845 | ||
|
|
afced7d9ab | ||
|
|
51c86fdae7 | ||
|
|
d08bba579d | ||
|
|
ac1dc03258 | ||
|
|
e8fe9275b5 | ||
|
|
0f97dd6fb3 | ||
|
|
e3bcbf5f15 | ||
|
|
d84e2d3f63 | ||
|
|
7912685905 | ||
|
|
2cc4da8fd4 | ||
|
|
a749a8b742 | ||
|
|
9a87057f0b | ||
|
|
efd5ed7328 | ||
|
|
2e87171e14 | ||
|
|
9cbd8695e7 | ||
|
|
6f0cad6843 | ||
|
|
ef10224e61 | ||
|
|
f3382743dd | ||
|
|
1dab585a26 | ||
|
|
a77ca1a4bf | ||
|
|
0779a5e11b | ||
|
|
a17c077f78 | ||
|
|
47010a3919 | ||
|
|
3c9b68dc15 | ||
|
|
ec72abc7b7 | ||
|
|
a08f56f9ba | ||
|
|
246267aa52 | ||
|
|
ce8d9dd1cb | ||
|
|
4fc535fbd6 | ||
|
|
2d529edf3e | ||
|
|
d37901fe06 | ||
|
|
dc59e67a12 | ||
|
|
09f7be13b6 | ||
|
|
d80397c7d7 | ||
|
|
efa3479e4e | ||
|
|
e8ec3efd3d | ||
|
|
8f102f9e62 | ||
|
|
876f6d69a8 | ||
|
|
50173ec7ec | ||
|
|
ecab260330 | ||
|
|
43ce0558b4 | ||
|
|
19b3f8c0ea | ||
|
|
5ad4b72ac7 | ||
|
|
d7dfbf026b | ||
|
|
79a1990774 | ||
|
|
106cde1ff8 | ||
|
|
965eeb68e2 | ||
|
|
0dbac38d12 | ||
|
|
f16e4dd22a | ||
|
|
ede6bc4d67 | ||
|
|
d2f91ab1b9 | ||
|
|
69faab3cf6 | ||
|
|
b7a1210964 | ||
|
|
0d5999e6a8 | ||
|
|
60dc41a5e4 | ||
|
|
ba5d873f63 | ||
|
|
f55f3d6ffd | ||
|
|
118f83f965 | ||
|
|
72afd29a9a | ||
|
|
30921aaff5 | ||
|
|
a3b65da80f | ||
|
|
ba2d8ba468 | ||
|
|
0ac3461c7d | ||
|
|
e7fc94e130 | ||
|
|
44708f4b01 | ||
|
|
0e9250264b | ||
|
|
5ffd507014 | ||
|
|
322fc31041 | ||
|
|
5ab9945345 | ||
|
|
b0cee7c0c5 | ||
|
|
5e4648232b | ||
|
|
3bd03d71a0 | ||
|
|
238efc025e | ||
|
|
a66158dd3d | ||
|
|
6863b5d289 | ||
|
|
9d573f4a1d | ||
|
|
070ecb036c | ||
|
|
107ec62baf | ||
|
|
ffcccd5986 | ||
|
|
c001b11320 | ||
|
|
e4c13c3fd4 | ||
|
|
6b11a9ec28 | ||
|
|
173a15b370 | ||
|
|
c4380107d6 | ||
|
|
09fe696fdd | ||
|
|
6fbff263e6 | ||
|
|
fcaacbf374 | ||
|
|
2d19520b5c | ||
|
|
1cca8ccca0 | ||
|
|
a9f1e2dfcd | ||
|
|
7a747fe320 | ||
|
|
547f205794 | ||
|
|
fa3639ba33 | ||
|
|
cd0f805832 | ||
|
|
579efdabb0 | ||
|
|
7b99712bcf | ||
|
|
58c7474838 | ||
|
|
a2521b1dc7 | ||
|
|
5d39a8283c | ||
|
|
01ef1e1500 | ||
|
|
80ece5921f | ||
|
|
bd4609f20e | ||
|
|
b901e94936 | ||
|
|
0cb84726d0 | ||
|
|
1cd48e4b2a | ||
|
|
bb56a37732 | ||
|
|
d1b5df06b0 | ||
|
|
71ba2e7f3c | ||
|
|
49271783a3 | ||
|
|
04d0716f37 | ||
|
|
55776451b4 | ||
|
|
476031f0ed | ||
|
|
c377a5b8a1 | ||
|
|
2410580d59 | ||
|
|
1355083708 | ||
|
|
6c5d4946e4 | ||
|
|
77da35db17 | ||
|
|
4fc22cdd4d | ||
|
|
ae83058be2 | ||
|
|
0e4758ac30 | ||
|
|
a058dcaf5f | ||
|
|
29f44c090e | ||
|
|
147214e18f | ||
|
|
503e7b708b | ||
|
|
7b9b173476 | ||
|
|
b686912622 | ||
|
|
c50adf10d9 | ||
|
|
2b6797dc42 | ||
|
|
eaf8977723 | ||
|
|
3601bb81c9 | ||
|
|
7142078707 | ||
|
|
b855404c71 | ||
|
|
653865559a | ||
|
|
ad0e4974c8 | ||
|
|
23d4108773 | ||
|
|
249551dbfa | ||
|
|
285a18d683 | ||
|
|
91fc5cb6c1 | ||
|
|
1d7ccc0ca6 | ||
|
|
db88ef35dd | ||
|
|
f222625b17 | ||
|
|
86a9f2b32f | ||
|
|
e3275b2040 | ||
|
|
1e72e25410 | ||
|
|
bc3e964e9d | ||
|
|
c641273606 | ||
|
|
98756bb26b | ||
|
|
42ff3aa75a | ||
|
|
5392dbc10e | ||
|
|
770a3889fd | ||
|
|
c5d1dc5f69 | ||
|
|
553e51ccba | ||
|
|
751d584b80 | ||
|
|
037f87d904 | ||
|
|
01ce56ab9e | ||
|
|
c88f58948a | ||
|
|
a456c8797f | ||
|
|
168fcc6965 | ||
|
|
c2d098b974 | ||
|
|
2072eebcea | ||
|
|
ae31ed4665 | ||
|
|
3f85abbd54 | ||
|
|
6f05abf21c | ||
|
|
ed21e84f46 | ||
|
|
9bc30a1ff8 | ||
|
|
21a26548a4 | ||
|
|
564a88006a | ||
|
|
babc9b234d | ||
|
|
844717f52b | ||
|
|
db9442bf84 | ||
|
|
5bddac3e34 | ||
|
|
87bd753cb3 | ||
|
|
e53e5476a7 | ||
|
|
7ceb4e4c87 | ||
|
|
ca620d6089 | ||
|
|
025ada1809 | ||
|
|
7ad8c44e28 | ||
|
|
0fc1b79b75 | ||
|
|
8155b8d3ce | ||
|
|
c25621d153 | ||
|
|
24e4099d36 | ||
|
|
eaac22b9aa | ||
|
|
f0324e99da | ||
|
|
4ea0ce9149 | ||
|
|
a676c3aeca | ||
|
|
918a7d9f54 | ||
|
|
aae32f5623 | ||
|
|
410254b485 | ||
|
|
4234bbe7bd | ||
|
|
71c5bdf6b3 | ||
|
|
149c0ad46f | ||
|
|
57e307f3a8 | ||
|
|
a0eec605ba | ||
|
|
7e7b35b5c0 | ||
|
|
7e80df2267 | ||
|
|
e70379811b | ||
|
|
0c9c6d2a68 | ||
|
|
4e56bcfc0e | ||
|
|
10ca10eb83 | ||
|
|
d5be917994 | ||
|
|
fe1e09a881 | ||
|
|
b2b226bb28 | ||
|
|
592321c7f5 | ||
|
|
cf12d6fcde | ||
|
|
26e52d7c5d | ||
|
|
628c9c3c7f | ||
|
|
5c4044cd80 | ||
|
|
46543d8e9b | ||
|
|
32171fc66d | ||
|
|
b220294f13 | ||
|
|
6274bc35dd | ||
|
|
a76f36b4e5 | ||
|
|
b47d12fe0a | ||
|
|
425f828178 | ||
|
|
f2b52ec432 | ||
|
|
01d27ef1db | ||
|
|
6df5fa424a | ||
|
|
ebd6619aaa | ||
|
|
0cf39669df | ||
|
|
512aef60ae | ||
|
|
2dff0c1a61 | ||
|
|
5def1fc8f6 | ||
|
|
07824b3053 | ||
|
|
0dc51dfe47 | ||
|
|
09be80c857 | ||
|
|
82af5c7f6d | ||
|
|
892b1f7583 | ||
|
|
3e93e00391 | ||
|
|
7acdacb253 | ||
|
|
b92336ab33 | ||
|
|
6f347a82aa | ||
|
|
f3300c1a9c | ||
|
|
42020a2331 | ||
|
|
e494f1b21e | ||
|
|
22d043997c | ||
|
|
81a52fae78 | ||
|
|
ab1717984d | ||
|
|
d6ea7cc49a | ||
|
|
fbaeea8adf | ||
|
|
85e943db50 | ||
|
|
67b94a96f7 | ||
|
|
75bc4a9b78 | ||
|
|
9622c56f37 | ||
|
|
9a83cae9dc | ||
|
|
1af76bc5a2 | ||
|
|
840b34684d | ||
|
|
6602961637 | ||
|
|
3a685e863e | ||
|
|
2dbceb319c | ||
|
|
b13dba2c19 | ||
|
|
31f7b17dd0 | ||
|
|
ea69f04cc7 | ||
|
|
1779f6aa9a | ||
|
|
a33603925d | ||
|
|
da325b0822 | ||
|
|
196e93f9e1 | ||
|
|
70478d34e3 | ||
|
|
fe5edb7ab0 | ||
|
|
de6d7dcca9 | ||
|
|
9e3762b6da | ||
|
|
5cd2665c29 | ||
|
|
4857d9204e | ||
|
|
c5df4ed62a | ||
|
|
4728e9d433 | ||
|
|
2f6dc73342 | ||
|
|
48936ab1c0 | ||
|
|
26ed32e67e | ||
|
|
01dc38a05c | ||
|
|
b21f81dade | ||
|
|
5bb626d4b1 | ||
|
|
2f247ed1a7 | ||
|
|
a5a2c57e88 | ||
|
|
bce9a9daed | ||
|
|
4071b3fad8 | ||
|
|
064ed4846d | ||
|
|
6007b12b30 | ||
|
|
eecd8373ed | ||
|
|
30737676de | ||
|
|
65a7496e51 | ||
|
|
48d18df69c | ||
|
|
a8c6e36323 | ||
|
|
38dbdc270e | ||
|
|
79b5f8c4e2 | ||
|
|
f111afc319 | ||
|
|
b6ed118f0c | ||
|
|
43fa8663f7 | ||
|
|
1aa9273640 | ||
|
|
19dd56f018 | ||
|
|
b6333c4a20 | ||
|
|
d723d5ff72 | ||
|
|
cdbcada3d7 | ||
|
|
5c36f24da2 | ||
|
|
1cdce314a7 | ||
|
|
a67f89e643 | ||
|
|
4fbd28a1a4 | ||
|
|
69d4e49630 | ||
|
|
60350eca1a | ||
|
|
6af6818fe9 | ||
|
|
d070ccbc03 | ||
|
|
fca6a0bd6a | ||
|
|
c546ba5d23 | ||
|
|
7fa782e3a0 | ||
|
|
b93edcd059 | ||
|
|
28985686c0 | ||
|
|
f9b95d1cb4 | ||
|
|
032512cebd | ||
|
|
5e1bffb724 | ||
|
|
e0328e28ee | ||
|
|
afdbfd2c7e | ||
|
|
17d45dfd6a | ||
|
|
f7c79db846 | ||
|
|
b1a0467ffd | ||
|
|
2c24ac1849 | ||
|
|
7a43d00a64 | ||
|
|
0cdbf5e04e | ||
|
|
320a820eb4 | ||
|
|
ebf0e7ebb1 | ||
|
|
9ee9b4283d | ||
|
|
213a9f9f34 | ||
|
|
8c0f2f0152 | ||
|
|
d0d8c95094 | ||
|
|
ec13574b19 | ||
|
|
a1165c8231 | ||
|
|
babd80b446 | ||
|
|
f01ffbf6f1 | ||
|
|
0da50cef4f | ||
|
|
76c347515a | ||
|
|
7f90bcf5b4 | ||
|
|
d81484bff9 | ||
|
|
27732a4248 | ||
|
|
3e677a6225 | ||
|
|
5cfa3672b3 | ||
|
|
0683e8f747 | ||
|
|
d2de2e7be1 | ||
|
|
224319f787 | ||
|
|
871e90aa4e | ||
|
|
ca0757d09f | ||
|
|
f1519259f8 | ||
|
|
eaf43a1bd9 | ||
|
|
dd80e968e8 | ||
|
|
99528ee295 | ||
|
|
2631e99238 | ||
|
|
9dc97ed143 | ||
|
|
76b0842994 | ||
|
|
eb42fe51da | ||
|
|
0bc52ddb85 | ||
|
|
a1c431c6ab | ||
|
|
121602e88f | ||
|
|
565cd4dd25 | ||
|
|
38730862fc | ||
|
|
999a4bb750 | ||
|
|
2292ff950a | ||
|
|
c5d62bcbfe | ||
|
|
8e04112762 | ||
|
|
c9df6cfd92 | ||
|
|
203c18352a | ||
|
|
ec674e6d5b | ||
|
|
322d2f8096 | ||
|
|
c35cb17b13 | ||
|
|
8b86ba96f8 | ||
|
|
01a0b31167 | ||
|
|
02ce5a585b | ||
|
|
ce63020110 | ||
|
|
5abf259908 | ||
|
|
31fe32afd1 | ||
|
|
fbd99c781f | ||
|
|
c9f46ca8c9 | ||
|
|
56a15976b5 | ||
|
|
cba0c20be8 | ||
|
|
60f43fb690 | ||
|
|
e32de02f0a | ||
|
|
ece219de2f | ||
|
|
8923e34d7f | ||
|
|
113bd34b6c | ||
|
|
73e569fec9 | ||
|
|
bd1ca4bb3f | ||
|
|
0a017b208b | ||
|
|
d406727016 | ||
|
|
09d85d8b24 | ||
|
|
e5e445f042 | ||
|
|
aae2356b91 | ||
|
|
5ea0e5608d | ||
|
|
a9485f19a5 | ||
|
|
dda6181fff | ||
|
|
d79f61e54d | ||
|
|
33a1e3acb9 | ||
|
|
831fed1c01 | ||
|
|
65e0906e69 | ||
|
|
c484943cab | ||
|
|
000e6875bd | ||
|
|
17e61c75a2 | ||
|
|
0277cd5252 | ||
|
|
621061d62f | ||
|
|
d53a057f5f | ||
|
|
7d0bfc6725 | ||
|
|
5771a0f9c4 | ||
|
|
5f61f1594d | ||
|
|
62ac3a01fa | ||
|
|
c9e7798978 | ||
|
|
ac7efa1964 | ||
|
|
8a98177025 | ||
|
|
fd76c00479 | ||
|
|
8786e7dddf | ||
|
|
3fd11d7e96 | ||
|
|
a3c2eb04b9 | ||
|
|
46f0f6e47e | ||
|
|
0e7138417c | ||
|
|
e9d5a9d395 | ||
|
|
9508b06513 | ||
|
|
b1f325d641 | ||
|
|
7c7815402a | ||
|
|
c9a52971f4 | ||
|
|
6f290fa386 | ||
|
|
1561a83c49 | ||
|
|
a1f413bcac | ||
|
|
2064fda582 | ||
|
|
efe5a33988 | ||
|
|
4873221429 | ||
|
|
ab0d06869e | ||
|
|
06f1828ee2 | ||
|
|
1368316b7f | ||
|
|
b0cbc9a74c | ||
|
|
64689f932c | ||
|
|
3e39f5bfec | ||
|
|
28af1e5e45 | ||
|
|
c6e3ad4ab9 | ||
|
|
26707a62fc | ||
|
|
0b44840299 | ||
|
|
02d94966c9 | ||
|
|
62d1d0516c | ||
|
|
7d120b83d1 | ||
|
|
0565a70eab | ||
|
|
252df3f1c0 | ||
|
|
608457defc | ||
|
|
4f392727c8 | ||
|
|
4bb2e9e921 | ||
|
|
1788b8b991 | ||
|
|
0e5bf5953e | ||
|
|
85841cd318 | ||
|
|
b1045cb693 | ||
|
|
151b4cc514 | ||
|
|
f194356d21 | ||
|
|
88573da12d | ||
|
|
2a68fa71eb | ||
|
|
fcd05bd031 | ||
|
|
d38177b11f | ||
|
|
9035618347 | ||
|
|
e22d494409 | ||
|
|
6365d8c39a | ||
|
|
b96954ef52 | ||
|
|
bb937f2357 | ||
|
|
dcc40b9609 | ||
|
|
3177e16b0d | ||
|
|
92457cbc39 | ||
|
|
73c4ede283 | ||
|
|
55907a8bf8 | ||
|
|
9de1013c94 | ||
|
|
589dc2d18f | ||
|
|
0adfe6c5a1 | ||
|
|
fd2da6da54 | ||
|
|
9b560747e8 | ||
|
|
bf3a2e010d | ||
|
|
9fcf1a5d4c | ||
|
|
4877caa462 | ||
|
|
8aa045806c | ||
|
|
b9363c8bb4 | ||
|
|
1dc47696c0 | ||
|
|
b741f3cbd3 | ||
|
|
9df55a8979 | ||
|
|
01c38610f5 | ||
|
|
40db88d0f8 | ||
|
|
ff819757be | ||
|
|
2d2587747f | ||
|
|
0bb7bd07d2 | ||
|
|
ebb140edda | ||
|
|
ec9e51abe6 | ||
|
|
b8f1347c99 | ||
|
|
d7370ce269 | ||
|
|
971b639739 | ||
|
|
5e13d577ac | ||
|
|
b6024fe861 | ||
|
|
9746d46009 | ||
|
|
82c930c364 | ||
|
|
c25b7e79cf | ||
|
|
8fe8aada87 | ||
|
|
231a135563 | ||
|
|
7994556f38 | ||
|
|
8c9e88f520 | ||
|
|
7e52a57121 | ||
|
|
35c812fda1 | ||
|
|
47888c18f7 | ||
|
|
a8e040ec30 | ||
|
|
2fb1c80f42 | ||
|
|
e1f3c74bdc | ||
|
|
52d2ff601b | ||
|
|
41b71487af | ||
|
|
3d3b34473b | ||
|
|
fc0aec6f1b | ||
|
|
7cafd22377 | ||
|
|
9aff19f51a | ||
|
|
bc823b6487 | ||
|
|
3d3d790c63 | ||
|
|
a90cabbe40 | ||
|
|
2539d7a862 | ||
|
|
30737b3e7f | ||
|
|
984691bb67 | ||
|
|
5f70b1ab53 | ||
|
|
afa4bc34b4 | ||
|
|
0648cde117 | ||
|
|
980ec713da | ||
|
|
26ed4e5413 | ||
|
|
161736ceb3 | ||
|
|
ce6fa79858 | ||
|
|
f2e7e5d899 | ||
|
|
d4de5d32bc | ||
|
|
efdb180f62 | ||
|
|
095202e218 | ||
|
|
f4e41e6c4f | ||
|
|
8aec198abc | ||
|
|
9084d9bc02 | ||
|
|
48c62ca48b | ||
|
|
70320482be | ||
|
|
e3a07f1997 | ||
|
|
bcf9448a75 | ||
|
|
a2f5e98baa | ||
|
|
a3b370fa87 | ||
|
|
b7a0c08b4f | ||
|
|
46275126b8 | ||
|
|
83c472c40d | ||
|
|
ac57c3193d | ||
|
|
7cf5e73fb7 | ||
|
|
c14008d77f | ||
|
|
168a8784f4 | ||
|
|
ee876aee28 | ||
|
|
8ed903d1d0 | ||
|
|
bfa8188dac | ||
|
|
56409c15c0 | ||
|
|
b614d97a2d | ||
|
|
2bb3a85a7c | ||
|
|
1247043c90 | ||
|
|
0ba76622a3 | ||
|
|
ab6770e77f | ||
|
|
c7920e9f87 | ||
|
|
167881bb83 | ||
|
|
73366c015f | ||
|
|
cfee71e779 | ||
|
|
1090b0c4af | ||
|
|
3f6de926f0 | ||
|
|
13343180b8 | ||
|
|
95dce90467 | ||
|
|
f85e09633d | ||
|
|
575450dfec | ||
|
|
6a2babac47 | ||
|
|
a6e192f020 | ||
|
|
233c6e9fb3 | ||
|
|
97286db546 | ||
|
|
1ac029c0f6 | ||
|
|
b18b636ea6 | ||
|
|
ac89e06c6e | ||
|
|
861b625a66 | ||
|
|
727c6378d2 |
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: ["Feature"]
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
23
.github/workflows/ci_docs.yml
vendored
23
.github/workflows/ci_docs.yml
vendored
@@ -2,10 +2,10 @@ name: Nim Docs CI
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'compiler/docgen.nim'
|
||||
- 'compiler/renderverbatim.nim'
|
||||
- 'compiler/**.nim'
|
||||
- 'config/nimdoc.cfg'
|
||||
- 'doc/**.rst'
|
||||
- 'doc/**.md'
|
||||
- 'doc/nimdoc.css'
|
||||
- 'lib/**.nim'
|
||||
- 'nimdoc/testproject/expected/testproject.html'
|
||||
@@ -13,13 +13,14 @@ on:
|
||||
- 'tools/kochdocs.nim'
|
||||
- '.github/workflows/ci_docs.yml'
|
||||
- 'koch.nim'
|
||||
|
||||
pull_request:
|
||||
# Run only on changes on these files.
|
||||
paths:
|
||||
- 'compiler/docgen.nim'
|
||||
- 'compiler/renderverbatim.nim'
|
||||
- 'compiler/**.nim'
|
||||
- 'config/nimdoc.cfg'
|
||||
- 'doc/**.rst'
|
||||
- 'doc/**.md'
|
||||
- 'doc/nimdoc.css'
|
||||
- 'lib/**.nim'
|
||||
- 'nimdoc/testproject/expected/testproject.html'
|
||||
@@ -28,6 +29,10 @@ on:
|
||||
- '.github/workflows/ci_docs.yml'
|
||||
- 'koch.nim'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
@@ -36,11 +41,11 @@ jobs:
|
||||
target: [linux, windows, osx]
|
||||
include:
|
||||
- target: linux
|
||||
os: ubuntu-20.04
|
||||
os: ubuntu-22.04
|
||||
- target: windows
|
||||
os: windows-2019
|
||||
os: windows-latest
|
||||
- target: osx
|
||||
os: macos-10.15
|
||||
os: macos-15
|
||||
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -48,7 +53,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
@@ -104,7 +109,7 @@ jobs:
|
||||
if: |
|
||||
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
|
||||
matrix.target == 'linux'
|
||||
uses: crazy-max/ghaction-github-pages@v1
|
||||
uses: crazy-max/ghaction-github-pages@v5
|
||||
with:
|
||||
build_dir: doc/html
|
||||
env:
|
||||
|
||||
32
.github/workflows/ci_packages.yml
vendored
32
.github/workflows/ci_packages.yml
vendored
@@ -1,13 +1,24 @@
|
||||
name: Packages CI
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 'devel'
|
||||
- 'version-2-2'
|
||||
- 'version-2-0'
|
||||
- 'version-1-6'
|
||||
- 'version-1-2'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-10.15]
|
||||
cpu: [amd64]
|
||||
os: [ubuntu-latest, macos-14]
|
||||
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
|
||||
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -17,26 +28,27 @@ jobs:
|
||||
NIM_TESTAMENT_BATCH: ${{ matrix.batch }}
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: 'Install node.js 16.x'
|
||||
uses: actions/setup-node@v2
|
||||
- name: 'Install node.js'
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '16.x'
|
||||
node-version: 24
|
||||
|
||||
- name: 'Install dependencies (Linux amd64)'
|
||||
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
|
||||
run: |
|
||||
sudo apt-fast update -qq
|
||||
sudo apt-get update -qq
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
sudo apt-fast install --no-install-recommends -yq \
|
||||
sudo apt-get install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
|
||||
valgrind libc6-dbg libblas-dev xorg-dev
|
||||
valgrind libc6-dbg libblas-dev liblapack-dev libpcre3 xorg-dev
|
||||
- name: 'Install dependencies (macOS)'
|
||||
if: runner.os == 'macOS'
|
||||
run: brew install boehmgc make sfml gtk+3
|
||||
# XXX can't find boehm and gtk on macos 13
|
||||
- name: 'Install dependencies (Windows)'
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- '*'
|
||||
- 'devel'
|
||||
- 'version-*'
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
@@ -19,32 +20,32 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
Linux_amd64:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
CPU: amd64
|
||||
# regularly breaks, refs bug #17325
|
||||
Linux_i386:
|
||||
# on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
|
||||
# g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
|
||||
vmImage: 'ubuntu-18.04'
|
||||
CPU: i386
|
||||
OSX_amd64:
|
||||
vmImage: 'macOS-10.15'
|
||||
CPU: amd64
|
||||
OSX_amd64_cpp:
|
||||
vmImage: 'macOS-10.15'
|
||||
CPU: amd64
|
||||
# Linux_i386:
|
||||
# # on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
|
||||
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
|
||||
# vmImage: 'ubuntu-18.04'
|
||||
# CPU: i386
|
||||
OSX_arm64:
|
||||
vmImage: 'macos-15'
|
||||
CPU: arm64
|
||||
OSX_arm64_cpp:
|
||||
vmImage: 'macos-15'
|
||||
CPU: arm64
|
||||
NIM_COMPILE_TO_CPP: true
|
||||
Windows_amd64_batch0_3:
|
||||
vmImage: 'windows-2019'
|
||||
vmImage: 'windows-2025'
|
||||
CPU: amd64
|
||||
# see also: `NIM_TEST_PACKAGES`
|
||||
NIM_TESTAMENT_BATCH: "0_3"
|
||||
Windows_amd64_batch1_3:
|
||||
vmImage: 'windows-2019'
|
||||
vmImage: 'windows-2025'
|
||||
CPU: amd64
|
||||
NIM_TESTAMENT_BATCH: "1_3"
|
||||
Windows_amd64_batch2_3:
|
||||
vmImage: 'windows-2019'
|
||||
vmImage: 'windows-2025'
|
||||
CPU: amd64
|
||||
NIM_TESTAMENT_BATCH: "2_3"
|
||||
|
||||
@@ -72,17 +73,19 @@ jobs:
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '16.x'
|
||||
displayName: 'Install node.js 16.x'
|
||||
versionSpec: '20.x'
|
||||
displayName: 'Install node.js 20.x'
|
||||
condition: and(succeeded(), eq(variables['skipci'], 'false'))
|
||||
|
||||
- bash: |
|
||||
set -e
|
||||
. ci/funs.sh
|
||||
echo_run sudo apt-fast update -qq
|
||||
echo_run sudo add-apt-repository universe
|
||||
echo_run sudo apt-get update -qq
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
echo_run sudo apt-fast install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
|
||||
echo_run sudo apt-get install --no-install-recommends -yq \
|
||||
gcc-14 g++-14 libpcre3 liblapack-dev libpcre3 liblapack-dev libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
|
||||
echo_run sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 60 --slave /usr/bin/g++ g++ /usr/bin/g++-14
|
||||
displayName: 'Install dependencies (amd64 Linux)'
|
||||
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
|
||||
|
||||
@@ -99,15 +102,16 @@ jobs:
|
||||
Pin-Priority: 1001
|
||||
EOF
|
||||
|
||||
# echo_run sudo apt-fast update -qq
|
||||
echo_run sudo apt-fast update -qq || echo "failed, see bug #17343"
|
||||
# echo_run sudo apt-get update -qq
|
||||
echo_run sudo apt-get update -qq || echo "failed, see bug #17343"
|
||||
# `:i386` (e.g. in `libffi-dev:i386`) is needed otherwise you may get:
|
||||
# `could not load: libffi.so` during dynamic loading.
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
echo_run sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
|
||||
echo_run sudo apt-get install --no-install-recommends --allow-downgrades -yq \
|
||||
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
|
||||
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386 libffi-dev:i386
|
||||
|
||||
|
||||
cat << EOF > bin/gcc
|
||||
#!/bin/bash
|
||||
|
||||
@@ -129,6 +133,7 @@ jobs:
|
||||
- bash: brew install boehmgc make sfml
|
||||
displayName: 'Install dependencies (OSX)'
|
||||
condition: and(succeeded(), eq(variables['skipci'], 'false'), eq(variables['Agent.OS'], 'Darwin'))
|
||||
# XXX can't find boehm on macos 13
|
||||
|
||||
- bash: |
|
||||
set -e
|
||||
|
||||
@@ -24,6 +24,6 @@ if not exist %nim_csources% (
|
||||
cd ..
|
||||
copy /y bin\nim.exe %nim_csources%
|
||||
)
|
||||
bin\nim.exe c --skipUserCfg --skipParentCfg --hints:off koch
|
||||
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
|
||||
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
|
||||
koch tools --skipUserCfg --skipParentCfg --hints:off
|
||||
|
||||
@@ -11,7 +11,7 @@ set -e # exit on first error
|
||||
. ci/funs.sh
|
||||
nimBuildCsourcesIfNeeded "$@"
|
||||
|
||||
echo_run bin/nim c --skipUserCfg --skipParentCfg --hints:off koch
|
||||
echo_run bin/nim c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
|
||||
echo_run ./koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
|
||||
echo_run ./koch tools --skipUserCfg --skipParentCfg --hints:off
|
||||
|
||||
|
||||
89
changelog.md
89
changelog.md
@@ -3,67 +3,65 @@
|
||||
|
||||
## 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.
|
||||
- `addr` is now available for all addressable locations,
|
||||
`unsafeAddr` is now deprecated and an alias for `addr`.
|
||||
|
||||
- Deprecated `std/sums`.
|
||||
- `io`, `assertions`, `formatfloat`, and `` dollars.`$` `` for objects are about to move out of the `system` module. You may instead import `std/syncio`, `std/assertions`, `std/formatfloat` and `std/objectdollar`.
|
||||
The `-d:nimPreviewSlimSystem` option makes these imports required.
|
||||
|
||||
- The `gc:v2` option is removed.
|
||||
|
||||
- The `mainmodule` and `m` options are removed.
|
||||
|
||||
- The `threads:on` option is now the default.
|
||||
|
||||
- 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.
|
||||
## Standard library additions and changes
|
||||
|
||||
- `addr` is now available for all addressable locations, `unsafeAddr` is deprecated and
|
||||
becomes an alias for `addr`.
|
||||
- Pointer to `cstring` conversion now triggers a `[PtrToCstringConv]` warning.
|
||||
This warning will become an error in future versions! Use a `cast` operation
|
||||
like `cast[cstring](x)` instead.
|
||||
|
||||
- io is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/syncio`.
|
||||
- `logging` will default to flushing all log level messages. To get the legacy behaviour of only flushing Error and Fatal messages, use `-d:nimV1LogFlushBehavior`.
|
||||
|
||||
- The `gc:v2` option is removed.
|
||||
- Object fields now support default values, see https://nim-lang.github.io/Nim/manual.html#types-default-values-for-object-fields for details.
|
||||
|
||||
- Redefining templates with the same signature was previously
|
||||
allowed to support certain macro code. To do this explicitly, the
|
||||
`{.redefine.}` pragma has been added. Note that this is only for templates.
|
||||
Implicit redefinition of templates is now deprecated and will give an error in the future.
|
||||
|
||||
- Using an unnamed break in a block is deprecated. This warning will become an error in future versions! Use a named block with a named break instead.
|
||||
|
||||
- Several Standard libraries are moved to nimble packages, use `nimble` to install them:
|
||||
- `std/punycode` => `punycode`
|
||||
- `std/asyncftpclient` => `asyncftpclient`
|
||||
- `std/smtp` => `smtp`
|
||||
- `std/db_common` => `db_connector/db_common`
|
||||
- `std/db_sqlite` => `db_connector/db_sqlite`
|
||||
- `std/db_mysql` => `db_connector/db_mysql`
|
||||
- `std/db_postgres` => `db_connector/db_postgres`
|
||||
- `std/db_odbc` => `db_connector/db_odbc`
|
||||
|
||||
- Previously, calls like `foo(a, b): ...` or `foo(a, b) do: ...` where the final argument of
|
||||
`foo` had type `proc ()` were assumed by the compiler to mean `foo(a, b, proc () = ...)`.
|
||||
This behavior is now deprecated. Use `foo(a, b) do (): ...` or `foo(a, b, proc () = ...)` instead.
|
||||
|
||||
- If no exception or any exception deriving from Exception but not Defect or CatchableError given in except, a `warnBareExcept` warning will be triggered.
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Changes:"
|
||||
- `macros.parseExpr` and `macros.parseStmt` now accept an optional.
|
||||
- `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.
|
||||
|
||||
@@ -96,15 +94,14 @@ becomes an alias for `addr`.
|
||||
```
|
||||
- [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
|
||||
|
||||
- `nim` can now compile version 1.4.0 as follows: `nim c --lib:lib --stylecheck:off compiler/nim`,
|
||||
without requiring `-d:nimVersion140` which is now a noop.
|
||||
|
||||
- `--styleCheck`, `--hintAsError` and `--warningAsError` now only applies to the current package.
|
||||
|
||||
|
||||
## Tool changes
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -282,7 +282,7 @@
|
||||
- Removed the deprecated `asyncdispatch.newAsyncNativeSocket`.
|
||||
- Removed the deprecated `dom.releaseEvents` and `dom.captureEvents`.
|
||||
|
||||
- Removed `sharedlist.initSharedList`, was deprecated and produces undefined behaviour.
|
||||
- Removed `sharedlists.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)
|
||||
|
||||
@@ -58,7 +58,11 @@ _nimNumCpu(){
|
||||
# FreeBSD | macOS: $(sysctl -n hw.ncpu)
|
||||
# OpenBSD: $(sysctl -n hw.ncpuonline)
|
||||
# windows: $NUMBER_OF_PROCESSORS ?
|
||||
echo $(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || 1)
|
||||
if env | grep -q '^NIMCORES='; then
|
||||
echo $NIMCORES
|
||||
else
|
||||
echo $(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || 1)
|
||||
fi
|
||||
}
|
||||
|
||||
_nimBuildCsourcesIfNeeded(){
|
||||
@@ -76,8 +80,6 @@ _nimBuildCsourcesIfNeeded(){
|
||||
makeX=gmake
|
||||
elif [ "$unamestr" = 'CROSSOS' ]; then
|
||||
makeX=gmake
|
||||
elif [ "$unamestr" = 'SunOS' ]; then
|
||||
makeX=gmake
|
||||
else
|
||||
makeX=make
|
||||
fi
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
version = system.NimVersion
|
||||
author = "Andreas Rumpf"
|
||||
description = "Compiler package providing the compiler sources as a library."
|
||||
license = "MIT"
|
||||
|
||||
installDirs = @["compiler", "nimsuggest"]
|
||||
|
||||
requires "nim >= 0.14.0"
|
||||
@@ -12,9 +12,6 @@
|
||||
import
|
||||
ast, astalgo, types, trees, intsets
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
TAnalysisResult* = enum
|
||||
arNo, arMaybe, arYes
|
||||
|
||||
@@ -13,9 +13,6 @@ import
|
||||
lineinfos, hashes, options, ropes, idents, int128, tables
|
||||
from strutils import toLowerAscii
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
export int128
|
||||
|
||||
type
|
||||
@@ -232,7 +229,7 @@ type
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
TSymFlag* = enum # 48 flags!
|
||||
TSymFlag* = enum # 49 flags!
|
||||
sfUsed, # read access of sym (for warnings) or simply used
|
||||
sfExported, # symbol is exported from module
|
||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||
@@ -303,6 +300,12 @@ type
|
||||
sfSingleUsedTemp # For temporaries that we know will only be used once
|
||||
sfNoalias # 'noalias' annotation, means C's 'restrict'
|
||||
sfEffectsDelayed # an 'effectsDelayed' parameter
|
||||
sfGeneratedType # A anonymous generic type that is generated by the compiler for
|
||||
# objects that do not have generic parameters in case one of the
|
||||
# object fields has one.
|
||||
#
|
||||
# This is disallowed but can cause the typechecking to go into
|
||||
# an infinite loop, this flag is used as a sentinel to stop it.
|
||||
|
||||
TSymFlags* = set[TSymFlag]
|
||||
|
||||
@@ -502,6 +505,7 @@ type
|
||||
nfLastRead # this node is a last read
|
||||
nfFirstWrite# this node is a first write
|
||||
nfHasComment # node has a comment
|
||||
nfSkipFieldChecking # node skips field visable checking
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45)
|
||||
@@ -673,7 +677,7 @@ type
|
||||
mInSet, mRepr, mExit,
|
||||
mSetLengthStr, mSetLengthSeq,
|
||||
mIsPartOf, mAstToStr, mParallel,
|
||||
mSwap, mIsNil, mArrToSeq,
|
||||
mSwap, mIsNil, mArrToSeq, mOpenArrayToSeq,
|
||||
mNewString, mNewStringOfCap, mParseBiggestFloat,
|
||||
mMove, mWasMoved, mDestroy, mTrace,
|
||||
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mAccessTypeField, mReset,
|
||||
@@ -707,8 +711,8 @@ type
|
||||
mSymIsInstantiationOf, mNodeId, mPrivateAccess
|
||||
|
||||
|
||||
# things that we can evaluate safely at compile time, even if not asked for it:
|
||||
const
|
||||
# things that we can evaluate safely at compile time, even if not asked for it:
|
||||
ctfeWhitelist* = {mNone, mSucc,
|
||||
mPred, mInc, mDec, mOrd, mLengthOpenArray,
|
||||
mLengthStr, mLengthArray, mLengthSeq,
|
||||
@@ -737,6 +741,9 @@ const
|
||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
||||
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||
mInSet, mRepr}
|
||||
|
||||
generatedMagics* = {mNone, mIsolate, mFinished, mOpenArrayToSeq}
|
||||
## magics that are generated as normal procs in the backend
|
||||
|
||||
type
|
||||
ItemId* = object
|
||||
@@ -780,6 +787,8 @@ type
|
||||
ident*: PIdent
|
||||
else:
|
||||
sons*: TNodeSeq
|
||||
when defined(nimsuggest):
|
||||
endInfo*: TLineInfo
|
||||
|
||||
TStrTable* = object # a table[PIdent] of PSym
|
||||
counter*: int
|
||||
@@ -876,6 +885,9 @@ type
|
||||
typ*: PType
|
||||
name*: PIdent
|
||||
info*: TLineInfo
|
||||
when defined(nimsuggest):
|
||||
endInfo*: TLineInfo
|
||||
hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints
|
||||
owner*: PSym
|
||||
flags*: TSymFlags
|
||||
ast*: PNode # syntax tree of proc, iterator, etc.:
|
||||
@@ -1061,7 +1073,8 @@ const
|
||||
nfDotSetter, nfDotField,
|
||||
nfIsRef, nfIsPtr, nfPreventCg, nfLL,
|
||||
nfFromTemplate, nfDefaultRefsParam,
|
||||
nfExecuteOnReload, nfLastRead, nfFirstWrite}
|
||||
nfExecuteOnReload, nfLastRead,
|
||||
nfFirstWrite, nfSkipFieldChecking}
|
||||
namePos* = 0
|
||||
patternPos* = 1 # empty except for term rewriting macros
|
||||
genericParamsPos* = 2
|
||||
@@ -1101,11 +1114,10 @@ const
|
||||
|
||||
proc getPIdent*(a: PNode): PIdent {.inline.} =
|
||||
## Returns underlying `PIdent` for `{nkSym, nkIdent}`, or `nil`.
|
||||
# xxx consider whether also returning the 1st ident for {nkOpenSymChoice, nkClosedSymChoice}
|
||||
# which may simplify code.
|
||||
case a.kind
|
||||
of nkSym: a.sym.name
|
||||
of nkIdent: a.ident
|
||||
of nkOpenSymChoice, nkClosedSymChoice: a.sons[0].sym.name
|
||||
else: nil
|
||||
|
||||
const
|
||||
@@ -1660,6 +1672,8 @@ proc copyNode*(src: PNode): PNode =
|
||||
of nkIdent: result.ident = src.ident
|
||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||
else: discard
|
||||
when defined(nimsuggest):
|
||||
result.endInfo = src.endInfo
|
||||
|
||||
template transitionNodeKindCommon(k: TNodeKind) =
|
||||
let obj {.inject.} = n[]
|
||||
@@ -1676,6 +1690,10 @@ proc transitionIntKind*(n: PNode, kind: range[nkCharLit..nkUInt64Lit]) =
|
||||
transitionNodeKindCommon(kind)
|
||||
n.intVal = obj.intVal
|
||||
|
||||
proc transitionIntToFloatKind*(n: PNode, kind: range[nkFloatLit..nkFloat128Lit]) =
|
||||
transitionNodeKindCommon(kind)
|
||||
n.floatVal = BiggestFloat(obj.intVal)
|
||||
|
||||
proc transitionNoneToSym*(n: PNode) =
|
||||
transitionNodeKindCommon(nkSym)
|
||||
|
||||
@@ -1708,6 +1726,8 @@ template copyNodeImpl(dst, src, processSonsStmt) =
|
||||
if src == nil: return
|
||||
dst = newNode(src.kind)
|
||||
dst.info = src.info
|
||||
when defined(nimsuggest):
|
||||
result.endInfo = src.endInfo
|
||||
dst.typ = src.typ
|
||||
dst.flags = src.flags * PersistentNodeFlags
|
||||
dst.comment = src.comment
|
||||
@@ -2013,6 +2033,9 @@ template detailedInfo*(sym: PSym): string =
|
||||
proc isInlineIterator*(typ: PType): bool {.inline.} =
|
||||
typ.kind == tyProc and tfIterator in typ.flags and typ.callConv != ccClosure
|
||||
|
||||
proc isIterator*(typ: PType): bool {.inline.} =
|
||||
typ.kind == tyProc and tfIterator in typ.flags
|
||||
|
||||
proc isClosureIterator*(typ: PType): bool {.inline.} =
|
||||
typ.kind == tyProc and tfIterator in typ.flags and typ.callConv == ccClosure
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@ 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,9 +10,6 @@
|
||||
# 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
|
||||
@@ -26,40 +23,53 @@ const
|
||||
template modElemSize(arg: untyped): untyped = arg and 7
|
||||
template divElemSize(arg: untyped): untyped = arg shr 3
|
||||
|
||||
proc bitSetIn*(x: TBitSet, e: BiggestInt): bool =
|
||||
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 =
|
||||
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
|
||||
@@ -86,6 +96,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,9 +10,6 @@
|
||||
## 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)
|
||||
|
||||
@@ -155,7 +155,7 @@ proc reifiedOpenArray(n: PNode): bool {.inline.} =
|
||||
else:
|
||||
result = true
|
||||
|
||||
proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, Rope) =
|
||||
proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareForMutation = false): (Rope, Rope) =
|
||||
var a, b, c: TLoc
|
||||
initLocExpr(p, q[1], a)
|
||||
initLocExpr(p, q[2], b)
|
||||
@@ -163,6 +163,8 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope,
|
||||
# but first produce the required index checks:
|
||||
if optBoundsCheck in p.options:
|
||||
genBoundsCheck(p, a, b, c)
|
||||
if prepareForMutation:
|
||||
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
|
||||
let ty = skipTypes(a.t, abstractVar+{tyPtr})
|
||||
let dest = getTypeDesc(p.module, destType)
|
||||
let lengthExpr = "($1)-($2)+1" % [rdLoc(c), rdLoc(b)]
|
||||
@@ -192,10 +194,12 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope,
|
||||
optSeqDestructors in p.config.globalOptions:
|
||||
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
|
||||
if atyp.kind in {tyVar} and not compileToCpp(p.module):
|
||||
result = ("($4*)(*$1)$3+($2)" % [rdLoc(a), rdLoc(b), dataField(p), dest],
|
||||
result = ("(($5) ? (($4*)(*$1)$3+($2)) : NIM_NIL)" %
|
||||
[rdLoc(a), rdLoc(b), dataField(p), dest, dataFieldAccessor(p, "*" & rdLoc(a))],
|
||||
lengthExpr)
|
||||
else:
|
||||
result = ("($4*)$1$3+($2)" % [rdLoc(a), rdLoc(b), dataField(p), dest],
|
||||
result = ("(($5) ? (($4*)$1$3+($2)) : NIM_NIL)" %
|
||||
[rdLoc(a), rdLoc(b), dataField(p), dest, dataFieldAccessor(p, rdLoc(a))],
|
||||
lengthExpr)
|
||||
else:
|
||||
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
||||
@@ -236,9 +240,12 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||
if ntyp.kind in {tyVar} and not compileToCpp(p.module):
|
||||
var t: TLoc
|
||||
t.r = "(*$1)" % [a.rdLoc]
|
||||
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
||||
result = "($4) ? ((*$1)$3) : NIM_NIL, $2" %
|
||||
[a.rdLoc, lenExpr(p, t), dataField(p),
|
||||
dataFieldAccessor(p, "*" & a.rdLoc)]
|
||||
else:
|
||||
result = "$1$3, $2" % [a.rdLoc, lenExpr(p, a), dataField(p)]
|
||||
result = "($4) ? ($1$3) : NIM_NIL, $2" %
|
||||
[a.rdLoc, lenExpr(p, a), dataField(p), dataFieldAccessor(p, a.rdLoc)]
|
||||
of tyArray:
|
||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
|
||||
of tyPtr, tyRef:
|
||||
@@ -246,7 +253,9 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||
of tyString, tySequence:
|
||||
var t: TLoc
|
||||
t.r = "(*$1)" % [a.rdLoc]
|
||||
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
||||
result = "($4) ? ((*$1)$3) : NIM_NIL, $2" %
|
||||
[a.rdLoc, lenExpr(p, t), dataField(p),
|
||||
dataFieldAccessor(p, "*" & a.rdLoc)]
|
||||
of tyArray:
|
||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]
|
||||
else:
|
||||
|
||||
@@ -292,8 +292,8 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
|
||||
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $2Len_0;$n",
|
||||
[rdLoc(d), a.rdLoc])
|
||||
of tySequence:
|
||||
linefmt(p, cpsStmts, "$1.Field0 = $2$3; $1.Field1 = $4;$n",
|
||||
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a)])
|
||||
linefmt(p, cpsStmts, "$1.Field0 = ($5) ? ($2$3) : NIM_NIL; $1.Field1 = $4;$n",
|
||||
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a), dataFieldAccessor(p, a.rdLoc)])
|
||||
of tyArray:
|
||||
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n",
|
||||
[rdLoc(d), rdLoc(a), rope(lengthOrd(p.config, a.t))])
|
||||
@@ -302,8 +302,8 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
|
||||
if etyp.kind in {tyVar} and optSeqDestructors in p.config.globalOptions:
|
||||
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
|
||||
|
||||
linefmt(p, cpsStmts, "$1.Field0 = $2$3; $1.Field1 = $4;$n",
|
||||
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a)])
|
||||
linefmt(p, cpsStmts, "$1.Field0 = ($5) ? ($2$3) : NIM_NIL; $1.Field1 = $4;$n",
|
||||
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a), dataFieldAccessor(p, a.rdLoc)])
|
||||
else:
|
||||
internalError(p.config, a.lode.info, "cannot handle " & $a.t.kind)
|
||||
|
||||
@@ -444,9 +444,10 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
|
||||
[addrLoc(p.config, dest), rdLoc(src),
|
||||
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||
of tyOpenArray, tyVarargs:
|
||||
let source = addrLocOrTemp(src)
|
||||
linefmt(p, cpsStmts,
|
||||
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
|
||||
[addrLoc(p.config, dest), addrLocOrTemp(src),
|
||||
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $2->Field1, $3);$n",
|
||||
[addrLoc(p.config, dest), source,
|
||||
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
|
||||
of tySet:
|
||||
if mapSetType(p.config, ty) == ctArray:
|
||||
@@ -599,7 +600,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
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)]
|
||||
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) =
|
||||
@@ -731,7 +732,22 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
|
||||
skipTypes(typ, abstractInstOwned).kind in {tyVar} and
|
||||
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
|
||||
|
||||
proc derefBlock(p: BProc, e: PNode, d: var TLoc) =
|
||||
# We transform (block: x)[] to (block: x[])
|
||||
let e0 = e[0]
|
||||
var n = shallowCopy(e0)
|
||||
n.typ = e.typ
|
||||
for i in 0 ..< e0.len - 1:
|
||||
n[i] = e0[i]
|
||||
n[e0.len-1] = newTreeIT(nkHiddenDeref, e.info, e.typ, e0[e0.len-1])
|
||||
expr p, n, d
|
||||
|
||||
proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||
if e.kind == nkHiddenDeref and e[0].kind in {nkBlockExpr, nkBlockStmt}:
|
||||
# bug #20107. Watch out to not deref the pointer too late.
|
||||
derefBlock(p, e, d)
|
||||
return
|
||||
|
||||
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]))
|
||||
if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags:
|
||||
# XXX the amount of hacks for C's arrays is incredible, maybe we should
|
||||
@@ -1346,7 +1362,7 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
|
||||
p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
|
||||
|
||||
if a.storage == OnHeap and usesWriteBarrier(p.config):
|
||||
if canFormAcycle(a.t):
|
||||
if canFormAcycle(p.module.g.graph, a.t):
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [a.rdLoc])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [a.rdLoc])
|
||||
@@ -1383,7 +1399,7 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
|
||||
var call: TLoc
|
||||
initLoc(call, locExpr, dest.lode, OnHeap)
|
||||
if dest.storage == OnHeap and usesWriteBarrier(p.config):
|
||||
if canFormAcycle(dest.t):
|
||||
if canFormAcycle(p.module.g.graph, dest.t):
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [dest.rdLoc])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [dest.rdLoc])
|
||||
@@ -1431,6 +1447,7 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
|
||||
getSeqPayloadType(p.module, seqtype),
|
||||
])
|
||||
else:
|
||||
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false) # bug #22560
|
||||
putIntoDest(p, d, e, ropecg(p.module,
|
||||
"($1)#nimNewSeqOfCap($2, $3)", [
|
||||
getTypeDesc(p.module, seqtype),
|
||||
@@ -1562,6 +1579,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
return
|
||||
if d.k == locNone:
|
||||
getTemp(p, n.typ, d)
|
||||
initLocExpr(p, n[1], a)
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
let L = toInt(lengthOrd(p.config, n[1].typ))
|
||||
if optSeqDestructors in p.config.globalOptions:
|
||||
@@ -1571,7 +1589,6 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
getSeqPayloadType(p.module, seqtype)])
|
||||
else:
|
||||
genNewSeqAux(p, d, intLiteral(L), L == 0)
|
||||
initLocExpr(p, n[1], a)
|
||||
# bug #5007; do not produce excessive C source code:
|
||||
if L < 10:
|
||||
for i in 0..<L:
|
||||
@@ -1699,7 +1716,9 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
|
||||
of tyString, tySequence:
|
||||
putIntoDest(p, b, e,
|
||||
"$1$3, $2" % [rdLoc(a), lenExpr(p, a), dataField(p)], a.storage)
|
||||
"($4) ? ($1$3) : NIM_NIL, $2" %
|
||||
[rdLoc(a), lenExpr(p, a), dataField(p), dataFieldAccessor(p, a.rdLoc)],
|
||||
a.storage)
|
||||
of tyArray:
|
||||
putIntoDest(p, b, e,
|
||||
"$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))], a.storage)
|
||||
@@ -1779,20 +1798,33 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
# Bug #9279, len(toOpenArray()) has to work:
|
||||
if a.kind in nkCallKinds and a[0].kind == nkSym and a[0].sym.magic == mSlice:
|
||||
# magic: pass slice to openArray:
|
||||
var m: TLoc
|
||||
var b, c: TLoc
|
||||
initLocExpr(p, a[1], m)
|
||||
initLocExpr(p, a[2], b)
|
||||
initLocExpr(p, a[3], c)
|
||||
if optBoundsCheck in p.options:
|
||||
genBoundsCheck(p, m, b, c)
|
||||
if op == mHigh:
|
||||
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)]))
|
||||
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1))", [rdLoc(b), rdLoc(c)]))
|
||||
else:
|
||||
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)]))
|
||||
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1)+1)", [rdLoc(b), rdLoc(c)]))
|
||||
else:
|
||||
if not reifiedOpenArray(a):
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
|
||||
else: unaryExpr(p, e, d, "$1Len_0")
|
||||
else:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1.Field1-1)")
|
||||
else: unaryExpr(p, e, d, "$1.Field1")
|
||||
let isDeref = a.kind in {nkHiddenDeref, nkDerefExpr}
|
||||
if op == mHigh:
|
||||
if isDeref:
|
||||
unaryExpr(p, e, d, "($1->Field1-1)")
|
||||
else:
|
||||
unaryExpr(p, e, d, "($1.Field1-1)")
|
||||
else:
|
||||
if isDeref:
|
||||
unaryExpr(p, e, d, "$1->Field1")
|
||||
else:
|
||||
unaryExpr(p, e, d, "$1.Field1")
|
||||
of tyCstring:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)")
|
||||
else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)")
|
||||
@@ -1843,7 +1875,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||
|
||||
initLoc(call, locCall, e, OnHeap)
|
||||
if not p.module.compileToCpp:
|
||||
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
|
||||
const setLenPattern = "($3) #setLengthSeqV2(($1)?&($1)->Sup:NIM_NIL, $4, $2)"
|
||||
call.r = ropecg(p.module, setLenPattern, [
|
||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
|
||||
@@ -2015,7 +2047,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mCard:
|
||||
var a: TLoc
|
||||
initLocExpr(p, e[1], a)
|
||||
putIntoDest(p, d, e, ropecg(p.module, "#cardSet($1, $2)", [rdCharLoc(a), size]))
|
||||
putIntoDest(p, d, e, ropecg(p.module, "#cardSet($1, $2)", [addrLoc(p.config, a), size]))
|
||||
of mLtSet, mLeSet:
|
||||
getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter
|
||||
initLocExpr(p, e[1], a)
|
||||
@@ -2077,6 +2109,11 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
|
||||
elif etyp.kind == tyBool and srcTyp.kind in IntegralTypes:
|
||||
putIntoDest(p, d, e, "(($1) != 0)" % [rdCharLoc(a)], a.storage)
|
||||
else:
|
||||
if etyp.kind == tyPtr:
|
||||
# generates the definition of structs for casts like cast[ptr object](addr x)[]
|
||||
let internalType = etyp.skipTypes({tyPtr})
|
||||
if internalType.kind == tyObject:
|
||||
discard getTypeDesc(p.module, internalType)
|
||||
putIntoDest(p, d, e, "(($1) ($2))" %
|
||||
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
|
||||
|
||||
@@ -2273,7 +2310,10 @@ proc genDispose(p: BProc; n: PNode) =
|
||||
lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)])
|
||||
|
||||
proc genSlice(p: BProc; e: PNode; d: var TLoc) =
|
||||
let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon)
|
||||
let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon,
|
||||
prepareForMutation = e[1].kind == nkHiddenDeref and
|
||||
e[1].typ.skipTypes(abstractInst).kind == tyString and
|
||||
p.config.selectedGC in {gcArc, gcOrc})
|
||||
if d.k == locNone: getTemp(p, e.typ, d)
|
||||
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n", [rdLoc(d), x, y])
|
||||
when false:
|
||||
@@ -2355,7 +2395,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
genDollar(p, e, d, "#nimFloatToStr($1)")
|
||||
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
|
||||
of mStrToStr, mUnown: expr(p, e[1], d)
|
||||
of mIsolate, mFinished: genCall(p, e, d)
|
||||
of generatedMagics: genCall(p, e, d)
|
||||
of mEnumToStr:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
genEnumToStr(p, e, d)
|
||||
@@ -2528,15 +2568,30 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
if not handleConstExpr(p, n, d):
|
||||
let t = n.typ
|
||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||
if d.k == locNone: getTemp(p, t, d)
|
||||
|
||||
var tmp: TLoc
|
||||
# bug #16331
|
||||
let doesAlias = lhsDoesAlias(d.lode, n)
|
||||
let dest = if doesAlias: addr(tmp) else: addr(d)
|
||||
if doesAlias:
|
||||
getTemp(p, n.typ, tmp)
|
||||
elif d.k == locNone:
|
||||
getTemp(p, n.typ, d)
|
||||
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
if it.kind == nkExprColonExpr: it = it[1]
|
||||
initLoc(rec, locExpr, it, d.storage)
|
||||
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
|
||||
initLoc(rec, locExpr, it, dest[].storage)
|
||||
rec.r = "$1.Field$2" % [rdLoc(dest[]), rope(i)]
|
||||
rec.flags.incl(lfEnforceDeref)
|
||||
expr(p, it, rec)
|
||||
|
||||
if doesAlias:
|
||||
if d.k == locNone:
|
||||
d = tmp
|
||||
else:
|
||||
genAssignment(p, d, tmp, {})
|
||||
|
||||
proc isConstClosure(n: PNode): bool {.inline.} =
|
||||
result = n[0].kind == nkSym and isRoutine(n[0].sym) and
|
||||
n[1].kind == nkNilLit
|
||||
@@ -2945,26 +3000,13 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt:
|
||||
discard
|
||||
of nkPragma: genPragma(p, n)
|
||||
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 nkPragmaBlock: expr(p, n.lastSon, d)
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
|
||||
if n[genericParamsPos].kind == nkEmpty:
|
||||
var prc = n[namePos].sym
|
||||
if useAliveDataFromDce in p.module.flags:
|
||||
if p.module.alive.contains(prc.itemId.item) and prc.magic in {mNone, mIsolate, mFinished}:
|
||||
if p.module.alive.contains(prc.itemId.item) and
|
||||
prc.magic in generatedMagics:
|
||||
genProc(p.module, prc)
|
||||
elif prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
|
||||
if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
|
||||
|
||||
@@ -83,11 +83,24 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
|
||||
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
|
||||
else:
|
||||
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
|
||||
of tyChar, tyBool, tyEnum, tyInt..tyUInt64:
|
||||
of tyChar, tyBool, tyEnum, tyRange, tyInt..tyUInt64:
|
||||
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
|
||||
of tyCstring, tyPointer, tyPtr, tyVar, tyLent:
|
||||
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
|
||||
else:
|
||||
of tySet:
|
||||
case mapSetType(p.config, typ)
|
||||
of ctArray:
|
||||
lineCg(p, cpsStmts, "#nimZeroMem($1, sizeof($2));$n",
|
||||
[accessor, getTypeDesc(p.module, typ)])
|
||||
of ctInt8, ctInt16, ctInt32, ctInt64:
|
||||
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
|
||||
else:
|
||||
doAssert false, "unexpected set type kind"
|
||||
of {tyNone, tyEmpty, tyNil, tyUntyped, tyTyped, tyGenericInvocation,
|
||||
tyGenericParam, tyOrdinal, tyOpenArray, tyForward, tyVarargs,
|
||||
tyUncheckedArray, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
||||
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot,
|
||||
tyAnything, tyStatic, tyFromExpr, tyConcept, tyVoid, tyIterable}:
|
||||
discard
|
||||
|
||||
proc specializeReset(p: BProc, a: TLoc) =
|
||||
|
||||
@@ -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, gcRefc} and
|
||||
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcV2, gcRefc} and
|
||||
optOwnedRefs notin p.config.globalOptions and
|
||||
containsGarbageCollectedRef(v.loc.t):
|
||||
# we register a specialized marked proc here; this has the advantage
|
||||
@@ -405,7 +405,7 @@ proc genClosureVar(p: BProc, a: PNode) =
|
||||
genLineDir(p, a)
|
||||
if immediateAsgn:
|
||||
loadInto(p, a[0], a[2], v)
|
||||
else:
|
||||
elif sfNoInit notin a[0][1].sym.flags:
|
||||
constructLoc(p, v)
|
||||
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
@@ -1367,13 +1367,18 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||
linefmt(p, cpsStmts, "$1.status = __builtin_setjmp($1.context);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimRawSetjmp"):
|
||||
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])
|
||||
if isDefined(p.config, "vcc") or isDefined(p.config, "clangcl"):
|
||||
# For the vcc compiler, use `setjmp()` with one argument.
|
||||
# See https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setjmp?view=msvc-170
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||
else:
|
||||
# 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:
|
||||
@@ -1566,7 +1571,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 and p.inUncheckedAssignSection == 0:
|
||||
if optTinyRtti notin p.config.globalOptions:
|
||||
let field = dotExpr[1].sym
|
||||
genDiscriminantCheck(p, a, tmp, dotExpr[0].typ, field)
|
||||
message(p.config, e.info, warnCaseTransition)
|
||||
@@ -1587,6 +1592,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||
initLoc(a, locNone, le, OnUnknown)
|
||||
a.flags.incl(lfEnforceDeref)
|
||||
a.flags.incl(lfPrepareForMutation)
|
||||
genLineDir(p, le) # it can be a nkBracketExpr, which may raise
|
||||
expr(p, le, a)
|
||||
a.flags.excl(lfPrepareForMutation)
|
||||
if fastAsgn: incl(a.flags, lfNoDeepCopy)
|
||||
|
||||
@@ -35,17 +35,97 @@ proc mangleField(m: BModule; name: PIdent): string =
|
||||
if isKeyword(name):
|
||||
result.add "_0"
|
||||
|
||||
|
||||
proc encodeName*(name: string): string =
|
||||
result = mangle(name)
|
||||
result = $result.len & result
|
||||
|
||||
proc makeUnique(m: BModule; s: PSym, name: string = ""): Rope =
|
||||
let str = if name == "": s.name.s else: name
|
||||
result.add str
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_u"
|
||||
result.add $s.itemId.item
|
||||
|
||||
proc encodeSym*(m: BModule; s: PSym; makeUnique: bool = false): string =
|
||||
#Module::Type
|
||||
var name = s.name.s
|
||||
if makeUnique:
|
||||
name = $makeUnique(m, s, name)
|
||||
"N" & encodeName(s.skipGenericOwner.name.s) & encodeName(name) & "E"
|
||||
|
||||
proc elementType*(n: PType): PType {.inline.} = n.sons[^1]
|
||||
|
||||
proc encodeType*(m: BModule; t: PType): string =
|
||||
result = ""
|
||||
var kindName = ($t.kind)[2..^1]
|
||||
kindName[0] = toLower($kindName[0])[0]
|
||||
case t.kind
|
||||
of tyObject, tyEnum, tyDistinct, tyUserTypeClass, tyGenericParam:
|
||||
result = encodeSym(m, t.sym)
|
||||
of tyGenericInst, tyUserTypeClassInst, tyGenericBody:
|
||||
result = encodeName(t[0].sym.name.s)
|
||||
result.add "I"
|
||||
for i in 1..<t.len - 1:
|
||||
result.add encodeType(m, t[i])
|
||||
result.add "E"
|
||||
of tySequence, tyOpenArray, tyArray, tyVarargs, tyTuple, tyProc, tySet, tyTypeDesc,
|
||||
tyPtr, tyRef, tyVar, tyLent, tySink, tyStatic, tyUncheckedArray, tyOr, tyAnd, tyBuiltInTypeClass:
|
||||
result =
|
||||
case t.kind:
|
||||
of tySequence: encodeName("seq")
|
||||
else: encodeName(kindName)
|
||||
result.add "I"
|
||||
for i in 0..<t.len:
|
||||
let s = t[i]
|
||||
if s.isNil: continue
|
||||
result.add encodeType(m, s)
|
||||
result.add "E"
|
||||
of tyRange:
|
||||
var val = "range_"
|
||||
if t.n[0].typ.kind in {tyFloat..tyFloat128}:
|
||||
val.addFloat t.n[0].floatVal
|
||||
val.add "_"
|
||||
val.addFloat t.n[1].floatVal
|
||||
else:
|
||||
val.add $t.n[0].intVal & "_" & $t.n[1].intVal
|
||||
result = encodeName(val)
|
||||
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
|
||||
result = encodeName(kindName)
|
||||
of tyAlias, tyInferred, tyOwned:
|
||||
result = encodeType(m, t.elementType)
|
||||
else:
|
||||
assert false, "encodeType " & $t.kind
|
||||
|
||||
proc mangleProc(m: BModule; s: PSym; makeUnique: bool): string =
|
||||
result = "_Z" # Common prefix in Itanium ABI
|
||||
result.add encodeSym(m, s, makeUnique)
|
||||
if s.typ.len > 1: #we dont care about the return param
|
||||
for i in 1..<s.typ.len:
|
||||
if s.typ[i].isNil: continue
|
||||
result.add encodeType(m, s.typ[i])
|
||||
|
||||
if result in m.g.mangledPrcs:
|
||||
result = mangleProc(m, s, true)
|
||||
else:
|
||||
m.g.mangledPrcs.incl(result)
|
||||
|
||||
proc mangleName(m: BModule; s: PSym): Rope =
|
||||
result = s.loc.r
|
||||
if result == nil:
|
||||
result = s.name.s.mangle.rope
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_"
|
||||
result.add rope s.itemId.item
|
||||
if $s.loc.r == "":
|
||||
var result: Rope
|
||||
if s.kind in routineKinds and optCDebug in m.g.config.globalOptions and
|
||||
m.g.config.symbolFiles == disabledSf:
|
||||
result = mangleProc(m, s, false).rope
|
||||
else:
|
||||
result = s.name.s.mangle.rope
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_u"
|
||||
result.add $s.itemId.item # s.disamb #
|
||||
if m.hcrOn:
|
||||
result.add "_"
|
||||
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts))
|
||||
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts, m.config))
|
||||
s.loc.r = result
|
||||
writeMangledName(m.ndi, s, m.config)
|
||||
|
||||
@@ -311,7 +391,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
|
||||
else: result = nil
|
||||
|
||||
if result != nil and typ.isImportedType():
|
||||
let sig = hashType typ
|
||||
let sig = hashType(typ, m.config)
|
||||
if cacheGetType(m.typeCache, sig) == nil:
|
||||
m.typeCache[sig] = result
|
||||
|
||||
@@ -371,10 +451,10 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TSymKind): R
|
||||
if isImportedCppType(etB) and t.kind == tyGenericInst:
|
||||
result = getTypeDescAux(m, t, check, kind)
|
||||
else:
|
||||
result = getTypeForward(m, t, hashType(t))
|
||||
result = getTypeForward(m, t, hashType(t, m.config))
|
||||
pushType(m, t)
|
||||
of tySequence:
|
||||
let sig = hashType(t)
|
||||
let sig = hashType(t, m.config)
|
||||
if optSeqDestructors in m.config.globalOptions:
|
||||
if skipTypes(etB[0], typedescInst).kind == tyEmpty:
|
||||
internalError(m.config, "cannot map the empty seq type to a C type")
|
||||
@@ -407,7 +487,7 @@ proc getSeqPayloadType(m: BModule; t: PType): Rope =
|
||||
#result = getTypeForward(m, t, hashType(t)) & "_Content"
|
||||
|
||||
proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
|
||||
let sig = hashType(t)
|
||||
let sig = hashType(t, m.config)
|
||||
let result = cacheGetType(m.typeCache, sig)
|
||||
if result == nil:
|
||||
discard getTypeDescAux(m, t, check, skVar)
|
||||
@@ -672,7 +752,7 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
|
||||
else: result.elemType
|
||||
|
||||
proc getOpenArrayDesc(m: BModule, t: PType, check: var IntSet; kind: TSymKind): Rope =
|
||||
let sig = hashType(t)
|
||||
let sig = hashType(t, m.config)
|
||||
if kind == skParam:
|
||||
result = getTypeDescWeak(m, t[0], check, kind) & "*"
|
||||
else:
|
||||
@@ -696,7 +776,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||
# C type generation into an analysis and a code generation phase somehow.
|
||||
if t.sym != nil: useHeader(m, t.sym)
|
||||
if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.sym)
|
||||
let sig = hashType(origTyp)
|
||||
let sig = hashType(origTyp, m.config)
|
||||
|
||||
defer: # defer is the simplest in this case
|
||||
if isImportedType(t) and not m.typeABICache.containsOrIncl(sig):
|
||||
@@ -725,7 +805,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||
result = getTypeDescAux(m, et, check, kind) & star
|
||||
else:
|
||||
# no restriction! We have a forward declaration for structs
|
||||
let name = getTypeForward(m, et, hashType et)
|
||||
let name = getTypeForward(m, et, hashType(et, m.config))
|
||||
result = name & star
|
||||
m.typeCache[sig] = result
|
||||
of tySequence:
|
||||
@@ -734,7 +814,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||
m.typeCache[sig] = result
|
||||
else:
|
||||
# no restriction! We have a forward declaration for structs
|
||||
let name = getTypeForward(m, et, hashType et)
|
||||
let name = getTypeForward(m, et, hashType(et, m.config))
|
||||
result = name & seqStar(m) & star
|
||||
m.typeCache[sig] = result
|
||||
pushType(m, et)
|
||||
@@ -897,7 +977,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||
discard # addAbiCheck(m, t, result) # already handled elsewhere
|
||||
of tySet:
|
||||
# Don't use the imported name as it may be scoped: 'Foo::SomeKind'
|
||||
result = $t.kind & '_' & t.lastSon.typeName & $t.lastSon.hashType
|
||||
result = $t.kind & '_' & t.lastSon.typeName & $t.lastSon.hashType(m.config)
|
||||
m.typeCache[sig] = result
|
||||
if not isImportedType(t):
|
||||
let s = int(getSize(m.config, t))
|
||||
@@ -1026,7 +1106,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
|
||||
# compute type flags for GC optimization
|
||||
var flags = 0
|
||||
if not containsGarbageCollectedRef(typ): flags = flags or 1
|
||||
if not canFormAcycle(typ): flags = flags or 2
|
||||
if not canFormAcycle(m.g.graph, typ): flags = flags or 2
|
||||
#else echo("can contain a cycle: " & typeToString(typ))
|
||||
if flags != 0:
|
||||
m.s[cfsTypeInit3].addf("$1.flags = $2;$n", [nameHcr, rope(flags)])
|
||||
@@ -1070,7 +1150,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
|
||||
objtype = objtype[0].skipTypes(abstractPtrs)
|
||||
if objtype.sym == nil:
|
||||
internalError(m.config, d.info, "anonymous obj with discriminator")
|
||||
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]
|
||||
result = "NimDT_$1_$2" % [rope($hashType(objtype, m.config)), rope(d.name.s.mangle)]
|
||||
|
||||
proc rope(arg: Int128): Rope = rope($arg)
|
||||
|
||||
@@ -1278,7 +1358,7 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
||||
var it = t
|
||||
while it != nil:
|
||||
it = it.skipTypes(skipPtrs)
|
||||
if it.sym != nil:
|
||||
if it.sym != nil and tfFromGeneric notin it.flags:
|
||||
var m = it.sym.owner
|
||||
while m != nil and m.kind != skModule: m = m.owner
|
||||
if m == nil or sfSystemModule in m.flags:
|
||||
@@ -1291,7 +1371,7 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
||||
res.add m.name.s & "."
|
||||
res.add it.sym.name.s
|
||||
else:
|
||||
res.add $hashType(it)
|
||||
res.add $hashType(it, m.config)
|
||||
res.add "|"
|
||||
it = it[0]
|
||||
result = makeCString(res)
|
||||
@@ -1312,7 +1392,7 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||
result = theProc.loc.r
|
||||
|
||||
when false:
|
||||
if not canFormAcycle(t) and op == attachedTrace:
|
||||
if not canFormAcycle(m.g.graph, t) and op == attachedTrace:
|
||||
echo "ayclic but has this =trace ", t, " ", theProc.ast
|
||||
else:
|
||||
when false:
|
||||
@@ -1339,7 +1419,7 @@ proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineIn
|
||||
let traceImpl = genHook(m, t, info, attachedTrace)
|
||||
|
||||
var flags = 0
|
||||
if not canFormAcycle(t): flags = flags or 1
|
||||
if not canFormAcycle(m.g.graph, t): flags = flags or 1
|
||||
|
||||
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.flags = $6;", [
|
||||
name, destroyImpl, getTypeDesc(m, t), typeName,
|
||||
@@ -1355,7 +1435,7 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
|
||||
let prefixTI = if m.hcrOn: "(" else: "(&"
|
||||
|
||||
let sig = hashType(origType)
|
||||
let sig = hashType(origType, m.config)
|
||||
result = m.typeInfoMarkerV2.getOrDefault(sig)
|
||||
if result != nil:
|
||||
return prefixTI.rope & result & ")".rope
|
||||
@@ -1426,7 +1506,7 @@ proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
|
||||
let prefixTI = if m.hcrOn: "(" else: "(&"
|
||||
|
||||
let sig = hashType(origType)
|
||||
let sig = hashType(origType, m.config)
|
||||
result = m.typeInfoMarker.getOrDefault(sig)
|
||||
if result != nil:
|
||||
return prefixTI.rope & result & ")".rope
|
||||
@@ -1483,12 +1563,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, gcGo}:
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcV2, 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, gcGo}:
|
||||
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcV2, 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,8 @@ import
|
||||
ast, types, hashes, strutils, msgs, wordrecg,
|
||||
platform, trees, options, cgendata
|
||||
|
||||
import std/[hashes, strutils]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
@@ -144,4 +146,3 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
|
||||
if s.position == 0 and retType != nil and retType.kind == tyLent:
|
||||
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
|
||||
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@ import
|
||||
lowerings, tables, sets, ndi, lineinfos, pathutils, transf,
|
||||
injectdestructors, astmsgs, modulepaths
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
when not defined(leanCompiler):
|
||||
import spawn, semparallel
|
||||
|
||||
@@ -263,7 +260,8 @@ proc genCLineDir(r: var Rope, filename: string, line: int; conf: ConfigRef) =
|
||||
[rope(makeSingleLineCString(filename)), rope(line)])
|
||||
|
||||
proc genCLineDir(r: var Rope, info: TLineInfo; conf: ConfigRef) =
|
||||
genCLineDir(r, toFullPath(conf, info), info.safeLineNm, conf)
|
||||
if optLineDir in conf.options:
|
||||
genCLineDir(r, toFullPath(conf, info), info.safeLineNm, conf)
|
||||
|
||||
proc freshLineInfo(p: BProc; info: TLineInfo): bool =
|
||||
if p.lastLineInfo.line != info.line or
|
||||
@@ -277,7 +275,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||
|
||||
if optEmbedOrigSrc in p.config.globalOptions:
|
||||
p.s(cpsStmts).add(~"//" & sourceLine(p.config, t.info) & "\L")
|
||||
genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config)
|
||||
genCLineDir(p.s(cpsStmts), t.info, p.config)
|
||||
if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
|
||||
if freshLineInfo(p, t.info):
|
||||
@@ -310,6 +308,12 @@ proc lenExpr(p: BProc; a: TLoc): Rope =
|
||||
else:
|
||||
result = "($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)]
|
||||
|
||||
proc dataFieldAccessor(p: BProc, sym: Rope): Rope =
|
||||
if optSeqDestructors in p.config.globalOptions:
|
||||
result = "(" & sym & ").p"
|
||||
else:
|
||||
result = sym
|
||||
|
||||
proc dataField(p: BProc): Rope =
|
||||
if optSeqDestructors in p.config.globalOptions:
|
||||
result = rope".p->data"
|
||||
@@ -528,6 +532,9 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
|
||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
||||
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
|
||||
|
||||
genCLineDir(result, n.info, p.config)
|
||||
|
||||
result.add getTypeDesc(p.module, s.typ, skVar)
|
||||
if s.constraint.isNil:
|
||||
if sfRegister in s.flags: result.add(" register")
|
||||
@@ -1064,11 +1071,9 @@ 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 and p.config.selectedGC notin {gcArc, gcOrc}: discard
|
||||
if sfNoInit in prc.flags: 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)
|
||||
@@ -1167,6 +1172,20 @@ proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
if lfNoDecl in prc.loc.flags:
|
||||
fillProcLoc(m, prc.ast[namePos])
|
||||
genProcPrototype(m, prc)
|
||||
elif lfDynamicLib in prc.loc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
fillProcLoc(q, prc.ast[namePos])
|
||||
genProcPrototype(m, prc)
|
||||
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
|
||||
symInDynamicLib(q, prc)
|
||||
# register the procedure even though it is in a different dynamic library and will not be
|
||||
# reloadable (and has no _actual suffix) - other modules will need to be able to get it through
|
||||
# the hcr dynlib (also put it in the DynLibInit section - right after it gets loaded)
|
||||
if isReloadable(q, prc):
|
||||
q.s[cfsDynLibInit].addf("\t$1 = ($2) hcrRegisterProc($3, \"$1\", (void*)$1);$n",
|
||||
[prc.loc.r, getTypeDesc(q, prc.loc.t), getModuleDllPath(m, q.module)])
|
||||
else:
|
||||
symInDynamicLibPartial(m, prc)
|
||||
elif prc.typ.callConv == ccInline:
|
||||
# We add inline procs to the calling module to enable C based inlining.
|
||||
# This also means that a check with ``q.declaredThings`` is wrong, we need
|
||||
@@ -1185,20 +1204,6 @@ proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
# prc.loc.r = mangleName(m, prc)
|
||||
genProcPrototype(m, prc)
|
||||
genProcAux(m, prc)
|
||||
elif lfDynamicLib in prc.loc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
fillProcLoc(q, prc.ast[namePos])
|
||||
genProcPrototype(m, prc)
|
||||
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
|
||||
symInDynamicLib(q, prc)
|
||||
# register the procedure even though it is in a different dynamic library and will not be
|
||||
# reloadable (and has no _actual suffix) - other modules will need to be able to get it through
|
||||
# the hcr dynlib (also put it in the DynLibInit section - right after it gets loaded)
|
||||
if isReloadable(q, prc):
|
||||
q.s[cfsDynLibInit].addf("\t$1 = ($2) hcrRegisterProc($3, \"$1\", (void*)$1);$n",
|
||||
[prc.loc.r, getTypeDesc(q, prc.loc.t), getModuleDllPath(m, q.module)])
|
||||
else:
|
||||
symInDynamicLibPartial(m, prc)
|
||||
elif sfImportc notin prc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
fillProcLoc(q, prc.ast[namePos])
|
||||
@@ -1261,10 +1266,10 @@ proc genVarPrototype(m: BModule, n: PNode) =
|
||||
if sym.owner.id != m.module.id:
|
||||
# else we already have the symbol generated!
|
||||
assert(sym.loc.r != nil)
|
||||
incl(m.declaredThings, sym.id)
|
||||
if sfThread in sym.flags:
|
||||
declareThreadVar(m, sym, true)
|
||||
else:
|
||||
incl(m.declaredThings, sym.id)
|
||||
if sym.kind in {skLet, skVar, skField, skForVar} and sym.alignment > 0:
|
||||
m.s[cfsVars].addf "NIM_ALIGN($1) ", [rope(sym.alignment)]
|
||||
m.s[cfsVars].add(if m.hcrOn: "static " else: "extern ")
|
||||
@@ -1325,7 +1330,7 @@ proc getSomeInitName(m: BModule, suffix: string): Rope =
|
||||
proc getInitName(m: BModule): Rope =
|
||||
if sfMainModule in m.module.flags:
|
||||
# generate constant name for main module, for "easy" debugging.
|
||||
result = rope"NimMainModule"
|
||||
result = rope(m.config.nimMainPrefix) & rope"NimMainModule"
|
||||
else:
|
||||
result = getSomeInitName(m, "Init000")
|
||||
|
||||
@@ -1358,35 +1363,35 @@ proc genMainProc(m: BModule) =
|
||||
preMainCode.add("\tinitStackBottomWith_actual((void *)&inner);\L")
|
||||
preMainCode.add("\t(*inner)();\L")
|
||||
else:
|
||||
preMainCode.add("\tPreMain();\L")
|
||||
preMainCode.add("\t$1PreMain();\L" % [rope m.config.nimMainPrefix])
|
||||
|
||||
var posixCmdLine: Rope
|
||||
if optNoMain notin m.config.globalOptions:
|
||||
posixCmdLine.add "\tN_LIB_PRIVATE int cmdCount;\L"
|
||||
posixCmdLine.add "\tN_LIB_PRIVATE char** cmdLine;\L"
|
||||
posixCmdLine.add "\tN_LIB_PRIVATE char** gEnv;\L"
|
||||
|
||||
const
|
||||
# not a big deal if we always compile these 3 global vars... makes the HCR code easier
|
||||
PosixCmdLine =
|
||||
"N_LIB_PRIVATE int cmdCount;$N" &
|
||||
"N_LIB_PRIVATE char** cmdLine;$N" &
|
||||
"N_LIB_PRIVATE char** gEnv;$N"
|
||||
|
||||
# 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.
|
||||
|
||||
PreMainVolatileBody =
|
||||
"\tvoid (*volatile inner)(void);$N" &
|
||||
"\tinner = PreMainInner;$N" &
|
||||
"\tinner = $3PreMainInner;$N" &
|
||||
"$1" &
|
||||
"\t(*inner)();$N"
|
||||
|
||||
PreMainNonVolatileBody =
|
||||
"$1" &
|
||||
"\tPreMainInner();$N"
|
||||
"\t$3PreMainInner();$N"
|
||||
|
||||
PreMainBodyStart = "$N" &
|
||||
"N_LIB_PRIVATE void PreMainInner(void) {$N" &
|
||||
"N_LIB_PRIVATE void $3PreMainInner(void) {$N" &
|
||||
"$2" &
|
||||
"}$N$N" &
|
||||
PosixCmdLine &
|
||||
"N_LIB_PRIVATE void PreMain(void) {$N"
|
||||
"$4" &
|
||||
"N_LIB_PRIVATE void $3PreMain(void) {$N"
|
||||
|
||||
PreMainBodyEnd =
|
||||
"}$N$N"
|
||||
@@ -1397,21 +1402,21 @@ proc genMainProc(m: BModule) =
|
||||
MainProcsWithResult =
|
||||
MainProcs & ("\treturn $1nim_program_result;$N")
|
||||
|
||||
NimMainInner = "N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {$N" &
|
||||
NimMainInner = "N_LIB_PRIVATE N_CDECL(void, $5NimMainInner)(void) {$N" &
|
||||
"$1" &
|
||||
"}$N$N"
|
||||
|
||||
NimMainVolatileBody =
|
||||
"\tvoid (*volatile inner)(void);$N" &
|
||||
"$4" &
|
||||
"\tinner = NimMainInner;$N" &
|
||||
"\tinner = $5NimMainInner;$N" &
|
||||
"$2" &
|
||||
"\t(*inner)();$N"
|
||||
|
||||
NimMainNonVolatileBody =
|
||||
"$4" &
|
||||
"$2" &
|
||||
"\tNimMainInner();$N"
|
||||
"\t$5NimMainInner();$N"
|
||||
|
||||
NimMainProcStart =
|
||||
"N_CDECL(void, $5NimMain)(void) {$N"
|
||||
@@ -1491,9 +1496,9 @@ proc genMainProc(m: BModule) =
|
||||
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", [])
|
||||
inc(m.labels)
|
||||
if m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
|
||||
appcg(m, m.s[cfsProcs], PreMainBodyStart & PreMainVolatileBody & PreMainBodyEnd, [m.g.mainDatInit, m.g.otherModsInit])
|
||||
appcg(m, m.s[cfsProcs], PreMainBodyStart & PreMainVolatileBody & PreMainBodyEnd, [m.g.mainDatInit, m.g.otherModsInit, m.config.nimMainPrefix, posixCmdLine])
|
||||
else:
|
||||
appcg(m, m.s[cfsProcs], PreMainBodyStart & PreMainNonVolatileBody & PreMainBodyEnd, [m.g.mainDatInit, m.g.otherModsInit])
|
||||
appcg(m, m.s[cfsProcs], PreMainBodyStart & PreMainNonVolatileBody & PreMainBodyEnd, [m.g.mainDatInit, m.g.otherModsInit, m.config.nimMainPrefix, posixCmdLine])
|
||||
|
||||
if m.config.target.targetOS == osWindows and
|
||||
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
@@ -1599,7 +1604,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
hcrModuleMeta.addf("\t\"\"};$n", [])
|
||||
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(void**, HcrGetImportedModules)() { return (void**)hcr_module_list; }$n", [])
|
||||
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(char*, HcrGetSigHash)() { return \"$1\"; }$n$n",
|
||||
[($sigHash(m.module)).rope])
|
||||
[($sigHash(m.module, m.config)).rope])
|
||||
if sfMainModule in m.module.flags:
|
||||
g.mainModProcs.add(hcrModuleMeta)
|
||||
g.mainModProcs.addf("static void* hcr_handle;$N", [])
|
||||
|
||||
@@ -99,7 +99,6 @@ 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]
|
||||
@@ -139,6 +138,7 @@ type
|
||||
# unconditionally...
|
||||
# nimtvDeps is VERY hard to cache because it's
|
||||
# not a list of IDs nor can it be made to be one.
|
||||
mangledPrcs*: HashSet[string]
|
||||
|
||||
TCGen = object of PPassContext # represents a C source file
|
||||
s*: TCFileSections # sections of the C file
|
||||
|
||||
@@ -13,10 +13,6 @@ 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)
|
||||
@@ -50,6 +46,7 @@ proc methodCall*(n: PNode; conf: ConfigRef): PNode =
|
||||
# replace ordinary method by dispatcher method:
|
||||
let disp = getDispatcher(result[0].sym)
|
||||
if disp != nil:
|
||||
result[0].typ = disp.typ
|
||||
result[0].sym = disp
|
||||
# change the arguments to up/downcasts to fit the dispatcher's parameters:
|
||||
for i in 1..<result.len:
|
||||
|
||||
@@ -121,7 +121,10 @@
|
||||
# yield 2
|
||||
# if :unrollFinally: # This node is created by `newEndFinallyNode`
|
||||
# if :curExc.isNil:
|
||||
# return :tmpResult
|
||||
# if nearestFinally == 0:
|
||||
# return :tmpResult
|
||||
# else:
|
||||
# :state = nearestFinally # bubble up
|
||||
# else:
|
||||
# closureIterSetupExc(nil)
|
||||
# raise
|
||||
@@ -133,9 +136,6 @@ import
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
|
||||
tables, options
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
Ctx = object
|
||||
g: ModuleGraph
|
||||
@@ -807,7 +807,10 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
# Generate the following code:
|
||||
# if :unrollFinally:
|
||||
# if :curExc.isNil:
|
||||
# return :tmpResult
|
||||
# if nearestFinally == 0:
|
||||
# return :tmpResult
|
||||
# else:
|
||||
# :state = nearestFinally # bubble up
|
||||
# else:
|
||||
# raise
|
||||
let curExc = ctx.newCurExcAccess()
|
||||
@@ -816,11 +819,20 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
let cmp = newTree(nkCall, newSymNode(ctx.g.getSysMagic(info, "==", mEqRef), info), curExc, nilnode)
|
||||
cmp.typ = ctx.g.getSysType(info, tyBool)
|
||||
|
||||
let asgn = newTree(nkFastAsgn,
|
||||
newSymNode(getClosureIterResult(ctx.g, ctx.fn, ctx.idgen), info),
|
||||
ctx.newTmpResultAccess())
|
||||
let retStmt =
|
||||
if ctx.nearestFinally == 0:
|
||||
# last finally, we can return
|
||||
let retValue = if ctx.fn.typ[0].isNil:
|
||||
ctx.g.emptyNode
|
||||
else:
|
||||
newTree(nkFastAsgn,
|
||||
newSymNode(getClosureIterResult(ctx.g, ctx.fn, ctx.idgen), info),
|
||||
ctx.newTmpResultAccess())
|
||||
newTree(nkReturnStmt, retValue)
|
||||
else:
|
||||
# bubble up to next finally
|
||||
newTree(nkGotoState, ctx.g.newIntLit(info, ctx.nearestFinally))
|
||||
|
||||
let retStmt = newTree(nkReturnStmt, asgn)
|
||||
let branch = newTree(nkElifBranch, cmp, retStmt)
|
||||
|
||||
let nullifyExc = newTree(nkCall, newSymNode(ctx.g.getCompilerProc("closureIterSetupExc")), nilnode)
|
||||
@@ -840,7 +852,9 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
|
||||
case n.kind
|
||||
of nkReturnStmt:
|
||||
# We're somewhere in try, transform to finally unrolling
|
||||
assert(ctx.nearestFinally != 0)
|
||||
if ctx.nearestFinally == 0:
|
||||
# return is within the finally
|
||||
return
|
||||
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
@@ -864,6 +878,13 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
|
||||
|
||||
of nkSkip:
|
||||
discard
|
||||
of nkTryStmt:
|
||||
if n.hasYields:
|
||||
# the inner try will handle these transformations
|
||||
discard
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
n[i] = ctx.transformReturnsInTry(n[i])
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
n[i] = ctx.transformReturnsInTry(n[i])
|
||||
@@ -1133,7 +1154,7 @@ proc newArrayType(g: ModuleGraph; n: int, t: PType; idgen: IdGenerator; owner: P
|
||||
result = newType(tyArray, nextTypeId(idgen), owner)
|
||||
|
||||
let rng = newType(tyRange, nextTypeId(idgen), owner)
|
||||
rng.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n))
|
||||
rng.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n - 1))
|
||||
rng.rawAddSon(t)
|
||||
|
||||
result.rawAddSon(rng)
|
||||
@@ -1350,6 +1371,7 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode =
|
||||
# detect: 'finally: raises X' which is currently not supported. We produce
|
||||
# an error for this case for now. All this will be done properly with Yuriy's
|
||||
# patch.
|
||||
|
||||
result = n
|
||||
case n.kind
|
||||
of nkTryStmt:
|
||||
@@ -1366,6 +1388,7 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode =
|
||||
discard c.finallys.pop()
|
||||
|
||||
of nkWhileStmt, nkBlockStmt:
|
||||
if n.hasYields == false: return n
|
||||
c.blocks.add((n, c.finallys.len))
|
||||
for i in 0 ..< n.len:
|
||||
result[i] = preprocess(c, n[i])
|
||||
|
||||
@@ -31,9 +31,6 @@ 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")
|
||||
@@ -262,6 +259,7 @@ 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
|
||||
@@ -334,7 +332,6 @@ 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,
|
||||
@@ -500,75 +497,6 @@ 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
|
||||
@@ -668,11 +596,60 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
|
||||
of "project":
|
||||
processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
|
||||
of "gc":
|
||||
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 "gc", "mm":
|
||||
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)
|
||||
of "warnings", "w":
|
||||
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
|
||||
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
|
||||
@@ -740,7 +717,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 or conf.cmd == cmdNimscript: discard
|
||||
if conf.backend == backendJs: discard
|
||||
else: processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
|
||||
#if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
|
||||
of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
|
||||
@@ -799,7 +776,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "clib":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}:
|
||||
conf.cLinkedLibs.add processPath(conf, arg, info).string
|
||||
conf.cLinkedLibs.add arg
|
||||
of "header":
|
||||
if conf != nil: conf.headerFile = arg
|
||||
incl(conf.globalOptions, optGenIndex)
|
||||
@@ -1051,10 +1028,6 @@ 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:
|
||||
@@ -1079,7 +1052,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
processOnOffSwitchG(conf, {optEnableDeepCopy}, arg, pass, info)
|
||||
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 "nilseqs", "nilchecks", "symbol", "taintmode", "cs", "deadcodeelim": warningOptionNoop(switch)
|
||||
of "nimmainprefix": conf.nimMainPrefix = arg
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
|
||||
|
||||
@@ -15,9 +15,6 @@ import ast, astalgo, semdata, lookups, lineinfos, idents, msgs, renderer, types,
|
||||
|
||||
from magicsys import addSonSkipIntLit
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
logBindings = false
|
||||
|
||||
|
||||
@@ -140,3 +140,5 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasEffectsOf")
|
||||
|
||||
defineSymbol("nimHasEnforceNoRaises")
|
||||
defineSymbol("nimHasWarnBareExcept")
|
||||
defineSymbol("nimHasTopDownInference")
|
||||
|
||||
@@ -54,19 +54,3 @@ 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
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
# This module implements a dependency file generator.
|
||||
|
||||
import
|
||||
options, ast, ropes, idents, passes, modulepaths, pathutils
|
||||
import options, ast, ropes, passes, pathutils, msgs, lineinfos
|
||||
|
||||
from modulegraphs import ModuleGraph, PPassContext
|
||||
import modulegraphs
|
||||
|
||||
import std/[os, strutils, parseutils]
|
||||
import std/private/globs
|
||||
|
||||
type
|
||||
TGen = object of PPassContext
|
||||
@@ -28,6 +30,54 @@ proc addDependencyAux(b: Backend; importing, imported: string) =
|
||||
b.dotGraph.addf("\"$1\" -> \"$2\";$n", [rope(importing), rope(imported)])
|
||||
# s1 -> s2_4[label="[0-9]"];
|
||||
|
||||
proc toNimblePath(s: string, isStdlib: bool): string =
|
||||
const stdPrefix = "std/"
|
||||
const pkgPrefix = "pkg/"
|
||||
if isStdlib:
|
||||
let sub = "lib/"
|
||||
var start = s.find(sub)
|
||||
if start < 0:
|
||||
doAssert false
|
||||
else:
|
||||
start += sub.len
|
||||
let base = s[start..^1]
|
||||
|
||||
if base.startsWith("system") or base.startsWith("std"):
|
||||
result = base
|
||||
else:
|
||||
for dir in stdlibDirs:
|
||||
if base.startsWith(dir):
|
||||
return stdPrefix & base.splitFile.name
|
||||
|
||||
result = stdPrefix & base
|
||||
else:
|
||||
var sub = getEnv("NIMBLE_DIR")
|
||||
if sub.len == 0:
|
||||
sub = ".nimble/pkgs/"
|
||||
else:
|
||||
sub.add "/pkgs/"
|
||||
var start = s.find(sub)
|
||||
if start < 0:
|
||||
sub[^1] = '2'
|
||||
sub.add '/'
|
||||
start = s.find(sub) # /pkgs2
|
||||
if start < 0:
|
||||
return s
|
||||
|
||||
start += sub.len
|
||||
start += skipUntil(s, '/', start)
|
||||
start += 1
|
||||
result = pkgPrefix & s[start..^1]
|
||||
|
||||
proc addDependency(c: PPassContext, g: PGen, b: Backend, n: PNode) =
|
||||
doAssert n.kind == nkSym, $n.kind
|
||||
|
||||
let path = splitFile(toProjPath(g.config, n.sym.position.FileIndex))
|
||||
let modulePath = splitFile(toProjPath(g.config, g.module.position.FileIndex))
|
||||
let parent = nativeToUnixPath(modulePath.dir / modulePath.name).toNimblePath(belongsToStdlib(g.graph, g.module))
|
||||
let child = nativeToUnixPath(path.dir / path.name).toNimblePath(belongsToStdlib(g.graph, n.sym))
|
||||
addDependencyAux(b, parent, child)
|
||||
|
||||
proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
let g = PGen(c)
|
||||
@@ -35,11 +85,9 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
||||
case n.kind
|
||||
of nkImportStmt:
|
||||
for i in 0..<n.len:
|
||||
var imported = getModuleName(g.config, n[i])
|
||||
addDependencyAux(b, g.module.name.s, imported)
|
||||
addDependency(c, g, b, n[i])
|
||||
of nkFromStmt, nkImportExceptStmt:
|
||||
var imported = getModuleName(g.config, n[0])
|
||||
addDependencyAux(b, g.module.name.s, imported)
|
||||
addDependency(c, g, b, n[0])
|
||||
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
|
||||
for i in 0..<n.len: discard addDotDependency(c, n[i])
|
||||
else:
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
import ast, intsets, lineinfos, renderer
|
||||
import std/private/asciitables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
InstrKind* = enum
|
||||
goto, fork, def, use
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import
|
||||
ast, strutils, strtabs, algorithm, sequtils, options, msgs, os, idents,
|
||||
wordrecg, syntaxes, renderer, lexer,
|
||||
packages/docutils/[rst, rstgen, dochelpers],
|
||||
packages/docutils/rst, packages/docutils/rstgen,
|
||||
json, xmltree, trees, types,
|
||||
typesrenderer, astalgo, lineinfos, intsets,
|
||||
pathutils, tables, nimpaths, renderverbatim, osproc, packages
|
||||
@@ -44,14 +44,8 @@ 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: Table[string, seq[Item]]
|
||||
## Map basic name -> pre-processed items.
|
||||
secItems: seq[Item] ## Pre-processed items.
|
||||
finalMarkup: string ## The items, after RST pass 2 and rendering.
|
||||
ModSections = array[TSymKind, ModSection]
|
||||
TocItem = object ## HTML TOC item
|
||||
@@ -97,22 +91,12 @@ 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
|
||||
@@ -232,7 +216,6 @@ 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
|
||||
@@ -241,7 +224,6 @@ template declareClosures =
|
||||
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
|
||||
@@ -255,7 +237,7 @@ template declareClosures =
|
||||
result = getCurrentDir() / s
|
||||
if not fileExists(result): result = ""
|
||||
|
||||
proc parseRst(text: string,
|
||||
proc parseRst(text, filename: string,
|
||||
line, column: int,
|
||||
conf: ConfigRef, sharedState: PRstSharedState): PRstNode =
|
||||
declareClosures()
|
||||
@@ -293,6 +275,10 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||
conf.configVars, filename.string,
|
||||
docgenFindFile, compilerMsgHandler)
|
||||
|
||||
if conf.configVars.hasKey("doc.googleAnalytics") and
|
||||
conf.configVars.hasKey("doc.plausibleAnalytics"):
|
||||
doAssert false, "Either use googleAnalytics or plausibleAnalytics"
|
||||
|
||||
if conf.configVars.hasKey("doc.googleAnalytics"):
|
||||
result.analytics = """
|
||||
<script>
|
||||
@@ -306,6 +292,10 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||
|
||||
</script>
|
||||
""" % [conf.configVars.getOrDefault"doc.googleAnalytics"]
|
||||
elif conf.configVars.hasKey("doc.plausibleAnalytics"):
|
||||
result.analytics = """
|
||||
<script defer data-domain="$1" src="https://plausible.io/js/plausible.js"></script>
|
||||
""" % [conf.configVars.getOrDefault"doc.plausibleAnalytics"]
|
||||
else:
|
||||
result.analytics = ""
|
||||
|
||||
@@ -371,8 +361,7 @@ proc getVarIdx(varnames: openArray[string], id: string): int =
|
||||
|
||||
proc genComment(d: PDoc, n: PNode): PRstNode =
|
||||
if n.comment.len > 0:
|
||||
d.sharedState.currFileIdx = addRstFileIndex(d, n.info)
|
||||
result = parseRst(n.comment,
|
||||
result = parseRst(n.comment, toFullPath(d.conf, n.info),
|
||||
toLinenumber(n.info),
|
||||
toColumn(n.info) + DocColOffset,
|
||||
d.conf, d.sharedState)
|
||||
@@ -540,7 +529,7 @@ proc runAllExamples(d: PDoc) =
|
||||
|
||||
proc quoted(a: string): string = result.addQuoted(a)
|
||||
|
||||
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): auto =
|
||||
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): (string, int, int) =
|
||||
# xxx expose in compiler/lineinfos.nim
|
||||
(conf.toMsgFilename(info), info.line.int, info.col.int + ColOffset)
|
||||
|
||||
@@ -902,64 +891,6 @@ 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
|
||||
@@ -990,8 +921,6 @@ 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)
|
||||
@@ -1000,32 +929,20 @@ 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.mgetOrPut(cleanPlainSymbol, newSeq[Item]()).add Item(
|
||||
d.section[k].secItems.add Item(
|
||||
descRst: comm,
|
||||
sortName: sortName,
|
||||
info: lineinfo,
|
||||
anchor: symbolOrId,
|
||||
detailedName: detailedName,
|
||||
name: name,
|
||||
substitutions: @[
|
||||
"uniqueName", uniqueName,
|
||||
"name", name, "uniqueName", uniqueName,
|
||||
"header", result, "itemID", $d.id,
|
||||
"header_plain", plainNameEsc, "itemSym", cleanPlainSymbol,
|
||||
"itemSymEnc", plainSymbolEnc,
|
||||
"itemSymOrID", symbolOrId, "itemSymEnc", plainSymbolEnc,
|
||||
"itemSymOrIDEnc", symbolOrIdEnc, "seeSrc", seeSrc,
|
||||
"deprecationMsg", deprecationMsg])
|
||||
|
||||
@@ -1273,11 +1190,6 @@ 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
|
||||
@@ -1291,22 +1203,6 @@ 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:
|
||||
@@ -1317,33 +1213,14 @@ 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:
|
||||
# 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
|
||||
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
|
||||
renderItemPre(d, d.modDescPre, d.modDescFinal)
|
||||
d.modDescPre.setLen 0
|
||||
d.hasToc = d.hasToc or d.sharedState.hasToc
|
||||
@@ -1355,9 +1232,10 @@ proc finishGenerateDoc*(d: var PDoc) =
|
||||
var str: string
|
||||
renderRstToOut(d[], resolved, str)
|
||||
entry.json[entry.rstField] = %str
|
||||
d.jEntriesFinal.add entry.json
|
||||
d.jEntriesPre[i].rst = nil
|
||||
|
||||
d.jEntriesFinal.add entry.json # generates docs
|
||||
|
||||
proc add(d: PDoc; j: JsonItem) =
|
||||
if j.json != nil or j.rst != nil: d.jEntriesPre.add j
|
||||
|
||||
@@ -1497,10 +1375,7 @@ 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 = AbsoluteFile(d.destFile)
|
||||
.relativeTo(d.conf.outDir, '/')
|
||||
.changeFileExt(HtmlExt)
|
||||
.string
|
||||
let external = presentationPath(d.conf, AbsoluteFile d.filename).changeFileExt(HtmlExt).string.nativeToUnixPath
|
||||
setIndexTerm(d[], external, "", title)
|
||||
else:
|
||||
# Modules get an automatic title for the HTML, but no entry in the index.
|
||||
@@ -1574,11 +1449,7 @@ proc writeOutput*(d: PDoc, useWarning = false, groupedToc = false) =
|
||||
outfile.string)
|
||||
if not d.wroteSupportFiles: # nimdoc.css + dochack.js
|
||||
let nimr = $d.conf.getPrefixDir()
|
||||
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)
|
||||
copyFile(docCss.interp(nimr = nimr), $d.conf.outDir / nimdocOutCss)
|
||||
if optGenIndex in d.conf.globalOptions:
|
||||
let docHackJs2 = getDocHacksJs(nimr, nim = getAppFilename())
|
||||
copyFile(docHackJs2, $d.conf.outDir / docHackJs2.lastPathPart)
|
||||
@@ -1629,7 +1500,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),
|
||||
let rst = parseRst(readFile(filen.string), filen.string,
|
||||
line=LineRstInit, column=ColRstInit,
|
||||
conf, d.sharedState)
|
||||
d.modDescPre = @[ItemFragment(isRst: true, rst: rst)]
|
||||
@@ -1665,7 +1536,7 @@ proc commandJson*(cache: IdentCache, conf: ConfigRef) =
|
||||
let filename = getOutFile(conf, RelativeFile conf.projectName, JsonExt)
|
||||
try:
|
||||
writeFile(filename, content)
|
||||
except:
|
||||
except IOError:
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
||||
proc commandTags*(cache: IdentCache, conf: ConfigRef) =
|
||||
@@ -1688,7 +1559,7 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
|
||||
let filename = getOutFile(conf, RelativeFile conf.projectName, TagsExt)
|
||||
try:
|
||||
writeFile(filename, content)
|
||||
except:
|
||||
except IOError:
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
||||
proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
|
||||
@@ -1709,5 +1580,5 @@ proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"")
|
||||
|
||||
try:
|
||||
writeFile(filename, code)
|
||||
except:
|
||||
except IOError:
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
|
||||
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,9 +12,6 @@
|
||||
|
||||
import ast, renderer, options, strutils, types
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
ErrorKind* = enum ## expand as you need.
|
||||
RawTypeMismatchError
|
||||
|
||||
@@ -110,8 +110,8 @@ proc mapCallConv(conf: ConfigRef, cc: TCallingConvention, info: TLineInfo): TABI
|
||||
else:
|
||||
globalError(conf, info, "cannot map calling convention to FFI")
|
||||
|
||||
template rd(T, p: untyped): untyped = (cast[ptr T](p))[]
|
||||
template wr(T, p, v: untyped): untyped = (cast[ptr T](p))[] = v
|
||||
template rd(typ, p: untyped): untyped = (cast[ptr typ](p))[]
|
||||
template wr(typ, p, v: untyped): untyped = (cast[ptr typ](p))[] = v
|
||||
template `+!`(x, y: untyped): untyped =
|
||||
cast[pointer](cast[ByteAddress](x) + y)
|
||||
|
||||
@@ -177,8 +177,8 @@ const maxPackDepth = 20
|
||||
var packRecCheck = 0
|
||||
|
||||
proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer) =
|
||||
template awr(T, v: untyped): untyped =
|
||||
wr(T, res, v)
|
||||
template awr(typ, v: untyped): untyped =
|
||||
wr(typ, res, v)
|
||||
|
||||
case typ.kind
|
||||
of tyBool: awr(bool, v.intVal != 0)
|
||||
|
||||
@@ -14,10 +14,7 @@
|
||||
|
||||
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
|
||||
import std/[os, strutils, osproc, sha1, streams, sequtils, times, strtabs, json, jsonutils, sugar, parseutils]
|
||||
|
||||
type
|
||||
TInfoCCProp* = enum # properties of the C compiler:
|
||||
@@ -153,7 +150,7 @@ compiler vcc:
|
||||
compileTmpl: "/c$vccplatform $options $include /nologo /Fo$objfile $file",
|
||||
buildGui: " /SUBSYSTEM:WINDOWS user32.lib ",
|
||||
buildDll: " /LD",
|
||||
buildLib: "lib /OUT:$libfile $objfiles",
|
||||
buildLib: "vccexe --command:lib$vccplatform /nologo /OUT:$libfile $objfiles",
|
||||
linkerExe: "cl",
|
||||
linkTmpl: "$builddll$vccplatform /Fe$exefile $objfiles $buildgui /nologo $options",
|
||||
includeCmd: " /I",
|
||||
@@ -434,13 +431,7 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
|
||||
# really: Cross compilation from Linux to Linux for example is entirely
|
||||
# reasonable.
|
||||
# `optGenMapping` is included here for niminst.
|
||||
# We use absolute paths for vcc / cl, see issue #19883.
|
||||
let options =
|
||||
if conf.cCompiler == ccVcc:
|
||||
{optGenMapping}
|
||||
else:
|
||||
{optGenScript, optGenMapping}
|
||||
result = conf.globalOptions * options != {}
|
||||
result = conf.globalOptions * {optGenScript, optGenMapping} != {}
|
||||
|
||||
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
|
||||
result = conf.compileOptions
|
||||
@@ -493,7 +484,10 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
|
||||
(conf.target.hostOS == osWindows)
|
||||
|
||||
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
|
||||
conf.backend == backendCpp and not cfile.string.endsWith(".c")
|
||||
# List of possible file extensions taken from gcc
|
||||
for ext in [".C", ".cc", ".cpp", ".CPP", ".c++", ".cp", ".cxx"]:
|
||||
if cfile.string.endsWith(ext): return true
|
||||
false
|
||||
|
||||
proc envFlags(conf: ConfigRef): string =
|
||||
result = if conf.backend == backendCpp:
|
||||
@@ -501,14 +495,14 @@ proc envFlags(conf: ConfigRef): string =
|
||||
else:
|
||||
getEnv("CFLAGS")
|
||||
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
|
||||
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; isCpp: bool): string =
|
||||
if compiler == ccEnv:
|
||||
result = if useCpp(conf, cfile):
|
||||
result = if isCpp:
|
||||
getEnv("CXX")
|
||||
else:
|
||||
getEnv("CC")
|
||||
else:
|
||||
result = if useCpp(conf, cfile):
|
||||
result = if isCpp:
|
||||
CC[compiler].cppCompiler
|
||||
else:
|
||||
CC[compiler].compilerExe
|
||||
@@ -522,47 +516,36 @@ proc ccHasSaneOverflow*(conf: ConfigRef): bool =
|
||||
result = false # assume an old or crappy GCC
|
||||
var exe = getConfigVar(conf, conf.cCompiler, ".exe")
|
||||
if exe.len == 0: exe = CC[conf.cCompiler].compilerExe
|
||||
let (s, exitCode) = try: execCmdEx(exe & " --version") except: ("", 1)
|
||||
# NOTE: should we need the full version, use -dumpfullversion
|
||||
let (s, exitCode) = try: execCmdEx(exe & " -dumpversion") except IOError, OSError, ValueError: ("", 1)
|
||||
if exitCode == 0:
|
||||
var i = 0
|
||||
var j = 0
|
||||
# the version is the last part of the first line:
|
||||
while i < s.len and s[i] != '\n':
|
||||
if s[i] in {' ', '\t'}: j = i+1
|
||||
inc i
|
||||
if j > 0:
|
||||
var major = 0
|
||||
while j < s.len and s[j] in {'0'..'9'}:
|
||||
major = major * 10 + (ord(s[j]) - ord('0'))
|
||||
inc j
|
||||
if i < s.len and s[j] == '.': inc j
|
||||
while j < s.len and s[j] in {'0'..'9'}:
|
||||
inc j
|
||||
if j+1 < s.len and s[j] == '.' and s[j+1] in {'0'..'9'}:
|
||||
# we found a third version number, chances are high
|
||||
# we really parsed the version:
|
||||
result = major >= 5
|
||||
var major: int
|
||||
discard parseInt(s, major)
|
||||
result = major >= 5
|
||||
else:
|
||||
result = conf.cCompiler == ccCLang
|
||||
|
||||
proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
|
||||
result = if CC[compiler].linkerExe.len > 0: CC[compiler].linkerExe
|
||||
elif optMixedMode in conf.globalOptions and conf.backend != backendCpp: CC[compiler].cppCompiler
|
||||
else: getCompilerExe(conf, compiler, AbsoluteFile"")
|
||||
else: getCompilerExe(conf, compiler, optMixedMode in conf.globalOptions or conf.backend == backendCpp)
|
||||
|
||||
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
||||
isMainFile = false; produceOutput = false): string =
|
||||
let c = conf.cCompiler
|
||||
let
|
||||
c = conf.cCompiler
|
||||
isCpp = useCpp(conf, cfile.cname)
|
||||
# We produce files like module.nim.cpp, so the absolute Nim filename is not
|
||||
# cfile.name but `cfile.cname.changeFileExt("")`:
|
||||
var options = cFileSpecificOptions(conf, cfile.nimname, cfile.cname.changeFileExt("").string)
|
||||
if useCpp(conf, cfile.cname):
|
||||
if isCpp:
|
||||
# needs to be prepended so that --passc:-std=c++17 can override default.
|
||||
# we could avoid allocation by making cFileSpecificOptions inplace
|
||||
options = CC[c].cppXsupport & ' ' & options
|
||||
# If any C++ file was compiled, we need to use C++ driver for linking as well
|
||||
incl conf.globalOptions, optMixedMode
|
||||
|
||||
var exe = getConfigVar(conf, c, ".exe")
|
||||
if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)
|
||||
if exe.len == 0: exe = getCompilerExe(conf, c, isCpp)
|
||||
|
||||
if needsExeExt(conf): exe = addFileExt(exe, "exe")
|
||||
if (optGenDynLib in conf.globalOptions or (conf.hcrOn and not isMainFile)) and
|
||||
@@ -582,7 +565,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
||||
|
||||
compilePattern = joinPath(conf.cCompilerPath, exe)
|
||||
else:
|
||||
compilePattern = getCompilerExe(conf, c, cfile.cname)
|
||||
compilePattern = exe
|
||||
|
||||
includeCmd.add(join([CC[c].includeCmd, quoteShell(conf.projectPath.string)]))
|
||||
|
||||
@@ -682,7 +665,8 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
|
||||
if removeStaticFile:
|
||||
removeFile output # fixes: bug #16947
|
||||
result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(output),
|
||||
"objfiles", objfiles]
|
||||
"objfiles", objfiles,
|
||||
"vccplatform", vccplatform(conf)]
|
||||
else:
|
||||
var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe")
|
||||
if linkerExe.len == 0: linkerExe = getLinkerExe(conf, conf.cCompiler)
|
||||
@@ -835,10 +819,22 @@ proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
|
||||
else:
|
||||
writeFile(linkerArgs, args)
|
||||
try:
|
||||
execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs)
|
||||
when defined(macosx):
|
||||
execLinkCmd(conf, "xargs " & cmd.substr(0, last) & " < " & linkerArgs)
|
||||
else:
|
||||
execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs)
|
||||
finally:
|
||||
removeFile(linkerArgs)
|
||||
|
||||
proc linkViaShellScript(conf: ConfigRef; cmd: string) =
|
||||
let linkerScript = conf.projectName & "_" & "linkerScript.sh"
|
||||
writeFile(linkerScript, cmd)
|
||||
let shell = getEnv("SHELL")
|
||||
try:
|
||||
execLinkCmd(conf, shell & " " & linkerScript)
|
||||
finally:
|
||||
removeFile(linkerScript)
|
||||
|
||||
proc getObjFilePath(conf: ConfigRef, f: Cfile): string =
|
||||
if noAbsolutePaths(conf): f.obj.extractFilename
|
||||
else: f.obj.string
|
||||
@@ -927,17 +923,21 @@ proc callCCompiler*(conf: ConfigRef) =
|
||||
objfiles.add(' ')
|
||||
objfiles.add(quoteShell(objFile))
|
||||
let mainOutput = if optGenScript notin conf.globalOptions: conf.prepareToWriteOutput
|
||||
else: AbsoluteFile(conf.outFile)
|
||||
else: AbsoluteFile(conf.projectName)
|
||||
|
||||
linkCmd = getLinkCmd(conf, mainOutput, objfiles, removeStaticFile = true)
|
||||
extraCmds = getExtraCmds(conf, mainOutput)
|
||||
if optCompileOnly notin conf.globalOptions:
|
||||
const MaxCmdLen = when defined(windows): 8_000 else: 32_000
|
||||
const MaxCmdLen = when defined(windows): 8_000 elif defined(macosx): 260_000 else: 32_000
|
||||
if linkCmd.len > MaxCmdLen:
|
||||
# Windows's command line limit is about 8K (don't laugh...) so C compilers on
|
||||
# Windows support a feature where the command line can be passed via ``@linkcmd``
|
||||
# to them.
|
||||
linkViaResponseFile(conf, linkCmd)
|
||||
when defined(macosx):
|
||||
# macOS's `ar` does not support response files
|
||||
linkViaShellScript(conf, linkCmd)
|
||||
else:
|
||||
# Windows's command line limit is about 8K (don't laugh...) so C compilers on
|
||||
# Windows support a feature where the command line can be passed via ``@linkcmd``
|
||||
# to them.
|
||||
linkViaResponseFile(conf, linkCmd)
|
||||
else:
|
||||
execLinkCmd(conf, linkCmd)
|
||||
for cmd in extraCmds:
|
||||
@@ -1023,7 +1023,7 @@ proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; jsonFile: Absolute
|
||||
proc runJsonBuildInstructions*(conf: ConfigRef; jsonFile: AbsoluteFile) =
|
||||
var bcache: BuildCache
|
||||
try: bcache.fromJson(jsonFile.string.parseFile)
|
||||
except:
|
||||
except ValueError, KeyError, JsonKindError:
|
||||
let e = getCurrentException()
|
||||
conf.quitOrRaise "\ncaught exception:\n$#\nstacktrace:\n$#error evaluating JSON file: $#" %
|
||||
[e.msg, e.getStackTrace(), jsonFile.string]
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
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,9 +12,6 @@
|
||||
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,9 +9,6 @@
|
||||
|
||||
# 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,9 +3,6 @@
|
||||
|
||||
import hashes, rodfiles
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
LitId* = distinct uint32
|
||||
|
||||
@@ -93,13 +90,13 @@ proc getOrIncl*[T](t: var BiTable[T]; v: T): LitId =
|
||||
t.vals.add v
|
||||
|
||||
|
||||
proc `[]`*[T](t: var BiTable[T]; LitId: LitId): var T {.inline.} =
|
||||
let idx = idToIdx LitId
|
||||
proc `[]`*[T](t: var BiTable[T]; litId: LitId): var T {.inline.} =
|
||||
let idx = idToIdx litId
|
||||
assert idx < t.vals.len
|
||||
result = t.vals[idx]
|
||||
|
||||
proc `[]`*[T](t: BiTable[T]; LitId: LitId): lent T {.inline.} =
|
||||
let idx = idToIdx LitId
|
||||
proc `[]`*[T](t: BiTable[T]; litId: LitId): lent T {.inline.} =
|
||||
let idx = idToIdx litId
|
||||
assert idx < t.vals.len
|
||||
result = t.vals[idx]
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
|
||||
import std/packedsets, algorithm, tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import ".."/[ast, options, lineinfos, modulegraphs, cgendata, cgen,
|
||||
pathutils, extccomp, msgs, modulepaths]
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
## 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
|
||||
|
||||
@@ -14,9 +14,6 @@ import ".." / [ast, idents, lineinfos, msgs, ropes, options,
|
||||
#import ".." / [renderer, astalgo]
|
||||
from os import removeFile, isAbsolute
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
type
|
||||
PackedConfig* = object
|
||||
backend: TBackend
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
## 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,9 +16,6 @@ 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,9 +16,6 @@ import hashes, tables, strtabs
|
||||
import bitabs
|
||||
import ".." / [ast, options]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
SymId* = distinct int32
|
||||
ModuleId* = distinct int32
|
||||
|
||||
@@ -16,9 +16,6 @@ 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,9 +16,6 @@
|
||||
|
||||
from typetraits import supportsCopyMem
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
## Overview
|
||||
## ========
|
||||
## `RodFile` represents a Rod File (versioned binary format), and the
|
||||
@@ -37,8 +34,7 @@ when defined(nimPreviewSlimSystem):
|
||||
##
|
||||
## Now read the bits below to understand what's missing.
|
||||
##
|
||||
## Issues with the Example
|
||||
## ```````````````````````
|
||||
## ### Issues with the Example
|
||||
## Missing Sections:
|
||||
## This is a low level API, so headers and sections need to be stored and
|
||||
## loaded by the user, see `storeHeader` & `loadHeader` and `storeSection` &
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
import
|
||||
hashes, wordrecg
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
PIdent* = ref TIdent
|
||||
TIdent*{.acyclic.} = object
|
||||
|
||||
@@ -15,9 +15,6 @@ 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()
|
||||
@@ -228,6 +225,11 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym; im
|
||||
for i in 0..n.safeLen-1:
|
||||
importForwarded(c, n[i], exceptSet, fromMod, importSet)
|
||||
|
||||
proc addUnique[T](x: var seq[T], y: sink T) {.noSideEffect.} =
|
||||
for i in 0..high(x):
|
||||
if x[i] == y: return
|
||||
x.add y
|
||||
|
||||
proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool): PSym =
|
||||
result = realModule
|
||||
template createModuleAliasImpl(ident): untyped =
|
||||
@@ -245,6 +247,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool)
|
||||
result.options.incl optImportHidden
|
||||
c.unusedImports.add((result, n.info))
|
||||
c.importModuleMap[result.id] = realModule.id
|
||||
c.importModuleLookup.mgetOrPut(result.name.id, @[]).addUnique realModule.id
|
||||
|
||||
proc transformImportAs(c: PContext; n: PNode): tuple[node: PNode, importHidden: bool] =
|
||||
var ret: typeof(result)
|
||||
@@ -323,22 +326,24 @@ proc evalImport*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkImportStmt, n.info)
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
|
||||
let sep = it[0]
|
||||
let dir = it[1]
|
||||
var imp = newNodeI(nkInfix, it.info)
|
||||
imp.add sep
|
||||
imp.add dir
|
||||
imp.add sep # dummy entry, replaced in the loop
|
||||
for x in it[2]:
|
||||
if it.kind in {nkInfix, nkPrefix} and it[^1].kind == nkBracket:
|
||||
let lastPos = it.len - 1
|
||||
var imp = copyNode(it)
|
||||
newSons(imp, it.len)
|
||||
for i in 0 ..< lastPos: imp[i] = it[i]
|
||||
imp[lastPos] = imp[0] # dummy entry, replaced in the loop
|
||||
for x in it[lastPos]:
|
||||
# transform `a/b/[c as d]` to `/a/b/c as d`
|
||||
if x.kind == nkInfix and x[0].ident.s == "as":
|
||||
let impAs = copyTree(x)
|
||||
imp[2] = x[1]
|
||||
var impAs = copyNode(x)
|
||||
newSons(impAs, 3)
|
||||
impAs[0] = x[0]
|
||||
imp[lastPos] = x[1]
|
||||
impAs[1] = imp
|
||||
impMod(c, imp, result)
|
||||
impAs[2] = x[2]
|
||||
impMod(c, impAs, result)
|
||||
else:
|
||||
imp[2] = x
|
||||
imp[lastPos] = x
|
||||
impMod(c, imp, result)
|
||||
else:
|
||||
impMod(c, it, result)
|
||||
|
||||
@@ -19,9 +19,6 @@ import
|
||||
lineinfos, parampatterns, sighashes, liftdestructors, optimizer,
|
||||
varpartitions
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
from trees import exprStructuralEquivalent, getRoot
|
||||
|
||||
type
|
||||
@@ -278,7 +275,7 @@ proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode
|
||||
var op = getAttachedOp(c.graph, t, kind)
|
||||
if op == nil or op.ast.isGenericRoutine:
|
||||
# give up and find the canonical type instead:
|
||||
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let h = sighashes.hashType(t, c.graph.config, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let canon = c.graph.canonTypes.getOrDefault(h)
|
||||
if canon != nil:
|
||||
op = getAttachedOp(c.graph, canon, kind)
|
||||
@@ -348,13 +345,13 @@ proc isCriticalLink(dest: PNode): bool {.inline.} =
|
||||
proc finishCopy(c: var Con; result, dest: PNode; isFromSink: bool) =
|
||||
if c.graph.config.selectedGC == gcOrc:
|
||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
if cyclicType(t):
|
||||
if cyclicType(c.graph, t):
|
||||
result.add boolLit(c.graph, result.info, isFromSink or isCriticalLink(dest))
|
||||
|
||||
proc genMarkCyclic(c: var Con; result, dest: PNode) =
|
||||
if c.graph.config.selectedGC == gcOrc:
|
||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
if cyclicType(t):
|
||||
if cyclicType(c.graph, t):
|
||||
if t.kind == tyRef:
|
||||
result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, dest)
|
||||
else:
|
||||
@@ -576,7 +573,7 @@ proc processScope(c: var Con; s: var Scope; ret: PNode): PNode =
|
||||
|
||||
template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: untyped): PNode =
|
||||
assert not ret.typ.isEmptyType
|
||||
var result = newNodeI(nkStmtListExpr, ret.info)
|
||||
var result = newNodeIT(nkStmtListExpr, ret.info, ret.typ)
|
||||
# There is a possibility to do this check: s.wasMoved.len > 0 or s.final.len > 0
|
||||
# later and use it to eliminate the temporary when theres no need for it, but its
|
||||
# tricky because you would have to intercept moveOrCopy at a certain point
|
||||
@@ -709,6 +706,11 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
|
||||
of nkWhen: # This should be a "when nimvm" node.
|
||||
result = copyTree(n)
|
||||
result[1][0] = processCall(n[1][0], s)
|
||||
of nkPragmaBlock:
|
||||
result = shallowCopy(n)
|
||||
for i in 0 ..< n.len-1:
|
||||
result[i] = p(n[i], c, s, normal)
|
||||
result[^1] = maybeVoid(n[^1], s)
|
||||
else: assert(false)
|
||||
|
||||
proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
|
||||
@@ -738,7 +740,7 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
|
||||
|
||||
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
|
||||
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt}:
|
||||
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt, nkPragmaBlock}:
|
||||
template process(child, s): untyped = p(child, c, s, mode)
|
||||
handleNestedTempl(n, process)
|
||||
elif mode == sinkArg:
|
||||
@@ -882,7 +884,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||
if ri.kind != nkEmpty:
|
||||
result.add moveOrCopy(v, ri, c, s, isDecl = v.kind == nkSym)
|
||||
elif ri.kind == nkEmpty and c.inLoop > 0:
|
||||
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, isDecl = v.kind == nkSym)
|
||||
let skipInit = v.kind == nkDotExpr and # Closure var
|
||||
sfNoInit in v[1].sym.flags
|
||||
if not skipInit:
|
||||
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, isDecl = v.kind == nkSym)
|
||||
else: # keep the var but transform 'ri':
|
||||
var v = copyNode(n)
|
||||
var itCopy = copyNode(it)
|
||||
@@ -915,7 +920,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
result = n
|
||||
|
||||
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange, nkPragmaBlock:
|
||||
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange:
|
||||
result = shallowCopy(n)
|
||||
for i in 0 ..< n.len:
|
||||
result[i] = p(n[i], c, s, normal)
|
||||
@@ -997,7 +1002,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
|
||||
|
||||
proc sameLocation*(a, b: PNode): bool =
|
||||
proc sameConstant(a, b: PNode): bool =
|
||||
a.kind in nkLiterals and a.intVal == b.intVal
|
||||
a.kind in nkLiterals and b.kind in nkLiterals and a.intVal == b.intVal
|
||||
|
||||
const nkEndPoint = {nkSym, nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}
|
||||
if a.kind in nkEndPoint and b.kind in nkEndPoint:
|
||||
@@ -1021,6 +1026,26 @@ proc sameLocation*(a, b: PNode): bool =
|
||||
of nkHiddenStdConv, nkHiddenSubConv: sameLocation(a[1], b)
|
||||
else: false
|
||||
|
||||
proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode, isDecl: bool): PNode =
|
||||
# with side effects
|
||||
var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), nextSymId c.idgen, c.owner, ri[1].info)
|
||||
temp.typ = ri[1].typ
|
||||
var v = newNodeI(nkLetSection, ri[1].info)
|
||||
let tempAsNode = newSymNode(temp)
|
||||
|
||||
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
|
||||
vpart[0] = tempAsNode
|
||||
vpart[1] = newNodeI(nkEmpty, tempAsNode.info)
|
||||
vpart[2] = ri[1]
|
||||
v.add(vpart)
|
||||
|
||||
var newAccess = copyNode(ri)
|
||||
newAccess.add ri[0]
|
||||
newAccess.add tempAsNode
|
||||
|
||||
var snk = c.genSink(dest, newAccess, isDecl)
|
||||
result = newTree(nkStmtList, v, snk, c.genWasMoved(newAccess))
|
||||
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNode =
|
||||
if sameLocation(dest, ri):
|
||||
# rule (self-assignment-removal):
|
||||
@@ -1034,7 +1059,8 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
|
||||
else:
|
||||
result = newTree(nkFastAsgn, dest, p(ri, c, s, normal))
|
||||
else:
|
||||
case ri.kind
|
||||
let ri2 = if ri.kind == nkWhen: ri[1][0] else: ri
|
||||
case ri2.kind
|
||||
of nkCallKinds:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
of nkBracketExpr:
|
||||
@@ -1044,8 +1070,11 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
|
||||
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
|
||||
if aliases(dest, ri) == no:
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
var snk = c.genSink(dest, ri, isDecl)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
if isAtom(ri[1]):
|
||||
var snk = c.genSink(dest, ri, isDecl)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = genFieldAccessSideEffects(c, dest, ri, isDecl)
|
||||
else:
|
||||
result = c.genSink(dest, destructiveMoveVar(ri, c, s), isDecl)
|
||||
else:
|
||||
|
||||
@@ -141,5 +141,5 @@ shortDesc: "The Nim Compiler"
|
||||
licenses: "bin/nim,MIT;lib/*,MIT;"
|
||||
|
||||
[nimble]
|
||||
pkgName: "compiler"
|
||||
pkgName: "nim"
|
||||
pkgFiles: "compiler/*;doc/basicopt.txt;doc/advopt.txt;doc/nimdoc.css"
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
from math import trunc
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
Int128* = object
|
||||
udata: array[4, uint32]
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
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 =
|
||||
@@ -74,7 +71,7 @@ proc isValueOnlyType(t: PType): bool =
|
||||
|
||||
proc canAlias*(arg, ret: PType): bool =
|
||||
if isValueOnlyType(arg):
|
||||
# can alias only with addr(arg.x) and we don't care if it is not safe
|
||||
# can alias only with unsafeAddr(arg.x) and we don't care if it is not safe
|
||||
result = false
|
||||
else:
|
||||
var marker = initIntSet()
|
||||
|
||||
@@ -259,7 +259,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
|
||||
if m.config.hcrOn:
|
||||
# When hot reloading is enabled, we must ensure that the names
|
||||
# of functions and types will be preserved across rebuilds:
|
||||
result.add(idOrSig(s, m.module.name.s, m.sigConflicts))
|
||||
result.add(idOrSig(s, m.module.name.s, m.sigConflicts, m.config))
|
||||
else:
|
||||
result.add("_")
|
||||
result.add(rope(s.id))
|
||||
@@ -1296,7 +1296,7 @@ template isIndirect(x: PSym): bool =
|
||||
v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator,
|
||||
skConst, skTemp, skLet})
|
||||
|
||||
proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
|
||||
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
|
||||
@@ -1451,7 +1451,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||
s.name.s)
|
||||
discard mangleName(p.module, s)
|
||||
r.res = s.loc.r
|
||||
if lfNoDecl in s.loc.flags or s.magic notin {mNone, mIsolate} or
|
||||
if lfNoDecl in s.loc.flags or s.magic notin generatedMagics or
|
||||
{sfImportc, sfInfixCall} * s.flags != {}:
|
||||
discard
|
||||
elif s.kind == skMethod and getBody(p.module.graph, s).kind == nkEmpty:
|
||||
@@ -2102,6 +2102,8 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
gen(p, n[1], x)
|
||||
useMagic(p, "nimCopy")
|
||||
r.res = "nimCopy(null, $1, $2)" % [x.rdLoc, genTypeInfo(p, n.typ)]
|
||||
of mOpenArrayToSeq:
|
||||
genCall(p, n, r)
|
||||
of mDestroy, mTrace: discard "ignore calls to the default destructor"
|
||||
of mOrd: genOrd(p, n, r)
|
||||
of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray:
|
||||
@@ -2392,7 +2394,6 @@ 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
|
||||
@@ -2407,17 +2408,18 @@ 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)
|
||||
let returnAddress = not isIndirect(resultSym) and
|
||||
# otherwise uses "fat pointers"
|
||||
let useRawPointer = not isIndirect(resultSym) and
|
||||
resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and
|
||||
mapType(p, resultSym.typ) == etyBaseIndex
|
||||
if returnAddress:
|
||||
if useRawPointer:
|
||||
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 returnAddress:
|
||||
if mapType(p, resultSym.typ) == etyBaseIndex:
|
||||
returnStmt = "return [$#, $#];$n" % [a.address, a.res]
|
||||
else:
|
||||
returnStmt = "return $#;$n" % [a.res]
|
||||
@@ -2618,7 +2620,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let s = n[namePos].sym
|
||||
discard mangleName(p.module, s)
|
||||
r.res = s.loc.r
|
||||
if lfNoDecl in s.loc.flags or s.magic notin {mNone, mIsolate}: discard
|
||||
if lfNoDecl in s.loc.flags or s.magic notin generatedMagics: discard
|
||||
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||
p.locals.add(genProc(p, s))
|
||||
of nkType: r.res = genTypeInfo(p, n.typ)
|
||||
@@ -2674,7 +2676,6 @@ 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]()
|
||||
@@ -2686,7 +2687,6 @@ 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;
|
||||
@@ -2717,8 +2717,6 @@ 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),
|
||||
@@ -2729,7 +2727,7 @@ proc genModule(p: PProc, n: PNode) =
|
||||
if p.config.hcrOn and n.kind == nkStmtList:
|
||||
let moduleSym = p.module.module
|
||||
var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" &
|
||||
idOrSig(moduleSym, moduleSym.name.s, p.module.sigConflicts)
|
||||
idOrSig(moduleSym, moduleSym.name.s, p.module.sigConflicts, p.config)
|
||||
lineF(p, "var $1;$n", [moduleLoadedVar])
|
||||
var inGuardedBlock = false
|
||||
|
||||
@@ -2747,7 +2745,6 @@ 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
|
||||
@@ -2760,7 +2757,6 @@ 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):
|
||||
@@ -2786,41 +2782,26 @@ proc getClassName(t: PType): Rope =
|
||||
else: result = rope(s.name.s)
|
||||
|
||||
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||
## Finalize JS code generation of a Nim module.
|
||||
## Param `n` may contain nodes returned from the last module close call.
|
||||
result = myProcess(b, n)
|
||||
var m = BModule(b)
|
||||
if sfMainModule in m.module.flags:
|
||||
# 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.
|
||||
for destructorCall in graph.globalDestructors:
|
||||
n.add destructorCall
|
||||
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))
|
||||
# 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)
|
||||
discard writeRopeIfNotEqual(code, outFile)
|
||||
|
||||
|
||||
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,9 +14,6 @@ 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:
|
||||
@@ -288,8 +285,7 @@ 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." &
|
||||
" Consider using a <ref $2> which can be captured.") %
|
||||
" safety, declared here: $3; using '-d:nimNoLentIterators' helps in some cases") %
|
||||
[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>" %
|
||||
@@ -302,6 +298,7 @@ type
|
||||
processed, capturedVars: IntSet
|
||||
ownerToType: Table[int, PType]
|
||||
somethingToDo: bool
|
||||
inTypeOf: bool
|
||||
graph: ModuleGraph
|
||||
idgen: IdGenerator
|
||||
|
||||
@@ -405,6 +402,9 @@ Consider:
|
||||
|
||||
"""
|
||||
|
||||
proc isTypeOf(n: PNode): bool =
|
||||
n.kind == nkSym and n.sym.magic in {mTypeOf, mType}
|
||||
|
||||
proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
|
||||
var cp = getEnvParam(fn)
|
||||
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
|
||||
@@ -441,7 +441,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
c.somethingToDo = true
|
||||
addClosureParam(c, owner, n.info)
|
||||
if interestingIterVar(s):
|
||||
if not c.capturedVars.containsOrIncl(s.id):
|
||||
if not c.capturedVars.contains(s.id):
|
||||
if not c.inTypeOf: c.capturedVars.incl(s.id)
|
||||
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
|
||||
@@ -450,7 +451,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
else:
|
||||
discard addField(obj, s, c.graph.cache, c.idgen)
|
||||
# direct or indirect dependency:
|
||||
elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s):
|
||||
elif (innerProc and not s.isIterator and s.typ.callConv == ccClosure) or interestingVar(s):
|
||||
discard """
|
||||
proc outer() =
|
||||
var x: int
|
||||
@@ -467,10 +468,12 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
addClosureParam(c, owner, n.info)
|
||||
#echo "capturing ", n.info
|
||||
# variable 's' is actually captured:
|
||||
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
|
||||
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
discard addField(obj, s, c.graph.cache, c.idgen)
|
||||
if interestingVar(s):
|
||||
if not c.capturedVars.contains(s.id):
|
||||
if not c.inTypeOf: c.capturedVars.incl(s.id)
|
||||
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
discard addField(obj, s, c.graph.cache, c.idgen)
|
||||
# create required upFields:
|
||||
var w = owner.skipGenericOwner
|
||||
if isInnerProc(w) or owner.isIterator:
|
||||
@@ -502,9 +505,14 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
detectCapturedVars(n[namePos], owner, c)
|
||||
of nkReturnStmt:
|
||||
detectCapturedVars(n[0], owner, c)
|
||||
of nkIdentDefs:
|
||||
detectCapturedVars(n[^1], owner, c)
|
||||
else:
|
||||
if n.isCallExpr and n[0].isTypeOf:
|
||||
c.inTypeOf = true
|
||||
for i in 0..<n.len:
|
||||
detectCapturedVars(n[i], owner, c)
|
||||
c.inTypeOf = false
|
||||
|
||||
type
|
||||
LiftingPass = object
|
||||
@@ -784,6 +792,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
of nkTypeOfExpr:
|
||||
result = n
|
||||
else:
|
||||
if n.isCallExpr and n[0].isTypeOf:
|
||||
return
|
||||
if owner.isIterator:
|
||||
if nfLL in n.flags:
|
||||
# special case 'when nimVm' due to bug #3636:
|
||||
|
||||
@@ -551,11 +551,15 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
|
||||
if not preventComment:
|
||||
emitComment(em, tok, dontIndent = false)
|
||||
of tkIntLit..tkStrLit, tkRStrLit, tkTripleStrLit, tkGStrLit, tkGTripleStrLit, tkCharLit:
|
||||
let lit = fileSection(em.config, em.fid, tok.offsetA, tok.offsetB)
|
||||
if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wrSpace(em)
|
||||
em.lineSpan = countNewlines(lit)
|
||||
if em.lineSpan > 0: calcCol(em, lit)
|
||||
wr em, lit, ltLit
|
||||
if not em.inquote:
|
||||
let lit = fileSection(em.config, em.fid, tok.offsetA, tok.offsetB)
|
||||
if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wrSpace(em)
|
||||
em.lineSpan = countNewlines(lit)
|
||||
if em.lineSpan > 0: calcCol(em, lit)
|
||||
wr em, lit, ltLit
|
||||
else:
|
||||
if endsInAlpha(em): wrSpace(em)
|
||||
wr em, tok.literal, ltLit
|
||||
of tkEof: discard
|
||||
else:
|
||||
let lit = if tok.ident != nil: tok.ident.s else: tok.literal
|
||||
|
||||
@@ -19,9 +19,6 @@ 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'}
|
||||
@@ -124,6 +121,8 @@ type
|
||||
cache*: IdentCache
|
||||
when defined(nimsuggest):
|
||||
previousToken: TLineInfo
|
||||
tokenEnd*: TLineInfo
|
||||
previousTokenEnd*: TLineInfo
|
||||
config*: ConfigRef
|
||||
|
||||
proc getLineInfo*(L: Lexer, tok: Token): TLineInfo {.inline.} =
|
||||
@@ -915,7 +914,7 @@ proc getSymbol(L: var Lexer, tok: var Token) =
|
||||
else: break
|
||||
tokenEnd(tok, pos-1)
|
||||
h = !$h
|
||||
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
|
||||
tok.ident = L.cache.getIdent(cast[cstring](addr(L.buf[L.bufpos])), pos - L.bufpos, h)
|
||||
if (tok.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
|
||||
(tok.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
|
||||
tok.tokType = tkSymbol
|
||||
@@ -929,7 +928,7 @@ proc getSymbol(L: var Lexer, tok: var Token) =
|
||||
proc endOperator(L: var Lexer, tok: var Token, pos: int,
|
||||
hash: Hash) {.inline.} =
|
||||
var h = !$hash
|
||||
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
|
||||
tok.ident = L.cache.getIdent(cast[cstring](addr(L.buf[L.bufpos])), pos - L.bufpos, h)
|
||||
if (tok.ident.id < oprLow) or (tok.ident.id > oprHigh): tok.tokType = tkOpr
|
||||
else: tok.tokType = TokType(tok.ident.id - oprLow + ord(tkColon))
|
||||
L.bufpos = pos
|
||||
@@ -1219,6 +1218,10 @@ proc skip(L: var Lexer, tok: var Token) =
|
||||
proc rawGetTok*(L: var Lexer, tok: var Token) =
|
||||
template atTokenEnd() {.dirty.} =
|
||||
when defined(nimsuggest):
|
||||
L.previousTokenEnd.line = L.tokenEnd.line
|
||||
L.previousTokenEnd.col = L.tokenEnd.col
|
||||
L.tokenEnd.line = tok.line.uint16
|
||||
L.tokenEnd.col = getColNumber(L, L.bufpos).int16
|
||||
# we attach the cursor to the last *strong* token
|
||||
if tok.tokType notin weakTokens:
|
||||
L.previousToken.line = tok.line.uint16
|
||||
|
||||
@@ -15,9 +15,6 @@ import modulegraphs, lineinfos, idents, ast, renderer, semdata,
|
||||
|
||||
from trees import isCaseObj
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
TLiftCtx = object
|
||||
g: ModuleGraph
|
||||
@@ -165,9 +162,12 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
|
||||
# the value needs to be destroyed before we assign the selector
|
||||
# or the value is lost
|
||||
let prevKind = c.kind
|
||||
let prevAddMemReset = c.addMemReset
|
||||
c.kind = attachedDestructor
|
||||
c.addMemReset = true
|
||||
fillBodyObj(c, n, body, x, y, enforceDefaultOp = false)
|
||||
c.kind = prevKind
|
||||
c.addMemReset = prevAddMemReset
|
||||
localEnforceDefaultOp = true
|
||||
|
||||
if c.kind != attachedDestructor:
|
||||
@@ -518,7 +518,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
forallElements(c, t, body, x, y)
|
||||
body.add genBuiltin(c, mDestroy, "destroy", x)
|
||||
of attachedTrace:
|
||||
if canFormAcycle(t.elemType):
|
||||
if canFormAcycle(c.g, t.elemType):
|
||||
# follow all elements:
|
||||
forallElements(c, t, body, x, y)
|
||||
|
||||
@@ -528,7 +528,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
# operation here:
|
||||
var t = t
|
||||
if t.assignment == nil or t.destructor == nil:
|
||||
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let h = sighashes.hashType(t,c.g.config, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let canon = c.g.canonTypes.getOrDefault(h)
|
||||
if canon != nil: t = canon
|
||||
|
||||
@@ -553,7 +553,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
doAssert t.destructor != nil
|
||||
body.add destructorCall(c, t.destructor, x)
|
||||
of attachedTrace:
|
||||
if t.kind != tyString and canFormAcycle(t.elemType):
|
||||
if t.kind != tyString and canFormAcycle(c.g, t.elemType):
|
||||
let op = getAttachedOp(c.g, t, c.kind)
|
||||
if op == nil:
|
||||
return # protect from recursion
|
||||
@@ -574,9 +574,9 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of attachedTrace:
|
||||
discard "strings are atomic and have no inner elements that are to trace"
|
||||
|
||||
proc cyclicType*(t: PType): bool =
|
||||
proc cyclicType*(g: ModuleGraph, t: PType): bool =
|
||||
case t.kind
|
||||
of tyRef: result = types.canFormAcycle(t.lastSon)
|
||||
of tyRef: result = types.canFormAcycle(g, t.lastSon)
|
||||
of tyProc: result = t.callConv == ccClosure
|
||||
else: result = false
|
||||
|
||||
@@ -604,7 +604,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let elemType = t.lastSon
|
||||
|
||||
createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen)
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(c.g, elemType)
|
||||
|
||||
let tmp =
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||
@@ -929,7 +929,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
result.typ.addParam src
|
||||
|
||||
if kind == attachedAsgn and g.config.selectedGC == gcOrc and
|
||||
cyclicType(typ.skipTypes(abstractInst)):
|
||||
cyclicType(g, typ.skipTypes(abstractInst)):
|
||||
let cycleParam = newSym(skParam, getIdent(g.cache, "cyclic"),
|
||||
nextSymId(idgen), result, info)
|
||||
cycleParam.typ = getSysType(g, info, tyBool)
|
||||
@@ -1072,7 +1072,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
|
||||
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
if isEmptyContainer(skipped) or skipped.kind == tyStatic: return
|
||||
|
||||
let h = sighashes.hashType(skipped, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let h = sighashes.hashType(skipped, g.config, {CoType, CoConsiderOwned, CoDistinct})
|
||||
var canon = g.canonTypes.getOrDefault(h)
|
||||
if canon == nil:
|
||||
g.canonTypes[h] = skipped
|
||||
|
||||
@@ -34,7 +34,6 @@ type
|
||||
errXExpected,
|
||||
errRstGridTableNotImplemented,
|
||||
errRstMarkdownIllformedTable,
|
||||
errRstIllformedTable,
|
||||
errRstNewSectionExpected,
|
||||
errRstGeneralParseError,
|
||||
errRstInvalidDirectiveX,
|
||||
@@ -52,7 +51,6 @@ type
|
||||
warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic",
|
||||
warnRstRedefinitionOfLabel = "RedefinitionOfLabel",
|
||||
warnRstUnknownSubstitutionX = "UnknownSubstitutionX",
|
||||
warnRstAmbiguousLink = "AmbiguousLink",
|
||||
warnRstBrokenLink = "BrokenLink",
|
||||
warnRstLanguageXNotSupported = "LanguageXNotSupported",
|
||||
warnRstFieldXNotSupported = "FieldXNotSupported",
|
||||
@@ -78,8 +76,10 @@ type
|
||||
warnAnyEnumConv = "AnyEnumConv",
|
||||
warnHoleEnumConv = "HoleEnumConv",
|
||||
warnCstringConv = "CStringConv",
|
||||
warnNoInitIgnored = "NoInitIgnored"
|
||||
warnPtrToCstringConv = "PtrToCstringConv",
|
||||
warnEffect = "Effect",
|
||||
warnBareExcept = "BareExcept",
|
||||
warnCastSizes = "CastSizes"
|
||||
warnUser = "User",
|
||||
# hints
|
||||
hintSuccess = "Success", hintSuccessX = "SuccessX",
|
||||
@@ -108,7 +108,6 @@ 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'",
|
||||
@@ -129,7 +128,6 @@ 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",
|
||||
@@ -171,8 +169,10 @@ const
|
||||
warnAnyEnumConv: "$1",
|
||||
warnHoleEnumConv: "$1",
|
||||
warnCstringConv: "$1",
|
||||
warnNoInitIgnored: "noinit pragma is ignored",
|
||||
warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; this will become a compile time error in the future",
|
||||
warnEffect: "$1",
|
||||
warnBareExcept: "$1",
|
||||
warnCastSizes: "$1",
|
||||
warnUser: "$1",
|
||||
hintSuccess: "operation successful: $#",
|
||||
# keep in sync with `testament.isSuccess`
|
||||
@@ -227,7 +227,7 @@ type
|
||||
TNoteKinds* = set[TNoteKind]
|
||||
|
||||
proc computeNotesVerbosity(): array[0..3, TNoteKinds] =
|
||||
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed, warnAnyEnumConv}
|
||||
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed, warnAnyEnumConv, warnBareExcept}
|
||||
result[2] = result[3] - {hintStackTrace, warnUninit, hintExtendedContext, hintDeclaredLoc, hintProcessingStmt}
|
||||
result[1] = result[2] - {warnProveField, warnProveIndex,
|
||||
warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd,
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
import std/strutils
|
||||
from std/sugar import dup
|
||||
|
||||
import options, ast, msgs, idents, lineinfos, wordrecg, astmsgs
|
||||
import options, ast, msgs, idents, lineinfos, wordrecg, astmsgs, semdata, packages
|
||||
export packages
|
||||
|
||||
const
|
||||
Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
|
||||
@@ -85,24 +86,33 @@ proc differ*(line: string, a, b: int, x: string): string =
|
||||
result = y
|
||||
|
||||
proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
|
||||
# operators stay as they are:
|
||||
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
|
||||
if k in {skType, skGenericParam} and sfAnon in s.flags: return
|
||||
if s.typ != nil and s.typ.kind == tyTypeDesc: return
|
||||
if {sfImportc, sfExportc} * s.flags != {}: return
|
||||
if optStyleCheck notin s.options: return
|
||||
let beau = beautifyName(s.name.s, k)
|
||||
if s.name.s != beau:
|
||||
lintReport(conf, info, beau, s.name.s)
|
||||
|
||||
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
|
||||
if {optStyleHint, optStyleError} * conf.globalOptions != {} and optStyleUsages notin conf.globalOptions:
|
||||
nep1CheckDefImpl(conf, info, s, k)
|
||||
template styleCheckDef*(ctx: PContext; info: TLineInfo; sym: PSym; k: TSymKind) =
|
||||
## Check symbol definitions adhere to NEP1 style rules.
|
||||
if optStyleCheck in ctx.config.options and # ignore if styleChecks are off
|
||||
{optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # check only if hint/error is enabled
|
||||
hintName in ctx.config.notes and # ignore if name checks are not requested
|
||||
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
|
||||
optStyleUsages notin ctx.config.globalOptions and # ignore if requested to only check name usage
|
||||
sym.kind != skResult and # ignore `result`
|
||||
sym.kind != skTemp and # ignore temporary variables created by the compiler
|
||||
sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
|
||||
k notin {skType, skGenericParam} and # ignore types and generic params
|
||||
(sym.typ == nil or sym.typ.kind != tyTypeDesc) and # ignore `typedesc`
|
||||
{sfImportc, sfExportc} * sym.flags == {} and # ignore FFI
|
||||
sfAnon notin sym.flags: # ignore if created by compiler
|
||||
nep1CheckDefImpl(ctx.config, info, sym, k)
|
||||
|
||||
template styleCheckDef*(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||
styleCheckDef(conf, info, s, s.kind)
|
||||
template styleCheckDef*(conf: ConfigRef; s: PSym) =
|
||||
styleCheckDef(conf, s.info, s, s.kind)
|
||||
template styleCheckDef*(ctx: PContext; info: TLineInfo; s: PSym) =
|
||||
## Check symbol definitions adhere to NEP1 style rules.
|
||||
styleCheckDef(ctx, info, s, s.kind)
|
||||
|
||||
template styleCheckDef*(ctx: PContext; s: PSym) =
|
||||
## Check symbol definitions adhere to NEP1 style rules.
|
||||
styleCheckDef(ctx, s.info, s, s.kind)
|
||||
|
||||
proc differs(conf: ConfigRef; info: TLineInfo; newName: string): string =
|
||||
let line = sourceLine(conf, info)
|
||||
@@ -116,23 +126,31 @@ proc differs(conf: ConfigRef; info: TLineInfo; newName: string): string =
|
||||
let last = first+identLen(line, first)-1
|
||||
result = differ(line, first, last, newName)
|
||||
|
||||
proc styleCheckUse*(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||
if info.fileIndex.int < 0: return
|
||||
# we simply convert it to what it looks like in the definition
|
||||
# for consistency
|
||||
|
||||
# operators stay as they are:
|
||||
if s.kind == skTemp or s.name.s[0] notin Letters or sfAnon in s.flags:
|
||||
return
|
||||
|
||||
proc styleCheckUseImpl(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||
let newName = s.name.s
|
||||
let badName = differs(conf, info, newName)
|
||||
if badName.len > 0:
|
||||
# special rules for historical reasons
|
||||
let forceHint = badName == "nnkArgList" and newName == "nnkArglist" or badName == "nnkArglist" and newName == "nnkArgList"
|
||||
lintReport(conf, info, newName, badName, forceHint = forceHint, extraMsg = "".dup(addDeclaredLoc(conf, s)))
|
||||
lintReport(conf, info, newName, badName, "".dup(addDeclaredLoc(conf, s)))
|
||||
|
||||
proc checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
|
||||
template styleCheckUse*(ctx: PContext; info: TLineInfo; sym: PSym) =
|
||||
## Check symbol uses match their definition's style.
|
||||
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
|
||||
hintName in ctx.config.notes and # ignore if name checks are not requested
|
||||
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
|
||||
sym.kind != skTemp and # ignore temporary variables created by the compiler
|
||||
sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
|
||||
sfAnon notin sym.flags: # ignore temporary variables created by the compiler
|
||||
styleCheckUseImpl(ctx.config, info, sym)
|
||||
|
||||
proc checkPragmaUseImpl(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
|
||||
let wanted = $w
|
||||
if pragmaName != wanted:
|
||||
lintReport(conf, info, wanted, pragmaName)
|
||||
|
||||
template checkPragmaUse*(ctx: PContext; info: TLineInfo; w: TSpecialWord; pragmaName: string, sym: PSym) =
|
||||
## Check builtin pragma uses match their definition's style.
|
||||
## Note: This only applies to builtin pragmas, not user pragmas.
|
||||
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
|
||||
hintName in ctx.config.notes and # ignore if name checks are not requested
|
||||
(sym != nil and ctx.config.belongsToProjectPackage(sym)): # ignore foreign packages
|
||||
checkPragmaUseImpl(ctx.config, info, w, pragmaName)
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
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)
|
||||
|
||||
@@ -8,14 +8,10 @@
|
||||
#
|
||||
|
||||
# This module implements lookup helpers.
|
||||
import std/[algorithm, strutils]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import std/[algorithm, strutils, tables]
|
||||
import
|
||||
intsets, ast, astalgo, idents, semdata, types, msgs, options,
|
||||
renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs
|
||||
renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs, wordrecg
|
||||
|
||||
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)
|
||||
|
||||
@@ -48,6 +44,11 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
|
||||
case x.kind
|
||||
of nkIdent: id.add(x.ident.s)
|
||||
of nkSym: id.add(x.sym.name.s)
|
||||
of nkSymChoices:
|
||||
if x[0].kind == nkSym:
|
||||
id.add(x[0].sym.name.s)
|
||||
else:
|
||||
handleError(n, origin)
|
||||
of nkLiterals - nkFloatLiterals: id.add(x.renderTree)
|
||||
else: handleError(n, origin)
|
||||
result = getIdent(c.cache, id)
|
||||
@@ -310,13 +311,15 @@ proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string;
|
||||
proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) =
|
||||
let conflict = scope.addUniqueSym(sym)
|
||||
if conflict != nil:
|
||||
if sym.kind == skModule and conflict.kind == skModule and sym.owner == conflict.owner:
|
||||
if sym.kind == skModule and conflict.kind == skModule:
|
||||
# e.g.: import foo; import foo
|
||||
# xxx we could refine this by issuing a different hint for the case
|
||||
# where a duplicate import happens inside an include.
|
||||
localError(c.config, info, hintDuplicateModuleImport,
|
||||
"duplicate import of '$1'; previous import here: $2" %
|
||||
[sym.name.s, c.config $ conflict.info])
|
||||
if c.importModuleMap[sym.id] == c.importModuleMap[conflict.id]:
|
||||
#only hints if the conflict is the actual module not just a shared name
|
||||
localError(c.config, info, hintDuplicateModuleImport,
|
||||
"duplicate import of '$1'; previous import here: $2" %
|
||||
[sym.name.s, c.config $ conflict.info])
|
||||
else:
|
||||
wrongRedefinition(c, info, sym.name.s, conflict.info, errGenerated)
|
||||
|
||||
@@ -419,7 +422,7 @@ type SpellCandidate = object
|
||||
msg: string
|
||||
sym: PSym
|
||||
|
||||
template toOrderTup(a: SpellCandidate): auto =
|
||||
template toOrderTup(a: SpellCandidate): (int, int, string) =
|
||||
# `dist` is first, to favor nearby matches
|
||||
# `depth` is next, to favor nearby enclosing scopes among ties
|
||||
# `sym.name.s` is last, to make the list ordered and deterministic among ties
|
||||
@@ -490,17 +493,24 @@ proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
|
||||
var amb: bool
|
||||
discard errorUseQualifier(c, info, s, amb)
|
||||
|
||||
proc errorUseQualifier(c: PContext; info: TLineInfo; candidates: seq[PSym]) =
|
||||
proc errorUseQualifier(c: PContext; info: TLineInfo; candidates: seq[PSym]; prefix = "use one of") =
|
||||
var err = "ambiguous identifier: '" & candidates[0].name.s & "'"
|
||||
var i = 0
|
||||
for candidate in candidates:
|
||||
if i == 0: err.add " -- use one of the following:\n"
|
||||
if i == 0: err.add " -- $1 the following:\n" % prefix
|
||||
else: err.add "\n"
|
||||
err.add " " & candidate.owner.name.s & "." & candidate.name.s
|
||||
err.add ": " & typeToString(candidate.typ)
|
||||
inc i
|
||||
localError(c.config, info, errGenerated, err)
|
||||
|
||||
proc errorUseQualifier*(c: PContext; info:TLineInfo; choices: PNode) =
|
||||
var candidates = newSeq[PSym](choices.len)
|
||||
let prefix = if choices[0].typ.kind != tyProc: "use one of" else: "you need a helper proc to disambiguate"
|
||||
for i, n in choices:
|
||||
candidates[i] = n.sym
|
||||
errorUseQualifier(c, info, candidates, prefix)
|
||||
|
||||
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extra = "") =
|
||||
var err = "undeclared identifier: '" & name & "'" & extra
|
||||
if c.recursiveDep.len > 0:
|
||||
@@ -585,11 +595,18 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
|
||||
if m == c.module:
|
||||
result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n, c.config)
|
||||
else:
|
||||
result = someSym(c.graph, m, ident).skipAlias(n, c.config)
|
||||
if c.importModuleLookup.getOrDefault(m.name.id).len > 1:
|
||||
var amb: bool
|
||||
result = errorUseQualifier(c, n.info, m, amb)
|
||||
else:
|
||||
result = someSym(c.graph, m, ident).skipAlias(n, c.config)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
result = errorUndeclaredIdentifierHint(c, n[1], ident)
|
||||
elif n[1].kind == nkSym:
|
||||
result = n[1].sym
|
||||
if result.owner != nil and result.owner != m and checkUndeclared in flags:
|
||||
# dotExpr in templates can end up here
|
||||
result = errorUndeclaredIdentifierHint(c, n[1], considerQuotedIdent(c, n[1]))
|
||||
elif checkUndeclared in flags and
|
||||
n[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
|
||||
localError(c.config, n[1].info, "identifier expected, but got: " &
|
||||
|
||||
@@ -15,9 +15,6 @@ 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
|
||||
@@ -132,7 +129,7 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; o
|
||||
|
||||
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
|
||||
vpart[0] = tempAsNode
|
||||
vpart[1] = newNodeI(nkEmpty, value.info)
|
||||
vpart[1] = newNodeI(nkTupleClassTy, value.info)
|
||||
vpart[2] = value
|
||||
v.add vpart
|
||||
result.add(v)
|
||||
@@ -238,10 +235,14 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym
|
||||
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
|
||||
let t = skipIntLit(s.typ, idgen)
|
||||
field.typ = t
|
||||
if s.kind in {skLet, skVar, skField, skForVar}:
|
||||
#field.bitsize = s.bitsize
|
||||
field.alignment = s.alignment
|
||||
assert t.kind != tyTyped
|
||||
propagateToOwner(obj, t)
|
||||
field.position = obj.n.len
|
||||
field.flags = s.flags * {sfCursor}
|
||||
# sfNoInit flag for skField is used in closureiterator codegen
|
||||
field.flags = s.flags * {sfCursor, sfNoInit}
|
||||
obj.n.add newSymNode(field)
|
||||
fieldCheck()
|
||||
result = field
|
||||
|
||||
@@ -22,10 +22,6 @@ import
|
||||
modules,
|
||||
modulegraphs, lineinfos, pathutils, vmprofiler
|
||||
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
import ic / [cbackend, integrity, navigator]
|
||||
from ic / ic import rodViewer
|
||||
|
||||
@@ -65,8 +61,6 @@ proc commandCheck(graph: ModuleGraph) =
|
||||
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)
|
||||
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
#
|
||||
#
|
||||
# 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,13 +11,10 @@
|
||||
## represents a complete Nim project. Single modules can either be kept in RAM
|
||||
## or stored in a rod-file.
|
||||
|
||||
import intsets, tables, hashes, md5_old, sequtils
|
||||
import intsets, tables, hashes, md5, 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
|
||||
|
||||
@@ -53,6 +50,11 @@ type
|
||||
concreteTypes*: seq[FullId]
|
||||
inst*: PInstantiation
|
||||
|
||||
SymInfoPair* = object
|
||||
sym*: PSym
|
||||
info*: TLineInfo
|
||||
isDecl*: bool
|
||||
|
||||
ModuleGraph* {.acyclic.} = ref object
|
||||
ifaces*: seq[Iface] ## indexed by int32 fileIdx
|
||||
packed*: PackedModuleGraph
|
||||
@@ -83,7 +85,7 @@ type
|
||||
doStopCompile*: proc(): bool {.closure.}
|
||||
usageSym*: PSym # for nimsuggest
|
||||
owners*: seq[PSym]
|
||||
suggestSymbols*: Table[FileIndex, seq[tuple[sym: PSym, info: TLineInfo]]]
|
||||
suggestSymbols*: Table[FileIndex, seq[SymInfoPair]]
|
||||
suggestErrors*: Table[FileIndex, seq[Suggest]]
|
||||
methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization!
|
||||
systemModule*: PSym
|
||||
@@ -372,34 +374,13 @@ template getPContext(): untyped =
|
||||
when c is PContext: c
|
||||
else: c.c
|
||||
|
||||
when defined(nimfind):
|
||||
template onUse*(info: TLineInfo; s: PSym) =
|
||||
let c = getPContext()
|
||||
if c.graph.onUsage != nil: c.graph.onUsage(c.graph, s, info)
|
||||
|
||||
template onDef*(info: TLineInfo; s: PSym) =
|
||||
let c = getPContext()
|
||||
if c.graph.onDefinition != nil: c.graph.onDefinition(c.graph, s, info)
|
||||
|
||||
template onDefResolveForward*(info: TLineInfo; s: PSym) =
|
||||
let c = getPContext()
|
||||
if c.graph.onDefinitionResolveForward != nil:
|
||||
c.graph.onDefinitionResolveForward(c.graph, s, info)
|
||||
|
||||
when defined(nimsuggest):
|
||||
template onUse*(info: TLineInfo; s: PSym) = discard
|
||||
template onDefResolveForward*(info: TLineInfo; s: PSym) = discard
|
||||
else:
|
||||
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
|
||||
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()
|
||||
@@ -457,7 +438,7 @@ proc initModuleGraphFields(result: ModuleGraph) =
|
||||
result.importStack = @[]
|
||||
result.inclToMod = initTable[FileIndex, FileIndex]()
|
||||
result.owners = @[]
|
||||
result.suggestSymbols = initTable[FileIndex, seq[tuple[sym: PSym, info: TLineInfo]]]()
|
||||
result.suggestSymbols = initTable[FileIndex, seq[SymInfoPair]]()
|
||||
result.suggestErrors = initTable[FileIndex, seq[Suggest]]()
|
||||
result.methods = @[]
|
||||
initStrTable(result.compilerprocs)
|
||||
@@ -593,7 +574,12 @@ proc markClientsDirty*(g: ModuleGraph; fileIdx: FileIndex) =
|
||||
# every module that *depends* on this file is also dirty:
|
||||
for i in 0i32..<g.ifaces.len.int32:
|
||||
if g.deps.contains(i.dependsOn(fileIdx.int)):
|
||||
g.markDirty(FileIndex(i))
|
||||
let
|
||||
fi = FileIndex(i)
|
||||
module = g.getModule(fi)
|
||||
if module != nil and not g.isDirty(module):
|
||||
g.markDirty(fi)
|
||||
g.markClientsDirty(fi)
|
||||
|
||||
proc needsCompilation*(g: ModuleGraph): bool =
|
||||
# every module that *depends* on this file is also dirty:
|
||||
@@ -656,9 +642,15 @@ 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] =
|
||||
proc `==`*(a, b: SymInfoPair): bool =
|
||||
result = a.sym == b.sym and a.info.exactEquals(b.info)
|
||||
|
||||
proc fileSymbols*(graph: ModuleGraph, fileIdx: FileIndex): seq[SymInfoPair] =
|
||||
result = graph.suggestSymbols.getOrDefault(fileIdx, @[])
|
||||
|
||||
iterator suggestSymbolsIter*(g: ModuleGraph): SymInfoPair =
|
||||
for xs in g.suggestSymbols.values:
|
||||
for x in xs.deduplicate:
|
||||
for x in xs:
|
||||
yield x
|
||||
|
||||
iterator suggestErrorsIter*(g: ModuleGraph): Suggest =
|
||||
|
||||
@@ -36,11 +36,14 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
|
||||
localError(n.info, "only '/' supported with $package notation")
|
||||
result = ""
|
||||
else:
|
||||
let modname = getModuleName(conf, n[2])
|
||||
# hacky way to implement 'x / y /../ z':
|
||||
result = getModuleName(conf, n1)
|
||||
result.add renderTree(n0, {renderNoComments}).replace(" ")
|
||||
result.add modname
|
||||
if n0.kind == nkIdent and n0.ident.s[0] == '/':
|
||||
let modname = getModuleName(conf, n[2])
|
||||
# hacky way to implement 'x / y /../ z':
|
||||
result = getModuleName(conf, n1)
|
||||
result.add renderTree(n0, {renderNoComments}).replace(" ")
|
||||
result.add modname
|
||||
else:
|
||||
result = ""
|
||||
of nkPrefix:
|
||||
when false:
|
||||
if n[0].kind == nkIdent and n[0].ident.s == "$":
|
||||
|
||||
@@ -14,9 +14,6 @@ import
|
||||
idents, lexer, passes, syntaxes, llstream, modulegraphs,
|
||||
lineinfos, pathutils, tables, packages
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
import ic / replayer
|
||||
|
||||
proc resetSystemArtifacts*(g: ModuleGraph) =
|
||||
|
||||
@@ -12,10 +12,6 @@ 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)
|
||||
|
||||
@@ -127,6 +123,13 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
|
||||
var dummy: bool
|
||||
result = fileInfoIdx(conf, filename, dummy)
|
||||
|
||||
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile; isKnownFile: var bool): FileIndex =
|
||||
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), isKnownFile)
|
||||
|
||||
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile): FileIndex =
|
||||
var dummy: bool
|
||||
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), dummy)
|
||||
|
||||
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
|
||||
result.fileIndex = fileInfoIdx
|
||||
if line < int high(uint16):
|
||||
@@ -411,17 +414,21 @@ To create a stacktrace, rerun compilation with './koch temp $1 <file>', see $2 f
|
||||
[conf.command, "intern.html#debugging-the-compiler".createDocLink], conf.unitSep)
|
||||
quit 1
|
||||
|
||||
proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string) =
|
||||
proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string, ignoreMsg: bool) =
|
||||
if msg in fatalMsgs:
|
||||
if conf.cmd == cmdIdeTools: log(s)
|
||||
quit(conf, msg)
|
||||
if conf.cmd != cmdIdeTools or msg != errFatal:
|
||||
quit(conf, msg)
|
||||
if msg >= errMin and msg <= errMax or
|
||||
(msg in warnMin..hintMax and msg in conf.warningAsErrors):
|
||||
(msg in warnMin..hintMax and msg in conf.warningAsErrors and not ignoreMsg):
|
||||
inc(conf.errorCounter)
|
||||
conf.exitcode = 1'i8
|
||||
if conf.errorCounter >= conf.errorMax:
|
||||
# only really quit when we're not in the new 'nim check --def' mode:
|
||||
if conf.ideCmd == ideNone:
|
||||
when defined(nimsuggest):
|
||||
#we need to inform the user that something went wrong when initializing NimSuggest
|
||||
raiseRecoverableError(s)
|
||||
else:
|
||||
quit(conf, msg)
|
||||
elif eh == doAbort and conf.cmd != cmdIdeTools:
|
||||
quit(conf, msg)
|
||||
@@ -524,8 +531,7 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
of warnMin..warnMax:
|
||||
sev = Severity.Warning
|
||||
ignoreMsg = not conf.hasWarn(msg)
|
||||
if msg in conf.warningAsErrors:
|
||||
ignoreMsg = false
|
||||
if not ignoreMsg and msg in conf.warningAsErrors:
|
||||
title = ErrorTitle
|
||||
else:
|
||||
title = WarningTitle
|
||||
@@ -535,8 +541,7 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
of hintMin..hintMax:
|
||||
sev = Severity.Hint
|
||||
ignoreMsg = not conf.hasHint(msg)
|
||||
if msg in conf.warningAsErrors:
|
||||
ignoreMsg = false
|
||||
if not ignoreMsg and msg in conf.warningAsErrors:
|
||||
title = ErrorTitle
|
||||
else:
|
||||
title = HintTitle
|
||||
@@ -562,7 +567,7 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
" compiler msg initiated here", KindColor,
|
||||
KindFormat % $hintMsgOrigin,
|
||||
resetStyle, conf.unitSep)
|
||||
handleError(conf, msg, eh, s)
|
||||
handleError(conf, msg, eh, s, ignoreMsg)
|
||||
if msg in fatalMsgs:
|
||||
# most likely would have died here but just in case, we restore state
|
||||
conf.m.errorOutputs = errorOutputsOld
|
||||
@@ -622,9 +627,9 @@ template internalAssert*(conf: ConfigRef, e: bool) =
|
||||
let arg = info2.toFileLineCol
|
||||
internalErrorImpl(conf, unknownLineInfo, arg, info2)
|
||||
|
||||
template lintReport*(conf: ConfigRef; info: TLineInfo, beau, got: string, forceHint = false, extraMsg = "") =
|
||||
template lintReport*(conf: ConfigRef; info: TLineInfo, beau, got: string, extraMsg = "") =
|
||||
let m = "'$1' should be: '$2'$3" % [got, beau, extraMsg]
|
||||
let msg = if optStyleError in conf.globalOptions and not forceHint: errGenerated else: hintName
|
||||
let msg = if optStyleError in conf.globalOptions: errGenerated else: hintName
|
||||
liMessage(conf, info, msg, m, doNothing, instLoc())
|
||||
|
||||
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
|
||||
import ast, msgs, ropes, options, pathutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
|
||||
type
|
||||
NdiFile* = object
|
||||
enabled: bool
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
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:
|
||||
|
||||
@@ -10,6 +10,7 @@ define:nimPreviewFloatRoundtrip
|
||||
|
||||
@if windows:
|
||||
cincludes: "$lib/wrappers/libffi/common"
|
||||
tlsEmulation:off
|
||||
@end
|
||||
|
||||
define:useStdoutAsStdmsg
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#
|
||||
|
||||
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
|
||||
@@ -41,6 +37,15 @@ when defined(profiler) or defined(memProfiler):
|
||||
{.hint: "Profiling support is turned on!".}
|
||||
import nimprof
|
||||
|
||||
proc nimbleLockExists(config: ConfigRef): bool =
|
||||
const nimbleLock = "nimble.lock"
|
||||
let pd = if not config.projectPath.isEmpty: config.projectPath else: AbsoluteDir(getCurrentDir())
|
||||
if optSkipParentConfigFiles notin config.globalOptions:
|
||||
for dir in parentDirs(pd.string, fromRoot=true, inclusive=false):
|
||||
if fileExists(dir / nimbleLock):
|
||||
return true
|
||||
return fileExists(pd.string / nimbleLock)
|
||||
|
||||
proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
|
||||
var p = parseopt.initOptParser(cmd)
|
||||
var argsCount = 0
|
||||
@@ -74,6 +79,11 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
|
||||
config.arguments.len > 0 and config.cmd notin {cmdTcc, cmdNimscript, cmdCrun}:
|
||||
rawMessage(config, errGenerated, errArgsNeedRunOption)
|
||||
|
||||
if config.nimbleLockExists:
|
||||
# disable nimble path if nimble.lock is present.
|
||||
# see https://github.com/nim-lang/nimble/issues/1004
|
||||
disableNimblePath(config)
|
||||
|
||||
proc getNimRunExe(conf: ConfigRef): string =
|
||||
# xxx consider defining `conf.getConfigVar("nimrun.exe")` to allow users to
|
||||
# customize the binary to run the command with, e.g. for custom `nodejs` or `wine`.
|
||||
@@ -120,8 +130,7 @@ 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`
|
||||
let cmd = cmdPrefix & output.quoteShell & ' ' & conf.arguments
|
||||
execExternalProgram(conf, cmd.strip(leading=false,trailing=true))
|
||||
execExternalProgram(conf, cmdPrefix & output.quoteShell & ' ' & conf.arguments)
|
||||
of cmdDocLike, cmdRst2html, cmdRst2tex: # bugfix(cmdRst2tex was missing)
|
||||
if conf.arguments.len > 0:
|
||||
# reserved for future use
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
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,9 +13,6 @@ 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
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ import
|
||||
ast, astalgo, modules, passes, condsyms,
|
||||
options, sem, llstream, lineinfos, vm,
|
||||
vmdef, modulegraphs, idents, os, pathutils,
|
||||
passaux, scriptconfig, std/compilesettings
|
||||
passaux,
|
||||
scriptconfig, std/[compilesettings, tables]
|
||||
|
||||
|
||||
type
|
||||
Interpreter* = ref object ## Use Nim as an interpreter with this object
|
||||
@@ -72,6 +74,9 @@ proc evalScript*(i: Interpreter; scriptStream: PLLStream = nil) =
|
||||
assert i != nil
|
||||
assert i.mainModule != nil, "no main module selected"
|
||||
initStrTables(i.graph, i.mainModule)
|
||||
i.graph.cacheSeqs.clear()
|
||||
i.graph.cacheCounters.clear()
|
||||
i.graph.cacheTables.clear()
|
||||
i.mainModule.ast = nil
|
||||
|
||||
let s = if scriptStream != nil: scriptStream
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
import
|
||||
llstream, strutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
Lrz* = ' '
|
||||
Apo* = '\''
|
||||
|
||||
@@ -19,19 +19,13 @@ 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,9 +12,6 @@
|
||||
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 destructor/tmatrix.test3:
|
||||
#[ Test 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,17 +14,12 @@ 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* = "2022"
|
||||
copyrightYear* = "2023"
|
||||
|
||||
nimEnableCovariance* = defined(nimEnableCovariance)
|
||||
|
||||
@@ -101,7 +96,6 @@ 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.
|
||||
@@ -183,6 +177,7 @@ 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
|
||||
@@ -190,7 +185,7 @@ type
|
||||
IdeCmd* = enum
|
||||
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
|
||||
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
|
||||
ideRecompile, ideChanged
|
||||
ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints
|
||||
|
||||
Feature* = enum ## experimental features; DO NOT RENAME THESE!
|
||||
implicitDeref,
|
||||
@@ -201,7 +196,7 @@ type
|
||||
notnil,
|
||||
dynamicBindSym,
|
||||
forLoopMacros, # not experimental anymore; remains here for backwards compatibility
|
||||
caseStmtMacros, # ditto
|
||||
caseStmtMacros,
|
||||
codeReordering,
|
||||
compiletimeFFI,
|
||||
## This requires building nim with `-d:nimHasLibFFI`
|
||||
@@ -269,8 +264,26 @@ type
|
||||
scope*, localUsages*, globalUsages*: int # more usages is better
|
||||
tokenLen*: int
|
||||
version*: int
|
||||
endLine*: uint16
|
||||
endCol*: int
|
||||
inlayHintInfo*: SuggestInlayHint
|
||||
|
||||
Suggestions* = seq[Suggest]
|
||||
|
||||
SuggestInlayHintKind* = enum
|
||||
sihkType = "Type",
|
||||
sihkParameter = "Parameter"
|
||||
|
||||
SuggestInlayHint* = ref object
|
||||
kind*: SuggestInlayHintKind
|
||||
line*: int # Starts at 1
|
||||
column*: int # Starts at 0
|
||||
label*: string
|
||||
paddingLeft*: bool
|
||||
paddingRight*: bool
|
||||
allowInsert*: bool
|
||||
tooltip*: string
|
||||
|
||||
ProfileInfo* = object
|
||||
time*: float
|
||||
count*: int
|
||||
@@ -399,6 +412,13 @@ type
|
||||
nimMainPrefix*: string
|
||||
vmProfileData*: ProfileData
|
||||
|
||||
expandProgress*: bool
|
||||
expandLevels*: int
|
||||
expandNodeResult*: string
|
||||
expandPosition*: TLineInfo
|
||||
|
||||
clientProcessId*: int
|
||||
|
||||
proc parseNimVersion*(a: string): NimVer =
|
||||
# could be moved somewhere reusable
|
||||
if a.len > 0:
|
||||
@@ -852,7 +872,7 @@ when (NimMajor, NimMinor) < (1, 1) or not declared(isRelativeTo):
|
||||
let ret = relativePath(path, base)
|
||||
result = path.len > 0 and not ret.startsWith ".."
|
||||
|
||||
const stdlibDirs = [
|
||||
const stdlibDirs* = [
|
||||
"pure", "core", "arch",
|
||||
"pure/collections",
|
||||
"pure/concurrency",
|
||||
@@ -986,6 +1006,9 @@ proc isDynlibOverride*(conf: ConfigRef; lib: string): bool =
|
||||
result = optDynlibOverrideAll in conf.globalOptions or
|
||||
conf.dllOverrides.hasKey(lib.canonDynlibName)
|
||||
|
||||
proc expandDone*(conf: ConfigRef): bool =
|
||||
result = conf.ideCmd == ideExpand and conf.expandLevels == 0 and conf.expandProgress
|
||||
|
||||
proc parseIdeCmd*(s: string): IdeCmd =
|
||||
case s:
|
||||
of "sug": ideSug
|
||||
@@ -1004,6 +1027,7 @@ proc parseIdeCmd*(s: string): IdeCmd =
|
||||
of "globalSymbols": ideGlobalSymbols
|
||||
of "recompile": ideRecompile
|
||||
of "changed": ideChanged
|
||||
of "type": ideType
|
||||
else: ideNone
|
||||
|
||||
proc `$`*(c: IdeCmd): string =
|
||||
@@ -1023,8 +1047,12 @@ proc `$`*(c: IdeCmd): string =
|
||||
of ideMsg: "msg"
|
||||
of ideProject: "project"
|
||||
of ideGlobalSymbols: "globalSymbols"
|
||||
of ideDeclaration: "declaration"
|
||||
of ideExpand: "expand"
|
||||
of ideRecompile: "recompile"
|
||||
of ideChanged: "changed"
|
||||
of ideType: "type"
|
||||
of ideInlayHints: "inlayHints"
|
||||
|
||||
proc floatInt64Align*(conf: ConfigRef): int16 =
|
||||
## Returns either 4 or 8 depending on reasons.
|
||||
|
||||
@@ -143,11 +143,8 @@ proc checkForSideEffects*(n: PNode): TSideEffectAnalysis =
|
||||
let s = op.sym
|
||||
if sfSideEffect in s.flags:
|
||||
return seSideEffect
|
||||
elif tfNoSideEffect in op.typ.flags:
|
||||
result = seNoSideEffect
|
||||
else:
|
||||
# assume side effect:
|
||||
result = seSideEffect
|
||||
# assume no side effect:
|
||||
result = seNoSideEffect
|
||||
elif tfNoSideEffect in op.typ.flags:
|
||||
# indirect call without side effects:
|
||||
result = seNoSideEffect
|
||||
@@ -179,7 +176,6 @@ 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]'
|
||||
|
||||
@@ -213,7 +209,7 @@ proc exprRoot*(n: PNode): PSym =
|
||||
else:
|
||||
break
|
||||
|
||||
proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult =
|
||||
## 'owner' can be nil!
|
||||
result = arNone
|
||||
case n.kind
|
||||
@@ -221,20 +217,20 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
if n.typ != nil and n.typ.kind in {tyVar}:
|
||||
result = arLValue
|
||||
of nkSym:
|
||||
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
|
||||
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
|
||||
elif n.sym.kind in kinds:
|
||||
if n.sym.kind in {skParam, skLet, skForVar}:
|
||||
result = arAddressableConst
|
||||
if owner != nil and owner == n.sym.owner and
|
||||
sfGlobal notin n.sym.flags:
|
||||
result = arLocalLValue
|
||||
else:
|
||||
if owner != nil and owner == n.sym.owner and
|
||||
sfGlobal notin n.sym.flags:
|
||||
result = arLocalLValue
|
||||
else:
|
||||
result = arLValue
|
||||
result = arLValue
|
||||
elif n.sym.kind == skType:
|
||||
let t = n.sym.typ.skipTypes({tyTypeDesc})
|
||||
if t.kind in {tyVar}: result = arStrange
|
||||
@@ -242,10 +238,10 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
elif t.kind == tyLent:
|
||||
result = arAddressableConst
|
||||
elif isUnsafeAddr and t.kind == tyLent:
|
||||
result = arLValue
|
||||
else:
|
||||
result = isAssignable(owner, n[0])
|
||||
result = isAssignable(owner, n[0], isUnsafeAddr)
|
||||
if result != arNone and n[1].kind == nkSym and
|
||||
sfDiscriminant in n[1].sym.flags:
|
||||
result = arDiscriminant
|
||||
@@ -253,23 +249,23 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
elif t.kind == tyLent:
|
||||
result = arAddressableConst
|
||||
elif isUnsafeAddr and t.kind == tyLent:
|
||||
result = arLValue
|
||||
else:
|
||||
result = isAssignable(owner, n[0])
|
||||
result = isAssignable(owner, n[0], isUnsafeAddr)
|
||||
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])
|
||||
result = isAssignable(owner, n[1], isUnsafeAddr)
|
||||
elif compareTypes(n.typ, n[1].typ, dcEqIgnoreDistinct):
|
||||
# types that are equal modulo distinction preserve l-value:
|
||||
result = isAssignable(owner, n[1])
|
||||
result = isAssignable(owner, n[1], isUnsafeAddr)
|
||||
of nkHiddenDeref:
|
||||
let n0 = n[0]
|
||||
if n0.typ.kind == tyLent:
|
||||
if n0.kind == nkSym and n0.sym.kind == skResult:
|
||||
if isUnsafeAddr or (n0.kind == nkSym and n0.sym.kind == skResult):
|
||||
result = arLValue
|
||||
else:
|
||||
result = arLentValue
|
||||
@@ -278,19 +274,18 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
|
||||
of nkDerefExpr, nkHiddenAddr:
|
||||
result = arLValue
|
||||
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
|
||||
result = isAssignable(owner, n[0])
|
||||
result = isAssignable(owner, n[0], isUnsafeAddr)
|
||||
of nkCallKinds:
|
||||
# builtin slice keeps lvalue-ness:
|
||||
if getMagic(n) in {mArrGet, mSlice}:
|
||||
result = isAssignable(owner, n[1])
|
||||
elif n.typ != nil:
|
||||
case n.typ.kind
|
||||
of tyVar: result = arLValue
|
||||
of tyLent: result = arLentValue
|
||||
else: discard
|
||||
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
|
||||
of nkStmtList, nkStmtListExpr:
|
||||
if n.typ != nil:
|
||||
result = isAssignable(owner, n.lastSon)
|
||||
result = isAssignable(owner, n.lastSon, isUnsafeAddr)
|
||||
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,9 +36,6 @@ 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
|
||||
@@ -334,6 +331,12 @@ proc colcom(p: var Parser, n: PNode) =
|
||||
|
||||
const tkBuiltInMagics = {tkType, tkStatic, tkAddr}
|
||||
|
||||
template setEndInfo() =
|
||||
when defined(nimsuggest):
|
||||
result.endInfo = TLineInfo(fileIndex: p.lex.fileIdx,
|
||||
line: p.lex.previousTokenEnd.line,
|
||||
col: p.lex.previousTokenEnd.col)
|
||||
|
||||
proc parseSymbol(p: var Parser, mode = smNormal): PNode =
|
||||
#| symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
|
||||
#| | IDENT | KEYW
|
||||
@@ -386,6 +389,7 @@ proc parseSymbol(p: var Parser, mode = smNormal): PNode =
|
||||
# if it is a keyword:
|
||||
#if not isKeyword(p.tok.tokType): getTok(p)
|
||||
result = p.emptyNode
|
||||
setEndInfo()
|
||||
|
||||
proc colonOrEquals(p: var Parser, a: PNode): PNode =
|
||||
if p.tok.tokType == tkColon:
|
||||
@@ -419,6 +423,24 @@ proc exprList(p: var Parser, endTok: TokType, result: PNode) =
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
# progress guaranteed
|
||||
var a = parseExpr(p)
|
||||
result.add(a)
|
||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
var a = parseExpr(p)
|
||||
result.add(a)
|
||||
when defined(nimpretty):
|
||||
dec p.em.doIndentMore
|
||||
|
||||
proc optionalExprList(p: var Parser, endTok: TokType, result: PNode) =
|
||||
#| optionalExprList = expr ^* comma
|
||||
when defined(nimpretty):
|
||||
inc p.em.doIndentMore
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
# progress guaranteed
|
||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||
var a = parseExpr(p)
|
||||
result.add(a)
|
||||
@@ -527,6 +549,7 @@ proc parseCast(p: var Parser): PNode =
|
||||
result.add(exprColonEqExpr(p))
|
||||
optPar(p)
|
||||
eat(p, tkParRi)
|
||||
setEndInfo()
|
||||
|
||||
proc setBaseFlags(n: PNode, base: NumericalBase) =
|
||||
case base
|
||||
@@ -549,6 +572,7 @@ proc parseGStrLit(p: var Parser, a: PNode): PNode =
|
||||
getTok(p)
|
||||
else:
|
||||
result = a
|
||||
setEndInfo()
|
||||
|
||||
proc complexOrSimpleStmt(p: var Parser): PNode
|
||||
proc simpleExpr(p: var Parser, mode = pmNormal): PNode
|
||||
@@ -653,6 +677,7 @@ proc parsePar(p: var Parser): PNode =
|
||||
skipComment(p, a)
|
||||
optPar(p)
|
||||
eat(p, tkParRi)
|
||||
setEndInfo()
|
||||
|
||||
proc identOrLiteral(p: var Parser, mode: PrimaryMode): PNode =
|
||||
#| literal = | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
@@ -814,7 +839,7 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
#| | DOTLIKEOP optInd symbol generalizedLit?
|
||||
#| | '[' optInd exprColonEqExprList optPar ']'
|
||||
#| | '{' optInd exprColonEqExprList optPar '}'
|
||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr (comma expr)* # command syntax
|
||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
|
||||
result = r
|
||||
|
||||
# progress guaranteed
|
||||
@@ -824,14 +849,14 @@ proc primarySuffix(p: var Parser, r: PNode,
|
||||
of tkParLe:
|
||||
# progress guaranteed
|
||||
if p.tok.strongSpaceA > 0:
|
||||
result = commandExpr(p, result, mode)
|
||||
# type sections allow full command syntax
|
||||
# inside type sections, expressions such as `ref (int, bar)`
|
||||
# are parsed as a nkCommand with a single tuple argument (nkPar)
|
||||
if mode == pmTypeDef:
|
||||
var isFirstParam = false
|
||||
while p.tok.tokType == tkComma:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
result.add(commandParam(p, isFirstParam, mode))
|
||||
result = newNodeP(nkCommand, p)
|
||||
result.add r
|
||||
result.add primary(p, pmNormal)
|
||||
else:
|
||||
result = commandExpr(p, result, mode)
|
||||
break
|
||||
result = namedParams(p, result, nkCall, tkParRi)
|
||||
if result.len > 1 and result[1].kind == nkExprColonExpr:
|
||||
@@ -872,18 +897,9 @@ 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 =
|
||||
@@ -908,6 +924,7 @@ proc parseOperators(p: var Parser, headNode: PNode,
|
||||
a.add(b)
|
||||
result = a
|
||||
opPrec = getPrecedence(p.tok)
|
||||
setEndInfo()
|
||||
|
||||
proc simpleExprAux(p: var Parser, limit: int, mode: PrimaryMode): PNode =
|
||||
result = primary(p, mode)
|
||||
@@ -954,6 +971,7 @@ proc parsePragma(p: var Parser): PNode =
|
||||
when defined(nimpretty):
|
||||
dec p.em.doIndentMore
|
||||
dec p.em.keepIndents
|
||||
setEndInfo()
|
||||
|
||||
proc identVis(p: var Parser; allowDot=false): PNode =
|
||||
#| identVis = symbol OPR? # postfix position
|
||||
@@ -1022,6 +1040,7 @@ proc parseIdentColonEquals(p: var Parser, flags: DeclaredIdentFlags): PNode =
|
||||
result.add(parseExpr(p))
|
||||
else:
|
||||
result.add(newNodeP(nkEmpty, p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseTuple(p: var Parser, indentAllowed = false): PNode =
|
||||
#| tupleDecl = 'tuple'
|
||||
@@ -1065,6 +1084,7 @@ proc parseTuple(p: var Parser, indentAllowed = false): PNode =
|
||||
parMessage(p, errGenerated, "the syntax for tuple types is 'tuple[...]', not 'tuple(...)'")
|
||||
else:
|
||||
result = newNodeP(nkTupleClassTy, p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseParamList(p: var Parser, retColon = true): PNode =
|
||||
#| paramList = '(' declColonEquals ^* (comma/semicolon) ')'
|
||||
@@ -1113,6 +1133,7 @@ proc parseParamList(p: var Parser, retColon = true): PNode =
|
||||
when defined(nimpretty):
|
||||
dec p.em.doIndentMore
|
||||
dec p.em.keepIndents
|
||||
setEndInfo()
|
||||
|
||||
proc optPragmas(p: var Parser): PNode =
|
||||
if p.tok.tokType == tkCurlyDotLe and (p.tok.indent < 0 or realInd(p)):
|
||||
@@ -1133,12 +1154,12 @@ proc parseDoBlock(p: var Parser; info: TLineInfo): PNode =
|
||||
result = newProcNode(nkDo, info,
|
||||
body = result, params = params, name = p.emptyNode, pattern = p.emptyNode,
|
||||
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
|
||||
setEndInfo()
|
||||
|
||||
proc parseProcExpr(p: var Parser; isExpr: bool; kind: TNodeKind): PNode =
|
||||
#| routineExpr = ('proc' | 'func' | 'iterator') paramListColon pragma? ('=' COMMENT? stmt)?
|
||||
# either a proc type or a anonymous proc
|
||||
let info = parLineInfo(p)
|
||||
getTok(p)
|
||||
let hasSignature = p.tok.tokType in {tkParLe, tkColon} and p.tok.indent < 0
|
||||
let params = parseParamList(p)
|
||||
let pragmas = optPragmas(p)
|
||||
@@ -1149,12 +1170,13 @@ proc parseProcExpr(p: var Parser; isExpr: bool; kind: TNodeKind): PNode =
|
||||
params = params, name = p.emptyNode, pattern = p.emptyNode,
|
||||
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
|
||||
else:
|
||||
result = newNodeI(nkProcTy, info)
|
||||
result = newNodeI(if kind == nkIteratorDef: nkIteratorTy else: nkProcTy, info)
|
||||
if hasSignature:
|
||||
result.add(params)
|
||||
if kind == nkFuncDef:
|
||||
parMessage(p, "func keyword is not allowed in type descriptions, use proc with {.noSideEffect.} pragma instead")
|
||||
result.add(pragmas)
|
||||
setEndInfo()
|
||||
|
||||
proc isExprStart(p: Parser): bool =
|
||||
case p.tok.tokType
|
||||
@@ -1174,6 +1196,7 @@ proc parseSymbolList(p: var Parser, result: PNode) =
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, s)
|
||||
setEndInfo()
|
||||
|
||||
proc parseTypeDescKAux(p: var Parser, kind: TNodeKind,
|
||||
mode: PrimaryMode): PNode =
|
||||
@@ -1196,6 +1219,7 @@ proc parseTypeDescKAux(p: var Parser, kind: TNodeKind,
|
||||
let list = newNodeP(nodeKind, p)
|
||||
result.add list
|
||||
parseSymbolList(p, list)
|
||||
setEndInfo()
|
||||
|
||||
proc parseVarTuple(p: var Parser): PNode
|
||||
|
||||
@@ -1221,6 +1245,7 @@ proc parseFor(p: var Parser): PNode =
|
||||
result.add(parseExpr(p))
|
||||
colcom(p, result)
|
||||
result.add(parseStmt(p))
|
||||
setEndInfo()
|
||||
|
||||
template nimprettyDontTouch(body) =
|
||||
when defined(nimpretty):
|
||||
@@ -1259,6 +1284,7 @@ proc parseExpr(p: var Parser): PNode =
|
||||
nimprettyDontTouch:
|
||||
result = parseTry(p, isExpr=true)
|
||||
else: result = simpleExpr(p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseEnum(p: var Parser): PNode
|
||||
proc parseObject(p: var Parser): PNode
|
||||
@@ -1290,12 +1316,15 @@ proc primary(p: var Parser, mode: PrimaryMode): PNode =
|
||||
|
||||
case p.tok.tokType
|
||||
of tkTuple: result = parseTuple(p, mode == pmTypeDef)
|
||||
of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
|
||||
of tkFunc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkFuncDef)
|
||||
of tkIterator:
|
||||
of tkProc:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
|
||||
if result.kind == nkLambda: result.transitionSonsKind(nkIteratorDef)
|
||||
else: result.transitionSonsKind(nkIteratorTy)
|
||||
of tkFunc:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkFuncDef)
|
||||
of tkIterator:
|
||||
getTok(p)
|
||||
result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkIteratorDef)
|
||||
of tkEnum:
|
||||
if mode == pmTypeDef:
|
||||
prettySection:
|
||||
@@ -1352,12 +1381,13 @@ proc parseTypeDesc(p: var Parser): PNode =
|
||||
newlineWasSplitting(p)
|
||||
result = simpleExpr(p, pmTypeDesc)
|
||||
result = binaryNot(p, result)
|
||||
setEndInfo()
|
||||
|
||||
proc parseTypeDefAux(p: var Parser): PNode =
|
||||
#| typeDefAux = simpleExpr ('not' expr
|
||||
#| | postExprBlocks)?
|
||||
#| typeDefAux = simpleExpr ('not' expr)?
|
||||
result = simpleExpr(p, pmTypeDef)
|
||||
result = binaryNot(p, result)
|
||||
setEndInfo()
|
||||
|
||||
proc makeCall(n: PNode): PNode =
|
||||
## Creates a call if the given node isn't already a call.
|
||||
@@ -1371,7 +1401,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
#| postExprBlocks = ':' stmt? ( IND{=} doBlock
|
||||
#| | IND{=} 'of' exprList ':' stmt
|
||||
#| | IND{=} 'elif' expr ':' stmt
|
||||
#| | IND{=} 'except' exprList ':' stmt
|
||||
#| | IND{=} 'except' optionalExprList ':' stmt
|
||||
#| | IND{=} 'finally' ':' stmt
|
||||
#| | IND{=} 'else' ':' stmt )*
|
||||
result = x
|
||||
@@ -1429,7 +1459,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||
nextBlock.add parseExpr(p)
|
||||
of tkExcept:
|
||||
nextBlock = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, nextBlock)
|
||||
optionalExprList(p, tkColon, nextBlock)
|
||||
of tkFinally:
|
||||
nextBlock = newNodeP(nkFinally, p)
|
||||
getTok(p)
|
||||
@@ -1483,6 +1513,7 @@ proc parseExprStmt(p: var Parser): PNode =
|
||||
else:
|
||||
result = a
|
||||
result = postExprBlocks(p, result)
|
||||
setEndInfo()
|
||||
|
||||
proc parseModuleName(p: var Parser, kind: TNodeKind): PNode =
|
||||
result = parseExpr(p)
|
||||
@@ -1494,6 +1525,7 @@ proc parseModuleName(p: var Parser, kind: TNodeKind): PNode =
|
||||
getTok(p)
|
||||
result.add(a)
|
||||
result.add(parseExpr(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseImport(p: var Parser, kind: TNodeKind): PNode =
|
||||
#| importStmt = 'import' optInd expr
|
||||
@@ -1522,6 +1554,7 @@ proc parseImport(p: var Parser, kind: TNodeKind): PNode =
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
#expectNl(p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseIncludeStmt(p: var Parser): PNode =
|
||||
#| includeStmt = 'include' optInd expr ^+ comma
|
||||
@@ -1538,6 +1571,7 @@ proc parseIncludeStmt(p: var Parser): PNode =
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
#expectNl(p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseFromStmt(p: var Parser): PNode =
|
||||
#| fromStmt = 'from' expr 'import' optInd expr (comma expr)*
|
||||
@@ -1558,6 +1592,7 @@ proc parseFromStmt(p: var Parser): PNode =
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
#expectNl(p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseReturnOrRaise(p: var Parser, kind: TNodeKind): PNode =
|
||||
#| returnStmt = 'return' optInd expr?
|
||||
@@ -1579,6 +1614,7 @@ proc parseReturnOrRaise(p: var Parser, kind: TNodeKind): PNode =
|
||||
var e = parseExpr(p)
|
||||
e = postExprBlocks(p, e)
|
||||
result.add(e)
|
||||
setEndInfo()
|
||||
|
||||
proc parseIfOrWhen(p: var Parser, kind: TNodeKind): PNode =
|
||||
#| condStmt = expr colcom stmt COMMENT?
|
||||
@@ -1603,6 +1639,7 @@ proc parseIfOrWhen(p: var Parser, kind: TNodeKind): PNode =
|
||||
colcom(p, branch)
|
||||
branch.add(parseStmt(p))
|
||||
result.add(branch)
|
||||
setEndInfo()
|
||||
|
||||
proc parseIfOrWhenExpr(p: var Parser, kind: TNodeKind): PNode =
|
||||
#| condExpr = expr colcom expr optInd
|
||||
@@ -1627,6 +1664,7 @@ proc parseIfOrWhenExpr(p: var Parser, kind: TNodeKind): PNode =
|
||||
colcom(p, branch)
|
||||
branch.add(parseStmt(p))
|
||||
result.add(branch)
|
||||
setEndInfo()
|
||||
|
||||
proc parseWhile(p: var Parser): PNode =
|
||||
#| whileStmt = 'while' expr colcom stmt
|
||||
@@ -1636,6 +1674,7 @@ proc parseWhile(p: var Parser): PNode =
|
||||
result.add(parseExpr(p))
|
||||
colcom(p, result)
|
||||
result.add(parseStmt(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseCase(p: var Parser): PNode =
|
||||
#| ofBranch = 'of' exprList colcom stmt
|
||||
@@ -1683,13 +1722,14 @@ proc parseCase(p: var Parser): PNode =
|
||||
|
||||
if wasIndented:
|
||||
p.currInd = oldInd
|
||||
setEndInfo()
|
||||
|
||||
proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||
#| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
||||
#| (IND{=}? 'except' exprList colcom stmt)*
|
||||
#| (IND{=}? 'except' optionalExprList colcom stmt)*
|
||||
#| (IND{=}? 'finally' colcom stmt)?
|
||||
#| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
||||
#| (optInd 'except' exprList colcom stmt)*
|
||||
#| (optInd 'except' optionalExprList colcom stmt)*
|
||||
#| (optInd 'finally' colcom stmt)?
|
||||
result = newNodeP(nkTryStmt, p)
|
||||
getTok(p)
|
||||
@@ -1700,7 +1740,7 @@ proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||
case p.tok.tokType
|
||||
of tkExcept:
|
||||
b = newNodeP(nkExceptBranch, p)
|
||||
exprList(p, tkColon, b)
|
||||
optionalExprList(p, tkColon, b)
|
||||
of tkFinally:
|
||||
b = newNodeP(nkFinally, p)
|
||||
getTok(p)
|
||||
@@ -1709,12 +1749,14 @@ proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||
b.add(parseStmt(p))
|
||||
result.add(b)
|
||||
if b == nil: parMessage(p, "expected 'except'")
|
||||
setEndInfo()
|
||||
|
||||
proc parseExceptBlock(p: var Parser, kind: TNodeKind): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
colcom(p, result)
|
||||
result.add(parseStmt(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseBlock(p: var Parser): PNode =
|
||||
#| blockStmt = 'block' symbol? colcom stmt
|
||||
@@ -1725,6 +1767,7 @@ proc parseBlock(p: var Parser): PNode =
|
||||
else: result.add(parseSymbol(p))
|
||||
colcom(p, result)
|
||||
result.add(parseStmt(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseStaticOrDefer(p: var Parser; k: TNodeKind): PNode =
|
||||
#| staticStmt = 'static' colcom stmt
|
||||
@@ -1733,6 +1776,7 @@ proc parseStaticOrDefer(p: var Parser; k: TNodeKind): PNode =
|
||||
getTok(p)
|
||||
colcom(p, result)
|
||||
result.add(parseStmt(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseAsm(p: var Parser): PNode =
|
||||
#| asmStmt = 'asm' pragma? (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
|
||||
@@ -1749,6 +1793,7 @@ proc parseAsm(p: var Parser): PNode =
|
||||
result.add(p.emptyNode)
|
||||
return
|
||||
getTok(p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseGenericParam(p: var Parser): PNode =
|
||||
#| genericParam = symbol (comma symbol)* (colon expr)? ('=' optInd expr)?
|
||||
@@ -1784,6 +1829,7 @@ proc parseGenericParam(p: var Parser): PNode =
|
||||
result.add(parseExpr(p))
|
||||
else:
|
||||
result.add(p.emptyNode)
|
||||
setEndInfo()
|
||||
|
||||
proc parseGenericParamList(p: var Parser): PNode =
|
||||
#| genericParamList = '[' optInd
|
||||
@@ -1802,12 +1848,14 @@ proc parseGenericParamList(p: var Parser): PNode =
|
||||
skipComment(p, a)
|
||||
optPar(p)
|
||||
eat(p, tkBracketRi)
|
||||
setEndInfo()
|
||||
|
||||
proc parsePattern(p: var Parser): PNode =
|
||||
#| pattern = '{' stmt '}'
|
||||
eat(p, tkCurlyLe)
|
||||
result = parseStmt(p)
|
||||
eat(p, tkCurlyRi)
|
||||
setEndInfo()
|
||||
|
||||
proc parseRoutine(p: var Parser, kind: TNodeKind): PNode =
|
||||
#| indAndComment = (IND{>} COMMENT)? | COMMENT?
|
||||
@@ -1816,6 +1864,12 @@ proc parseRoutine(p: var Parser, kind: TNodeKind): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
if kind in {nkProcDef, nkLambda, nkIteratorDef, nkFuncDef} and
|
||||
p.tok.tokType notin {tkSymbol, tokKeywordLow..tokKeywordHigh, tkAccent}:
|
||||
# no name; lambda or proc type
|
||||
# in every context that we can parse a routine, we can also parse these
|
||||
result = parseProcExpr(p, true, if kind == nkProcDef: nkLambda else: kind)
|
||||
return
|
||||
result.add(identVis(p))
|
||||
if p.tok.tokType == tkCurlyLe and p.validInd: result.add(p.parsePattern)
|
||||
else: result.add(p.emptyNode)
|
||||
@@ -1846,6 +1900,7 @@ proc parseRoutine(p: var Parser, kind: TNodeKind): PNode =
|
||||
#else:
|
||||
# assert false, p.lex.config$body.info # avoids hard to track bugs, fail early.
|
||||
# Yeah, that worked so well. There IS a bug in this logic, now what?
|
||||
setEndInfo()
|
||||
|
||||
proc newCommentStmt(p: var Parser): PNode =
|
||||
#| commentStmt = COMMENT
|
||||
@@ -1881,6 +1936,7 @@ proc parseSection(p: var Parser, kind: TNodeKind,
|
||||
result.add(defparser(p))
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, p.tok)
|
||||
setEndInfo()
|
||||
|
||||
proc parseEnum(p: var Parser): PNode =
|
||||
#| enumDecl = 'enum' optInd (symbol pragma? optInd ('=' optInd expr COMMENT?)? comma?)+
|
||||
@@ -1927,6 +1983,7 @@ proc parseEnum(p: var Parser): PNode =
|
||||
break
|
||||
if result.len <= 1:
|
||||
parMessage(p, errIdentifierExpected, p.tok)
|
||||
setEndInfo()
|
||||
|
||||
proc parseObjectPart(p: var Parser): PNode
|
||||
proc parseObjectWhen(p: var Parser): PNode =
|
||||
@@ -1952,6 +2009,7 @@ proc parseObjectWhen(p: var Parser): PNode =
|
||||
branch.add(parseObjectPart(p))
|
||||
flexComment(p, branch)
|
||||
result.add(branch)
|
||||
setEndInfo()
|
||||
|
||||
proc parseObjectCase(p: var Parser): PNode =
|
||||
#| objectBranch = 'of' exprList colcom objectPart
|
||||
@@ -1997,6 +2055,7 @@ proc parseObjectCase(p: var Parser): PNode =
|
||||
if b.kind == nkElse: break
|
||||
if wasIndented:
|
||||
p.currInd = oldInd
|
||||
setEndInfo()
|
||||
|
||||
proc parseObjectPart(p: var Parser): PNode =
|
||||
#| objectPart = IND{>} objectPart^+IND{=} DED
|
||||
@@ -2029,6 +2088,7 @@ proc parseObjectPart(p: var Parser): PNode =
|
||||
result = p.emptyNode
|
||||
else:
|
||||
result = p.emptyNode
|
||||
setEndInfo()
|
||||
|
||||
proc parseObject(p: var Parser): PNode =
|
||||
#| objectDecl = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
|
||||
@@ -2054,6 +2114,7 @@ proc parseObject(p: var Parser): PNode =
|
||||
result.add(p.emptyNode)
|
||||
else:
|
||||
result.add(parseObjectPart(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseTypeClassParam(p: var Parser): PNode =
|
||||
let modifier =
|
||||
@@ -2071,6 +2132,7 @@ proc parseTypeClassParam(p: var Parser): PNode =
|
||||
result.add(p.parseSymbol)
|
||||
else:
|
||||
result = p.parseSymbol
|
||||
setEndInfo()
|
||||
|
||||
proc parseTypeClass(p: var Parser): PNode =
|
||||
#| conceptParam = ('var' | 'out')? symbol
|
||||
@@ -2114,6 +2176,7 @@ proc parseTypeClass(p: var Parser): PNode =
|
||||
result.add(p.emptyNode)
|
||||
else:
|
||||
result.add(parseStmt(p))
|
||||
setEndInfo()
|
||||
|
||||
proc parseTypeDef(p: var Parser): PNode =
|
||||
#|
|
||||
@@ -2162,6 +2225,7 @@ proc parseTypeDef(p: var Parser): PNode =
|
||||
else:
|
||||
result.add(p.emptyNode)
|
||||
indAndComment(p, result) # special extension!
|
||||
setEndInfo()
|
||||
|
||||
proc parseVarTuple(p: var Parser): PNode =
|
||||
#| varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
|
||||
@@ -2178,6 +2242,7 @@ proc parseVarTuple(p: var Parser): PNode =
|
||||
result.add(p.emptyNode) # no type desc
|
||||
optPar(p)
|
||||
eat(p, tkParRi)
|
||||
setEndInfo()
|
||||
|
||||
proc parseVariable(p: var Parser): PNode =
|
||||
#| colonBody = colcom stmt postExprBlocks?
|
||||
@@ -2190,6 +2255,7 @@ proc parseVariable(p: var Parser): PNode =
|
||||
else: result = parseIdentColonEquals(p, {withPragma, withDot})
|
||||
result[^1] = postExprBlocks(p, result[^1])
|
||||
indAndComment(p, result)
|
||||
setEndInfo()
|
||||
|
||||
proc parseConstant(p: var Parser): PNode =
|
||||
#| constant = (varTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
|
||||
@@ -2209,6 +2275,7 @@ proc parseConstant(p: var Parser): PNode =
|
||||
result.add(parseExpr(p))
|
||||
result[^1] = postExprBlocks(p, result[^1])
|
||||
indAndComment(p, result)
|
||||
setEndInfo()
|
||||
|
||||
proc parseBind(p: var Parser, k: TNodeKind): PNode =
|
||||
#| bindStmt = 'bind' optInd qualifiedIdent ^+ comma
|
||||
@@ -2224,6 +2291,7 @@ proc parseBind(p: var Parser, k: TNodeKind): PNode =
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
#expectNl(p)
|
||||
setEndInfo()
|
||||
|
||||
proc parseStmtPragma(p: var Parser): PNode =
|
||||
#| pragmaStmt = pragma (':' COMMENT? stmt)?
|
||||
@@ -2235,6 +2303,7 @@ proc parseStmtPragma(p: var Parser): PNode =
|
||||
skipComment(p, result)
|
||||
result.add a
|
||||
result.add parseStmt(p)
|
||||
setEndInfo()
|
||||
|
||||
proc simpleStmt(p: var Parser): PNode =
|
||||
#| simpleStmt = ((returnStmt | raiseStmt | yieldStmt | discardStmt | breakStmt
|
||||
@@ -2377,6 +2446,7 @@ proc parseStmt(p: var Parser): PNode =
|
||||
if p.tok.tokType != tkSemiColon: break
|
||||
getTok(p)
|
||||
if err and p.tok.tokType == tkEof: break
|
||||
setEndInfo()
|
||||
|
||||
proc parseAll(p: var Parser): PNode =
|
||||
## Parses the rest of the input stream held by the parser into a PNode.
|
||||
@@ -2392,10 +2462,7 @@ proc parseAll(p: var Parser): PNode =
|
||||
getTok(p)
|
||||
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)
|
||||
setEndInfo()
|
||||
|
||||
proc parseTopLevelStmt(p: var Parser): PNode =
|
||||
## Implements an iterator which, when called repeatedly, returns the next
|
||||
@@ -2425,6 +2492,7 @@ proc parseTopLevelStmt(p: var Parser): PNode =
|
||||
result = complexOrSimpleStmt(p)
|
||||
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
||||
break
|
||||
setEndInfo()
|
||||
|
||||
proc parseString*(s: string; cache: IdentCache; config: ConfigRef;
|
||||
filename: string = ""; line: int = 0;
|
||||
@@ -2436,9 +2504,10 @@ proc parseString*(s: string; cache: IdentCache; config: ConfigRef;
|
||||
var stream = llStreamOpen(s)
|
||||
stream.lineOffset = line
|
||||
|
||||
var parser: Parser
|
||||
parser.lex.errorHandler = errorHandler
|
||||
openParser(parser, AbsoluteFile filename, stream, cache, config)
|
||||
var p: Parser
|
||||
p.lex.errorHandler = errorHandler
|
||||
openParser(p, AbsoluteFile filename, stream, cache, config)
|
||||
|
||||
result = parser.parseAll
|
||||
closeParser(parser)
|
||||
result = p.parseAll
|
||||
closeParser(p)
|
||||
setEndInfo()
|
||||
|
||||
@@ -16,8 +16,6 @@ import
|
||||
syntaxes, modulegraphs, reorder,
|
||||
lineinfos, pathutils, std/sha1, packages
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/syncio
|
||||
|
||||
type
|
||||
TPassData* = tuple[input: PNode, closeOutput: PNode]
|
||||
@@ -149,7 +147,6 @@ 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)
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
## Path handling utilities for Nim. Strictly typed code in order
|
||||
## to avoid the never ending time sink in getting path handling right.
|
||||
|
||||
import os, pathnorm
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[syncio, assertions]
|
||||
import os, pathnorm, strutils
|
||||
|
||||
type
|
||||
AbsoluteFile* = distinct string
|
||||
@@ -102,3 +99,52 @@ when true:
|
||||
proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.}
|
||||
|
||||
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
|
||||
|
||||
proc skipHomeDir(x: string): int =
|
||||
when defined(windows):
|
||||
if x.continuesWith("Users/", len("C:/")):
|
||||
result = 3
|
||||
else:
|
||||
result = 0
|
||||
else:
|
||||
if x.startsWith("/home/") or x.startsWith("/Users/"):
|
||||
result = 3
|
||||
elif x.startsWith("/mnt/") and x.continuesWith("/Users/", len("/mnt/c")):
|
||||
result = 5
|
||||
else:
|
||||
result = 0
|
||||
|
||||
proc relevantPart(s: string; afterSlashX: int): string =
|
||||
result = newStringOfCap(s.len - 8)
|
||||
var slashes = afterSlashX
|
||||
for i in 0..<s.len:
|
||||
if slashes == 0:
|
||||
result.add s[i]
|
||||
elif s[i] == '/':
|
||||
dec slashes
|
||||
|
||||
template canonSlashes(x: string): string =
|
||||
when defined(windows):
|
||||
x.replace('\\', '/')
|
||||
else:
|
||||
x
|
||||
|
||||
proc customPathImpl(x: string): string =
|
||||
# Idea: Encode a "protocol" via "//protocol/path" which is not ambiguous
|
||||
# as path canonicalization would have removed the double slashes.
|
||||
# /mnt/X/Users/Y
|
||||
# X:\\Users\Y
|
||||
# /home/Y
|
||||
# -->
|
||||
# //user/
|
||||
if not isAbsolute(x):
|
||||
result = customPathImpl(canonSlashes(getCurrentDir() / x))
|
||||
else:
|
||||
let slashes = skipHomeDir(x)
|
||||
if slashes > 0:
|
||||
result = "//user/" & relevantPart(x, slashes)
|
||||
else:
|
||||
result = x
|
||||
|
||||
proc customPath*(x: string): string =
|
||||
customPathImpl canonSlashes x
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
import
|
||||
ast, types, semdata, sigmatch, idents, aliases, parampatterns, trees
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
TPatternContext = object
|
||||
owner: PSym
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
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).
|
||||
@@ -205,8 +201,7 @@ 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,
|
||||
cpuE2k, cpuLoongArch64
|
||||
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32
|
||||
|
||||
type
|
||||
TInfoCPU* = tuple[name: string, intSize: int, endian: Endianness,
|
||||
@@ -241,9 +236,7 @@ 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: "e2k", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
|
||||
(name: "loongarch64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)]
|
||||
(name: "wasm32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32)]
|
||||
|
||||
type
|
||||
Target* = object
|
||||
|
||||
@@ -15,7 +15,7 @@ import ".." / [ast, astalgo,
|
||||
proc semLocals*(c: PContext, n: PNode): PNode =
|
||||
var counter = 0
|
||||
var tupleType = newTypeS(tyTuple, c)
|
||||
result = newNodeIT(nkPar, n.info, tupleType)
|
||||
result = newNodeIT(nkTupleConstr, n.info, tupleType)
|
||||
tupleType.n = newNodeI(nkRecList, n.info)
|
||||
let owner = getCurrOwner(c)
|
||||
# for now we skip openarrays ...
|
||||
|
||||
@@ -12,10 +12,7 @@
|
||||
import
|
||||
os, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
|
||||
wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees,
|
||||
types, lookups, lineinfos, pathutils, linter
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
types, lookups, lineinfos, pathutils, linter, modulepaths
|
||||
|
||||
from ic / ic import addCompilerProc
|
||||
|
||||
@@ -55,7 +52,7 @@ const
|
||||
wDeprecated,
|
||||
wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||
wExperimental, wThis, wUsed, wInvariant, wAssume, wAssert}
|
||||
wExperimental, wDoctype, wThis, wUsed, wInvariant, wAssume, wAssert}
|
||||
stmtPragmasTopLevel* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
|
||||
wBoundChecks, wOverflowChecks, wNilChecks, wStaticBoundchecks,
|
||||
wStyleChecks, wAssertions,
|
||||
@@ -500,12 +497,19 @@ proc relativeFile(c: PContext; n: PNode; ext=""): AbsoluteFile =
|
||||
if result.isEmpty: result = AbsoluteFile s
|
||||
|
||||
proc processCompile(c: PContext, n: PNode) =
|
||||
## This pragma can take two forms. The first is a simple file input:
|
||||
## {.compile: "file.c".}
|
||||
## The second is a tuple where the second arg is the output name strutils formatter:
|
||||
## {.compile: ("file.c", "$1.o").}
|
||||
proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile; customArgs: string) =
|
||||
var cf = Cfile(nimname: splitFile(src).name,
|
||||
cname: src, obj: dest, flags: {CfileFlag.External},
|
||||
customArgs: customArgs)
|
||||
extccomp.addExternalFileToCompile(c.config, cf)
|
||||
recordPragma(c, it, "compile", src.string, dest.string, customArgs)
|
||||
if not fileExists(src):
|
||||
localError(c.config, n.info, "cannot find: " & src.string)
|
||||
else:
|
||||
extccomp.addExternalFileToCompile(c.config, cf)
|
||||
recordPragma(c, it, "compile", src.string, dest.string, customArgs)
|
||||
|
||||
proc getStrLit(c: PContext, n: PNode; i: int): string =
|
||||
n[i] = c.semConstExpr(c, n[i])
|
||||
@@ -542,7 +546,8 @@ proc processCompile(c: PContext, n: PNode) =
|
||||
else:
|
||||
found = findFile(c.config, s)
|
||||
if found.isEmpty: found = AbsoluteFile s
|
||||
let obj = toObjFile(c.config, completeCfilePath(c.config, found, false))
|
||||
let mangled = completeCfilePath(c.config, mangleModuleName(c.config, found).AbsoluteFile)
|
||||
let obj = toObjFile(c.config, mangled)
|
||||
docompile(c, it, found, obj, customArgs)
|
||||
|
||||
proc processLink(c: PContext, n: PNode) =
|
||||
@@ -648,6 +653,7 @@ proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
invalidPragma(c, n)
|
||||
|
||||
var userPragma = newSym(skTemplate, it[1].ident, nextSymId(c.idgen), c.module, it.info, c.config.options)
|
||||
styleCheckDef(c, userPragma)
|
||||
userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
|
||||
strTableAdd(c.userPragmas, userPragma)
|
||||
|
||||
@@ -810,7 +816,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
validPragmas: TSpecialWords,
|
||||
comesFromPush, isStatement: bool): bool =
|
||||
var it = n[i]
|
||||
var key = if it.kind in nkPragmaCallKinds and it.len > 1: it[0] else: it
|
||||
let keyDeep = it.kind in nkPragmaCallKinds and it.len > 1
|
||||
var key = if keyDeep: it[0] else: it
|
||||
if key.kind == nkBracketExpr:
|
||||
processNote(c, it)
|
||||
return
|
||||
@@ -829,14 +836,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
let ident = considerQuotedIdent(c, key)
|
||||
var userPragma = strTableGet(c.userPragmas, ident)
|
||||
if userPragma != nil:
|
||||
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||
styleCheckUse(c.config, key.info, userPragma)
|
||||
styleCheckUse(c, key.info, userPragma)
|
||||
|
||||
# number of pragmas increase/decrease with user pragma expansion
|
||||
inc c.instCounter
|
||||
if c.instCounter > 100:
|
||||
globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s)
|
||||
|
||||
if keyDeep:
|
||||
localError(c.config, it.info, "user pragma cannot have arguments")
|
||||
|
||||
pragma(c, sym, userPragma.ast, validPragmas, isStatement)
|
||||
n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
|
||||
i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty
|
||||
@@ -844,8 +853,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
else:
|
||||
let k = whichKeyword(ident)
|
||||
if k in validPragmas:
|
||||
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||
checkPragmaUse(c.config, key.info, k, ident.s)
|
||||
checkPragmaUse(c, key.info, k, ident.s, (if sym != nil: sym else: c.module))
|
||||
case k
|
||||
of wExportc, wExportCpp:
|
||||
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
@@ -1215,6 +1223,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if not isTopLevel(c):
|
||||
localError(c.config, n.info, "'experimental' pragma only valid as toplevel statement or in a 'push' environment")
|
||||
processExperimental(c, it)
|
||||
of wDoctype:
|
||||
if not isTopLevel(c):
|
||||
localError(c.config, n.info, "\"doctype\" pragma only valid as top-level statement")
|
||||
message(c.config, it.info, hintUser,
|
||||
"doctype is not really implemented in Nim 1")
|
||||
of wThis:
|
||||
if it.kind in nkPragmaCallKinds and it.len == 2:
|
||||
c.selfName = considerQuotedIdent(c, it[1])
|
||||
@@ -1250,7 +1263,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
elif comesFromPush and whichKeyword(ident) != wInvalid:
|
||||
discard "ignore the .push pragma; it doesn't apply"
|
||||
else:
|
||||
if sym == nil or (sym.kind in {skVar, skLet, skParam,
|
||||
if sym == nil or (sym.kind in {skVar, skLet, skParam, skIterator,
|
||||
skField, skProc, skFunc, skConverter, skMethod, skType}):
|
||||
n[i] = semCustomPragma(c, it)
|
||||
elif sym != nil:
|
||||
|
||||
@@ -17,9 +17,6 @@ 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,
|
||||
@@ -379,6 +376,7 @@ proc atom(g: TSrcGen; n: PNode): string =
|
||||
of nkEmpty: result = ""
|
||||
of nkIdent: result = n.ident.s
|
||||
of nkSym: result = n.sym.name.s
|
||||
of nkClosedSymChoice, nkOpenSymChoice: result = n[0].sym.name.s
|
||||
of nkStrLit: result = ""; result.addQuoted(n.strVal)
|
||||
of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"'
|
||||
of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\""
|
||||
|
||||
@@ -4,9 +4,6 @@ import
|
||||
msgs, modulegraphs, syntaxes, options, modulepaths,
|
||||
lineinfos
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
DepN = ref object
|
||||
pnode: PNode
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
## 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,10 +60,6 @@ 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
|
||||
@@ -333,3 +329,10 @@ 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,9 +16,6 @@ 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
|
||||
|
||||
|
||||
105
compiler/sem.nim
105
compiler/sem.nim
@@ -27,11 +27,11 @@ when not defined(leanCompiler):
|
||||
|
||||
# implementation
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode
|
||||
proc semExprNoType(c: PContext, n: PNode): PNode
|
||||
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semProcBody(c: PContext, n: PNode): PNode
|
||||
proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode
|
||||
proc changeType(c: PContext; n: PNode, newType: PType, check: bool)
|
||||
@@ -48,7 +48,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode
|
||||
proc finishMethod(c: PContext, s: PSym)
|
||||
proc evalAtCompileTime(c: PContext, n: PNode): PNode
|
||||
proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode
|
||||
proc semStaticExpr(c: PContext, n: PNode): PNode
|
||||
proc semStaticExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode
|
||||
proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType
|
||||
proc semTypeOf(c: PContext; n: PNode): PNode
|
||||
proc computeRequiresInit(c: PContext, t: PType): bool
|
||||
@@ -78,7 +78,7 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
|
||||
proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
let x = arg.skipConv
|
||||
if (x.kind == nkCurly and formal.kind == tySet and formal.base.kind != tyGenericParam) or
|
||||
(x.kind in {nkPar, nkTupleConstr}) and formal.kind notin {tyUntyped, tyBuiltInTypeClass}:
|
||||
(x.kind in {nkPar, nkTupleConstr}) and formal.kind notin {tyUntyped, tyBuiltInTypeClass, tyAnything}:
|
||||
changeType(c, x, formal, check=true)
|
||||
result = arg
|
||||
result = skipHiddenSubConv(result, c.graph, c.idgen)
|
||||
@@ -203,12 +203,58 @@ proc commonType*(c: PContext; x, y: PType): PType =
|
||||
result.addSonSkipIntLit(r, c.idgen)
|
||||
|
||||
proc endsInNoReturn(n: PNode): bool =
|
||||
# check if expr ends in raise exception or call of noreturn proc
|
||||
## check if expr ends the block like raising or call of noreturn procs do
|
||||
result = false # assume it does return
|
||||
|
||||
template checkBranch(branch) =
|
||||
if not endsInNoReturn(branch):
|
||||
# proved a branch returns
|
||||
return false
|
||||
|
||||
var it = n
|
||||
# skip these beforehand, no special handling needed
|
||||
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||
it = it.lastSon
|
||||
result = it.kind in nkLastBlockStmts or
|
||||
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||
|
||||
case it.kind
|
||||
of nkIfStmt:
|
||||
var hasElse = false
|
||||
for branch in it:
|
||||
checkBranch:
|
||||
if branch.len == 2:
|
||||
branch[1]
|
||||
elif branch.len == 1:
|
||||
hasElse = true
|
||||
branch[0]
|
||||
else:
|
||||
raiseAssert "Malformed `if` statement during endsInNoReturn"
|
||||
# none of the branches returned
|
||||
result = hasElse # Only truly a no-return when it's exhaustive
|
||||
of nkCaseStmt:
|
||||
for i in 1 ..< it.len:
|
||||
let branch = it[i]
|
||||
checkBranch:
|
||||
case branch.kind
|
||||
of nkOfBranch:
|
||||
branch[^1]
|
||||
of nkElifBranch:
|
||||
branch[1]
|
||||
of nkElse:
|
||||
branch[0]
|
||||
else:
|
||||
raiseAssert "Malformed `case` statement in endsInNoReturn"
|
||||
# none of the branches returned
|
||||
result = true
|
||||
of nkTryStmt:
|
||||
checkBranch(it[0])
|
||||
for i in 1 ..< it.len:
|
||||
let branch = it[i]
|
||||
checkBranch(branch[^1])
|
||||
# none of the branches returned
|
||||
result = true
|
||||
else:
|
||||
result = it.kind in nkLastBlockStmts or
|
||||
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||
|
||||
proc commonType*(c: PContext; x: PType, y: PNode): PType =
|
||||
# ignore exception raising branches in case/if expressions
|
||||
@@ -269,12 +315,12 @@ proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||
typeAllowedCheck(c, typ.n.info, typ, skProc)
|
||||
|
||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode
|
||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||
flags: TExprFlags = {}): PNode
|
||||
flags: TExprFlags = {}; expectedType: PType = nil): PNode
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
flags: TExprFlags = {}): PNode
|
||||
flags: TExprFlags = {}; expectedType: PType = nil): PNode
|
||||
|
||||
proc symFromType(c: PContext; t: PType, info: TLineInfo): PSym =
|
||||
if t.sym != nil: return t.sym
|
||||
@@ -334,8 +380,8 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
|
||||
isArrayConstr(arg):
|
||||
arg.typ = eOrig.typ
|
||||
|
||||
proc tryConstExpr(c: PContext, n: PNode): PNode =
|
||||
var e = semExprWithType(c, n)
|
||||
proc tryConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
var e = semExprWithType(c, n, expectedType = expectedType)
|
||||
if e == nil: return
|
||||
|
||||
result = getConstExpr(c.module, e, c.idgen, c.graph)
|
||||
@@ -365,8 +411,8 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
|
||||
const
|
||||
errConstExprExpected = "constant expression expected"
|
||||
|
||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
var e = semExprWithType(c, n)
|
||||
proc semConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
var e = semExprWithType(c, n, expectedType = expectedType)
|
||||
if e == nil:
|
||||
localError(c.config, n.info, errConstExprExpected)
|
||||
return n
|
||||
@@ -388,14 +434,14 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
result = fixupTypeAfterEval(c, result, e)
|
||||
|
||||
proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
if efNeedStatic in flags:
|
||||
if efPreferNilResult in flags:
|
||||
return tryConstExpr(c, n)
|
||||
return tryConstExpr(c, n, expectedType)
|
||||
else:
|
||||
return semConstExpr(c, n)
|
||||
return semConstExpr(c, n, expectedType)
|
||||
else:
|
||||
result = semExprWithType(c, n, flags)
|
||||
result = semExprWithType(c, n, flags, expectedType)
|
||||
if efPreferStatic in flags:
|
||||
var evaluated = getConstExpr(c.module, result, c.idgen, c.graph)
|
||||
if evaluated != nil: return evaluated
|
||||
@@ -414,7 +460,7 @@ proc resetSemFlag(n: PNode) =
|
||||
resetSemFlag(n[i])
|
||||
|
||||
proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
s: PSym, flags: TExprFlags): PNode =
|
||||
s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
## Semantically check the output of a macro.
|
||||
## This involves processes such as re-checking the macro output for type
|
||||
## coherence, making sure that variables declared with 'let' aren't
|
||||
@@ -436,12 +482,12 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
# does not mean we expect a tyTypeDesc.
|
||||
retType = retType[0]
|
||||
case retType.kind
|
||||
of tyUntyped:
|
||||
of tyUntyped, tyAnything:
|
||||
# Not expecting a type here allows templates like in ``tmodulealias.in``.
|
||||
result = semExpr(c, result, flags)
|
||||
result = semExpr(c, result, flags, expectedType)
|
||||
of tyTyped:
|
||||
# More restrictive version.
|
||||
result = semExprWithType(c, result, flags)
|
||||
result = semExprWithType(c, result, flags, expectedType)
|
||||
of tyTypeDesc:
|
||||
if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListType)
|
||||
var typ = semTypeNode(c, result, nil)
|
||||
@@ -465,8 +511,11 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
retType = generateTypeInstance(c, paramTypes,
|
||||
macroResult.info, retType)
|
||||
|
||||
result = semExpr(c, result, flags)
|
||||
result = fitNode(c, retType, result, result.info)
|
||||
if retType.kind == tyVoid:
|
||||
result = semStmt(c, result, flags)
|
||||
else:
|
||||
result = semExpr(c, result, flags, expectedType)
|
||||
result = fitNode(c, retType, result, result.info)
|
||||
#globalError(s.info, errInvalidParamKindX, typeToString(s.typ[0]))
|
||||
dec(c.config.evalTemplateCounter)
|
||||
discard c.friendModules.pop()
|
||||
@@ -476,7 +525,7 @@ const
|
||||
errFloatToString = "cannot convert '$1' to '$2'"
|
||||
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
flags: TExprFlags = {}; expectedType: PType = nil): PNode =
|
||||
rememberExpansion(c, nOrig.info, sym)
|
||||
pushInfoContext(c.config, nOrig.info, sym.detailedInfo)
|
||||
|
||||
@@ -496,7 +545,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
# c.evalContext = c.createEvalContext(emStatic)
|
||||
result = evalMacroCall(c.module, c.idgen, c.graph, c.templInstCounter, n, nOrig, sym)
|
||||
if efNoSemCheck notin flags:
|
||||
result = semAfterMacroCall(c, n, result, sym, flags)
|
||||
result = semAfterMacroCall(c, n, result, sym, flags, expectedType)
|
||||
if c.config.macrosToExpand.hasKey(sym.name.s):
|
||||
message(c.config, nOrig.info, hintExpandMacro, renderTree(result))
|
||||
result = wrapInComesFrom(nOrig.info, sym, result)
|
||||
@@ -507,7 +556,7 @@ proc forceBool(c: PContext, n: PNode): PNode =
|
||||
if result == nil: result = n
|
||||
|
||||
proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
||||
result = forceBool(c, semConstExpr(c, n))
|
||||
result = forceBool(c, semConstExpr(c, n, getSysType(c.graph, n.info, tyBool)))
|
||||
if result.kind != nkIntLit:
|
||||
localError(c.config, n.info, errConstExprExpected)
|
||||
|
||||
|
||||
@@ -288,8 +288,23 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||
# fail fast:
|
||||
globalError(c.config, n.info, "type mismatch")
|
||||
return
|
||||
# see getMsgDiagnostic:
|
||||
if nfExplicitCall notin n.flags and {nfDotField, nfDotSetter} * n.flags != {}:
|
||||
let ident = considerQuotedIdent(c, n[0], n).s
|
||||
let sym = n[1].typ.typSym
|
||||
var typeHint = ""
|
||||
if sym == nil:
|
||||
discard
|
||||
else:
|
||||
typeHint = " for type " & getProcHeader(c.config, sym)
|
||||
localError(c.config, n.info, errUndeclaredField % ident & typeHint)
|
||||
return
|
||||
if errors.len == 0:
|
||||
localError(c.config, n.info, "expression '$1' cannot be called" % n[0].renderTree)
|
||||
if n[0].kind in nkIdentKinds:
|
||||
let ident = considerQuotedIdent(c, n[0], n).s
|
||||
localError(c.config, n.info, errUndeclaredRoutine % ident)
|
||||
else:
|
||||
localError(c.config, n.info, "expression '$1' cannot be called" % n[0].renderTree)
|
||||
return
|
||||
|
||||
let (prefer, candidates) = presentFailedCandidates(c, n, errors)
|
||||
@@ -331,7 +346,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||
sym = nextOverloadIter(o, c, f)
|
||||
|
||||
let ident = considerQuotedIdent(c, f, n).s
|
||||
if {nfDotField, nfExplicitCall} * n.flags == {nfDotField}:
|
||||
if nfExplicitCall notin n.flags and {nfDotField, nfDotSetter} * n.flags != {}:
|
||||
let sym = n[1].typ.typSym
|
||||
var typeHint = ""
|
||||
if sym == nil:
|
||||
@@ -364,11 +379,15 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
else:
|
||||
initialBinding = nil
|
||||
|
||||
template pickBest(headSymbol) =
|
||||
pickBestCandidate(c, f, n, orig, initialBinding,
|
||||
filter, result, alt, errors, efExplain in flags,
|
||||
errorsEnabled, flags)
|
||||
|
||||
var dummyErrors: CandidateErrors
|
||||
template pickSpecialOp(headSymbol) =
|
||||
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
|
||||
filter, result, alt, errors, efExplain in flags,
|
||||
errorsEnabled, flags)
|
||||
pickBest(f)
|
||||
filter, result, alt, dummyErrors, efExplain in flags,
|
||||
false, flags)
|
||||
|
||||
let overloadsState = result.state
|
||||
if overloadsState != csMatch:
|
||||
@@ -380,7 +399,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
n.sons.insert(hiddenArg, 1)
|
||||
orig.sons.insert(hiddenArg, 1)
|
||||
|
||||
pickBest(f)
|
||||
pickSpecialOp(f)
|
||||
|
||||
if result.state != csMatch:
|
||||
n.sons.delete(1)
|
||||
@@ -400,7 +419,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
let op = newIdentNode(getIdent(c.cache, x), n.info)
|
||||
n[0] = op
|
||||
orig[0] = op
|
||||
pickBest(op)
|
||||
pickSpecialOp(op)
|
||||
|
||||
if nfExplicitCall in n.flags:
|
||||
tryOp ".()"
|
||||
@@ -414,23 +433,13 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
let callOp = newIdentNode(getIdent(c.cache, ".="), n.info)
|
||||
n.sons[0..1] = [callOp, n[1], calleeName]
|
||||
orig.sons[0..1] = [callOp, orig[1], calleeName]
|
||||
pickBest(callOp)
|
||||
pickSpecialOp(callOp)
|
||||
|
||||
if overloadsState == csEmpty and result.state == csEmpty:
|
||||
if efNoUndeclared notin flags: # for tests/pragmas/tcustom_pragma.nim
|
||||
template impl() =
|
||||
# xxx adapt/use errorUndeclaredIdentifierHint(c, n, f.ident)
|
||||
localError(c.config, n.info, getMsgDiagnostic(c, flags, n, f))
|
||||
if n[0].kind == nkIdent and n[0].ident.s == ".=" and n[2].kind == nkIdent:
|
||||
let sym = n[1].typ.sym
|
||||
if sym == nil:
|
||||
impl()
|
||||
else:
|
||||
let field = n[2].ident.s
|
||||
let msg = errUndeclaredField % field & " for type " & getProcHeader(c.config, sym)
|
||||
localError(c.config, orig[2].info, msg)
|
||||
else:
|
||||
impl()
|
||||
result.state = csNoMatch
|
||||
# xxx adapt/use errorUndeclaredIdentifierHint(c, n, f.ident)
|
||||
localError(c.config, n.info, getMsgDiagnostic(c, flags, n, f))
|
||||
return
|
||||
elif result.state != csMatch:
|
||||
if nfExprCall in n.flags:
|
||||
@@ -619,7 +628,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
if efExplain notin flags:
|
||||
# repeat the overload resolution,
|
||||
# this time enabling all the diagnostic output (this should fail again)
|
||||
discard semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})
|
||||
result = semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})
|
||||
elif efNoUndeclared notin flags:
|
||||
notFoundError(c, n, errors)
|
||||
|
||||
@@ -651,14 +660,18 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
onUse(info, s)
|
||||
result = newSymNode(newInst, info)
|
||||
|
||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
assert n.kind == nkBracketExpr
|
||||
proc setGenericParams(c: PContext, n: PNode) =
|
||||
## sems generic params in subscript expression
|
||||
for i in 1..<n.len:
|
||||
let e = semExpr(c, n[i])
|
||||
let e = semExprWithType(c, n[i])
|
||||
if e.typ == nil:
|
||||
n[i].typ = errorType(c)
|
||||
else:
|
||||
n[i].typ = e.typ.skipTypes({tyTypeDesc})
|
||||
|
||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
assert n.kind == nkBracketExpr
|
||||
setGenericParams(c, n)
|
||||
var s = s
|
||||
var a = n[0]
|
||||
if a.kind == nkSym:
|
||||
@@ -730,4 +743,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,9 +11,6 @@
|
||||
|
||||
import tables
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
import
|
||||
intsets, options, ast, astalgo, msgs, idents, renderer,
|
||||
magicsys, vmdef, modulegraphs, lineinfos, sets, pathutils
|
||||
@@ -73,6 +70,7 @@ type
|
||||
efNoUndeclared
|
||||
# Use this if undeclared identifiers should not raise an error during
|
||||
# overload resolution.
|
||||
efNoDiagnostics
|
||||
|
||||
TExprFlags* = set[TExprFlag]
|
||||
|
||||
@@ -121,10 +119,10 @@ type
|
||||
symMapping*: TIdTable # every gensym'ed symbol needs to be mapped
|
||||
# to some new symbol in a generic instantiation
|
||||
libs*: seq[PLib] # all libs used by this module
|
||||
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semConstExpr*: proc (c: PContext, n: PNode; expectedType: PType = nil): PNode {.nimcall.} # for the pragmas
|
||||
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode {.nimcall.}
|
||||
semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.}
|
||||
semTryConstExpr*: proc (c: PContext, n: PNode; expectedType: PType = nil): PNode {.nimcall.}
|
||||
computeRequiresInit*: proc (c: PContext, t: PType): bool {.nimcall.}
|
||||
hasUnresolvedArgs*: proc (c: PContext, n: PNode): bool
|
||||
|
||||
@@ -164,6 +162,7 @@ type
|
||||
lastTLineInfo*: TLineInfo
|
||||
sideEffects*: Table[int, seq[(TLineInfo, PSym)]] # symbol.id index
|
||||
inUncheckedAssignSection*: int
|
||||
importModuleLookup*: Table[int, seq[int]] # (module.ident.id, [module.id])
|
||||
|
||||
template config*(c: PContext): ConfigRef = c.graph.config
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ const
|
||||
errUndeclaredFieldX = "undeclared field: '$1'"
|
||||
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
flags: TExprFlags = {}; expectedType: PType = nil): PNode =
|
||||
rememberExpansion(c, n.info, s)
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c, info, s)
|
||||
@@ -36,7 +36,8 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||
pushInfoContext(c.config, n.info, s.detailedInfo)
|
||||
result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache,
|
||||
c.templInstCounter, c.idgen, efFromHlo in flags)
|
||||
if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
|
||||
if efNoSemCheck notin flags:
|
||||
result = semAfterMacroCall(c, n, result, s, flags, expectedType)
|
||||
popInfoContext(c.config)
|
||||
|
||||
# XXX: A more elaborate line info rewrite might be needed
|
||||
@@ -65,9 +66,9 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
|
||||
proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType = nil): PNode =
|
||||
rejectEmptyNode(n)
|
||||
result = semExpr(c, n, flags+{efWantValue})
|
||||
result = semExpr(c, n, flags+{efWantValue}, expectedType)
|
||||
|
||||
let
|
||||
isEmpty = result.kind == nkEmpty
|
||||
@@ -82,8 +83,8 @@ proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# do not produce another redundant error message:
|
||||
result = errorNode(c, n)
|
||||
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semExprCheck(c, n, flags)
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode =
|
||||
result = semExprCheck(c, n, flags, expectedType)
|
||||
if result.typ == nil and efInTypeof in flags:
|
||||
result.typ = c.voidType
|
||||
elif result.typ == nil or result.typ == c.enforceVoidContext:
|
||||
@@ -196,10 +197,10 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
|
||||
else:
|
||||
discard
|
||||
|
||||
proc isCastable(c: PContext; dst, src: PType): bool =
|
||||
proc isCastable(c: PContext; dst, src: PType, info: TLineInfo): bool =
|
||||
## Checks whether the source type can be cast to the destination type.
|
||||
## Casting is very unrestrictive; casts are allowed as long as
|
||||
## castDest.size >= src.size, and typeAllowed(dst, skParam)
|
||||
## dst.size >= src.size, and typeAllowed(dst, skParam)
|
||||
#const
|
||||
# castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString,
|
||||
# tySequence, tyPointer, tyNil, tyOpenArray,
|
||||
@@ -228,19 +229,21 @@ proc isCastable(c: PContext; dst, src: PType): bool =
|
||||
# Just assume the programmer knows what he is doing.
|
||||
return true
|
||||
if dstSize < 0:
|
||||
result = false
|
||||
return false
|
||||
elif srcSize < 0:
|
||||
result = false
|
||||
elif typeAllowed(dst, skParam, c) != nil:
|
||||
result = false
|
||||
return false
|
||||
elif typeAllowed(dst, skParam, c, {taIsCastable}) != nil:
|
||||
return false
|
||||
elif dst.kind == tyProc and dst.callConv == ccClosure:
|
||||
result = src.kind == tyProc and src.callConv == ccClosure
|
||||
return src.kind == tyProc and src.callConv == ccClosure
|
||||
else:
|
||||
result = (dstSize >= srcSize) or
|
||||
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
||||
(skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
|
||||
if result and (dstSize > srcSize):
|
||||
message(conf, info, warnCastSizes, "target type is larger than source type")
|
||||
if result and src.kind == tyNil:
|
||||
result = dst.size <= conf.target.ptrSize
|
||||
return dst.size <= conf.target.ptrSize
|
||||
|
||||
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||
result = n.kind in nkSymChoices
|
||||
@@ -259,7 +262,7 @@ proc isOwnedSym(c: PContext; n: PNode): bool =
|
||||
let s = qualifiedLookUp(c, n, {})
|
||||
result = s != nil and sfSystemModule in s.owner.flags and s.name.s == "owned"
|
||||
|
||||
proc semConv(c: PContext, n: PNode): PNode =
|
||||
proc semConv(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
if n.len != 2:
|
||||
localError(c.config, n.info, "a type conversion takes exactly one argument")
|
||||
return n
|
||||
@@ -267,7 +270,7 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkConv, n.info)
|
||||
|
||||
var targetType = semTypeNode(c, n[0], nil)
|
||||
case targetType.kind
|
||||
case targetType.skipTypes({tyDistinct}).kind
|
||||
of tyTypeDesc:
|
||||
internalAssert c.config, targetType.len > 0
|
||||
if targetType.base.kind == tyNone:
|
||||
@@ -275,7 +278,7 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
targetType = targetType.base
|
||||
of tyStatic:
|
||||
var evaluated = semStaticExpr(c, n[1])
|
||||
var evaluated = semStaticExpr(c, n[1], expectedType)
|
||||
if evaluated.kind == nkType or evaluated.typ.kind == tyTypeDesc:
|
||||
result = n
|
||||
result.typ = c.makeTypeDesc semStaticType(c, evaluated, nil)
|
||||
@@ -284,6 +287,8 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||
return evaluated
|
||||
else:
|
||||
targetType = targetType.base
|
||||
of tyAnything, tyUntyped, tyTyped:
|
||||
localError(c.config, n.info, "illegal type conversion to '$1'" % typeToString(targetType))
|
||||
else: discard
|
||||
|
||||
maybeLiftType(targetType, c, n[0].info)
|
||||
@@ -357,9 +362,13 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, 2, c.config)
|
||||
let targetType = semTypeNode(c, n[0], nil)
|
||||
let castedExpr = semExprWithType(c, n[1])
|
||||
if castedExpr.kind == nkClosedSymChoice:
|
||||
errorUseQualifier(c, n[1].info, castedExpr)
|
||||
if targetType == nil:
|
||||
localError(c.config, n.info, "Invalid usage of cast, cast requires a type to convert to, e.g., cast[int](0d).")
|
||||
if tfHasMeta in targetType.flags:
|
||||
localError(c.config, n[0].info, "cannot cast to a non concrete type: '$1'" % $targetType)
|
||||
if not isCastable(c, targetType, castedExpr.typ):
|
||||
if not isCastable(c, targetType, castedExpr.typ, n.info):
|
||||
let tar = $targetType
|
||||
let alt = typeToString(targetType, preferDesc)
|
||||
let msg = if tar != alt: tar & "=" & alt else: tar
|
||||
@@ -522,7 +531,7 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(par, n.info)
|
||||
for i in 0..<n.len: result.add n[i]
|
||||
result = semExpr(c, result)
|
||||
result = semExpr(c, result, flags = {efNoUndeclared})
|
||||
|
||||
proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
case n.kind
|
||||
@@ -581,21 +590,36 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
|
||||
typ[0] = makeRangeType(c, 0, n.len - 1, n.info)
|
||||
result = typ
|
||||
|
||||
proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = newNodeI(nkBracket, n.info)
|
||||
result.typ = newTypeS(tyArray, c)
|
||||
var expectedElementType, expectedIndexType: PType = nil
|
||||
if expectedType != nil:
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct})
|
||||
case expected.kind
|
||||
of tyArray:
|
||||
expectedIndexType = expected[0]
|
||||
expectedElementType = expected[1]
|
||||
of tyOpenArray:
|
||||
expectedElementType = expected[0]
|
||||
else: discard
|
||||
rawAddSon(result.typ, nil) # index type
|
||||
var
|
||||
firstIndex, lastIndex: Int128
|
||||
indexType = getSysType(c.graph, n.info, tyInt)
|
||||
lastValidIndex = lastOrd(c.config, indexType)
|
||||
if n.len == 0:
|
||||
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||
rawAddSon(result.typ,
|
||||
if expectedElementType != nil and
|
||||
typeAllowed(expectedElementType, skLet, c) == nil:
|
||||
expectedElementType
|
||||
else:
|
||||
newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||
lastIndex = toInt128(-1)
|
||||
else:
|
||||
var x = n[0]
|
||||
if x.kind == nkExprColonExpr and x.len == 2:
|
||||
var idx = semConstExpr(c, x[0])
|
||||
var idx = semConstExpr(c, x[0], expectedIndexType)
|
||||
if not isOrdinalType(idx.typ):
|
||||
localError(c.config, idx.info, "expected ordinal value for array " &
|
||||
"index, got '$1'" % renderTree(idx))
|
||||
@@ -606,8 +630,10 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
lastValidIndex = lastOrd(c.config, indexType)
|
||||
x = x[1]
|
||||
|
||||
let yy = semExprWithType(c, x)
|
||||
let yy = semExprWithType(c, x, expectedType = expectedElementType)
|
||||
var typ = yy.typ
|
||||
if expectedElementType == nil:
|
||||
expectedElementType = typ
|
||||
result.add yy
|
||||
#var typ = skipTypes(result[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal})
|
||||
for i in 1..<n.len:
|
||||
@@ -619,13 +645,13 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
x = n[i]
|
||||
if x.kind == nkExprColonExpr and x.len == 2:
|
||||
var idx = semConstExpr(c, x[0])
|
||||
var idx = semConstExpr(c, x[0], indexType)
|
||||
idx = fitNode(c, indexType, idx, x.info)
|
||||
if lastIndex+1 != getOrdValue(idx):
|
||||
localError(c.config, x.info, "invalid order in array constructor")
|
||||
x = x[1]
|
||||
|
||||
let xx = semExprWithType(c, x, {})
|
||||
let xx = semExprWithType(c, x, {}, expectedElementType)
|
||||
result.add xx
|
||||
typ = commonType(c, typ, xx.typ)
|
||||
#n[i] = semExprWithType(c, x, {})
|
||||
@@ -640,6 +666,9 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc fixAbstractType(c: PContext, n: PNode) =
|
||||
for i in 1..<n.len:
|
||||
let it = n[i]
|
||||
if it == nil:
|
||||
localError(c.config, n.info, "'$1' has nil child at index $2" % [renderTree(n, {renderNoComments}), $i])
|
||||
return
|
||||
# do not get rid of nkHiddenSubConv for OpenArrays, the codegen needs it:
|
||||
if it.kind == nkHiddenSubConv and
|
||||
skipTypes(it.typ, abstractVar).kind notin {tyOpenArray, tyVarargs}:
|
||||
@@ -650,8 +679,8 @@ proc fixAbstractType(c: PContext, n: PNode) =
|
||||
changeType(c, it[1], s, check=true)
|
||||
n[i] = it[1]
|
||||
|
||||
proc isAssignable(c: PContext, n: PNode): TAssignableResult =
|
||||
result = parampatterns.isAssignable(c.p.owner, n)
|
||||
proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult =
|
||||
result = parampatterns.isAssignable(c.p.owner, n, isUnsafeAddr)
|
||||
|
||||
proc isUnresolvedSym(s: PSym): bool =
|
||||
result = s.kind == skGenericParam
|
||||
@@ -851,10 +880,10 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
#if result != n:
|
||||
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
||||
|
||||
proc semStaticExpr(c: PContext, n: PNode): PNode =
|
||||
proc semStaticExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
inc c.inStaticContext
|
||||
openScope(c)
|
||||
let a = semExprWithType(c, n)
|
||||
let a = semExprWithType(c, n, expectedType = expectedType)
|
||||
closeScope(c)
|
||||
dec c.inStaticContext
|
||||
if a.findUnresolvedStatic != nil: return a
|
||||
@@ -886,7 +915,8 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
case callee.kind
|
||||
of skMacro, skTemplate: discard
|
||||
else:
|
||||
if callee.kind == skIterator and callee.id == c.p.owner.id:
|
||||
if callee.kind == skIterator and callee.id == c.p.owner.id and
|
||||
not isClosureIterator(c.p.owner.typ):
|
||||
localError(c.config, n.info, errRecursiveDependencyIteratorX % callee.name.s)
|
||||
# error correction, prevents endless for loop elimination in transf.
|
||||
# See bug #2051:
|
||||
@@ -897,7 +927,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
rawAddSon(typ, result.typ)
|
||||
result.typ = typ
|
||||
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode
|
||||
|
||||
proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
|
||||
t: PType): TCandidate =
|
||||
@@ -916,26 +946,30 @@ proc bracketedMacro(n: PNode): PSym =
|
||||
if result.kind notin {skMacro, skTemplate}:
|
||||
result = nil
|
||||
|
||||
proc setGenericParams(c: PContext, n: PNode) =
|
||||
for i in 1..<n.len:
|
||||
n[i].typ = semTypeNode(c, n[i], nil)
|
||||
|
||||
proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
|
||||
proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
if efNoSemCheck notin flags and n.typ != nil and n.typ.kind == tyError:
|
||||
return errorNode(c, n)
|
||||
|
||||
result = n
|
||||
|
||||
when defined(nimsuggest):
|
||||
if c.config.expandProgress:
|
||||
if c.config.expandLevels == 0:
|
||||
return n
|
||||
else:
|
||||
c.config.expandLevels -= 1
|
||||
|
||||
let callee = result[0].sym
|
||||
case callee.kind
|
||||
of skMacro: result = semMacroExpr(c, result, orig, callee, flags)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee, flags)
|
||||
of skMacro: result = semMacroExpr(c, result, orig, callee, flags, expectedType)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee, flags, expectedType)
|
||||
else:
|
||||
semFinishOperands(c, result)
|
||||
activate(c, result)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
if callee.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
result = magicsAfterOverloadResolution(c, result, flags, expectedType)
|
||||
when false:
|
||||
if result.typ != nil and
|
||||
not (result.typ.kind == tySequence and result.typ[0].kind == tyEmpty):
|
||||
@@ -944,7 +978,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
|
||||
if c.matchedConcept == nil:
|
||||
result = evalAtCompileTime(c, result)
|
||||
|
||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = nil
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
var prc = n[0]
|
||||
@@ -969,13 +1003,20 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
let s = bracketedMacro(n[0])
|
||||
if s != nil:
|
||||
setGenericParams(c, n[0])
|
||||
return semDirectOp(c, n, flags)
|
||||
return semDirectOp(c, n, flags, expectedType)
|
||||
elif isSymChoice(n[0]) and nfDotField notin n.flags:
|
||||
# overloaded generic procs e.g. newSeq[int] can end up here
|
||||
return semDirectOp(c, n, flags, expectedType)
|
||||
|
||||
let nOrig = n.copyTree
|
||||
semOpAux(c, n)
|
||||
var t: PType = nil
|
||||
if n[0].typ != nil:
|
||||
t = skipTypes(n[0].typ, abstractInst+{tyOwned}-{tyTypeDesc, tyDistinct})
|
||||
if t != nil and t.kind == tyTypeDesc:
|
||||
if n.len == 1: return semObjConstr(c, n, flags, expectedType)
|
||||
return semConv(c, n)
|
||||
|
||||
let nOrig = n.copyTree
|
||||
semOpAux(c, n)
|
||||
if t != nil and t.kind == tyProc:
|
||||
# This is a proc variable, apply normal overload resolution
|
||||
let m = resolveIndirectCall(c, n, nOrig, t)
|
||||
@@ -1009,19 +1050,15 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
msg.addDeclaredLocMaybe(c.config, typ)
|
||||
localError(c.config, n.info, msg)
|
||||
return errorNode(c, n)
|
||||
result = nil
|
||||
else:
|
||||
result = m.call
|
||||
instGenericConvertersSons(c, result, m)
|
||||
|
||||
elif t != nil and t.kind == tyTypeDesc:
|
||||
if n.len == 1: return semObjConstr(c, n, flags)
|
||||
return semConv(c, n)
|
||||
else:
|
||||
result = overloadedCallOpr(c, n)
|
||||
result = overloadedCallOpr(c, n) # this uses efNoUndeclared
|
||||
# Now that nkSym does not imply an iteration over the proc/iterator space,
|
||||
# the old ``prc`` (which is likely an nkIdent) has to be restored:
|
||||
if result == nil:
|
||||
if result == nil or result.kind == nkEmpty:
|
||||
# XXX: hmm, what kind of symbols will end up here?
|
||||
# do we really need to try the overload resolution?
|
||||
n[0] = prc
|
||||
@@ -1035,17 +1072,17 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
return result
|
||||
#result = afterCallActions(c, result, nOrig, flags)
|
||||
if result[0].kind == nkSym:
|
||||
result = afterCallActions(c, result, nOrig, flags)
|
||||
result = afterCallActions(c, result, nOrig, flags, expectedType)
|
||||
else:
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
# this seems to be a hotspot in the compiler!
|
||||
let nOrig = n.copyTree
|
||||
#semLazyOpAux(c, n)
|
||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||
if result != nil: result = afterCallActions(c, result, nOrig, flags)
|
||||
if result != nil: result = afterCallActions(c, result, nOrig, flags, expectedType)
|
||||
else: result = errorNode(c, n)
|
||||
|
||||
proc buildEchoStmt(c: PContext, n: PNode): PNode =
|
||||
@@ -1585,7 +1622,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
{tyInt..tyInt64}:
|
||||
let idx = getOrdValue(n[1])
|
||||
if idx >= 0 and idx < arr.len: n.typ = arr[toInt(idx)]
|
||||
else: localError(c.config, n.info, "invalid index value for tuple subscript")
|
||||
else:
|
||||
localError(c.config, n.info,
|
||||
"invalid index $1 in subscript for tuple of length $2" %
|
||||
[$idx, $arr.len])
|
||||
result = n
|
||||
else:
|
||||
result = nil
|
||||
@@ -1618,11 +1658,11 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else:
|
||||
discard
|
||||
|
||||
proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = semSubscript(c, n, flags)
|
||||
if result == nil:
|
||||
# overloaded [] operator:
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, getIdent(c.cache, "[]")), flags)
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, getIdent(c.cache, "[]")), flags, expectedType)
|
||||
|
||||
proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
|
||||
var id = considerQuotedIdent(c, a[1], a)
|
||||
@@ -1663,11 +1703,9 @@ 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)
|
||||
let valid = isAssignable(c, n, isLent)
|
||||
if valid != arLValue:
|
||||
if valid in {arAddressableConst, arLentValue} and isLent:
|
||||
discard "ok"
|
||||
elif valid == arLocalLValue:
|
||||
if valid == arLocalLValue:
|
||||
localError(c.config, n.info, errXStackEscape % renderTree(n, {renderNoComments}))
|
||||
else:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
@@ -1765,7 +1803,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
result.add(n[1])
|
||||
if mode == noOverloadedSubscript:
|
||||
bracketNotFoundError(c, result)
|
||||
return n
|
||||
return errorNode(c, n)
|
||||
else:
|
||||
result = semExprNoType(c, result)
|
||||
return result
|
||||
@@ -1791,20 +1829,22 @@ 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, arAddressableConst}) or (
|
||||
isAssignable(c, a) in {arNone, arLentValue}) 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 %
|
||||
renderTree(a, {renderNoComments}))
|
||||
else:
|
||||
let lhs = n[0]
|
||||
let rhs = semExprWithType(c, n[1], {})
|
||||
let rhs = semExprWithType(c, n[1], {}, le)
|
||||
if lhs.kind == nkSym and lhs.sym.kind == skResult:
|
||||
n.typ = c.enforceVoidContext
|
||||
if c.p.owner.kind != skMacro and resultTypeIsInferrable(lhs.sym.typ):
|
||||
var rhsTyp = rhs.typ
|
||||
if rhsTyp.kind in tyUserTypeClasses and rhsTyp.isResolvedUserTypeClass:
|
||||
rhsTyp = rhsTyp.lastSon
|
||||
if lhs.sym.typ.kind == tyAnything:
|
||||
rhsTyp = rhsTyp.skipIntLit(c.idgen)
|
||||
if cmpTypes(c, lhs.typ, rhsTyp) in {isGeneric, isEqual}:
|
||||
internalAssert c.config, c.p.resultSym != nil
|
||||
# Make sure the type is valid for the result variable
|
||||
@@ -1847,9 +1887,12 @@ proc semReturn(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
localError(c.config, n.info, "'return' not allowed here")
|
||||
|
||||
proc semProcBody(c: PContext, n: PNode): PNode =
|
||||
proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
when defined(nimsuggest):
|
||||
if c.graph.config.expandDone():
|
||||
return n
|
||||
openScope(c)
|
||||
result = semExpr(c, n)
|
||||
result = semExpr(c, n, expectedType = expectedType)
|
||||
if c.p.resultSym != nil and not isEmptyType(result.typ):
|
||||
if result.kind == nkNilLit:
|
||||
# or ImplicitlyDiscardable(result):
|
||||
@@ -1878,8 +1921,8 @@ proc semProcBody(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
localError(c.config, c.p.resultSym.info, errCannotInferReturnType %
|
||||
c.p.owner.name.s)
|
||||
if isInlineIterator(c.p.owner.typ) and c.p.owner.typ[0] != nil and
|
||||
c.p.owner.typ[0].kind == tyUntyped:
|
||||
if isIterator(c.p.owner.typ) and c.p.owner.typ[0] != nil and
|
||||
c.p.owner.typ[0].kind == tyAnything:
|
||||
localError(c.config, c.p.owner.info, errCannotInferReturnType %
|
||||
c.p.owner.name.s)
|
||||
closeScope(c)
|
||||
@@ -1905,6 +1948,8 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||
tupleConstr[i] = takeImplicitAddr(c, tupleConstr[i], e.kind == tyLent)
|
||||
else:
|
||||
localError(c.config, n[0].info, errXExpected, "tuple constructor")
|
||||
elif e.kind == tyEmpty:
|
||||
localError(c.config, n[0].info, errTypeExpected)
|
||||
else:
|
||||
when false:
|
||||
# XXX investigate what we really need here.
|
||||
@@ -2266,7 +2311,7 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
result = foldSizeOf(c.config, n, n)
|
||||
|
||||
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
# this is a hotspot in the compiler!
|
||||
result = n
|
||||
case s.magic # magics that need special treatment
|
||||
@@ -2274,7 +2319,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])
|
||||
result[1] = semAddrArg(c, n[1], s.name.s == "unsafeAddr")
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
of mTypeOf:
|
||||
markUsed(c, n.info, s)
|
||||
@@ -2382,8 +2427,21 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
of mSizeOf:
|
||||
markUsed(c, n.info, s)
|
||||
result = semSizeof(c, setMs(n, s))
|
||||
of mArrToSeq, mOpenArrayToSeq:
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tySequence, tyOpenArray}):
|
||||
# seq type inference
|
||||
var arrayType = newType(tyOpenArray, nextTypeId(c.idgen), expected.owner)
|
||||
arrayType.rawAddSon(expected[0])
|
||||
if n[0].kind == nkSym and sfFromGeneric in n[0].sym.flags:
|
||||
# may have been resolved to `@`[empty] at some point,
|
||||
# reset to `@` to deal with this
|
||||
n[0] = newSymNode(n[0].sym.owner, n[0].info)
|
||||
n[1] = semExpr(c, n[1], flags, arrayType)
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
|
||||
proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
# If semCheck is set to false, ``when`` will return the verbatim AST of
|
||||
@@ -2401,8 +2459,8 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
# ...
|
||||
var whenNimvm = false
|
||||
var typ = commonTypeBegin
|
||||
if n.len == 2 and n[0].kind == nkElifBranch and
|
||||
n[1].kind == nkElse:
|
||||
if n.len in 1..2 and n[0].kind == nkElifBranch and (
|
||||
n.len == 1 or n[1].kind == nkElse):
|
||||
let exprNode = n[0][0]
|
||||
if exprNode.kind == nkIdent:
|
||||
whenNimvm = lookUp(c, exprNode).magic == mNimvm
|
||||
@@ -2440,35 +2498,54 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
else: illFormedAst(n, c.config)
|
||||
if result == nil:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
if whenNimvm: result.typ = typ
|
||||
if whenNimvm:
|
||||
result.typ = typ
|
||||
if n.len == 1:
|
||||
result.add(newTree(nkElse, newNode(nkStmtList)))
|
||||
|
||||
proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||
proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||
result = newNodeI(nkCurly, n.info)
|
||||
result.typ = newTypeS(tySet, c)
|
||||
result.typ.flags.incl tfIsConstructor
|
||||
var expectedElementType: PType = nil
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind == tySet):
|
||||
expectedElementType = expected[0]
|
||||
if n.len == 0:
|
||||
rawAddSon(result.typ, newTypeS(tyEmpty, c))
|
||||
rawAddSon(result.typ,
|
||||
if expectedElementType != nil and
|
||||
typeAllowed(expectedElementType, skLet, c) == nil:
|
||||
expectedElementType
|
||||
else:
|
||||
newTypeS(tyEmpty, c))
|
||||
else:
|
||||
# only semantic checking for all elements, later type checking:
|
||||
var typ: PType = nil
|
||||
for i in 0..<n.len:
|
||||
if isRange(n[i]):
|
||||
checkSonsLen(n[i], 3, c.config)
|
||||
n[i][1] = semExprWithType(c, n[i][1])
|
||||
n[i][2] = semExprWithType(c, n[i][2])
|
||||
n[i][1] = semExprWithType(c, n[i][1], {}, expectedElementType)
|
||||
n[i][2] = semExprWithType(c, n[i][2], {}, expectedElementType)
|
||||
if typ == nil:
|
||||
typ = skipTypes(n[i][1].typ,
|
||||
{tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
|
||||
if expectedElementType == nil:
|
||||
expectedElementType = typ
|
||||
n[i].typ = n[i][2].typ # range node needs type too
|
||||
elif n[i].kind == nkRange:
|
||||
# already semchecked
|
||||
if typ == nil:
|
||||
typ = skipTypes(n[i][0].typ,
|
||||
{tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
|
||||
if expectedElementType == nil:
|
||||
expectedElementType = typ
|
||||
else:
|
||||
n[i] = semExprWithType(c, n[i])
|
||||
n[i] = semExprWithType(c, n[i], {}, expectedElementType)
|
||||
if typ == nil:
|
||||
typ = skipTypes(n[i].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
|
||||
if expectedElementType == nil:
|
||||
expectedElementType = typ
|
||||
if not isOrdinalType(typ, allowEnumWithHoles=true):
|
||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
||||
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
|
||||
@@ -2487,7 +2564,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||
m = fitNode(c, typ, n[i], info)
|
||||
result.add m
|
||||
|
||||
proc semTableConstr(c: PContext, n: PNode): PNode =
|
||||
proc semTableConstr(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
# we simply transform ``{key: value, key2, key3: value}`` to
|
||||
# ``[(key, value), (key2, value2), (key3, value2)]``
|
||||
result = newNodeI(nkBracket, n.info)
|
||||
@@ -2509,7 +2586,7 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
|
||||
lastKey = i+1
|
||||
|
||||
if lastKey != n.len: illFormedAst(n, c.config)
|
||||
result = semExpr(c, result)
|
||||
result = semExpr(c, result, expectedType = expectedType)
|
||||
|
||||
type
|
||||
TParKind = enum
|
||||
@@ -2536,8 +2613,13 @@ proc checkPar(c: PContext; n: PNode): TParKind =
|
||||
localError(c.config, n[i].info, errNamedExprNotAllowed)
|
||||
return paNone
|
||||
|
||||
proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = newNodeI(nkTupleConstr, n.info)
|
||||
var expected: PType = nil
|
||||
if expectedType != nil:
|
||||
expected = expectedType.skipTypes(abstractRange-{tyDistinct})
|
||||
if not (expected.kind == tyTuple and expected.len == n.len):
|
||||
expected = nil
|
||||
var typ = newTypeS(tyTuple, c)
|
||||
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
||||
var ids = initIntSet()
|
||||
@@ -2547,7 +2629,9 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
let id = considerQuotedIdent(c, n[i][0])
|
||||
if containsOrIncl(ids, id.id):
|
||||
localError(c.config, n[i].info, errFieldInitTwice % id.s)
|
||||
n[i][1] = semExprWithType(c, n[i][1], {})
|
||||
# can check if field name matches expected type here
|
||||
let expectedElemType = if expected != nil: expected[i] else: nil
|
||||
n[i][1] = semExprWithType(c, n[i][1], {}, expectedElemType)
|
||||
|
||||
if n[i][1].typ.kind == tyTypeDesc:
|
||||
localError(c.config, n[i][1].info, "typedesc not allowed as tuple field.")
|
||||
@@ -2562,18 +2646,24 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.add n[i]
|
||||
result.typ = typ
|
||||
|
||||
proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = n # we don't modify n, but compute the type:
|
||||
result.transitionSonsKind(nkTupleConstr)
|
||||
var expected: PType = nil
|
||||
if expectedType != nil:
|
||||
expected = expectedType.skipTypes(abstractRange-{tyDistinct})
|
||||
if not (expected.kind == tyTuple and expected.len == n.len):
|
||||
expected = nil
|
||||
var typ = newTypeS(tyTuple, c) # leave typ.n nil!
|
||||
for i in 0..<n.len:
|
||||
n[i] = semExprWithType(c, n[i], {})
|
||||
let expectedElemType = if expected != nil: expected[i] else: nil
|
||||
n[i] = semExprWithType(c, n[i], {}, expectedElemType)
|
||||
addSonSkipIntLit(typ, n[i].typ, c.idgen)
|
||||
result.typ = typ
|
||||
|
||||
include semobjconstr
|
||||
|
||||
proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
proc semBlock(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = n
|
||||
inc(c.p.nestedBlockCounter)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
@@ -2586,9 +2676,9 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
labl.owner = c.p.owner
|
||||
n[0] = newSymNode(labl, n[0].info)
|
||||
suggestSym(c.graph, n[0].info, labl, c.graph.usageSym)
|
||||
styleCheckDef(c.config, labl)
|
||||
styleCheckDef(c, labl)
|
||||
onDef(n[0].info, labl)
|
||||
n[1] = semExpr(c, n[1], flags)
|
||||
n[1] = semExpr(c, n[1], flags, expectedType)
|
||||
n.typ = n[1].typ
|
||||
if isEmptyType(n.typ): n.transitionSonsKind(nkBlockStmt)
|
||||
else: n.transitionSonsKind(nkBlockExpr)
|
||||
@@ -2654,8 +2744,8 @@ proc semExport(c: PContext, n: PNode): PNode =
|
||||
|
||||
s = nextOverloadIter(o, c, a)
|
||||
|
||||
proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var tupexp = semTuplePositionsConstr(c, n, flags)
|
||||
proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
var tupexp = semTuplePositionsConstr(c, n, flags, expectedType)
|
||||
var isTupleType: bool
|
||||
if tupexp.len > 0: # don't interpret () as type
|
||||
isTupleType = tupexp[0].typ.kind == tyTypeDesc
|
||||
@@ -2780,7 +2870,7 @@ proc semPragmaStmt(c: PContext; n: PNode) =
|
||||
else:
|
||||
pragma(c, c.p.owner, n, stmtPragmas, true)
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode =
|
||||
when defined(nimCompilerStacktraceHints):
|
||||
setFrameMsg c.config$n.info & " " & $n.kind
|
||||
when false: # see `tdebugutils`
|
||||
@@ -2790,18 +2880,53 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if isCompilerDebug():
|
||||
echo ("<", c.config$n.info, n, ?.result.typ)
|
||||
|
||||
template directLiteral(typeKind: TTypeKind) =
|
||||
if result.typ == nil:
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind == typeKind):
|
||||
result.typ = expected
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, typeKind)
|
||||
|
||||
result = n
|
||||
when defined(nimsuggest):
|
||||
var expandStarted = false
|
||||
if c.config.ideCmd == ideExpand and not c.config.expandProgress and
|
||||
((n.kind in {nkFuncDef, nkProcDef, nkIteratorDef, nkTemplateDef, nkMethodDef, nkConverterDef} and
|
||||
n.info.exactEquals(c.config.expandPosition)) or
|
||||
(n.kind in {nkCall, nkCommand} and
|
||||
n[0].info.exactEquals(c.config.expandPosition))):
|
||||
expandStarted = true
|
||||
c.config.expandProgress = true
|
||||
if c.config.expandLevels == 0:
|
||||
c.config.expandNodeResult = $n
|
||||
suggestQuit()
|
||||
|
||||
if c.config.cmd == cmdIdeTools: suggestExpr(c, n)
|
||||
if nfSem in n.flags: return
|
||||
case n.kind
|
||||
of nkIdent, nkAccQuoted:
|
||||
let checks = if efNoEvaluateGeneric in flags:
|
||||
{checkUndeclared, checkPureEnumFields}
|
||||
elif efInCall in flags:
|
||||
{checkUndeclared, checkModule, checkPureEnumFields}
|
||||
else:
|
||||
{checkUndeclared, checkModule, checkAmbiguity, checkPureEnumFields}
|
||||
var s = qualifiedLookUp(c, n, checks)
|
||||
var s: PSym
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind == tyEnum):
|
||||
let nameId = considerQuotedIdent(c, n).id
|
||||
for f in expected.n:
|
||||
if f.kind == nkSym and f.sym.name.id == nameId:
|
||||
s = f.sym
|
||||
break
|
||||
if s == nil:
|
||||
let checks = if efNoEvaluateGeneric in flags:
|
||||
{checkUndeclared, checkPureEnumFields}
|
||||
elif efInCall in flags:
|
||||
{checkUndeclared, checkModule, checkPureEnumFields}
|
||||
else:
|
||||
{checkUndeclared, checkModule, checkAmbiguity, checkPureEnumFields}
|
||||
s = qualifiedLookUp(c, n, checks)
|
||||
if s == nil:
|
||||
return
|
||||
if c.matchedConcept == nil: semCaptureSym(s, c.p.owner)
|
||||
case s.kind
|
||||
of skProc, skFunc, skMethod, skConverter, skIterator:
|
||||
@@ -2821,6 +2946,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semSym(c, n, s, flags)
|
||||
else:
|
||||
result = semSym(c, n, s, flags)
|
||||
if expectedType != nil and isSymChoice(result):
|
||||
result = fitNode(c, expectedType, result, n.info)
|
||||
if result.kind == nkSym:
|
||||
result = semSym(c, result, result.sym, flags)
|
||||
of nkSym:
|
||||
# because of the changed symbol binding, this does not mean that we
|
||||
# don't have to check the symbol for semantics here again!
|
||||
@@ -2828,39 +2957,56 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkEmpty, nkNone, nkCommentStmt, nkType:
|
||||
discard
|
||||
of nkNilLit:
|
||||
if result.typ == nil: result.typ = getNilType(c)
|
||||
if result.typ == nil:
|
||||
result.typ = getNilType(c)
|
||||
if expectedType != nil:
|
||||
var m = newCandidate(c, result.typ)
|
||||
if typeRel(m, expectedType, result.typ) >= isSubtype:
|
||||
result.typ = expectedType
|
||||
# or: result = fitNode(c, expectedType, result, n.info)
|
||||
of nkIntLit:
|
||||
if result.typ == nil: setIntLitType(c, result)
|
||||
of nkInt8Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyInt8)
|
||||
of nkInt16Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyInt16)
|
||||
of nkInt32Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyInt32)
|
||||
of nkInt64Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyInt64)
|
||||
of nkUIntLit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyUInt)
|
||||
of nkUInt8Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyUInt8)
|
||||
of nkUInt16Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyUInt16)
|
||||
of nkUInt32Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyUInt32)
|
||||
of nkUInt64Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyUInt64)
|
||||
#of nkFloatLit:
|
||||
# if result.typ == nil: result.typ = getFloatLitType(result)
|
||||
of nkFloat32Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyFloat32)
|
||||
of nkFloat64Lit, nkFloatLit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyFloat64)
|
||||
of nkFloat128Lit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyFloat128)
|
||||
if result.typ == nil:
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyInt..tyInt64,
|
||||
tyUInt..tyUInt64,
|
||||
tyFloat..tyFloat128}):
|
||||
result.typ = expected
|
||||
if expected.kind in {tyFloat..tyFloat128}:
|
||||
n.transitionIntToFloatKind(nkFloatLit)
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
setIntLitType(c, result)
|
||||
of nkInt8Lit: directLiteral(tyInt8)
|
||||
of nkInt16Lit: directLiteral(tyInt16)
|
||||
of nkInt32Lit: directLiteral(tyInt32)
|
||||
of nkInt64Lit: directLiteral(tyInt64)
|
||||
of nkUIntLit: directLiteral(tyUInt)
|
||||
of nkUInt8Lit: directLiteral(tyUInt8)
|
||||
of nkUInt16Lit: directLiteral(tyUInt16)
|
||||
of nkUInt32Lit: directLiteral(tyUInt32)
|
||||
of nkUInt64Lit: directLiteral(tyUInt64)
|
||||
of nkFloatLit:
|
||||
if result.typ == nil:
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyFloat..tyFloat128}):
|
||||
result.typ = expected
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, tyFloat64)
|
||||
of nkFloat32Lit: directLiteral(tyFloat32)
|
||||
of nkFloat64Lit: directLiteral(tyFloat64)
|
||||
of nkFloat128Lit: directLiteral(tyFloat128)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyString)
|
||||
of nkCharLit:
|
||||
if result.typ == nil: result.typ = getSysType(c.graph, n.info, tyChar)
|
||||
if result.typ == nil:
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyString, tyCstring}):
|
||||
result.typ = expectedType
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
of nkCharLit: directLiteral(tyChar)
|
||||
of nkDotExpr:
|
||||
result = semFieldAccess(c, n, flags)
|
||||
if result.kind == nkDotCall:
|
||||
@@ -2868,8 +3014,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semExpr(c, result, flags)
|
||||
of nkBind:
|
||||
message(c.config, n.info, warnDeprecated, "bind is deprecated")
|
||||
result = semExpr(c, n[0], flags)
|
||||
of nkTypeOfExpr..nkTupleClassTy, nkStaticTy, nkRefTy..nkEnumTy:
|
||||
result = semExpr(c, n[0], flags, expectedType)
|
||||
of nkTypeOfExpr, nkTupleTy, nkTupleClassTy, nkRefTy..nkEnumTy, nkStaticTy:
|
||||
if c.matchedConcept != nil and n.len == 1:
|
||||
let modifier = n.modifierTypeKindOfNode
|
||||
if modifier != tyNone:
|
||||
@@ -2894,40 +3040,40 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
# pretty.checkUse(n[0][1].info, s)
|
||||
case s.kind
|
||||
of skMacro, skTemplate:
|
||||
result = semDirectOp(c, n, flags)
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
of skType:
|
||||
# XXX think about this more (``set`` procs)
|
||||
let ambig = c.isAmbiguous
|
||||
if not (n[0].kind in {nkClosedSymChoice, nkOpenSymChoice, nkIdent} and ambig) and n.len == 2:
|
||||
result = semConv(c, n)
|
||||
result = semConv(c, n, expectedType)
|
||||
elif ambig and n.len == 1:
|
||||
errorUseQualifier(c, n.info, s)
|
||||
elif n.len == 1:
|
||||
result = semObjConstr(c, n, flags)
|
||||
elif s.magic == mNone: result = semDirectOp(c, n, flags)
|
||||
else: result = semMagic(c, n, s, flags)
|
||||
result = semObjConstr(c, n, flags, expectedType)
|
||||
elif s.magic == mNone: result = semDirectOp(c, n, flags, expectedType)
|
||||
else: result = semMagic(c, n, s, flags, expectedType)
|
||||
of skProc, skFunc, skMethod, skConverter, skIterator:
|
||||
if s.magic == mNone: result = semDirectOp(c, n, flags)
|
||||
else: result = semMagic(c, n, s, flags)
|
||||
else: result = semMagic(c, n, s, flags, expectedType)
|
||||
else:
|
||||
#liMessage(n.info, warnUser, renderTree(n));
|
||||
result = semIndirectOp(c, n, flags)
|
||||
result = semIndirectOp(c, n, flags, expectedType)
|
||||
elif (n[0].kind == nkBracketExpr or shouldBeBracketExpr(n)) and
|
||||
isSymChoice(n[0][0]):
|
||||
# indirectOp can deal with explicit instantiations; the fixes
|
||||
# the 'newSeq[T](x)' bug
|
||||
setGenericParams(c, n[0])
|
||||
result = semDirectOp(c, n, flags)
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
elif nfDotField in n.flags:
|
||||
result = semDirectOp(c, n, flags)
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
elif isSymChoice(n[0]):
|
||||
let b = asBracketExpr(c, n)
|
||||
if b != nil:
|
||||
result = semExpr(c, b, flags)
|
||||
result = semExpr(c, b, flags, expectedType)
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
else:
|
||||
result = semIndirectOp(c, n, flags)
|
||||
result = semIndirectOp(c, n, flags, expectedType)
|
||||
|
||||
if nfDefaultRefsParam in result.flags:
|
||||
result = result.copyTree #XXX: Figure out what causes default param nodes to be shared.. (sigmatch bug?)
|
||||
@@ -2946,12 +3092,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
# This is a "when nimvm" stmt.
|
||||
result = semWhen(c, n, true)
|
||||
else:
|
||||
result = semExpr(c, result, flags)
|
||||
result = semExpr(c, result, flags, expectedType)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
result = semArrayAccess(c, n, flags)
|
||||
result = semArrayAccess(c, n, flags, expectedType)
|
||||
of nkCurlyExpr:
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, getIdent(c.cache, "{}")), flags)
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, getIdent(c.cache, "{}")), flags, expectedType)
|
||||
of nkPragmaExpr:
|
||||
var
|
||||
pragma = n[1]
|
||||
@@ -2973,12 +3119,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkPar, nkTupleConstr:
|
||||
case checkPar(c, n)
|
||||
of paNone: result = errorNode(c, n)
|
||||
of paTuplePositions: result = semTupleConstr(c, n, flags)
|
||||
of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
|
||||
of paSingle: result = semExpr(c, n[0], flags)
|
||||
of nkCurly: result = semSetConstr(c, n)
|
||||
of nkBracket: result = semArrayConstr(c, n, flags)
|
||||
of nkObjConstr: result = semObjConstr(c, n, flags)
|
||||
of paTuplePositions: result = semTupleConstr(c, n, flags, expectedType)
|
||||
of paTupleFields: result = semTupleFieldsConstr(c, n, flags, expectedType)
|
||||
of paSingle: result = semExpr(c, n[0], flags, expectedType)
|
||||
of nkCurly: result = semSetConstr(c, n, expectedType)
|
||||
of nkBracket: result = semArrayConstr(c, n, flags, expectedType)
|
||||
of nkObjConstr: result = semObjConstr(c, n, flags, expectedType)
|
||||
of nkLambdaKinds: result = semProcAux(c, n, skProc, lambdaPragmas, flags)
|
||||
of nkDerefExpr: result = semDeref(c, n)
|
||||
of nkAddr:
|
||||
@@ -2988,9 +3134,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result.typ = makePtrType(c, result[0].typ)
|
||||
of nkHiddenAddr, nkHiddenDeref:
|
||||
checkSonsLen(n, 1, c.config)
|
||||
n[0] = semExpr(c, n[0], flags)
|
||||
n[0] = semExpr(c, n[0], flags, expectedType)
|
||||
of nkCast: result = semCast(c, n)
|
||||
of nkIfExpr, nkIfStmt: result = semIf(c, n, flags)
|
||||
of nkIfExpr, nkIfStmt: result = semIf(c, n, flags, expectedType)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv:
|
||||
checkSonsLen(n, 2, c.config)
|
||||
considerGenSyms(c, n)
|
||||
@@ -3004,15 +3150,15 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
considerGenSyms(c, n)
|
||||
of nkTableConstr:
|
||||
result = semTableConstr(c, n)
|
||||
result = semTableConstr(c, n, expectedType)
|
||||
of nkClosedSymChoice, nkOpenSymChoice:
|
||||
# handling of sym choices is context dependent
|
||||
# the node is left intact for now
|
||||
discard
|
||||
of nkStaticExpr: result = semStaticExpr(c, n[0])
|
||||
of nkAsgn: result = semAsgn(c, n)
|
||||
of nkBlockStmt, nkBlockExpr: result = semBlock(c, n, flags)
|
||||
of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags)
|
||||
of nkStaticExpr: result = semStaticExpr(c, n[0], expectedType)
|
||||
of nkAsgn, nkFastAsgn: result = semAsgn(c, n)
|
||||
of nkBlockStmt, nkBlockExpr: result = semBlock(c, n, flags, expectedType)
|
||||
of nkStmtList, nkStmtListExpr: result = semStmtList(c, n, flags, expectedType)
|
||||
of nkRaiseStmt: result = semRaise(c, n)
|
||||
of nkVarSection: result = semVarOrLet(c, n, skVar)
|
||||
of nkLetSection: result = semVarOrLet(c, n, skLet)
|
||||
@@ -3020,10 +3166,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkTypeSection: result = semTypeSection(c, n)
|
||||
of nkDiscardStmt: result = semDiscard(c, n)
|
||||
of nkWhileStmt: result = semWhile(c, n, flags)
|
||||
of nkTryStmt, nkHiddenTryStmt: result = semTry(c, n, flags)
|
||||
of nkTryStmt, nkHiddenTryStmt: result = semTry(c, n, flags, expectedType)
|
||||
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
|
||||
of nkForStmt, nkParForStmt: result = semFor(c, n, flags)
|
||||
of nkCaseStmt: result = semCase(c, n, flags)
|
||||
of nkCaseStmt: result = semCase(c, n, flags, expectedType)
|
||||
of nkReturnStmt: result = semReturn(c, n)
|
||||
of nkUsingStmt: result = semUsing(c, n)
|
||||
of nkAsmStmt: result = semAsm(c, n)
|
||||
@@ -3062,13 +3208,15 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "export")
|
||||
result = semExportExcept(c, n)
|
||||
of nkPragmaBlock:
|
||||
result = semPragmaBlock(c, n)
|
||||
result = semPragmaBlock(c, n, expectedType)
|
||||
of nkStaticStmt:
|
||||
result = semStaticStmt(c, n)
|
||||
of nkDefer:
|
||||
if c.currentScope == c.topLevelScope:
|
||||
localError(c.config, n.info, "defer statement not supported at top level")
|
||||
openScope(c)
|
||||
n[0] = semExpr(c, n[0])
|
||||
closeScope(c)
|
||||
if not n[0].typ.isEmptyType and not implicitlyDiscardable(n[0]):
|
||||
localError(c.config, n.info, "'defer' takes a 'void' expression")
|
||||
#localError(c.config, n.info, errGenerated, "'defer' not allowed in this context")
|
||||
@@ -3089,3 +3237,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
localError(c.config, n.info, "invalid expression: " &
|
||||
renderTree(n, {renderNoComments}))
|
||||
if result != nil: incl(result.flags, nfSem)
|
||||
|
||||
when defined(nimsuggest):
|
||||
if expandStarted:
|
||||
c.config.expandNodeResult = $result
|
||||
suggestQuit()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user