mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 10:53:40 +00:00
Compare commits
762 Commits
version-0-
...
v1.0.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89b39ee8fe | ||
|
|
d038e1b750 | ||
|
|
a6846b81eb | ||
|
|
de43bdfa70 | ||
|
|
25a4026cda | ||
|
|
2e9d595f92 | ||
|
|
13ad15dffe | ||
|
|
0ff510ca07 | ||
|
|
16eaebbf51 | ||
|
|
61c8a2b1e7 | ||
|
|
b64d59635c | ||
|
|
cd28e01a1a | ||
|
|
2f557f74e5 | ||
|
|
f1ec998e71 | ||
|
|
a3d5a3ca9b | ||
|
|
74350447ed | ||
|
|
83c1ec46ce | ||
|
|
29b6dd6196 | ||
|
|
8994e8f2e2 | ||
|
|
3e76777de8 | ||
|
|
d237b73e6e | ||
|
|
7134d57cd4 | ||
|
|
17ddc7e894 | ||
|
|
26331a9005 | ||
|
|
6d2884be9c | ||
|
|
e636b47429 | ||
|
|
4028514eeb | ||
|
|
8b956dba09 | ||
|
|
78f9933b8f | ||
|
|
46be787fb2 | ||
|
|
7afe6b1f4b | ||
|
|
f9d30dc1e5 | ||
|
|
89b244a2f5 | ||
|
|
4c120c1978 | ||
|
|
bc601a62a2 | ||
|
|
9167eb6c89 | ||
|
|
7c4bc63b00 | ||
|
|
261592de18 | ||
|
|
f52395f2d8 | ||
|
|
d807c4b7c0 | ||
|
|
65aa564c54 | ||
|
|
0f05a0dd5b | ||
|
|
512727d75e | ||
|
|
00408a4554 | ||
|
|
09be379b91 | ||
|
|
6f520fb6d9 | ||
|
|
789a984c1e | ||
|
|
1edb81b66c | ||
|
|
340c9248f1 | ||
|
|
9ec09bfa55 | ||
|
|
a13f623f16 | ||
|
|
5129a1e88d | ||
|
|
3f6a08d5b0 | ||
|
|
299f1e99cd | ||
|
|
a02a4d8fc5 | ||
|
|
10935a71ed | ||
|
|
d0e8ad17b5 | ||
|
|
60100a9a64 | ||
|
|
c8998c498f | ||
|
|
97e0ce3c75 | ||
|
|
aa7b0c8581 | ||
|
|
d6f52f3cef | ||
|
|
fa15083cc9 | ||
|
|
c868f1ef67 | ||
|
|
8f0b891e68 | ||
|
|
4084ef19a3 | ||
|
|
7d444ff04c | ||
|
|
aaf06dba1b | ||
|
|
0e1dd54fee | ||
|
|
c78cee697d | ||
|
|
4c4116d63a | ||
|
|
9d17d02734 | ||
|
|
e8578c926e | ||
|
|
5937c40928 | ||
|
|
f3e088f11a | ||
|
|
39122ecd93 | ||
|
|
7ea60f78b5 | ||
|
|
ee260dd838 | ||
|
|
23881b188e | ||
|
|
e5f968da0c | ||
|
|
cb2f8d4d39 | ||
|
|
e2aa1d6d84 | ||
|
|
beaead0fd1 | ||
|
|
763486a3aa | ||
|
|
d61dd518d9 | ||
|
|
2a292c0e71 | ||
|
|
814e237ab6 | ||
|
|
8324b7a86d | ||
|
|
7ccefbc422 | ||
|
|
8fddc8e8a1 | ||
|
|
f47d977f6d | ||
|
|
a5c98bf3af | ||
|
|
93b868bff9 | ||
|
|
274f94c84a | ||
|
|
1ff3494dab | ||
|
|
1d43c8620e | ||
|
|
f5e096b13f | ||
|
|
29c099ccd1 | ||
|
|
6887d6de80 | ||
|
|
7c2d64c18d | ||
|
|
f991d2c1fd | ||
|
|
d6ae4e00f4 | ||
|
|
2a2a9110b2 | ||
|
|
4a7ccfa333 | ||
|
|
476d677c6f | ||
|
|
ee0c1482d7 | ||
|
|
731d1dff84 | ||
|
|
e02dc971f5 | ||
|
|
5f77d5ad85 | ||
|
|
f69dac8038 | ||
|
|
338f43f305 | ||
|
|
d1d8cd1000 | ||
|
|
f042acc535 | ||
|
|
eac5452082 | ||
|
|
80861998c7 | ||
|
|
c1fd463834 | ||
|
|
dedff71ca0 | ||
|
|
cd60067638 | ||
|
|
bf047d6ef1 | ||
|
|
313b2f0d71 | ||
|
|
f5269876ea | ||
|
|
89738fd95d | ||
|
|
ab51a8e08b | ||
|
|
6ffe5ee7e8 | ||
|
|
ab2a8344b3 | ||
|
|
fc9cccccd3 | ||
|
|
faf5ffd970 | ||
|
|
6fc9327ebf | ||
|
|
93aeb9c825 | ||
|
|
59e8ca721e | ||
|
|
193b3c66bb | ||
|
|
0b134412f8 | ||
|
|
1526ae8791 | ||
|
|
b914573d18 | ||
|
|
f579d29b68 | ||
|
|
f79f7fed98 | ||
|
|
e0c4015bbe | ||
|
|
7b500cbfad | ||
|
|
53e4692665 | ||
|
|
b0e595b3cf | ||
|
|
4e3c997d40 | ||
|
|
f16bb4d85b | ||
|
|
8f1dea614e | ||
|
|
63d710f5a1 | ||
|
|
2ebd47089a | ||
|
|
535f0b9c9d | ||
|
|
813b371758 | ||
|
|
a09379f5fd | ||
|
|
e9f7455bd6 | ||
|
|
e03b1b79ae | ||
|
|
0ea770c8f0 | ||
|
|
8a0012de42 | ||
|
|
1d4916b481 | ||
|
|
2de758e68a | ||
|
|
c8c9699850 | ||
|
|
5df7f3fd5c | ||
|
|
44d45b763c | ||
|
|
f7c150766a | ||
|
|
4ae143ca60 | ||
|
|
0a8dcd5e11 | ||
|
|
929aa99665 | ||
|
|
bae10d44fa | ||
|
|
4632e8b26e | ||
|
|
97e2e06b00 | ||
|
|
b827431499 | ||
|
|
99d448deeb | ||
|
|
9afd19b236 | ||
|
|
0d0cf86401 | ||
|
|
5785444520 | ||
|
|
1b3f5eed70 | ||
|
|
517538dcf8 | ||
|
|
59916007cc | ||
|
|
a5bcbe6dff | ||
|
|
cd3d4b5e05 | ||
|
|
ac2181c5b9 | ||
|
|
4675aae90b | ||
|
|
a0402b2012 | ||
|
|
cbdc48ec66 | ||
|
|
f19edae1b8 | ||
|
|
c5b9a44894 | ||
|
|
3009eafc89 | ||
|
|
1e97abec96 | ||
|
|
95a655a975 | ||
|
|
39f5a2b218 | ||
|
|
6c1f389d72 | ||
|
|
1ae9cac3a4 | ||
|
|
fa7f5742d3 | ||
|
|
c8314b7c9c | ||
|
|
52ea15cc24 | ||
|
|
7926440ae3 | ||
|
|
bda6e071cd | ||
|
|
f7a8fc46c0 | ||
|
|
5b43c98897 | ||
|
|
f388817a79 | ||
|
|
b865c2a54b | ||
|
|
6e681b546f | ||
|
|
2565d3d102 | ||
|
|
39185b46ca | ||
|
|
e0f2b3ba8f | ||
|
|
b04ef2973d | ||
|
|
be82d11576 | ||
|
|
c2fced129f | ||
|
|
5abe880469 | ||
|
|
9776f926a2 | ||
|
|
908b553215 | ||
|
|
96b3bae99b | ||
|
|
a404ec540a | ||
|
|
dea9e38d26 | ||
|
|
c623ab62cc | ||
|
|
f576df2bcc | ||
|
|
05e80e1cda | ||
|
|
7839658323 | ||
|
|
1b20f768c7 | ||
|
|
38ab51c445 | ||
|
|
7bc5bf8334 | ||
|
|
04c803d6df | ||
|
|
162d74db91 | ||
|
|
363d0ada50 | ||
|
|
a948deebb3 | ||
|
|
188ce5f3ee | ||
|
|
f8000d4ba1 | ||
|
|
48537fec81 | ||
|
|
638a4d9d9f | ||
|
|
93f74e4f93 | ||
|
|
910ed5888e | ||
|
|
618316beb9 | ||
|
|
ea8a049af3 | ||
|
|
c9f3a8b269 | ||
|
|
f1b7c0494e | ||
|
|
62aa1a3cfe | ||
|
|
77c6425e65 | ||
|
|
754531fff3 | ||
|
|
059a16b34d | ||
|
|
2a59f499e9 | ||
|
|
6c487a6309 | ||
|
|
8b4c17a140 | ||
|
|
3f87453981 | ||
|
|
1c03604ec6 | ||
|
|
fd63443419 | ||
|
|
5018e7f304 | ||
|
|
ee6df5bd24 | ||
|
|
d79fb77974 | ||
|
|
eb241f4241 | ||
|
|
ca7bf3be8b | ||
|
|
5b923cd149 | ||
|
|
5783cd67a8 | ||
|
|
e134a722de | ||
|
|
8c81cddf7e | ||
|
|
560eef5bbe | ||
|
|
944bab4c3c | ||
|
|
5a520a8454 | ||
|
|
33b8a00aa8 | ||
|
|
c55ceafd9a | ||
|
|
99425ff21d | ||
|
|
ee36931f26 | ||
|
|
cf99c9bfb5 | ||
|
|
d363eced3a | ||
|
|
1fa1024ddf | ||
|
|
58077450cc | ||
|
|
5d9c1544bf | ||
|
|
60911304b4 | ||
|
|
81c23bba7b | ||
|
|
92f2d68802 | ||
|
|
ed1d41c51e | ||
|
|
aa95ae6af9 | ||
|
|
f915064e07 | ||
|
|
e5139b0662 | ||
|
|
18135cc194 | ||
|
|
790f5bac01 | ||
|
|
3255b55266 | ||
|
|
8362d92e47 | ||
|
|
4bbafb47dc | ||
|
|
3eb89481cb | ||
|
|
4129993689 | ||
|
|
5a8fddf29b | ||
|
|
e0f3e8432a | ||
|
|
0e01a5f76c | ||
|
|
24f52d855c | ||
|
|
32769c478b | ||
|
|
8397554315 | ||
|
|
40c5175145 | ||
|
|
488f3ed085 | ||
|
|
0882a09986 | ||
|
|
49f63d3aae | ||
|
|
a5e2db2ac5 | ||
|
|
58bcf6cd46 | ||
|
|
c2ba0ee144 | ||
|
|
92c012d86d | ||
|
|
a9c7fb2fcc | ||
|
|
fa5707e7e2 | ||
|
|
cb0450398a | ||
|
|
07a986afa1 | ||
|
|
ea1a26294f | ||
|
|
459fbb9525 | ||
|
|
4972d797e4 | ||
|
|
35f1519ad6 | ||
|
|
79f1b8592a | ||
|
|
ac6fcab7a4 | ||
|
|
d70e292571 | ||
|
|
5a03eea518 | ||
|
|
545ddf4a4f | ||
|
|
f8f96d816c | ||
|
|
7ef85db9a9 | ||
|
|
18ca1788f0 | ||
|
|
fc7fe636e2 | ||
|
|
23c44f009a | ||
|
|
3d4ad9739c | ||
|
|
ba18c12005 | ||
|
|
755c4428fe | ||
|
|
2396f0ee71 | ||
|
|
e765687646 | ||
|
|
e6ec88d4c3 | ||
|
|
ad82e65387 | ||
|
|
ab48d7901e | ||
|
|
35268c500f | ||
|
|
6e01be34ef | ||
|
|
326a333c8b | ||
|
|
15213028b7 | ||
|
|
2b565aad89 | ||
|
|
a6428657e9 | ||
|
|
efe1bed82e | ||
|
|
a388c35741 | ||
|
|
a055f628f4 | ||
|
|
9ae0dd611f | ||
|
|
f9600b7207 | ||
|
|
82d5e773e3 | ||
|
|
25581c796f | ||
|
|
029dcc6259 | ||
|
|
2a3b056314 | ||
|
|
d0e5bd2305 | ||
|
|
9203d3a982 | ||
|
|
cd106cf680 | ||
|
|
5f7a6aff06 | ||
|
|
21fc8b4d4d | ||
|
|
42d2e68bca | ||
|
|
c9f49cbc0a | ||
|
|
84351da9d8 | ||
|
|
d4af0554c4 | ||
|
|
20dec10722 | ||
|
|
eaebbfa785 | ||
|
|
d564130a3b | ||
|
|
eff0837ff4 | ||
|
|
00d46ca1c0 | ||
|
|
114da04cbb | ||
|
|
d8177a3980 | ||
|
|
8df745a42e | ||
|
|
3f5599b344 | ||
|
|
329e169e96 | ||
|
|
def6234903 | ||
|
|
66a8856152 | ||
|
|
ab8241ad42 | ||
|
|
1ccff0324c | ||
|
|
ddc155af64 | ||
|
|
b044523c5a | ||
|
|
5a9edb222b | ||
|
|
97d77bf37e | ||
|
|
0c41fd0f50 | ||
|
|
d8d2a9e985 | ||
|
|
8117a949c5 | ||
|
|
ae9bb4474b | ||
|
|
88814bbe98 | ||
|
|
931ee0ca82 | ||
|
|
5df7d72afe | ||
|
|
73dd73f961 | ||
|
|
ce7f29e8e6 | ||
|
|
f2e8c39e85 | ||
|
|
547fcd69c3 | ||
|
|
c3c5839329 | ||
|
|
fbb2763204 | ||
|
|
b07694cd90 | ||
|
|
2212a90458 | ||
|
|
e1539c7344 | ||
|
|
806f3b592f | ||
|
|
f28a47ea7b | ||
|
|
9aad99bdfd | ||
|
|
085fbcea6f | ||
|
|
9eee15f668 | ||
|
|
170cb4f4cb | ||
|
|
a562de2d91 | ||
|
|
2b2efe3dbe | ||
|
|
5304b16a55 | ||
|
|
4264e9576d | ||
|
|
d00c8febee | ||
|
|
b1b0960c36 | ||
|
|
75baaa5e25 | ||
|
|
ceb742351a | ||
|
|
cf4390a24a | ||
|
|
742862b847 | ||
|
|
ac7a365137 | ||
|
|
d5840e1e3d | ||
|
|
7cb31455ee | ||
|
|
b68380f09b | ||
|
|
db9e27dffd | ||
|
|
cf09ef47b8 | ||
|
|
15e681ce66 | ||
|
|
721ca3e830 | ||
|
|
39f4a3e418 | ||
|
|
b9dd972c32 | ||
|
|
7023241aaf | ||
|
|
bebda3851f | ||
|
|
c7e77edecc | ||
|
|
ba577c7e1b | ||
|
|
cf22dec584 | ||
|
|
1fb9a6d946 | ||
|
|
d31404ac27 | ||
|
|
922e2a5098 | ||
|
|
511298242d | ||
|
|
296dfae8af | ||
|
|
b095203f28 | ||
|
|
630e18a6eb | ||
|
|
a25d43ca6b | ||
|
|
65ed2d7fe8 | ||
|
|
e6cb7e34ef | ||
|
|
5ef62fcb25 | ||
|
|
1874b3e786 | ||
|
|
83397a69fc | ||
|
|
433613e267 | ||
|
|
322ce1872f | ||
|
|
289b5e9ef9 | ||
|
|
c9c28bf85e | ||
|
|
da64c8762f | ||
|
|
212ae2f125 | ||
|
|
0e4a8bfb28 | ||
|
|
da37177ac2 | ||
|
|
3b8f721460 | ||
|
|
082c440f13 | ||
|
|
81ddc67785 | ||
|
|
04708742e7 | ||
|
|
e3c0bf48c5 | ||
|
|
0d5bd7e8b5 | ||
|
|
44e7a7b6c2 | ||
|
|
fda51b6ca2 | ||
|
|
756fabb979 | ||
|
|
48968f3c84 | ||
|
|
addd7b5e20 | ||
|
|
c8cffaf420 | ||
|
|
c0d240b8cd | ||
|
|
f34ae81971 | ||
|
|
9321b33cd2 | ||
|
|
afbcd1b330 | ||
|
|
8407a57499 | ||
|
|
3d7d5cf121 | ||
|
|
ce148e71ef | ||
|
|
42e83ac24c | ||
|
|
d208d7a995 | ||
|
|
61c66abbfe | ||
|
|
7024bb800c | ||
|
|
65d1140d11 | ||
|
|
b73d097d36 | ||
|
|
343ace8194 | ||
|
|
51d998390c | ||
|
|
df32c45757 | ||
|
|
bcfb540e57 | ||
|
|
50e921bb94 | ||
|
|
a906b3952b | ||
|
|
829f719670 | ||
|
|
803406d07c | ||
|
|
bb949a75db | ||
|
|
ceb1a1b688 | ||
|
|
f58d87cb43 | ||
|
|
c9c8fa99cc | ||
|
|
b9c15371a3 | ||
|
|
f7c99838e2 | ||
|
|
25e6c53bb5 | ||
|
|
1a77040278 | ||
|
|
2fdba334da | ||
|
|
4c73139316 | ||
|
|
95856ab8d3 | ||
|
|
d7bc4e43a2 | ||
|
|
3bb6d1916e | ||
|
|
3ccda773d6 | ||
|
|
13190435a6 | ||
|
|
44aadd50cf | ||
|
|
5484352d26 | ||
|
|
8c93c692b9 | ||
|
|
30f2cec671 | ||
|
|
46f2271968 | ||
|
|
d563efb719 | ||
|
|
67a6effb7b | ||
|
|
affe1be47c | ||
|
|
dc38b88f7e | ||
|
|
1868cbc449 | ||
|
|
5a020d641d | ||
|
|
313cc337f2 | ||
|
|
de69e1856f | ||
|
|
70e8551e37 | ||
|
|
903d06bab8 | ||
|
|
a5d6080a81 | ||
|
|
fbb0642e27 | ||
|
|
9852cf804b | ||
|
|
6d8913ee14 | ||
|
|
7deb49e992 | ||
|
|
5b7273b4f8 | ||
|
|
4becd5a2a8 | ||
|
|
07d465ca42 | ||
|
|
4137a4dbf3 | ||
|
|
f50e4500c2 | ||
|
|
745669ac25 | ||
|
|
d40872bf9b | ||
|
|
404b224945 | ||
|
|
210988c532 | ||
|
|
1acb9bae94 | ||
|
|
e11494f1cf | ||
|
|
326860e84c | ||
|
|
15d2a92be0 | ||
|
|
bae08d0961 | ||
|
|
43940294c5 | ||
|
|
44d80dd863 | ||
|
|
3f7142fcfd | ||
|
|
0b511b15ea | ||
|
|
dcbb2d66da | ||
|
|
1f32498a47 | ||
|
|
102b71f42e | ||
|
|
8550a8127c | ||
|
|
76f9ddb6ab | ||
|
|
ec9d0ee86d | ||
|
|
8513f50a8d | ||
|
|
dd7dd1b6dc | ||
|
|
ad67a46e5d | ||
|
|
52cbd0c558 | ||
|
|
edbe02b4e1 | ||
|
|
df53c68a36 | ||
|
|
58e0dad371 | ||
|
|
e06046ab51 | ||
|
|
fab70e4fe3 | ||
|
|
44c12d9d20 | ||
|
|
9db369063c | ||
|
|
a59fb5b352 | ||
|
|
cf36e4a44a | ||
|
|
de1ede77fe | ||
|
|
d55cc0888d | ||
|
|
423e8cca91 | ||
|
|
416ba133ad | ||
|
|
bb5ca0772e | ||
|
|
f45a1b927a | ||
|
|
03ded27021 | ||
|
|
2895ad70c8 | ||
|
|
38b836b49e | ||
|
|
7606efc0bf | ||
|
|
6d125da93f | ||
|
|
13253f4154 | ||
|
|
5bf3734984 | ||
|
|
974362c98f | ||
|
|
fd24a8923e | ||
|
|
eaf4b42ff9 | ||
|
|
511b6ae27c | ||
|
|
2f0a50fa51 | ||
|
|
3d88d06b32 | ||
|
|
b8be1ccb85 | ||
|
|
ac458448d8 | ||
|
|
cb3c3c306c | ||
|
|
38bdf1cd7f | ||
|
|
b2f9447896 | ||
|
|
87a2ced1ba | ||
|
|
73cc029fec | ||
|
|
dc0bbba3fa | ||
|
|
78174857f8 | ||
|
|
b03421d087 | ||
|
|
bc7733827d | ||
|
|
6663dbbe57 | ||
|
|
e5425b5f2f | ||
|
|
c94647aeca | ||
|
|
96523cdd3e | ||
|
|
18182e4bfd | ||
|
|
ff4a9a226f | ||
|
|
bd689849f2 | ||
|
|
c6c9e30379 | ||
|
|
7a39eb13a5 | ||
|
|
2255d8795b | ||
|
|
55e8aefbea | ||
|
|
73c570d1d9 | ||
|
|
ad58ed344a | ||
|
|
eb059fa848 | ||
|
|
a85e20c125 | ||
|
|
fa982b43f0 | ||
|
|
96d49608c0 | ||
|
|
eefcea8892 | ||
|
|
fc34193483 | ||
|
|
0193c8ad2e | ||
|
|
7993d61d00 | ||
|
|
2c2f2de614 | ||
|
|
f64179e7fe | ||
|
|
7c62de0cb7 | ||
|
|
11dad688fe | ||
|
|
063ae96a66 | ||
|
|
5ddea6a98f | ||
|
|
5fce81edfd | ||
|
|
6375df4c53 | ||
|
|
b80d70b0f3 | ||
|
|
a6526695f0 | ||
|
|
b50ae6817a | ||
|
|
124a584eb2 | ||
|
|
655cb08461 | ||
|
|
9e7d885f35 | ||
|
|
d0616ed115 | ||
|
|
085a21ebf4 | ||
|
|
bab1f67971 | ||
|
|
6a7f8e8ab5 | ||
|
|
3258c1e2a3 | ||
|
|
465815e894 | ||
|
|
6ce6bce12e | ||
|
|
d2684cdfd2 | ||
|
|
cab0c3e544 | ||
|
|
64e1408920 | ||
|
|
2678fa679a | ||
|
|
02b9af2f75 | ||
|
|
25cd8a5490 | ||
|
|
34c09a98c7 | ||
|
|
7d5d9f7703 | ||
|
|
176eaf5c90 | ||
|
|
d1f6c820dd | ||
|
|
2c0c0e772c | ||
|
|
96a19ea1b4 | ||
|
|
95f2f2396f | ||
|
|
28c9c062a4 | ||
|
|
b64dd795b1 | ||
|
|
5f515410af | ||
|
|
d914dca513 | ||
|
|
0a501932c2 | ||
|
|
dad3c40f55 | ||
|
|
4450fca6fd | ||
|
|
a59f0adc50 | ||
|
|
7d29f8b1a4 | ||
|
|
64168d4aea | ||
|
|
0718d6c2cd | ||
|
|
045eeab6b4 | ||
|
|
0ca71dd92c | ||
|
|
1e9316e23c | ||
|
|
c0db1705dc | ||
|
|
476b4ff372 | ||
|
|
a157c2baef | ||
|
|
20d0ef8afb | ||
|
|
0a1cb631a2 | ||
|
|
ab6dec6e90 | ||
|
|
71b7383f12 | ||
|
|
c522a455df | ||
|
|
cce8a739da | ||
|
|
766960dc15 | ||
|
|
9b949855c7 | ||
|
|
2c10b246ec | ||
|
|
bd55c862a6 | ||
|
|
c352892232 | ||
|
|
413dff03a0 | ||
|
|
a5686961bd | ||
|
|
d7a7662a7f | ||
|
|
dd39b11b13 | ||
|
|
d37c4e44d3 | ||
|
|
e259f80fc7 | ||
|
|
7113c1e931 | ||
|
|
3606e035f5 | ||
|
|
7ddb31262e | ||
|
|
5be5bf0222 | ||
|
|
284a8cb58a | ||
|
|
d72edfb14b | ||
|
|
765ff4b67b | ||
|
|
17bbce7c8a | ||
|
|
d9604d7d0b | ||
|
|
bab83c4d8b | ||
|
|
f36a61e6d4 | ||
|
|
fb878330a9 | ||
|
|
135fdde6a9 | ||
|
|
19b142401c | ||
|
|
48cbf1c496 | ||
|
|
ce2777af5a | ||
|
|
f65eaa51f1 | ||
|
|
e083a1533b | ||
|
|
326e3ad09d | ||
|
|
b6fb47df77 | ||
|
|
f288e1b11a | ||
|
|
0a81b038fd | ||
|
|
993b3909a8 | ||
|
|
b7f8031e98 | ||
|
|
206f2478b8 | ||
|
|
0f868b587b | ||
|
|
2f1a1b7106 | ||
|
|
0d50b0c8a7 | ||
|
|
91f0626dcb | ||
|
|
181350f6c9 | ||
|
|
2a7cf71db3 | ||
|
|
403fd3ac43 | ||
|
|
e9a23cee0a | ||
|
|
436f570651 | ||
|
|
e90d91f0e4 | ||
|
|
800bc661b6 | ||
|
|
bb9b60604b | ||
|
|
b81fd958d1 | ||
|
|
3d50f7e2a1 | ||
|
|
79c721d418 | ||
|
|
0db3c670ac | ||
|
|
35df59b3ce | ||
|
|
12eebf48b6 | ||
|
|
a4c613c110 | ||
|
|
23e95dc629 | ||
|
|
d6b0e46ee4 | ||
|
|
45bbf1ef5b | ||
|
|
55da84e141 | ||
|
|
f310cf5250 | ||
|
|
280193cc07 | ||
|
|
7e4748beee | ||
|
|
bc9fb4885b | ||
|
|
678beb8ef9 | ||
|
|
6adcc09877 | ||
|
|
c83914b435 | ||
|
|
50afafdb38 | ||
|
|
af10788dcc | ||
|
|
16d81fa205 | ||
|
|
96bed814d2 | ||
|
|
0adb1c6223 | ||
|
|
c65a5d754b | ||
|
|
1a074fffa4 | ||
|
|
ab36ffbeb1 | ||
|
|
ff89f7e33a | ||
|
|
de88fdb86e | ||
|
|
ae5a4cea98 | ||
|
|
cf47c2c60c | ||
|
|
24ac13f653 | ||
|
|
f67be92512 | ||
|
|
296c48de5e | ||
|
|
79a23fe805 | ||
|
|
7c637c2faf | ||
|
|
8ee0f14ab6 | ||
|
|
c99ce5051e | ||
|
|
38f05bb9a3 | ||
|
|
a009cbdc2f | ||
|
|
c8268330be | ||
|
|
ac3449b93b | ||
|
|
6cad5c7861 | ||
|
|
b70fd0400e | ||
|
|
eb087b3546 | ||
|
|
aa7f23e1ee | ||
|
|
9f6187b46c | ||
|
|
7182922622 | ||
|
|
eadea343ef | ||
|
|
6dc6487311 | ||
|
|
68cce40510 | ||
|
|
d1ce86fdc6 | ||
|
|
e96afd6324 | ||
|
|
c656714623 | ||
|
|
57a83df745 | ||
|
|
80320c72d3 | ||
|
|
bda9fd149c | ||
|
|
e11d582fa1 | ||
|
|
e7188cdfa8 | ||
|
|
06ef56ba72 | ||
|
|
e2f99a2026 | ||
|
|
165ea46284 | ||
|
|
af39f26a3a | ||
|
|
b70295c768 | ||
|
|
08fdffc717 | ||
|
|
73c44c6e9b | ||
|
|
bde899d4f8 | ||
|
|
da035e9c83 | ||
|
|
b056d32a79 | ||
|
|
e4d0f4fee0 | ||
|
|
c07973e313 | ||
|
|
549d8cc0c6 | ||
|
|
572b7c37a5 | ||
|
|
c7e1c665a1 | ||
|
|
3d13103443 | ||
|
|
a9aef65b2d | ||
|
|
b3d2cd738a | ||
|
|
7cfc7cfb26 |
@@ -51,6 +51,8 @@ addons:
|
||||
- libsdl1.2-dev
|
||||
- libgc-dev
|
||||
- libsfml-dev
|
||||
- libc6-dbg
|
||||
- valgrind
|
||||
homebrew:
|
||||
packages:
|
||||
- boehmgc
|
||||
|
||||
@@ -15,10 +15,6 @@ cache:
|
||||
- '%MINGW_ARCHIVE%'
|
||||
- '%DLLS_ARCHIVE%'
|
||||
|
||||
matrix:
|
||||
#allow_failures:
|
||||
# - NIM_TEST_PACKAGES: true
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
- ps: Install-Product node 8 # node 8 or later is required to test js async stuff
|
||||
|
||||
148
azure-pipelines.yml
Normal file
148
azure-pipelines.yml
Normal file
@@ -0,0 +1,148 @@
|
||||
strategy:
|
||||
matrix:
|
||||
Linux_amd64:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
CPU: amd64
|
||||
Linux_i386:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
CPU: i386
|
||||
OSX_amd64:
|
||||
vmImage: 'macOS-10.14'
|
||||
CPU: amd64
|
||||
OSX_amd64_cpp:
|
||||
vmImage: 'macOS-10.14'
|
||||
CPU: amd64
|
||||
NIM_COMPILE_TO_CPP: true
|
||||
Windows_amd64:
|
||||
vmImage: 'windows-2019'
|
||||
CPU: amd64
|
||||
Windows_amd64_pkg:
|
||||
vmImage: 'windows-2019'
|
||||
CPU: amd64
|
||||
NIM_TEST_PACKAGES: true
|
||||
|
||||
pool:
|
||||
vmImage: $(vmImage)
|
||||
|
||||
workspace:
|
||||
clean: all
|
||||
|
||||
steps:
|
||||
- bash: git config --global core.autocrlf false
|
||||
displayName: 'Disable auto conversion to CRLF by git (Windows-only)'
|
||||
condition: eq(variables['Agent.OS'], 'Windows_NT')
|
||||
|
||||
- checkout: self
|
||||
|
||||
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
displayName: 'Checkout csources'
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '8.x'
|
||||
displayName: 'Install node.js 8.x'
|
||||
|
||||
- bash: |
|
||||
sudo apt-fast update -qq
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
sudo apt-fast install --no-install-recommends -yq \
|
||||
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev valgrind libc6-dbg
|
||||
displayName: 'Install dependencies (amd64 Linux)'
|
||||
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
|
||||
|
||||
- bash: |
|
||||
sudo dpkg --add-architecture i386
|
||||
|
||||
# Downgrade llvm, libgcc and libstdc++:
|
||||
# - llvm has to be downgraded to have 32bit version installed for sfml.
|
||||
# - libgcc and libstdc++ have to be downgraded as an optimization to
|
||||
# prevent the use of the toolchain ppa, which has a terrible download
|
||||
# speed.
|
||||
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
|
||||
Package: libllvm6.0 libgcc1 libstdc++6
|
||||
Pin: origin "azure.archive.ubuntu.com"
|
||||
Pin-Priority: 1001
|
||||
|
||||
Package: *
|
||||
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
|
||||
Pin-Priority: 100
|
||||
EOF
|
||||
|
||||
sudo apt-fast update -qq
|
||||
DEBIAN_FRONTEND='noninteractive' \
|
||||
sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
|
||||
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
|
||||
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386
|
||||
|
||||
cat << EOF > bin/gcc
|
||||
#!/bin/bash
|
||||
|
||||
exec $(which gcc) -m32 "\$@"
|
||||
EOF
|
||||
cat << EOF > bin/g++
|
||||
#!/bin/bash
|
||||
|
||||
exec $(which g++) -m32 "\$@"
|
||||
EOF
|
||||
|
||||
chmod 755 bin/gcc
|
||||
chmod 755 bin/g++
|
||||
|
||||
displayName: 'Install dependencies (i386 Linux)'
|
||||
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'i386'))
|
||||
|
||||
- bash: brew install boehmgc make sfml
|
||||
displayName: 'Install dependencies (OSX)'
|
||||
condition: eq(variables['Agent.OS'], 'Darwin')
|
||||
|
||||
- bash: |
|
||||
mkdir dist
|
||||
curl -L https://nim-lang.org/download/mingw64-6.3.0.7z -o dist/mingw64.7z
|
||||
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
|
||||
7z x dist/mingw64.7z -odist
|
||||
7z x dist/dlls.zip -obin
|
||||
echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/dist/mingw64/bin'
|
||||
|
||||
displayName: 'Install dependencies (Windows)'
|
||||
condition: eq(variables['Agent.OS'], 'Windows_NT')
|
||||
|
||||
- bash: echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/bin'
|
||||
displayName: 'Add build binaries to PATH'
|
||||
|
||||
- bash: |
|
||||
echo 'PATH:' "$PATH"
|
||||
echo '##[section]gcc version'
|
||||
gcc -v
|
||||
echo '##[section]nodejs version'
|
||||
node -v
|
||||
echo '##[section]make version'
|
||||
make -v
|
||||
displayName: 'System information'
|
||||
|
||||
- bash: |
|
||||
ncpu=
|
||||
case '$(Agent.OS)' in
|
||||
'Linux')
|
||||
ncpu=$(nproc)
|
||||
;;
|
||||
'Darwin')
|
||||
ncpu=$(sysctl -n hw.ncpu)
|
||||
;;
|
||||
'Windows_NT')
|
||||
ncpu=$NUMBER_OF_PROCESSORS
|
||||
;;
|
||||
esac
|
||||
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
|
||||
|
||||
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
|
||||
displayName: 'Build csources'
|
||||
|
||||
- bash: nim c koch
|
||||
displayName: 'Build koch'
|
||||
|
||||
# set result to omit the "bash exited with error code '1'" message
|
||||
- bash: |
|
||||
./koch runCI || echo '##vso[task.complete result=Failed]'
|
||||
displayName: 'Run CI'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
16
build_all.bat
Normal file
16
build_all.bat
Normal file
@@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
rem build development version of the compiler; can be rerun safely
|
||||
if not exist csources (
|
||||
git clone --depth 1 https://github.com/nim-lang/csources.git
|
||||
)
|
||||
if not exist bin\nim.exe (
|
||||
cd csources
|
||||
if PROCESSOR_ARCHITECTURE == AMD64 (
|
||||
SET ARCH=64
|
||||
)
|
||||
CALL build.bat
|
||||
cd ..
|
||||
)
|
||||
bin\nim.exe c --skipUserCfg --skipParentCfg koch
|
||||
koch.exe boot -d:release
|
||||
koch.exe tools
|
||||
16
changelog.md
16
changelog.md
@@ -1,37 +1,41 @@
|
||||
# v1.1 - XXXX-XX-XX
|
||||
# v1.1 - xxxx-xx-xx
|
||||
|
||||
|
||||
## Changes affecting backwards compatibility
|
||||
|
||||
|
||||
|
||||
### Breaking changes in the standard library
|
||||
|
||||
|
||||
|
||||
### Breaking changes in the compiler
|
||||
|
||||
|
||||
|
||||
## Library additions
|
||||
|
||||
|
||||
|
||||
## Library changes
|
||||
|
||||
- Added `os.delEnv` and `nimscript.delEnv`. (#11466)
|
||||
|
||||
- Enable Oid usage in hashtables. (#11472)
|
||||
|
||||
#
|
||||
# Language additions
|
||||
## Language additions
|
||||
|
||||
|
||||
|
||||
## Language changes
|
||||
|
||||
|
||||
|
||||
### Tool changes
|
||||
|
||||
|
||||
|
||||
### Compiler changes
|
||||
|
||||
- VM can now cast integer type arbitrarily. (#11459)
|
||||
|
||||
|
||||
|
||||
## Bugfixes
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
# v0.20.4 - xxxx-xx-xx
|
||||
|
||||
|
||||
## Changes affecting backwards compatibility
|
||||
|
||||
|
||||
### Breaking changes in the standard library
|
||||
|
||||
|
||||
### Breaking changes in the compiler
|
||||
|
||||
|
||||
## Library additions
|
||||
|
||||
|
||||
## Library changes
|
||||
|
||||
|
||||
## Language additions
|
||||
|
||||
|
||||
## Language changes
|
||||
|
||||
|
||||
### Tool changes
|
||||
|
||||
|
||||
### Compiler changes
|
||||
|
||||
|
||||
## Bugfixes
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
- We changed how array accesses "from backwards" like ``a[^1]`` or ``a[0..^1]`` are
|
||||
implemented. These are now implemented purely in ``system.nim`` without compiler
|
||||
support. There is a new "heterogenous" slice type ``system.HSlice`` that takes 2
|
||||
support. There is a new "heterogeneous" slice type ``system.HSlice`` that takes 2
|
||||
generic parameters which can be ``BackwardsIndex`` indices. ``BackwardsIndex`` is
|
||||
produced by ``system.^``.
|
||||
This means if you overload ``[]`` or ``[]=`` you need to ensure they also work
|
||||
@@ -660,4 +660,4 @@ for i in a..b:
|
||||
- Fixed "C++: SIGABRT instead of IndexError for out-of-bounds"
|
||||
([#6512](https://github.com/nim-lang/Nim/issues/6512))
|
||||
- Fixed "An uncaught exception in cpp mode doesn't show the exception name/msg"
|
||||
([#6431](https://github.com/nim-lang/Nim/issues/6431))
|
||||
([#6431](https://github.com/nim-lang/Nim/issues/6431))
|
||||
|
||||
138
changelogs/changelog_1_0_0.md
Normal file
138
changelogs/changelog_1_0_0.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# v1.0 - 2019-09-23
|
||||
|
||||
|
||||
## Changes affecting backwards compatibility
|
||||
|
||||
- The switch ``-d:nimBinaryStdFiles`` does not exist anymore. Instead
|
||||
stdin/stdout/stderr are binary files again. This change only affects
|
||||
Windows.
|
||||
|
||||
- On Windows console applications the code-page is set at program startup
|
||||
to UTF-8. Use the new switch `-d:nimDontSetUtf8CodePage` to disable this
|
||||
feature.
|
||||
|
||||
- The language definition and compiler are now stricter about ``gensym``'ed
|
||||
symbols in hygienic templates. See the section in the
|
||||
[manual](https://nim-lang.org/docs/manual.html#templates-hygiene-in-templates)
|
||||
for further details. Use the compiler switch `--oldgensym:on` for a
|
||||
transition period.
|
||||
|
||||
|
||||
### Breaking changes in the standard library
|
||||
|
||||
- We removed `unicode.Rune16` without any deprecation period as the name
|
||||
was wrong (see the [RFC](https://github.com/nim-lang/RFCs/issues/151) for details)
|
||||
and we didn't find any usages of it in the wild. If you still need it, add this
|
||||
piece of code to your project:
|
||||
```nim
|
||||
type
|
||||
Rune16* = distinct int16
|
||||
```
|
||||
|
||||
- `exportc` now uses C instead of C++ mangling with `nim cpp`, matching behavior
|
||||
of `importc`, see #10578.
|
||||
Use the new `exportcpp` to mangle as C++ when using `nim cpp`.
|
||||
|
||||
|
||||
### Breaking changes in the compiler
|
||||
|
||||
- A bug allowing `int` to be implicitly converted to range types of smaller size
|
||||
(e.g `range[0'i8..10'i8]`) has been fixed.
|
||||
|
||||
|
||||
|
||||
## Library additions
|
||||
|
||||
- `encodings.getCurrentEncoding` now distinguishes between the console's
|
||||
encoding and the OS's encoding. This distinction is only meaningful on
|
||||
Windows.
|
||||
- Added `system.getOsFileHandle` which is usually more useful
|
||||
than `system.getFileHandle`. This distinction is only meaningful on
|
||||
Windows.
|
||||
- Added a `json.parseJsonFragments` iterator that can be used to speedup
|
||||
JSON processing substantially when there are JSON fragments separated
|
||||
by whitespace.
|
||||
|
||||
|
||||
|
||||
## Library changes
|
||||
|
||||
- Added `os.delEnv` and `nimscript.delEnv`. (#11466)
|
||||
|
||||
- Enabled Oid usage in hashtables. (#11472)
|
||||
|
||||
- Added `unsafeColumnAt` procs, that return unsafe cstring from InstantRow. (#11647)
|
||||
|
||||
- Make public `Sha1Digest` and `Sha1State` types and `newSha1State`,
|
||||
`update` and `finalize` procedures from `sha1` module. (#11694)
|
||||
|
||||
- Added the `std/monotimes` module which implements monotonic timestamps.
|
||||
|
||||
- Consistent error handling of two `exec` overloads. (#10967)
|
||||
|
||||
- Officially the following modules now have an unstable API:
|
||||
- std/varints
|
||||
- core/allocators
|
||||
- core/hotcodereloading
|
||||
- asyncstreams
|
||||
- base64
|
||||
- browsers
|
||||
- collections/rtarrays
|
||||
- collections/sharedlist
|
||||
- collections/sharedtable
|
||||
- concurrency/atomics
|
||||
- concurrency/cpuload
|
||||
- concurrency/threadpool
|
||||
- coro
|
||||
- endians
|
||||
- httpcore
|
||||
- parsesql
|
||||
- pathnorm
|
||||
- reservedmem
|
||||
- typetraits
|
||||
|
||||
Every other stdlib module is API stable with respect to version 1.
|
||||
|
||||
|
||||
|
||||
## Language additions
|
||||
|
||||
- Inline iterators returning `lent T` types are now supported, similarly to
|
||||
iterators returning `var T`:
|
||||
```nim
|
||||
iterator myitems[T](x: openarray[T]): lent T
|
||||
iterator mypairs[T](x: openarray[T]): tuple[idx: int, val: lent T]
|
||||
```
|
||||
|
||||
- Added an `importjs` pragma that can now be used instead of `importcpp`
|
||||
and `importc` to import symbols from JavaScript. `importjs` for routines always
|
||||
takes a "pattern" for maximum flexibility.
|
||||
|
||||
|
||||
|
||||
## Language changes
|
||||
|
||||
- `uint64` is now finally a regular ordinal type. This means `high(uint64)` compiles
|
||||
and yields the correct value.
|
||||
|
||||
|
||||
### Tool changes
|
||||
|
||||
- The Nim compiler now does not recompile the Nim project via ``nim c -r`` if
|
||||
no dependent Nim file changed. This feature can be overridden by
|
||||
the ``--forceBuild`` command line option.
|
||||
- The Nim compiler now warns about unused module imports. You can use a
|
||||
top level ``{.used.}`` pragma in the module that you want to be importable
|
||||
without producing this warning.
|
||||
- The "testament" testing tool's name was changed
|
||||
from `tester` to `testament` and is generally available as a tool to run Nim
|
||||
tests automatically.
|
||||
|
||||
|
||||
### Compiler changes
|
||||
|
||||
- VM can now cast integer type arbitrarily. (#11459)
|
||||
|
||||
|
||||
|
||||
## Bugfixes
|
||||
56
changelogs/changelog_1_0_2.md
Normal file
56
changelogs/changelog_1_0_2.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# v1.0.2 - 2019-10-23
|
||||
|
||||
|
||||
## Bugfixes
|
||||
|
||||
* fixes the --verbosity:2 regression
|
||||
* Fixed "Fail to compile a file twice under Windows (v1.0 bug)." [#12242](https://github.com/nim-lang/Nim/issues/12242)
|
||||
* fix nimpretty removing space before pragma
|
||||
* JS: gensym is stricter for 'this'
|
||||
* Fixed "VM Assertion Error with newruntime" [#12294](https://github.com/nim-lang/Nim/issues/12294)
|
||||
* Fixed "Assertion error when running `nim check` on compiler/nim.nim" [#12281](https://github.com/nim-lang/Nim/issues/12281)
|
||||
* Fixed "Compiler crash with empty array and generic instantiation with int as parameter" [#12264](https://github.com/nim-lang/Nim/issues/12264)
|
||||
* Fixed "Regression in JS backend codegen "Error: request to generate code for .compileTime proc"" [#12240](https://github.com/nim-lang/Nim/issues/12240)
|
||||
* Fix how `relativePath` handle case sensitiviy
|
||||
* Fixed "SIGSEGV in compiler when using generic types and seqs" [#12336](https://github.com/nim-lang/Nim/issues/12336)
|
||||
* Fixed "[1.0.0] weird interaction between `import os` and casting integer to char on macosx trigger bad codegen" [#12291](https://github.com/nim-lang/Nim/issues/12291)
|
||||
* VM: no special casing for big endian machines
|
||||
* Fixed "`internal error: environment misses` with a simple template inside one of Jester macros" [#12323](https://github.com/nim-lang/Nim/issues/12323)
|
||||
* nimsuggest: fix tcp socket leak
|
||||
* nimsuggest: fix tcp socket leak for epc backend
|
||||
* Fixed "`writeFile` and `write(f, str)` skip null bytes on Windows" [#12315](https://github.com/nim-lang/Nim/issues/12315)
|
||||
* Fixed "Crash in intsets symmetric_difference" [#12366](https://github.com/nim-lang/Nim/issues/12366)
|
||||
* Fixed "[regression] VM crash when dealing with var param of a proc result" [#12244](https://github.com/nim-lang/Nim/issues/12244)
|
||||
* fixes a koch regression that made 'koch boot --listcmd' not work anymore
|
||||
* Fixed "[regression] inconsistent signed int `mod` operator between runtime, compiletime, and semfold" [#12332](https://github.com/nim-lang/Nim/issues/12332)
|
||||
* Fixed "Boehm disables interior pointer checking" [#12286](https://github.com/nim-lang/Nim/issues/12286)
|
||||
* Fixes semCustomPragma when nkSym
|
||||
* Fixed yield in nkCheckedFieldExpr
|
||||
* Fixed "`randomize()` from `random` not working on JS" [#12418](https://github.com/nim-lang/Nim/issues/12418)
|
||||
* Fixed "Compiler crash with invalid object variant" [#12379](https://github.com/nim-lang/Nim/issues/12379)
|
||||
* fix type's case in random.nim
|
||||
* Fixed "Update docs with a better way to signal unimplemented methods" [#10804](https://github.com/nim-lang/Nim/issues/10804)
|
||||
* Fixed "Nim language manual, push pragma is not explained well" [#10824](https://github.com/nim-lang/Nim/issues/10824)
|
||||
* Fixed "[regression] Importing more than one module with same name from different packages produce bad codegen" [#12420](https://github.com/nim-lang/Nim/issues/12420)
|
||||
* Namespace unittest enums to avoid name conflicts
|
||||
* Fixed "VM checks unsigned integers for overflow." [#12310](https://github.com/nim-lang/Nim/issues/12310)
|
||||
* Fixed "line directive is not generated for first line of function definition" [#12426](https://github.com/nim-lang/Nim/issues/12426)
|
||||
|
||||
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* threadpool: fix link in docs (#12258)
|
||||
* Fix spellings (#12277)
|
||||
* fix #12278, don't expose internal PCRE documentation
|
||||
* Fixed "Documentation of quitprocs is wrong" [#12279](https://github.com/nim-lang/Nim/issues/12279)
|
||||
* Fix typo in docs
|
||||
* Fix reference to parseSpec proc in readme
|
||||
* [doc/tut1] removed discard discussion in comments
|
||||
* Documentation improvements around the db interface
|
||||
* Easier build instructions for windows - just run `build_all.bat`.
|
||||
* fix a few dead links and a missing sentence in documentation
|
||||
* Macro docs additions
|
||||
* Updated the code example in the os module to use better grammar.
|
||||
* Mention "lambdas" and `=>` in the manual
|
||||
* Better documentation on Garbage Collector
|
||||
75
changelogs/changelog_1_0_4.md
Normal file
75
changelogs/changelog_1_0_4.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# v1.0.4 - 2019-11-26
|
||||
|
||||
|
||||
|
||||
## Language changes
|
||||
|
||||
- Conversions to unsigned integers are unchecked at runtime, imitating earlier Nim
|
||||
versions. The documentation was improved to acknowledge this special case.
|
||||
See https://github.com/nim-lang/RFCs/issues/175 for more details. (#12688)
|
||||
|
||||
- Add `or detectOs(Manjaro)` (#12587)
|
||||
|
||||
- --os:ios needs to imply defined(macosx) (#12585)
|
||||
|
||||
- export nim.cfg parser (#12602)
|
||||
|
||||
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fixed "gorge(Ex) fails after a few calls on OSX"
|
||||
([#12337](https://github.com/nim-lang/Nim/issues/12337))
|
||||
- Fixed "Improve posix module"
|
||||
([#10723](https://github.com/nim-lang/Nim/issues/10723))
|
||||
- Fixed "nim check allows gorgeEx but doesn't allow writeFile"
|
||||
([#12491](https://github.com/nim-lang/Nim/issues/12491))
|
||||
- Fixed "Low level arithmetics bug: -3 mod 7 == 3"
|
||||
([#12514](https://github.com/nim-lang/Nim/issues/12514))
|
||||
- Fixed "Broken link to c2nim in backends.rst/.html"
|
||||
([#12537](https://github.com/nim-lang/Nim/issues/12537))
|
||||
- Fixed "generic argument with default value causes incorrect generic type resolution"
|
||||
([#12528](https://github.com/nim-lang/Nim/issues/12528))
|
||||
- Fixed "regression: compiler/vmgen.nim(354, 20) `false` leaking temporary 10 slotTempInt [AssertionError]
|
||||
([#12547](https://github.com/nim-lang/Nim/issues/12547))
|
||||
- Fixed "Compile/link broken for nim (64-bit only) on Windows"
|
||||
([#12536](https://github.com/nim-lang/Nim/issues/12536))
|
||||
- Fixed "No `=destroy` for elements of closure environments other than for latest devel --gc:destructors"
|
||||
([#12577](https://github.com/nim-lang/Nim/issues/12577))
|
||||
- Fixed "[1.0.0] Cannot compile anything with --cpu:avr"
|
||||
([#12395](https://github.com/nim-lang/Nim/issues/12395))
|
||||
- Fixed "Compiler crash with invalid object variant"
|
||||
([#12379](https://github.com/nim-lang/Nim/issues/12379))
|
||||
- Fixed "push pragma is silently ignored if position is in front of import statement"
|
||||
([#5050](https://github.com/nim-lang/Nim/issues/5050))
|
||||
- Fixed "Error with strformat + asyncdispatch + const"
|
||||
([#12612](https://github.com/nim-lang/Nim/issues/12612))
|
||||
- Fixed "The --nimblePath is additive; need a pain-free workaround"
|
||||
([#12601](https://github.com/nim-lang/Nim/issues/12601))
|
||||
- Fixed "nim.cfg syntax for --define:FOO:VAL undocumented or absent"
|
||||
([#12367](https://github.com/nim-lang/Nim/issues/12367))
|
||||
- Fixed "vm string literals do not work when generated by a macro"
|
||||
([#12670](https://github.com/nim-lang/Nim/issues/12670))
|
||||
- Fixed "StaticRead does force a recompile if static file changes."
|
||||
([#12663](https://github.com/nim-lang/Nim/issues/12663))
|
||||
- Fixed crash in terminate handler
|
||||
([#12572](https://github.com/nim-lang/Nim/pull/12572))
|
||||
- Fixed newLit for objects having string fields
|
||||
([#12542](https://github.com/nim-lang/Nim/pull/12542))
|
||||
|
||||
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
- Documentation Math module (#12460)
|
||||
- Fix many broken links and prefer relative links within docs (#12463)
|
||||
- sequtils: replace deprecated 'random' call within example (#12515)
|
||||
- integer literal documentation (#12513)
|
||||
- Fix code style errors (#12545)
|
||||
- fix several typos in documentation and comments (#12553)
|
||||
- Add docs to better distinguish among getProjectPath, getCurrentDir and currentSourcePath (#12565)
|
||||
- doc/tut3.rst: Fix typo in Introduction (#12607)
|
||||
- Add links to packaging and distro pages (#12603)
|
||||
- fix documentation of `$`\*(dt: DateTime) (#12660)
|
||||
- Clarifies experimental / parallel example on manual.rst (#12472)
|
||||
- Fix wrong section hierarchy in the manual (#12724)
|
||||
68
changelogs/changelog_1_0_6.md
Normal file
68
changelogs/changelog_1_0_6.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# v1.0.6 - 2020-01-24
|
||||
|
||||
|
||||
## Bugfixes
|
||||
|
||||
### Fixed issues
|
||||
|
||||
- Fixed "Nim stdlib style issues with --styleCheck:error"
|
||||
([#12687](https://github.com/nim-lang/Nim/issues/12687))
|
||||
- Fixed "new(ref MyObject) doesn't work at compile time"
|
||||
([#12488](https://github.com/nim-lang/Nim/issues/12488))
|
||||
- Fixed "Accessing the wrong variant field in the VM does not trigger the appropriate error message"
|
||||
([#11727](https://github.com/nim-lang/Nim/issues/11727))
|
||||
- Fixed "orderedTable.del() crashes with unitialized table"
|
||||
([#12798](https://github.com/nim-lang/Nim/issues/12798))
|
||||
- Fixed "semfold bug with negative value * 0"
|
||||
([#12783](https://github.com/nim-lang/Nim/issues/12783))
|
||||
- Fixed "nimsuggest `use` command does not return all instances of symbol"
|
||||
([#12832](https://github.com/nim-lang/Nim/issues/12832))
|
||||
- Fixed "Codegen ICE in allPathsAsgnResult"
|
||||
([#12827](https://github.com/nim-lang/Nim/issues/12827))
|
||||
- Fixed "Static[T] + syntactic error in the for loop = compiler crash"
|
||||
([#12148](https://github.com/nim-lang/Nim/issues/12148))
|
||||
- Fixed "Incorrect unused import warning involving templates and tables"
|
||||
([#12885](https://github.com/nim-lang/Nim/issues/12885))
|
||||
- Fixed "regression(1.0.4): undeclared identifier: 'readLines'; plus another regression and bug"
|
||||
([#13013](https://github.com/nim-lang/Nim/issues/13013))
|
||||
- Fixed "`nim doc` treats `export localSymbol` incorrectly"
|
||||
([#13100](https://github.com/nim-lang/Nim/issues/13100))
|
||||
- Fixed "symbols not defined in the grammar"
|
||||
([#10665](https://github.com/nim-lang/Nim/issues/10665))
|
||||
- Fixed "nim-gdb is missing from all released packages"
|
||||
([#13104](https://github.com/nim-lang/Nim/issues/13104))
|
||||
- Fixed "[JS] Move is not defined"
|
||||
([#9674](https://github.com/nim-lang/Nim/issues/9674))
|
||||
- Fixed "Error: usage of 'isNil' is a user-defined error"
|
||||
([#11440](https://github.com/nim-lang/Nim/issues/11440))
|
||||
|
||||
|
||||
### Other bugfixes
|
||||
|
||||
- make addQuoted work on nimscript (#12717)
|
||||
- fix db_mysql getRow() when column is null error raised (#12806)
|
||||
- Fixed objects being erroneously zeroed out before object construction (#12814)
|
||||
- added cstrutils (#12858): fixed for 'csuCmpIgnoreStyle' error on hotcodereloading
|
||||
- Better clang_cl support (#12896)
|
||||
- fix cmdline bugs affecting nimBetterRun correctness (#12933)
|
||||
- fixes a bug that kept sugar.collect from working with for loop macros
|
||||
- Path substitution for --out and --outdir (#12796)
|
||||
- fix crash due to errant symbols in nim.cfg (#13073)
|
||||
- Allow `-o` option for `buildIndex` (#13037)
|
||||
- Deleted misplaced separator (#13085): Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.
|
||||
- fixes an asyncftpclient bug; refs #13096
|
||||
- fix the ftp store function read the local file bug (#13108)
|
||||
- fix rtti sizeof for varargs in global scope (#13125)
|
||||
- Correctly remove a key from CountTable when it is set to zero.
|
||||
- fixes the distros.nim regression
|
||||
- fixes a critical times.nim bug reported on IRC
|
||||
- c_fflush() the rawWrite() buffer
|
||||
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
- Fixed "Documentation, Testament missing from "Tools available with Nim""
|
||||
([#12251](https://github.com/nim-lang/Nim/issues/12251))
|
||||
- Manual update: custom exceptions (#12847)
|
||||
- times/getClockStr(): fix mistake in doc
|
||||
- Fix typo and improve in code-block of 'lib/pure/parseutils.nim'
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
## Library additions
|
||||
|
||||
- `set[T].len` is now an alias for `set[T].card` (cardinality)
|
||||
|
||||
## Library changes
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
|
||||
result = arNo
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result = isPartOfAux(n.sons[i], b, marker)
|
||||
if result == arYes: return
|
||||
of nkRecCase:
|
||||
assert(n.sons[0].kind == nkSym)
|
||||
result = isPartOfAux(n.sons[0], b, marker)
|
||||
if result == arYes: return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
|
||||
@@ -52,7 +52,7 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
|
||||
of tyGenericInst, tyDistinct, tyAlias, tySink:
|
||||
result = isPartOfAux(lastSon(a), b, marker)
|
||||
of tyArray, tySet, tyTuple:
|
||||
for i in 0 ..< sonsLen(a):
|
||||
for i in 0 ..< len(a):
|
||||
result = isPartOfAux(a.sons[i], b, marker)
|
||||
if result == arYes: return
|
||||
else: discard
|
||||
@@ -193,4 +193,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
|
||||
if res != arNo:
|
||||
result = res
|
||||
if res == arYes: break
|
||||
of nkBracket:
|
||||
if b.len > 0:
|
||||
result = isPartOf(a, b[0])
|
||||
else: discard
|
||||
|
||||
@@ -71,7 +71,7 @@ iterator parseTableCells*(s: string, delim = '\t'): Cell =
|
||||
proc alignTable*(s: string, delim = '\t', fill = ' ', sep = " "): string =
|
||||
## formats a `delim`-delimited `s` representing a table; each cell is aligned
|
||||
## to a width that's computed for each column; consecutive columns are
|
||||
## delimted by `sep`, and alignment space is filled using `fill`.
|
||||
## delimited by `sep`, and alignment space is filled using `fill`.
|
||||
## More customized formatting can be done by calling `parseTableCells` directly.
|
||||
for cell in parseTableCells(s, delim):
|
||||
result.add cell.text
|
||||
|
||||
157
compiler/ast.nim
157
compiler/ast.nim
@@ -10,7 +10,9 @@
|
||||
# abstract syntax tree + symbol table
|
||||
|
||||
import
|
||||
lineinfos, hashes, options, ropes, idents, idgen
|
||||
lineinfos, hashes, options, ropes, idents, idgen, int128
|
||||
|
||||
export int128
|
||||
|
||||
type
|
||||
TCallingConvention* = enum
|
||||
@@ -183,7 +185,7 @@ type
|
||||
nkStmtListExpr, # a statement list followed by an expr; this is used
|
||||
# to allow powerful multi-line templates
|
||||
nkBlockExpr, # a statement block ending in an expr; this is used
|
||||
# to allowe powerful multi-line templates that open a
|
||||
# to allow powerful multi-line templates that open a
|
||||
# temporary scope
|
||||
nkStmtListType, # a statement list ending in a type; for macros
|
||||
nkBlockType, # a statement block ending in a type; for macros
|
||||
@@ -226,7 +228,7 @@ type
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
TSymFlag* = enum # already 36 flags!
|
||||
TSymFlag* = enum # already 38 flags!
|
||||
sfUsed, # read access of sym (for warnings) or simply used
|
||||
sfExported, # symbol is exported from module
|
||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||
@@ -237,6 +239,7 @@ type
|
||||
sfForward, # symbol is forward declared
|
||||
sfImportc, # symbol is external; imported
|
||||
sfExportc, # symbol is exported (under a specified name)
|
||||
sfMangleCpp, # mangle as cpp (combines with `sfExportc`)
|
||||
sfVolatile, # variable is volatile
|
||||
sfRegister, # variable should be placed in a register
|
||||
sfPure, # object is "pure" that means it has no type-information
|
||||
@@ -269,7 +272,7 @@ type
|
||||
sfNamedParamCall, # symbol needs named parameter call syntax in target
|
||||
# language; for interfacing with Objective C
|
||||
sfDiscardable, # returned value may be discarded implicitly
|
||||
sfOverriden, # proc is overriden
|
||||
sfOverriden, # proc is overridden
|
||||
sfCallsite # A flag for template symbols to tell the
|
||||
# compiler it should use line information from
|
||||
# the calling side of the macro, not from the
|
||||
@@ -280,6 +283,7 @@ type
|
||||
sfGeneratedOp # proc is a generated '='; do not inject destructors in it
|
||||
# variable is generated closure environment; requires early
|
||||
# destruction for --newruntime.
|
||||
sfTemplateParam # symbol is a template parameter
|
||||
|
||||
|
||||
TSymFlags* = set[TSymFlag]
|
||||
@@ -287,10 +291,6 @@ type
|
||||
const
|
||||
sfNoInit* = sfMainModule # don't generate code to init the variable
|
||||
|
||||
sfCursor* = sfDispatcher
|
||||
# local variable has been computed to be a "cursor".
|
||||
# see cursors.nim for details about what that means.
|
||||
|
||||
sfAllUntyped* = sfVolatile # macro or template is immediately expanded \
|
||||
# in a generic context
|
||||
|
||||
@@ -531,11 +531,12 @@ type
|
||||
tfTriggersCompileTime # uses the NimNode type which make the proc
|
||||
# implicitly '.compiletime'
|
||||
tfRefsAnonObj # used for 'ref object' and 'ptr object'
|
||||
tfCovariant # covariant generic param mimicing a ptr type
|
||||
tfWeakCovariant # covariant generic param mimicing a seq/array type
|
||||
tfCovariant # covariant generic param mimicking a ptr type
|
||||
tfWeakCovariant # covariant generic param mimicking a seq/array type
|
||||
tfContravariant # contravariant generic param
|
||||
tfCheckedForDestructor # type was checked for having a destructor.
|
||||
# If it has one, t.destructor is not nil.
|
||||
tfIncompleteStruct # treat this type as if it had sizeof(pointer)
|
||||
|
||||
TTypeFlags* = set[TTypeFlag]
|
||||
|
||||
@@ -577,7 +578,6 @@ type
|
||||
const
|
||||
routineKinds* = {skProc, skFunc, skMethod, skIterator,
|
||||
skConverter, skMacro, skTemplate}
|
||||
tfIncompleteStruct* = tfVarargs
|
||||
tfUnion* = tfNoSideEffect
|
||||
tfGcSafe* = tfThread
|
||||
tfObjHasKids* = tfEnumHasHoles
|
||||
@@ -606,7 +606,6 @@ type
|
||||
mAddF64, mSubF64, mMulF64, mDivF64,
|
||||
mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI,
|
||||
mMinI, mMaxI,
|
||||
mMinF64, mMaxF64,
|
||||
mAddU, mSubU, mMulU, mDivU, mModU,
|
||||
mEqI, mLeI, mLtI,
|
||||
mEqF64, mLeF64, mLtF64,
|
||||
@@ -619,9 +618,7 @@ type
|
||||
mXor, mEqCString, mEqProc,
|
||||
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
|
||||
mUnaryPlusI, mBitnotI,
|
||||
mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
|
||||
mToFloat, mToBiggestFloat,
|
||||
mToInt, mToBiggestInt,
|
||||
mUnaryPlusF64, mUnaryMinusF64,
|
||||
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
|
||||
mStrToStr, mEnumToStr,
|
||||
mAnd, mOr,
|
||||
@@ -665,7 +662,8 @@ type
|
||||
mInstantiationInfo, mGetTypeInfo,
|
||||
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
|
||||
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
|
||||
mSymIsInstantiationOf
|
||||
mSymIsInstantiationOf, mNodeId
|
||||
|
||||
|
||||
# things that we can evaluate safely at compile time, even if not asked for it:
|
||||
const
|
||||
@@ -678,7 +676,6 @@ const
|
||||
mAddF64, mSubF64, mMulF64, mDivF64,
|
||||
mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
|
||||
mMinI, mMaxI,
|
||||
mMinF64, mMaxF64,
|
||||
mAddU, mSubU, mMulU, mDivU, mModU,
|
||||
mEqI, mLeI, mLtI,
|
||||
mEqF64, mLeF64, mLtF64,
|
||||
@@ -689,9 +686,7 @@ const
|
||||
mEqB, mLeB, mLtB,
|
||||
mEqRef, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
|
||||
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
|
||||
mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
|
||||
mToFloat, mToBiggestFloat,
|
||||
mToInt, mToBiggestInt,
|
||||
mUnaryPlusF64, mUnaryMinusF64,
|
||||
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
|
||||
mStrToStr, mEnumToStr,
|
||||
mAnd, mOr,
|
||||
@@ -854,7 +849,6 @@ type
|
||||
# for modules, an unique index corresponding
|
||||
# to the module's fileIdx
|
||||
# for variables a slot index for the evaluator
|
||||
# for routines a superop-ID
|
||||
offset*: int # offset of record field
|
||||
loc*: TLoc
|
||||
annex*: PLib # additional fields (seldom used, so we use a
|
||||
@@ -901,6 +895,7 @@ type
|
||||
size*: BiggestInt # the size of the type in bytes
|
||||
# -1 means that the size is unkwown
|
||||
align*: int16 # the type's alignment requirements
|
||||
paddingAtEnd*: int16 #
|
||||
lockLevel*: TLockLevel # lock level as required for deadlock checking
|
||||
loc*: TLoc
|
||||
typeInst*: PType # for generic instantiations the tyGenericInst that led to this
|
||||
@@ -1024,7 +1019,9 @@ proc isCallExpr*(n: PNode): bool =
|
||||
|
||||
proc discardSons*(father: PNode)
|
||||
|
||||
proc len*(n: PNode): int {.inline.} =
|
||||
type Indexable = PNode | PType
|
||||
|
||||
proc len*(n: Indexable): int {.inline.} =
|
||||
when defined(nimNoNilSeqs):
|
||||
result = len(n.sons)
|
||||
else:
|
||||
@@ -1048,8 +1045,6 @@ proc add*(father, son: PNode) =
|
||||
if isNil(father.sons): father.sons = @[]
|
||||
add(father.sons, son)
|
||||
|
||||
type Indexable = PNode | PType
|
||||
|
||||
template `[]`*(n: Indexable, i: int): Indexable = n.sons[i]
|
||||
template `[]=`*(n: Indexable, i: int; x: Indexable) = n.sons[i] = x
|
||||
|
||||
@@ -1057,7 +1052,7 @@ template `[]`*(n: Indexable, i: BackwardsIndex): Indexable = n[n.len - i.int]
|
||||
template `[]=`*(n: Indexable, i: BackwardsIndex; x: Indexable) = n[n.len - i.int] = x
|
||||
|
||||
when defined(useNodeIds):
|
||||
const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879
|
||||
const nodeIdToDebug* = -1 # 2322968
|
||||
var gNodeId: int
|
||||
|
||||
proc newNode*(kind: TNodeKind): PNode =
|
||||
@@ -1235,10 +1230,48 @@ proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
|
||||
result = newNode(kind)
|
||||
result.intVal = intVal
|
||||
|
||||
proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode =
|
||||
result = newIntNode(kind, intVal)
|
||||
proc newIntNode*(kind: TNodeKind, intVal: Int128): PNode =
|
||||
result = newNode(kind)
|
||||
result.intVal = castToInt64(intVal)
|
||||
|
||||
proc lastSon*(n: Indexable): Indexable = n.sons[^1]
|
||||
|
||||
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
|
||||
## Used throughout the compiler code to test whether a type tree contains or
|
||||
## doesn't contain a specific type/types - it is often the case that only the
|
||||
## last child nodes of a type tree need to be searched. This is a really hot
|
||||
## path within the compiler!
|
||||
result = t
|
||||
while result.kind in kinds: result = lastSon(result)
|
||||
|
||||
proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
|
||||
|
||||
# this is dirty. abstractVarRange isn't defined yet and therefore it
|
||||
# is duplicated here.
|
||||
const abstractVarRange = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
||||
tyTypeDesc, tyAlias, tyInferred, tySink, tyOwned}
|
||||
case skipTypes(typ, abstractVarRange).kind
|
||||
of tyInt: result = newNode(nkIntLit)
|
||||
of tyInt8: result = newNode(nkInt8Lit)
|
||||
of tyInt16: result = newNode(nkInt16Lit)
|
||||
of tyInt32: result = newNode(nkInt32Lit)
|
||||
of tyInt64: result = newNode(nkInt64Lit)
|
||||
of tyChar: result = newNode(nkCharLit)
|
||||
of tyUInt: result = newNode(nkUIntLit)
|
||||
of tyUInt8: result = newNode(nkUInt8Lit)
|
||||
of tyUInt16: result = newNode(nkUInt16Lit)
|
||||
of tyUInt32: result = newNode(nkUInt32Lit)
|
||||
of tyUInt64: result = newNode(nkUInt64Lit)
|
||||
else: # tyBool, tyEnum
|
||||
# XXX: does this really need to be the kind nkIntLit?
|
||||
result = newNode(nkIntLit)
|
||||
result.intVal = intVal
|
||||
result.typ = typ
|
||||
|
||||
proc newIntTypeNode*(intVal: Int128, typ: PType): PNode =
|
||||
# XXX: introduce range check
|
||||
newIntTypeNode(castToInt64(intVal), typ)
|
||||
|
||||
proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
|
||||
result = newNode(kind)
|
||||
result.floatVal = floatVal
|
||||
@@ -1305,7 +1338,7 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
|
||||
if a.lode == nil: a.lode = b.lode
|
||||
if a.r == nil: a.r = b.r
|
||||
|
||||
proc newSons*(father: PNode, length: int) =
|
||||
proc newSons*(father: Indexable, length: int) =
|
||||
when defined(nimNoNilSeqs):
|
||||
setLen(father.sons, length)
|
||||
else:
|
||||
@@ -1314,21 +1347,6 @@ proc newSons*(father: PNode, length: int) =
|
||||
else:
|
||||
setLen(father.sons, length)
|
||||
|
||||
proc newSons*(father: PType, length: int) =
|
||||
when defined(nimNoNilSeqs):
|
||||
setLen(father.sons, length)
|
||||
else:
|
||||
if isNil(father.sons):
|
||||
newSeq(father.sons, length)
|
||||
else:
|
||||
setLen(father.sons, length)
|
||||
|
||||
proc sonsLen*(n: PType): int = n.sons.len
|
||||
proc len*(n: PType): int = n.sons.len
|
||||
proc sonsLen*(n: PNode): int = n.sons.len
|
||||
proc lastSon*(n: PNode): PNode = n.sons[^1]
|
||||
proc lastSon*(n: PType): PType = n.sons[^1]
|
||||
|
||||
proc assignType*(dest, src: PType) =
|
||||
dest.kind = src.kind
|
||||
dest.flags = src.flags
|
||||
@@ -1346,8 +1364,8 @@ proc assignType*(dest, src: PType) =
|
||||
mergeLoc(dest.sym.loc, src.sym.loc)
|
||||
else:
|
||||
dest.sym = src.sym
|
||||
newSons(dest, sonsLen(src))
|
||||
for i in 0 ..< sonsLen(src): dest.sons[i] = src.sons[i]
|
||||
newSons(dest, len(src))
|
||||
for i in 0 ..< len(src): dest.sons[i] = src.sons[i]
|
||||
|
||||
proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
|
||||
result = newType(t.kind, owner)
|
||||
@@ -1423,14 +1441,6 @@ proc initNodeTable*(x: var TNodeTable) =
|
||||
x.counter = 0
|
||||
newSeq(x.data, StartSize)
|
||||
|
||||
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
|
||||
## Used throughout the compiler code to test whether a type tree contains or
|
||||
## doesn't contain a specific type/types - it is often the case that only the
|
||||
## last child nodes of a type tree need to be searched. This is a really hot
|
||||
## path within the compiler!
|
||||
result = t
|
||||
while result.kind in kinds: result = lastSon(result)
|
||||
|
||||
proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =
|
||||
result = t
|
||||
var i = maxIters
|
||||
@@ -1469,14 +1479,14 @@ proc propagateToOwner*(owner, elem: PType) =
|
||||
if tfHasAsgn in elem.flags:
|
||||
let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
if o2.kind in {tyTuple, tyObject, tyArray,
|
||||
tySequence, tyOpt, tySet, tyDistinct}:
|
||||
tySequence, tyOpt, tySet, tyDistinct, tyOpenArray, tyVarargs}:
|
||||
o2.flags.incl tfHasAsgn
|
||||
owner.flags.incl tfHasAsgn
|
||||
|
||||
if tfHasOwned in elem.flags:
|
||||
let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
if o2.kind in {tyTuple, tyObject, tyArray,
|
||||
tySequence, tyOpt, tySet, tyDistinct}:
|
||||
tySequence, tyOpt, tySet, tyDistinct, tyOpenArray, tyVarargs}:
|
||||
o2.flags.incl tfHasOwned
|
||||
owner.flags.incl tfHasOwned
|
||||
|
||||
@@ -1509,7 +1519,7 @@ proc delSon*(father: PNode, idx: int) =
|
||||
if father.len == 0: return
|
||||
else:
|
||||
if isNil(father.sons): return
|
||||
var length = sonsLen(father)
|
||||
var length = len(father)
|
||||
for i in idx .. length - 2: father.sons[i] = father.sons[i + 1]
|
||||
setLen(father.sons, length - 1)
|
||||
|
||||
@@ -1550,7 +1560,7 @@ proc shallowCopy*(src: PNode): PNode =
|
||||
of nkSym: result.sym = src.sym
|
||||
of nkIdent: result.ident = src.ident
|
||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||
else: newSeq(result.sons, sonsLen(src))
|
||||
else: newSeq(result.sons, len(src))
|
||||
|
||||
proc copyTree*(src: PNode): PNode =
|
||||
# copy a whole syntax tree; performs deep copying
|
||||
@@ -1571,12 +1581,12 @@ proc copyTree*(src: PNode): PNode =
|
||||
of nkIdent: result.ident = src.ident
|
||||
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
|
||||
else:
|
||||
newSeq(result.sons, sonsLen(src))
|
||||
for i in 0 ..< sonsLen(src):
|
||||
newSeq(result.sons, len(src))
|
||||
for i in 0 ..< len(src):
|
||||
result.sons[i] = copyTree(src.sons[i])
|
||||
|
||||
proc hasSonWith*(n: PNode, kind: TNodeKind): bool =
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if n.sons[i].kind == kind:
|
||||
return true
|
||||
result = false
|
||||
@@ -1594,30 +1604,43 @@ proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
|
||||
case n.kind
|
||||
of nkEmpty..nkNilLit: result = n.kind in kinds
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if n.kind in kinds or containsNode(n.sons[i], kinds): return true
|
||||
|
||||
proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
|
||||
case n.kind
|
||||
of nkEmpty..nkNilLit: result = n.kind == kind
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
|
||||
return true
|
||||
result = false
|
||||
|
||||
proc getInt*(a: PNode): BiggestInt =
|
||||
proc getInt*(a: PNode): Int128 =
|
||||
case a.kind
|
||||
of nkCharLit..nkUInt64Lit: result = a.intVal
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit:
|
||||
result = toInt128(cast[uint64](a.intVal))
|
||||
of nkInt8Lit..nkInt64Lit:
|
||||
result = toInt128(a.intVal)
|
||||
of nkIntLit:
|
||||
# XXX: enable this assert
|
||||
# assert a.typ.kind notin {tyChar, tyUint..tyUInt64}
|
||||
result = toInt128(a.intVal)
|
||||
else:
|
||||
raiseRecoverableError("cannot extract number from invalid AST node")
|
||||
|
||||
proc getInt64*(a: PNode): int64 {.deprecated: "use getInt".} =
|
||||
case a.kind
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
|
||||
result = a.intVal
|
||||
else:
|
||||
raiseRecoverableError("cannot extract number from invalid AST node")
|
||||
#internalError(a.info, "getInt")
|
||||
#doAssert false, "getInt"
|
||||
#result = 0
|
||||
|
||||
proc getFloat*(a: PNode): BiggestFloat =
|
||||
case a.kind
|
||||
of nkFloatLiterals: result = a.floatVal
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
|
||||
result = BiggestFloat a.intVal
|
||||
else:
|
||||
raiseRecoverableError("cannot extract number from invalid AST node")
|
||||
#doAssert false, "getFloat"
|
||||
|
||||
@@ -31,6 +31,15 @@ when declared(echo):
|
||||
proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.}
|
||||
proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.}
|
||||
|
||||
proc typekinds*(t: PType) {.deprecated.} =
|
||||
var t = t
|
||||
var s = ""
|
||||
while t != nil and t.len > 0:
|
||||
s.add $t.kind
|
||||
s.add " "
|
||||
t = t.lastSon
|
||||
echo s
|
||||
|
||||
template debug*(x: PSym|PType|PNode) {.deprecated.} =
|
||||
when compiles(c.config):
|
||||
debug(c.config, x)
|
||||
@@ -77,7 +86,6 @@ proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym
|
||||
proc lookupInRecord*(n: PNode, field: PIdent): PSym
|
||||
proc mustRehash*(length, counter: int): bool
|
||||
proc nextTry*(h, maxHash: Hash): Hash {.inline.}
|
||||
@@ -117,7 +125,7 @@ proc sameValue*(a, b: PNode): bool =
|
||||
result = false
|
||||
case a.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if b.kind in {nkCharLit..nkUInt64Lit}: result = a.intVal == b.intVal
|
||||
if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) == getInt(b)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -131,8 +139,8 @@ proc leValue*(a, b: PNode): bool =
|
||||
# a <= b?
|
||||
result = false
|
||||
case a.kind
|
||||
of nkCharLit..nkUInt32Lit:
|
||||
if b.kind in {nkCharLit..nkUInt32Lit}: result = a.intVal <= b.intVal
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) <= getInt(b)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -152,14 +160,14 @@ proc lookupInRecord(n: PNode, field: PIdent): PSym =
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result = lookupInRecord(n.sons[i], field)
|
||||
if result != nil: return
|
||||
of nkRecCase:
|
||||
if (n.sons[0].kind != nkSym): return nil
|
||||
result = lookupInRecord(n.sons[0], field)
|
||||
if result != nil: return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
result = lookupInRecord(lastSon(n.sons[i]), field)
|
||||
@@ -174,14 +182,54 @@ proc getModule*(s: PSym): PSym =
|
||||
assert((result.kind == skModule) or (result.owner != result))
|
||||
while result != nil and result.kind != skModule: result = result.owner
|
||||
|
||||
proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym =
|
||||
for i in start ..< sonsLen(list):
|
||||
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym =
|
||||
for i in start ..< len(list):
|
||||
if list.sons[i].kind == nkSym:
|
||||
result = list.sons[i].sym
|
||||
if result.name.id == ident.id: return
|
||||
else: return nil
|
||||
result = nil
|
||||
|
||||
proc sameIgnoreBacktickGensymInfo(a, b: string): bool =
|
||||
if a[0] != b[0]: return false
|
||||
var alen = a.len - 1
|
||||
while alen > 0 and a[alen] != '`': dec(alen)
|
||||
if alen <= 0: alen = a.len
|
||||
|
||||
var i = 1
|
||||
var j = 1
|
||||
while true:
|
||||
while i < alen and a[i] == '_': inc i
|
||||
while j < b.len and b[j] == '_': inc j
|
||||
var aa = if i < alen: toLowerAscii(a[i]) else: '\0'
|
||||
var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
|
||||
if aa != bb: return false
|
||||
|
||||
# the characters are identical:
|
||||
if i >= alen:
|
||||
# both cursors at the end:
|
||||
if j >= b.len: return true
|
||||
# not yet at the end of 'b':
|
||||
return false
|
||||
elif j >= b.len:
|
||||
return false
|
||||
inc i
|
||||
inc j
|
||||
|
||||
proc getNamedParamFromList*(list: PNode, ident: PIdent): PSym =
|
||||
## Named parameters are special because a named parameter can be
|
||||
## gensym'ed and then they have '`<number>' suffix that we need to
|
||||
## ignore, see compiler / evaltempl.nim, snippet:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
|
||||
## if c.instLines: actual.info else: templ.info)
|
||||
for i in 1 ..< len(list):
|
||||
let it = list[i].sym
|
||||
if it.name.id == ident.id or
|
||||
sameIgnoreBacktickGensymInfo(it.name.s, ident.s): return it
|
||||
|
||||
proc hashNode(p: RootRef): Hash =
|
||||
result = hash(cast[pointer](p))
|
||||
|
||||
@@ -279,9 +327,9 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
|
||||
sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope(
|
||||
strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
|
||||
else:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
sonsRope = rope("[")
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if i > 0: add(sonsRope, ",")
|
||||
addf(sonsRope, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n.sons[i],
|
||||
marker, indent + 4, maxRecDepth - 1)])
|
||||
@@ -328,9 +376,9 @@ proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
|
||||
else:
|
||||
addf(result, ",$N$1\"ident\": null", [istr])
|
||||
else:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
addf(result, ",$N$1\"sons\": [", [istr])
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if i > 0: add(result, ",")
|
||||
addf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n.sons[i],
|
||||
marker, indent + 4, maxRecDepth - 1)])
|
||||
@@ -515,12 +563,12 @@ proc value(this: var DebugPrinter; value: PType) =
|
||||
this.key "n"
|
||||
this.value value.n
|
||||
|
||||
if sonsLen(value) > 0:
|
||||
if len(value) > 0:
|
||||
this.key "sons"
|
||||
this.openBracket
|
||||
for i in 0 ..< sonsLen(value):
|
||||
for i in 0 ..< len(value):
|
||||
this.value value.sons[i]
|
||||
if i != sonsLen(value) - 1:
|
||||
if i != len(value) - 1:
|
||||
this.comma
|
||||
this.closeBracket
|
||||
|
||||
@@ -568,12 +616,12 @@ proc value(this: var DebugPrinter; value: PNode) =
|
||||
if this.renderSymType and value.typ != nil:
|
||||
this.key "typ"
|
||||
this.value value.typ
|
||||
if sonsLen(value) > 0:
|
||||
if len(value) > 0:
|
||||
this.key "sons"
|
||||
this.openBracket
|
||||
for i in 0 ..< sonsLen(value):
|
||||
for i in 0 ..< len(value):
|
||||
this.value value.sons[i]
|
||||
if i != sonsLen(value) - 1:
|
||||
if i != len(value) - 1:
|
||||
this.comma
|
||||
this.closeBracket
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ proc hashType(c: var MD5Context, t: PType) =
|
||||
|
||||
case t.kind
|
||||
of tyGenericBody, tyGenericInst, tyGenericInvocation:
|
||||
for i in 0 ..< sonsLen(t)-ord(t.kind != tyGenericInvocation):
|
||||
for i in 0 ..< len(t)-ord(t.kind != tyGenericInvocation):
|
||||
c.hashType t.sons[i]
|
||||
of tyUserTypeClass:
|
||||
internalAssert t.sym != nil and t.sym.owner != nil
|
||||
@@ -128,7 +128,7 @@ proc hashType(c: var MD5Context, t: PType) =
|
||||
of tyUserTypeClassInst:
|
||||
let body = t.base
|
||||
c.hashSym body.sym
|
||||
for i in 1 .. sonsLen(t) - 2:
|
||||
for i in 1 .. len(t) - 2:
|
||||
c.hashType t.sons[i]
|
||||
of tyFromExpr:
|
||||
c.hashTree(t.n)
|
||||
@@ -137,15 +137,15 @@ proc hashType(c: var MD5Context, t: PType) =
|
||||
c.hashType(t.sons[1])
|
||||
of tyTuple:
|
||||
if t.n != nil:
|
||||
assert(sonsLen(t.n) == sonsLen(t))
|
||||
for i in 0 ..< sonsLen(t.n):
|
||||
assert(len(t.n) == len(t))
|
||||
for i in 0 ..< len(t.n):
|
||||
assert(t.n.sons[i].kind == nkSym)
|
||||
c &= t.n.sons[i].sym.name.s
|
||||
c &= ":"
|
||||
c.hashType(t.sons[i])
|
||||
c &= ","
|
||||
else:
|
||||
for i in 0 ..< sonsLen(t): c.hashType t.sons[i]
|
||||
for i in 0 ..< len(t): c.hashType t.sons[i]
|
||||
of tyRange:
|
||||
c.hashTree(t.n)
|
||||
c.hashType(t.sons[0])
|
||||
@@ -238,7 +238,7 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
|
||||
encodeVInt(n.sym.id, result)
|
||||
pushSym(w, n.sym)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
encodeNode(w, n.info, n.sons[i], result)
|
||||
add(result, ')')
|
||||
|
||||
@@ -304,7 +304,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
||||
add(result, '=')
|
||||
encodeVInt(t.align, result)
|
||||
encodeLoc(w, t.loc, result)
|
||||
for i in 0 ..< sonsLen(t):
|
||||
for i in 0 ..< len(t):
|
||||
if t.sons[i] == nil:
|
||||
add(result, "^()")
|
||||
else:
|
||||
|
||||
@@ -79,9 +79,19 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
|
||||
proc openArrayLoc(p: BProc, n: PNode): Rope =
|
||||
var a: TLoc
|
||||
|
||||
let q = skipConv(n)
|
||||
var q = skipConv(n)
|
||||
var skipped = false
|
||||
while q.kind == nkStmtListExpr and q.len > 0:
|
||||
skipped = true
|
||||
q = q.lastSon
|
||||
if getMagic(q) == mSlice:
|
||||
# magic: pass slice to openArray:
|
||||
if skipped:
|
||||
q = skipConv(n)
|
||||
while q.kind == nkStmtListExpr and q.len > 0:
|
||||
for i in 0..q.len-2:
|
||||
genStmts(p, q[i])
|
||||
q = q.lastSon
|
||||
var b, c: TLoc
|
||||
initLocExpr(p, q[1], a)
|
||||
initLocExpr(p, q[2], b)
|
||||
@@ -90,21 +100,23 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
|
||||
if optBoundsCheck in p.options:
|
||||
genBoundsCheck(p, a, b, c)
|
||||
let ty = skipTypes(a.t, abstractVar+{tyPtr})
|
||||
let dest = getTypeDesc(p.module, n.typ.sons[0])
|
||||
case ty.kind
|
||||
of tyArray:
|
||||
let first = firstOrd(p.config, ty)
|
||||
let first = toInt64(firstOrd(p.config, ty))
|
||||
if first == 0:
|
||||
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
|
||||
result = "($4*)(($1)+($2)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
|
||||
else:
|
||||
result = "($1)+(($2)-($4)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first)]
|
||||
of tyOpenArray, tyVarargs, tyUncheckedArray:
|
||||
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
|
||||
result = "($5*)($1)+(($2)-($4)), ($3)-($2)+1" %
|
||||
[rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first), dest]
|
||||
of tyOpenArray, tyVarargs, tyUncheckedArray, tyCString:
|
||||
result = "($4*)($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
|
||||
of tyString, tySequence:
|
||||
if skipTypes(n.typ, abstractInst).kind == tyVar and
|
||||
not compileToCpp(p.module):
|
||||
result = "(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p)]
|
||||
result = "($5*)(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
|
||||
else:
|
||||
result = "$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p)]
|
||||
result = "($5*)$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
|
||||
else:
|
||||
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
||||
else:
|
||||
@@ -174,7 +186,7 @@ proc genArgNoParam(p: BProc, n: PNode): Rope =
|
||||
result = rdLoc(a)
|
||||
|
||||
template genParamLoop(params) {.dirty.} =
|
||||
if i < sonsLen(typ):
|
||||
if i < len(typ):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
let paramType = typ.n.sons[i]
|
||||
if not paramType.typ.isCompileTimeOnly:
|
||||
@@ -184,8 +196,8 @@ template genParamLoop(params) {.dirty.} =
|
||||
if params != nil: add(params, ~", ")
|
||||
add(params, genArgNoParam(p, ri.sons[i]))
|
||||
|
||||
proc addActualPrefixForHCR(res: var Rope, module: PSym, sym: PSym) =
|
||||
if sym.flags * {sfImportc, sfNonReloadable} == {} and
|
||||
proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
|
||||
if sym.flags * {sfImportc, sfNonReloadable} == {} and sym.loc.k == locProc and
|
||||
(sym.typ.callConv == ccInline or sym.owner.id == module.id):
|
||||
res = res & "_actual".rope
|
||||
|
||||
@@ -197,13 +209,13 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri.sons[0].typ, abstractInstOwned)
|
||||
assert(typ.kind == tyProc)
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
var length = sonsLen(ri)
|
||||
assert(len(typ) == len(typ.n))
|
||||
var length = len(ri)
|
||||
for i in 1 ..< length:
|
||||
genParamLoop(params)
|
||||
var callee = rdLoc(op)
|
||||
if p.hcrOn and ri.sons[0].kind == nkSym:
|
||||
callee.addActualPrefixForHCR(p.module.module, ri.sons[0].sym)
|
||||
callee.addActualSuffixForHCR(p.module.module, ri.sons[0].sym)
|
||||
fixupCall(p, le, ri, d, callee, params)
|
||||
|
||||
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
@@ -222,9 +234,9 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
|
||||
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
var length = sonsLen(ri)
|
||||
var length = len(ri)
|
||||
for i in 1 ..< length:
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
assert(len(typ) == len(typ.n))
|
||||
genParamLoop(pl)
|
||||
|
||||
template genCallPattern {.dirty.} =
|
||||
@@ -236,7 +248,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
let rawProc = getRawProcType(p, typ)
|
||||
if typ.sons[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ.sons[0]):
|
||||
if sonsLen(ri) > 1: add(pl, ~", ")
|
||||
if len(ri) > 1: add(pl, ~", ")
|
||||
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
||||
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
|
||||
# Great, we can use 'd':
|
||||
@@ -268,7 +280,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
genCallPattern()
|
||||
|
||||
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
|
||||
if i < sonsLen(typ):
|
||||
if i < len(typ):
|
||||
# 'var T' is 'T&' in C++. This means we ignore the request of
|
||||
# any nkHiddenAddr when it's a 'var T'.
|
||||
let paramType = typ.n.sons[i]
|
||||
@@ -345,7 +357,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
|
||||
# for better or worse c2nim translates the 'this' argument to a 'var T'.
|
||||
# However manual wrappers may also use 'ptr T'. In any case we support both
|
||||
# for convenience.
|
||||
internalAssert p.config, i < sonsLen(typ)
|
||||
internalAssert p.config, i < len(typ)
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
# if the parameter is lying (tyVar) and thus we required an additional deref,
|
||||
# skip the deref:
|
||||
@@ -382,11 +394,14 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
|
||||
while i < pat.len:
|
||||
case pat[i]
|
||||
of '@':
|
||||
if j < ri.len:
|
||||
result.add genOtherArg(p, ri, j, typ)
|
||||
for k in j+1 ..< ri.len:
|
||||
result.add(~", ")
|
||||
result.add genOtherArg(p, ri, k, typ)
|
||||
var first = true
|
||||
for k in j ..< ri.len:
|
||||
let arg = genOtherArg(p, ri, k, typ)
|
||||
if arg.len > 0:
|
||||
if not first:
|
||||
result.add(~", ")
|
||||
first = false
|
||||
result.add arg
|
||||
inc i
|
||||
of '#':
|
||||
if i+1 < pat.len and pat[i+1] in {'+', '@'}:
|
||||
@@ -436,8 +451,8 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
var length = sonsLen(ri)
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
var length = len(ri)
|
||||
assert(len(typ) == len(typ.n))
|
||||
# don't call '$' here for efficiency:
|
||||
let pat = ri.sons[0].sym.loc.r.data
|
||||
internalAssert p.config, pat.len > 0
|
||||
@@ -472,7 +487,7 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
var params: Rope
|
||||
for i in 2 ..< length:
|
||||
if params != nil: params.add(~", ")
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
assert(len(typ) == len(typ.n))
|
||||
add(params, genOtherArg(p, ri, i, typ))
|
||||
fixupCall(p, le, ri, d, pl, params)
|
||||
|
||||
@@ -484,8 +499,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
var length = sonsLen(ri)
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
var length = len(ri)
|
||||
assert(len(typ) == len(typ.n))
|
||||
|
||||
# don't call '$' here for efficiency:
|
||||
let pat = ri.sons[0].sym.loc.r.data
|
||||
@@ -507,8 +522,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
add(pl, ~": ")
|
||||
add(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
|
||||
for i in start ..< length:
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
if i >= sonsLen(typ):
|
||||
assert(len(typ) == len(typ.n))
|
||||
if i >= len(typ):
|
||||
internalError(p.config, ri.info, "varargs for objective C method?")
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
@@ -518,7 +533,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
add(pl, genArg(p, ri.sons[i], param, ri))
|
||||
if typ.sons[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ.sons[0]):
|
||||
if sonsLen(ri) > 1: add(pl, ~" ")
|
||||
if len(ri) > 1: add(pl, ~" ")
|
||||
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||
if d.k in {locTemp, locNone}:
|
||||
# We already got a temp. Great, special case it:
|
||||
|
||||
@@ -30,6 +30,9 @@ proc intLiteral(i: BiggestInt): Rope =
|
||||
else:
|
||||
result = ~"(IL64(-9223372036854775807) - IL64(1))"
|
||||
|
||||
proc intLiteral(i: Int128): Rope =
|
||||
intLiteral(toInt64(i))
|
||||
|
||||
proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||
case n.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
@@ -585,8 +588,6 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mBitxorI: applyFormat("($4)($1 ^ $2)")
|
||||
of mMinI: applyFormat("(($1 <= $2) ? $1 : $2)")
|
||||
of mMaxI: applyFormat("(($1 >= $2) ? $1 : $2)")
|
||||
of mMinF64: applyFormat("(($1 <= $2) ? $1 : $2)")
|
||||
of mMaxF64: applyFormat("(($1 >= $2) ? $1 : $2)")
|
||||
of mAddU: applyFormat("($4)((NU$3)($1) + (NU$3)($2))")
|
||||
of mSubU: applyFormat("($4)((NU$3)($1) - (NU$3)($2))")
|
||||
of mMulU: applyFormat("($4)((NU$3)($1) * (NU$3)($2))")
|
||||
@@ -660,17 +661,6 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
applyFormat("$1")
|
||||
of mUnaryMinusF64:
|
||||
applyFormat("-($1)")
|
||||
of mAbsF64:
|
||||
applyFormat("($1 < 0? -($1) : ($1))")
|
||||
# BUGFIX: fabs() makes problems for Tiny C
|
||||
of mToFloat:
|
||||
applyFormat("((double) ($1))")
|
||||
of mToBiggestFloat:
|
||||
applyFormat("((double) ($1))")
|
||||
of mToInt:
|
||||
applyFormat("float64ToInt32($1)")
|
||||
of mToBiggestInt:
|
||||
applyFormat("float64ToInt64($1)")
|
||||
else:
|
||||
assert false, $op
|
||||
|
||||
@@ -807,7 +797,7 @@ proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
||||
|
||||
proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
||||
var test, u, v: TLoc
|
||||
for i in 1 ..< sonsLen(e):
|
||||
for i in 1 ..< len(e):
|
||||
var it = e.sons[i]
|
||||
assert(it.kind in nkCallKinds)
|
||||
assert(it.sons[0].kind == nkSym)
|
||||
@@ -822,7 +812,8 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
||||
v.r.add(".")
|
||||
v.r.add(disc.sym.loc.r)
|
||||
genInExprAux(p, it, u, v, test)
|
||||
let strLit = genStringLiteral(p.module, newStrNode(nkStrLit, field.name.s))
|
||||
let msg = genFieldError(field, disc.sym)
|
||||
let strLit = genStringLiteral(p.module, newStrNode(nkStrLit, msg))
|
||||
if op.magic == mNot:
|
||||
linefmt(p, cpsStmts,
|
||||
"if ($1) #raiseFieldError($2);$n",
|
||||
@@ -1036,7 +1027,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
|
||||
dec p.splitDecls
|
||||
|
||||
proc genEcho(p: BProc, n: PNode) =
|
||||
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
||||
# this unusual way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
||||
# is threadsafe.
|
||||
internalAssert p.config, n.kind == nkBracket
|
||||
if p.config.target.targetOS == osGenode:
|
||||
@@ -1096,7 +1087,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
var L = 0
|
||||
var appends: Rope = nil
|
||||
var lens: Rope = nil
|
||||
for i in 0 .. sonsLen(e) - 2:
|
||||
for i in 0 .. len(e) - 2:
|
||||
# compute the length expression:
|
||||
initLocExpr(p, e.sons[i + 1], a)
|
||||
if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar:
|
||||
@@ -1135,7 +1126,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
assert(d.k == locNone)
|
||||
var L = 0
|
||||
initLocExpr(p, e.sons[1], dest)
|
||||
for i in 0 .. sonsLen(e) - 3:
|
||||
for i in 0 .. len(e) - 3:
|
||||
# compute the length expression:
|
||||
initLocExpr(p, e.sons[i + 2], a)
|
||||
if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar:
|
||||
@@ -1202,6 +1193,8 @@ proc genDefault(p: BProc; n: PNode; d: var TLoc) =
|
||||
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
|
||||
else: resetLoc(p, d)
|
||||
|
||||
proc trivialDestructor(s: PSym): bool {.inline.} = s.ast[bodyPos].len == 0
|
||||
|
||||
proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
||||
var sizeExpr = sizeExpr
|
||||
let typ = a.t
|
||||
@@ -1213,13 +1206,13 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
||||
if sizeExpr.isNil:
|
||||
sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)]
|
||||
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optOwnedRefs in p.config.globalOptions:
|
||||
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
|
||||
[getTypeDesc(p.module, typ), sizeExpr])
|
||||
genAssignment(p, a, b, {})
|
||||
else:
|
||||
let ti = genTypeInfo(p.module, typ, a.lode.info)
|
||||
if bt.destructor != nil:
|
||||
if bt.destructor != nil and not trivialDestructor(bt.destructor):
|
||||
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
|
||||
# finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
|
||||
# convention at least:
|
||||
@@ -1409,7 +1402,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
elif d.k == locNone:
|
||||
getTemp(p, n.typ, d)
|
||||
|
||||
let l = intLiteral(sonsLen(n))
|
||||
let l = intLiteral(len(n))
|
||||
if p.config.selectedGC == gcDestructors:
|
||||
let seqtype = n.typ
|
||||
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
||||
@@ -1419,7 +1412,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
genNewSeqAux(p, dest[], l,
|
||||
optNilSeqs notin p.options and n.len == 0)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
initLoc(arr, locExpr, n[i], OnHeap)
|
||||
arr.r = ropecg(p.module, "$1$3[$2]", [rdLoc(dest[]), intLiteral(i), dataField(p)])
|
||||
arr.storage = OnHeap # we know that sequences are on the heap
|
||||
@@ -1440,7 +1433,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
if d.k == locNone:
|
||||
getTemp(p, n.typ, d)
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
let L = int(lengthOrd(p.config, n.sons[1].typ))
|
||||
let L = toInt(lengthOrd(p.config, n.sons[1].typ))
|
||||
if p.config.selectedGC == gcDestructors:
|
||||
let seqtype = n.typ
|
||||
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
||||
@@ -1491,7 +1484,7 @@ proc genNewFinalize(p: BProc, e: PNode) =
|
||||
gcUsage(p.config, e)
|
||||
|
||||
proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
result = ropecg(p.module, "#isObj($1.m_type, $2)",
|
||||
[a, genTypeInfo2Name(p.module, dest)])
|
||||
else:
|
||||
@@ -1542,7 +1535,7 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) =
|
||||
genOf(p, n.sons[1], n.sons[2].typ, d)
|
||||
|
||||
proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
localError(p.config, e.info, "'repr' is not available for --newruntime")
|
||||
var a: TLoc
|
||||
initLocExpr(p, e.sons[1], a)
|
||||
@@ -1735,7 +1728,7 @@ proc fewCmps(conf: ConfigRef; s: PNode): bool =
|
||||
elif elemType(s.typ).kind in {tyInt, tyInt16..tyInt64}:
|
||||
result = true # better not emit the set if int is basetype!
|
||||
else:
|
||||
result = sonsLen(s) <= 8 # 8 seems to be a good value
|
||||
result = len(s) <= 8 # 8 seems to be a good value
|
||||
|
||||
template binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =
|
||||
putIntoDest(p, d, e, frmt % [rdLoc(a), rdSetElemLoc(p.config, b, a.t)])
|
||||
@@ -1768,7 +1761,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||
e.sons[2]
|
||||
initLocExpr(p, ea, a)
|
||||
initLoc(b, locExpr, e, OnUnknown)
|
||||
var length = sonsLen(e.sons[1])
|
||||
var length = len(e.sons[1])
|
||||
if length > 0:
|
||||
b.r = rope("(")
|
||||
for i in 0 ..< length:
|
||||
@@ -1938,7 +1931,8 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||
proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
|
||||
var a: TLoc
|
||||
var dest = skipTypes(n.typ, abstractVar)
|
||||
if optRangeCheck notin p.options:
|
||||
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
|
||||
checkUnsignedConversions notin p.config.legacyFeatures):
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
putIntoDest(p, d, n, "(($1) ($2))" %
|
||||
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)
|
||||
@@ -2032,7 +2026,7 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
resetLoc(p, a)
|
||||
|
||||
proc genDestroy(p: BProc; n: PNode) =
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if p.config.selectedGC == gcDestructors:
|
||||
let arg = n[1].skipAddr
|
||||
let t = arg.typ.skipTypes(abstractInst)
|
||||
case t.kind
|
||||
@@ -2090,7 +2084,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
|
||||
proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
case op
|
||||
of mOr, mAnd: genAndOr(p, e, d, op)
|
||||
of mNot..mToBiggestInt: unaryArith(p, e, d, op)
|
||||
of mNot..mUnaryMinusF64: unaryArith(p, e, d, op)
|
||||
of mUnaryMinusI..mAbsI: unaryArithOverflow(p, e, d, op)
|
||||
of mAddF64..mDivF64: binaryFloatArith(p, e, d, op)
|
||||
of mShrI..mXor: binaryArith(p, e, d, op)
|
||||
@@ -2155,7 +2149,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
|
||||
of mStrToStr, mUnown: expr(p, e.sons[1], d)
|
||||
of mEnumToStr:
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
genEnumToStr(p, e, d)
|
||||
else:
|
||||
genRepr(p, e, d)
|
||||
@@ -2272,7 +2266,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
|
||||
of mSlice:
|
||||
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
|
||||
" 'toOpenArray' is only valid within a call expression")
|
||||
"'toOpenArray' is only valid within a call expression")
|
||||
else:
|
||||
when defined(debugMagics):
|
||||
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
|
||||
@@ -2330,7 +2324,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
let t = n.typ
|
||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||
if d.k == locNone: getTemp(p, t, d)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr: it = it.sons[1]
|
||||
initLoc(rec, locExpr, it, d.storage)
|
||||
@@ -2372,7 +2366,7 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var arr: TLoc
|
||||
if not handleConstExpr(p, n, d):
|
||||
if d.k == locNone: getTemp(p, n.typ, d)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
|
||||
arr.r = "$1[$2]" % [rdLoc(d), intLiteral(i)]
|
||||
expr(p, n.sons[i], arr)
|
||||
@@ -2430,7 +2424,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
while t.kind == tyObject and t.sons[0] != nil:
|
||||
add(r, ".Sup")
|
||||
t = skipTypes(t.sons[0], skipPtrs)
|
||||
let checkFor = if optNimV2 in p.config.globalOptions:
|
||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||
genTypeInfo2Name(p.module, dest)
|
||||
else:
|
||||
genTypeInfo(p.module, dest, n.info)
|
||||
@@ -2542,6 +2536,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of skVar, skForVar, skResult, skLet:
|
||||
if {sfGlobal, sfThread} * sym.flags != {}:
|
||||
genVarPrototype(p.module, n)
|
||||
if sfCompileTime in sym.flags:
|
||||
genSingleVar(p, sym, n, astdef(sym))
|
||||
|
||||
if sym.loc.r == nil or sym.loc.t == nil:
|
||||
#echo "FAILED FOR PRCO ", p.prc.name.s
|
||||
#echo renderTree(p.prc.ast, {renderIds})
|
||||
@@ -2752,7 +2749,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
|
||||
getNullValueAux(p, t, it, cons, result, count)
|
||||
of nkRecCase:
|
||||
getNullValueAux(p, t, obj.sons[0], cons, result, count)
|
||||
for i in 1 ..< sonsLen(obj):
|
||||
for i in 1 ..< len(obj):
|
||||
getNullValueAux(p, t, lastSon(obj.sons[i]), cons, result, count)
|
||||
of nkSym:
|
||||
if count > 0: result.add ", "
|
||||
@@ -2800,7 +2797,7 @@ proc genConstObjConstr(p: BProc; n: PNode): Rope =
|
||||
result = "{$1}$n" % [result]
|
||||
|
||||
proc genConstSimpleList(p: BProc, n: PNode): Rope =
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
result = rope("{")
|
||||
for i in 0 .. length - 2:
|
||||
addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])])
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# included from cgen.nim
|
||||
|
||||
## This include file contains the logic to produce constant string
|
||||
## and seq literals. The code here is responsible that
|
||||
## ``const x = ["a", "b"]`` works without hidden runtime creation code.
|
||||
@@ -19,7 +21,7 @@ template detectVersion(field, corename) =
|
||||
if core == nil or core.kind != skConst:
|
||||
m.g.field = 1
|
||||
else:
|
||||
m.g.field = int ast.getInt(core.ast)
|
||||
m.g.field = toInt(ast.getInt(core.ast))
|
||||
result = m.g.field
|
||||
|
||||
proc detectStrVersion(m: BModule): int =
|
||||
|
||||
@@ -17,7 +17,7 @@ const
|
||||
|
||||
proc getTraverseProc(p: BProc, v: PSym): Rope =
|
||||
if p.config.selectedGC in {gcMarkAndSweep, gcDestructors, gcV2, gcRefc} and
|
||||
optNimV2 notin p.config.globalOptions and
|
||||
optOwnedRefs notin p.config.globalOptions and
|
||||
containsGarbageCollectedRef(v.loc.t):
|
||||
# we register a specialized marked proc here; this has the advantage
|
||||
# that it works out of the box for thread local storage then :-)
|
||||
@@ -62,7 +62,7 @@ proc endBlock(p: BProc)
|
||||
proc genVarTuple(p: BProc, n: PNode) =
|
||||
var tup, field: TLoc
|
||||
if n.kind != nkVarTuple: internalError(p.config, n.info, "genVarTuple")
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
|
||||
# if we have a something that's been captured, use the lowering instead:
|
||||
for i in 0 .. L-3:
|
||||
@@ -199,7 +199,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
# Called by return and break stmts.
|
||||
# Deals with issues faced when jumping out of try/except/finally stmts,
|
||||
|
||||
var stack = newSeq[tuple[n: PNode, inExcept: bool]](0)
|
||||
var stack = newSeq[tuple[fin: PNode, inExcept: bool]](0)
|
||||
|
||||
for i in 1 .. howManyTrys:
|
||||
let tryStmt = p.nestedTryStmts.pop
|
||||
@@ -214,9 +214,9 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
|
||||
# Find finally-stmt for this try-stmt
|
||||
# and generate a copy of its sons
|
||||
var finallyStmt = lastSon(tryStmt.n)
|
||||
if finallyStmt.kind == nkFinally:
|
||||
genStmts(p, finallyStmt.sons[0])
|
||||
var finallyStmt = tryStmt.fin
|
||||
if finallyStmt != nil:
|
||||
genStmts(p, finallyStmt[0])
|
||||
|
||||
# push old elements again:
|
||||
for i in countdown(howManyTrys-1, 0):
|
||||
@@ -246,10 +246,10 @@ proc genGotoState(p: BProc, n: PNode) =
|
||||
lineF(p, cpsStmts, " goto BeforeRet_;$n", [])
|
||||
var statesCounter = lastOrd(p.config, n.sons[0].typ)
|
||||
if n.len >= 2 and n[1].kind == nkIntLit:
|
||||
statesCounter = n[1].intVal
|
||||
statesCounter = getInt(n[1])
|
||||
let prefix = if n.len == 3 and n[2].kind == nkStrLit: n[2].strVal.rope
|
||||
else: rope"STATE"
|
||||
for i in 0i64 .. statesCounter:
|
||||
for i in 0i64 .. toInt64(statesCounter):
|
||||
lineF(p, cpsStmts, "case $2: goto $1$2;$n", [prefix, rope(i)])
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
|
||||
@@ -271,19 +271,16 @@ proc genGotoVar(p: BProc; value: PNode) =
|
||||
else:
|
||||
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
|
||||
|
||||
proc genSingleVar(p: BProc, a: PNode) =
|
||||
let vn = a.sons[0]
|
||||
let v = vn.sym
|
||||
if sfCompileTime in v.flags: return
|
||||
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
if sfGoto in v.flags:
|
||||
# translate 'var state {.goto.} = X' into 'goto LX':
|
||||
genGotoVar(p, a.sons[2])
|
||||
genGotoVar(p, value)
|
||||
return
|
||||
var targetProc = p
|
||||
var traverseProc: Rope
|
||||
if sfGlobal in v.flags:
|
||||
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
||||
a.sons[2].kind == nkEmpty and
|
||||
value.kind == nkEmpty and
|
||||
v.loc.flags * {lfHeader, lfNoDecl} != {}:
|
||||
return
|
||||
if sfPure in v.flags:
|
||||
@@ -313,14 +310,13 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||
if traverseProc != nil and not p.hcrOn:
|
||||
registerTraverseProc(p, v, traverseProc)
|
||||
else:
|
||||
let value = a.sons[2]
|
||||
let imm = isAssignedImmediately(p.config, value)
|
||||
if imm and p.module.compileToCpp and p.splitDecls == 0 and
|
||||
not containsHiddenPointer(v.typ):
|
||||
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
|
||||
# parameterless constructor followed by an assignment operator. So we
|
||||
# generate better code here: 'Foo f = x;'
|
||||
genLineDir(p, a)
|
||||
genLineDir(p, vn)
|
||||
let decl = localVarDecl(p, vn)
|
||||
var tmp: TLoc
|
||||
if value.kind in nkCallKinds and value[0].kind == nkSym and
|
||||
@@ -330,7 +326,7 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||
assert(typ.kind == tyProc)
|
||||
for i in 1..<value.len:
|
||||
if params != nil: params.add(~", ")
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
assert(len(typ) == len(typ.n))
|
||||
add(params, genOtherArg(p, value, i, typ))
|
||||
if params == nil:
|
||||
lineF(p, cpsStmts, "$#;$n", [decl])
|
||||
@@ -363,12 +359,17 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
|
||||
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
|
||||
startBlock(targetProc)
|
||||
if a.sons[2].kind != nkEmpty:
|
||||
genLineDir(targetProc, a)
|
||||
loadInto(targetProc, a.sons[0], a.sons[2], v.loc)
|
||||
if value.kind != nkEmpty:
|
||||
genLineDir(targetProc, vn)
|
||||
loadInto(targetProc, vn, value, v.loc)
|
||||
if forHcr:
|
||||
endBlock(targetProc)
|
||||
|
||||
proc genSingleVar(p: BProc, a: PNode) =
|
||||
let v = a[0].sym
|
||||
if sfCompileTime in v.flags: return
|
||||
genSingleVar(p, v, a[0], a.sons[2])
|
||||
|
||||
proc genClosureVar(p: BProc, a: PNode) =
|
||||
var immediateAsgn = a.sons[2].kind != nkEmpty
|
||||
var v: TLoc
|
||||
@@ -428,7 +429,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||
else:
|
||||
expr(p, it.sons[1], d)
|
||||
endBlock(p)
|
||||
if sonsLen(n) > 1:
|
||||
if len(n) > 1:
|
||||
lineF(p, cpsStmts, "goto $1;$n", [lend])
|
||||
fixLabel(p, lelse)
|
||||
elif it.len == 1:
|
||||
@@ -436,7 +437,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||
expr(p, it.sons[0], d)
|
||||
endBlock(p)
|
||||
else: internalError(p.config, n.info, "genIf()")
|
||||
if sonsLen(n) > 1: fixLabel(p, lend)
|
||||
if len(n) > 1: fixLabel(p, lend)
|
||||
|
||||
proc genReturnStmt(p: BProc, t: PNode) =
|
||||
if nfPreventCg in t.flags: return
|
||||
@@ -494,7 +495,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
if aSize > 10_000:
|
||||
localError(p.config, it.info,
|
||||
"case statement has too many cases for computed goto"); return
|
||||
arraySize = aSize.int
|
||||
arraySize = toInt(aSize)
|
||||
if firstOrd(p.config, it.sons[0].typ) != 0:
|
||||
localError(p.config, it.info,
|
||||
"case statement has to start at 0 for computed goto"); return
|
||||
@@ -527,7 +528,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
return
|
||||
|
||||
let val = getOrdValue(it.sons[j])
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)])
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(toInt64(val)+id+1)])
|
||||
|
||||
genStmts(p, it.lastSon)
|
||||
|
||||
@@ -564,7 +565,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||
# significantly worse code
|
||||
var
|
||||
a: TLoc
|
||||
assert(sonsLen(t) == 2)
|
||||
assert(len(t) == 2)
|
||||
inc(p.withinLoop)
|
||||
genLineDir(p, t)
|
||||
|
||||
@@ -611,7 +612,7 @@ proc genBlock(p: BProc, n: PNode, d: var TLoc) =
|
||||
endBlock(p)
|
||||
|
||||
proc genParForStmt(p: BProc, t: PNode) =
|
||||
assert(sonsLen(t) == 3)
|
||||
assert(len(t) == 3)
|
||||
inc(p.withinLoop)
|
||||
genLineDir(p, t)
|
||||
|
||||
@@ -622,12 +623,12 @@ proc genParForStmt(p: BProc, t: PNode) =
|
||||
#initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
|
||||
#discard mangleName(forLoopVar)
|
||||
let call = t.sons[1]
|
||||
assert(sonsLen(call) in {4, 5})
|
||||
assert(len(call) in {4, 5})
|
||||
initLocExpr(p, call.sons[1], rangeA)
|
||||
initLocExpr(p, call.sons[2], rangeB)
|
||||
|
||||
# $n at the beginning because of #9710
|
||||
if call.sonsLen == 4: # `||`(a, b, annotation)
|
||||
if call.len == 4: # `||`(a, b, annotation)
|
||||
lineF(p, cpsStmts, "$n#pragma omp $4$n" &
|
||||
"for ($1 = $2; $1 <= $3; ++$1)",
|
||||
[forLoopVar.loc.rdLoc,
|
||||
@@ -675,8 +676,8 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if p.nestedTryStmts.len > 0 and p.nestedTryStmts[^1].inExcept:
|
||||
# if the current try stmt have a finally block,
|
||||
# we must execute it before reraising
|
||||
var finallyBlock = p.nestedTryStmts[^1].n[^1]
|
||||
if finallyBlock.kind == nkFinally:
|
||||
let finallyBlock = p.nestedTryStmts[^1].fin
|
||||
if finallyBlock != nil:
|
||||
genSimpleBlock(p, finallyBlock[0])
|
||||
if t[0].kind != nkEmpty:
|
||||
var a: TLoc
|
||||
@@ -691,7 +692,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
[e, makeCString(typ.sym.name.s),
|
||||
makeCString(if p.prc != nil: p.prc.name.s else: p.module.module.name.s),
|
||||
quotedFilename(p.config, t.info), toLinenumber(t.info)])
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optOwnedRefs in p.config.globalOptions:
|
||||
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [e])
|
||||
else:
|
||||
genLineDir(p, t)
|
||||
@@ -705,7 +706,7 @@ template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||
rangeFormat, eqFormat: FormatStr, labl: TLabel) =
|
||||
var
|
||||
x, y: TLoc
|
||||
var length = sonsLen(b)
|
||||
var length = len(b)
|
||||
for i in 0 .. length - 2:
|
||||
if b.sons[i].kind == nkRange:
|
||||
initLocExpr(p, b.sons[i].sons[0], x)
|
||||
@@ -724,7 +725,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
|
||||
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
|
||||
lineF(p, cpsStmts, "LA$1_: ;$n", [rope(labId + i)])
|
||||
if t.sons[i].kind == nkOfBranch:
|
||||
var length = sonsLen(t.sons[i])
|
||||
var length = len(t.sons[i])
|
||||
exprBlock(p, t.sons[i].sons[length - 1], d)
|
||||
lineF(p, cpsStmts, "goto $1;$n", [lend])
|
||||
else:
|
||||
@@ -758,13 +759,13 @@ template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
|
||||
rangeFormat, eqFormat: FormatStr) =
|
||||
var a: TLoc
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a)
|
||||
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, len(t)-1, a)
|
||||
fixLabel(p, lend)
|
||||
|
||||
proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
branches: var openArray[Rope]) =
|
||||
var x: TLoc
|
||||
var length = sonsLen(b)
|
||||
var length = len(b)
|
||||
for i in 0 .. length - 2:
|
||||
assert(b.sons[i].kind != nkRange)
|
||||
initLocExpr(p, b.sons[i], x)
|
||||
@@ -776,16 +777,16 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
# count how many constant strings there are in the case:
|
||||
var strings = 0
|
||||
for i in 1 ..< sonsLen(t):
|
||||
if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1)
|
||||
for i in 1 ..< len(t):
|
||||
if t.sons[i].kind == nkOfBranch: inc(strings, len(t.sons[i]) - 1)
|
||||
if strings > stringCaseThreshold:
|
||||
var bitMask = math.nextPowerOfTwo(strings) - 1
|
||||
var branches: seq[Rope]
|
||||
newSeq(branches, bitMask + 1)
|
||||
var a: TLoc
|
||||
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
|
||||
initLocExpr(p, t.sons[0], a) # fist pass: generate ifs+goto:
|
||||
var labId = p.labels
|
||||
for i in 1 ..< sonsLen(t):
|
||||
for i in 1 ..< len(t):
|
||||
inc(p.labels)
|
||||
if t.sons[i].kind == nkOfBranch:
|
||||
genCaseStringBranch(p, t.sons[i], a, "LA" & rope(p.labels) & "_",
|
||||
@@ -801,16 +802,16 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
||||
[intLiteral(j), branches[j]])
|
||||
lineF(p, cpsStmts, "}$n", []) # else statement:
|
||||
if t.sons[sonsLen(t)-1].kind != nkOfBranch:
|
||||
if t.sons[len(t)-1].kind != nkOfBranch:
|
||||
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
|
||||
# third pass: generate statements
|
||||
var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
|
||||
var lend = genCaseSecondPass(p, t, d, labId, len(t)-1)
|
||||
fixLabel(p, lend)
|
||||
else:
|
||||
genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
|
||||
|
||||
proc branchHasTooBigRange(b: PNode): bool =
|
||||
for i in 0 .. sonsLen(b)-2:
|
||||
for i in 0 .. len(b)-2:
|
||||
# last son is block
|
||||
if (b.sons[i].kind == nkRange) and
|
||||
b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit:
|
||||
@@ -924,7 +925,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
getTemp(p, t.typ, d)
|
||||
genLineDir(p, t)
|
||||
discard cgsym(p.module, "popCurrentExceptionEx")
|
||||
add(p.nestedTryStmts, (t, false))
|
||||
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
|
||||
add(p.nestedTryStmts, (fin, false))
|
||||
startBlock(p, "try {$n")
|
||||
expr(p, t[0], d)
|
||||
endBlock(p)
|
||||
@@ -1021,8 +1023,9 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||
var length = sonsLen(t)
|
||||
add(p.nestedTryStmts, (t, quirkyExceptions))
|
||||
let length = len(t)
|
||||
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
|
||||
add(p.nestedTryStmts, (fin, quirkyExceptions))
|
||||
expr(p, t.sons[0], d)
|
||||
if not quirkyExceptions:
|
||||
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
|
||||
@@ -1039,7 +1042,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||
# bug #4230: avoid false sharing between branches:
|
||||
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
|
||||
var blen = sonsLen(t.sons[i])
|
||||
var blen = len(t.sons[i])
|
||||
if blen == 1:
|
||||
# general except section:
|
||||
if i > 1: lineF(p, cpsStmts, "else", [])
|
||||
@@ -1054,7 +1057,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
for j in 0 .. blen - 2:
|
||||
assert(t.sons[i].sons[j].kind == nkType)
|
||||
if orExpr != nil: add(orExpr, "||")
|
||||
let checkFor = if optNimV2 in p.config.globalOptions:
|
||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||
genTypeInfo2Name(p.module, t[i][j].typ)
|
||||
else:
|
||||
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
|
||||
@@ -1159,36 +1162,10 @@ proc genEmit(p: BProc, t: PNode) =
|
||||
genLineDir(p, t)
|
||||
line(p, cpsStmts, s)
|
||||
|
||||
proc genBreakPoint(p: BProc, t: PNode) =
|
||||
var name: string
|
||||
if optEndb in p.options:
|
||||
if t.kind == nkExprColonExpr:
|
||||
assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
|
||||
name = normalize(t.sons[1].strVal)
|
||||
else:
|
||||
inc(p.module.g.breakPointId)
|
||||
name = "bp" & $p.module.g.breakPointId
|
||||
genLineDir(p, t) # BUGFIX
|
||||
appcg(p.module, p.module.g.breakpoints,
|
||||
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
||||
toLinenumber(t.info), makeCString(toFilename(p.config, t.info)),
|
||||
makeCString(name)])
|
||||
|
||||
proc genWatchpoint(p: BProc, n: PNode) =
|
||||
if optEndb notin p.options: return
|
||||
var a: TLoc
|
||||
initLocExpr(p, n.sons[1], a)
|
||||
let typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
lineCg(p, cpsStmts, "#dbgRegisterWatchpoint($1, (NCSTRING)$2, $3);$n",
|
||||
[addrLoc(p.config, a), makeCString(renderTree(n.sons[1])),
|
||||
genTypeInfo(p.module, typ, n.info)])
|
||||
|
||||
proc genPragma(p: BProc, n: PNode) =
|
||||
for it in n.sons:
|
||||
case whichPragma(it)
|
||||
of wEmit: genEmit(p, it)
|
||||
of wBreakpoint: genBreakPoint(p, it)
|
||||
of wWatchPoint: genWatchpoint(p, it)
|
||||
of wInjectStmt:
|
||||
var p = newProc(nil, p.module)
|
||||
p.options = p.options - {optLineTrace, optStackTrace}
|
||||
@@ -1211,7 +1188,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||
var t = skipTypes(objtype, abstractVar)
|
||||
assert t.kind == tyObject
|
||||
discard genTypeInfo(p.module, t, a.lode.info)
|
||||
var L = lengthOrd(p.config, field.typ)
|
||||
var L = toInt64(lengthOrd(p.config, field.typ))
|
||||
if not containsOrIncl(p.module.declaredThings, field.id):
|
||||
appcg(p.module, cfsVars, "extern $1",
|
||||
[discriminatorTableDecl(p.module, t, field)])
|
||||
@@ -1243,7 +1220,7 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||
getTemp(p, a.t, tmp)
|
||||
expr(p, e.sons[1], tmp)
|
||||
let field = dotExpr.sons[1].sym
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
let t = dotExpr[0].typ.skipTypes(abstractInst)
|
||||
var oldVal, newVal: TLoc
|
||||
genCaseObjDiscMapping(p, e[0], t, field, oldVal)
|
||||
|
||||
@@ -17,7 +17,7 @@ type
|
||||
visitorFrmt: string
|
||||
|
||||
const
|
||||
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
|
||||
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
|
||||
|
||||
proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType)
|
||||
proc genCaseRange(p: BProc, branch: PNode)
|
||||
@@ -28,7 +28,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
genTraverseProc(c, accessor, n.sons[i], typ)
|
||||
of nkRecCase:
|
||||
if (n.sons[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
|
||||
@@ -38,7 +38,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
|
||||
if disc.loc.t == nil:
|
||||
internalError(c.p.config, n.info, "genTraverseProc()")
|
||||
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
let branch = n.sons[i]
|
||||
assert branch.kind in {nkOfBranch, nkElse}
|
||||
if branch.kind == nkOfBranch:
|
||||
@@ -87,14 +87,14 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||
else:
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
of tyObject:
|
||||
for i in 0 ..< sonsLen(typ):
|
||||
for i in 0 ..< len(typ):
|
||||
var x = typ.sons[i]
|
||||
if x != nil: x = x.skipTypes(skipPtrs)
|
||||
genTraverseProc(c, accessor.parentObj(c.p.module), x)
|
||||
if typ.n != nil: genTraverseProc(c, accessor, typ.n, typ)
|
||||
of tyTuple:
|
||||
let typ = getUniqueType(typ)
|
||||
for i in 0 ..< sonsLen(typ):
|
||||
for i in 0 ..< len(typ):
|
||||
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ.sons[i])
|
||||
of tyRef:
|
||||
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
|
||||
@@ -104,7 +104,8 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||
elif containsGarbageCollectedRef(typ.lastSon):
|
||||
# destructor based seqs are themselves not traced but their data is, if
|
||||
# they contain a GC'ed type:
|
||||
genTraverseProcSeq(c, accessor, typ)
|
||||
lineCg(p, cpsStmts, "#nimGCvisitSeq((void*)$1, $2);$n", [accessor, c.visitorFrmt])
|
||||
#genTraverseProcSeq(c, accessor, typ)
|
||||
of tyString:
|
||||
if tfHasAsgn notin typ.flags:
|
||||
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
|
||||
|
||||
@@ -61,7 +61,7 @@ proc mangleParamName(m: BModule; s: PSym): Rope =
|
||||
var res = s.name.s.mangle
|
||||
# Take into account if HCR is on because of the following scenario:
|
||||
# if a module gets imported and it has some more importc symbols in it,
|
||||
# some param names might recieve the "_0" suffix to distinguish from what
|
||||
# some param names might receive the "_0" suffix to distinguish from what
|
||||
# is newly available. That might lead to changes in the C code in nimcache
|
||||
# that contain only a parameter name change, but that is enough to mandate
|
||||
# recompilation of that source file and thus a new shared object will be
|
||||
@@ -155,6 +155,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
|
||||
of tyNone, tyTyped: result = ctVoid
|
||||
of tyBool: result = ctBool
|
||||
of tyChar: result = ctChar
|
||||
of tyNil: result = ctPtr
|
||||
of tySet: result = mapSetType(conf, typ)
|
||||
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctArray
|
||||
of tyObject, tyTuple: result = ctStruct
|
||||
@@ -286,6 +287,7 @@ proc fillResult(conf: ConfigRef; param: PNode) =
|
||||
|
||||
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
|
||||
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
|
||||
useHeader(m, t.sym)
|
||||
result = t.sym.loc.r
|
||||
else:
|
||||
result = rope(literal)
|
||||
@@ -449,7 +451,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
rettype = ~"void"
|
||||
else:
|
||||
rettype = getTypeDescAux(m, t.sons[0], check)
|
||||
for i in 1 ..< sonsLen(t.n):
|
||||
for i in 1 ..< len(t.n):
|
||||
if t.n.sons[i].kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
|
||||
var param = t.n.sons[i].sym
|
||||
if isCompileTimeOnly(param.typ): continue
|
||||
@@ -469,7 +471,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
add(params, param.loc.r)
|
||||
# declare the len field for open arrays:
|
||||
var arr = param.typ
|
||||
if arr.kind in {tyVar, tyLent}: arr = arr.lastSon
|
||||
if arr.kind in {tyVar, tyLent, tySink}: arr = arr.lastSon
|
||||
var j = 0
|
||||
while arr.kind in {tyOpenArray, tyVarargs}:
|
||||
# this fixes the 'sort' bug:
|
||||
@@ -477,7 +479,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
# need to pass hidden parameter:
|
||||
addf(params, ", NI $1Len_$2", [param.loc.r, j.rope])
|
||||
inc(j)
|
||||
arr = arr.sons[0]
|
||||
arr = arr.sons[0].skipTypes({tySink})
|
||||
if t.sons[0] != nil and isInvalidReturnType(m.config, t.sons[0]):
|
||||
var arr = t.sons[0]
|
||||
if params != nil: add(params, ", ")
|
||||
@@ -510,7 +512,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
add(result, genRecordFieldsAux(m, n.sons[i], rectype, check))
|
||||
of nkRecCase:
|
||||
if n.sons[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
||||
@@ -518,7 +520,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||
# since identifiers are not allowed to start with '_'
|
||||
var unionBody: Rope = nil
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
let k = lastSon(n.sons[i])
|
||||
@@ -633,7 +635,7 @@ proc getTupleDesc(m: BModule, typ: PType, name: Rope,
|
||||
check: var IntSet): Rope =
|
||||
result = "$1 $2 {$n" % [structOrUnion(typ), name]
|
||||
var desc: Rope = nil
|
||||
for i in 0 ..< sonsLen(typ):
|
||||
for i in 0 ..< len(typ):
|
||||
addf(desc, "$1 Field$2;$n",
|
||||
[getTypeDescAux(m, typ.sons[i], check), rope(i)])
|
||||
if desc == nil: add(result, "char dummy;\L")
|
||||
@@ -805,7 +807,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||
let foo = getTypeDescAux(m, t.sons[0], check)
|
||||
addf(m.s[cfsTypes], "typedef $1 $2[1];$n", [foo, result])
|
||||
of tyArray:
|
||||
var n: BiggestInt = lengthOrd(m.config, t)
|
||||
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
|
||||
if n <= 0: n = 1 # make an array of at least one element
|
||||
result = getTypeName(m, origTyp, sig)
|
||||
m.typeCache[sig] = result
|
||||
@@ -956,7 +958,7 @@ proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
|
||||
fillLoc(prc.loc, locProc, prc.ast[namePos], mangleName(m, prc), OnUnknown)
|
||||
genProcParams(m, prc.typ, rettype, params, check)
|
||||
# handle the 2 options for hotcodereloading codegen - function pointer
|
||||
# (instead of forward declaration) or header for function budy with "_actual" postfix
|
||||
# (instead of forward declaration) or header for function body with "_actual" postfix
|
||||
let asPtrStr = rope(if asPtr: "_PTR" else: "")
|
||||
var name = prc.loc.r
|
||||
if isReloadable(m, prc) and not asPtr:
|
||||
@@ -1027,7 +1029,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
|
||||
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
|
||||
info: TLineInfo) =
|
||||
var base: Rope
|
||||
if sonsLen(typ) > 0 and typ.lastSon != nil:
|
||||
if len(typ) > 0 and typ.lastSon != nil:
|
||||
var x = typ.lastSon
|
||||
if typ.kind == tyObject: x = x.skipTypes(skipPtrs)
|
||||
if typ.kind == tyPtr and x.kind == tyObject and incompleteType(x):
|
||||
@@ -1047,6 +1049,8 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
|
||||
internalError(m.config, d.info, "anonymous obj with discriminator")
|
||||
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]
|
||||
|
||||
proc rope(arg: Int128): Rope = rope($arg)
|
||||
|
||||
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
||||
discard cgsym(m, "TNimNode")
|
||||
var tmp = discriminatorTableName(m, objtype, d)
|
||||
@@ -1064,7 +1068,7 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||
info: TLineInfo) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
if L == 1:
|
||||
genObjectFields(m, typ, origType, n.sons[0], expr, info)
|
||||
elif L > 0:
|
||||
@@ -1095,18 +1099,18 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||
makeCString(field.name.s),
|
||||
tmp, rope(L)])
|
||||
addf(m.s[cfsData], "TNimNode* $1[$2];$n", [tmp, rope(L+1)])
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var b = n.sons[i] # branch
|
||||
var tmp2 = getNimNode(m)
|
||||
genObjectFields(m, typ, origType, lastSon(b), tmp2, info)
|
||||
case b.kind
|
||||
of nkOfBranch:
|
||||
if sonsLen(b) < 2:
|
||||
if len(b) < 2:
|
||||
internalError(m.config, b.info, "genObjectFields; nkOfBranch broken")
|
||||
for j in 0 .. sonsLen(b) - 2:
|
||||
for j in 0 .. len(b) - 2:
|
||||
if b.sons[j].kind == nkRange:
|
||||
var x = int(getOrdValue(b.sons[j].sons[0]))
|
||||
var y = int(getOrdValue(b.sons[j].sons[1]))
|
||||
var x = toInt(getOrdValue(b.sons[j].sons[0]))
|
||||
var y = toInt(getOrdValue(b.sons[j].sons[1]))
|
||||
while x <= y:
|
||||
addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(x), tmp2])
|
||||
inc(x)
|
||||
@@ -1152,7 +1156,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo
|
||||
proc genTupleInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo) =
|
||||
genTypeInfoAuxBase(m, typ, typ, name, rope("0"), info)
|
||||
var expr = getNimNode(m)
|
||||
var length = sonsLen(typ)
|
||||
var length = len(typ)
|
||||
if length > 0:
|
||||
var tmp = getTempName(m) & "_" & $length
|
||||
genTNimNodeArray(m, tmp, rope(length))
|
||||
@@ -1178,7 +1182,7 @@ proc genEnumInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
||||
# anyway. We generate a cstring array and a loop over it. Exceptional
|
||||
# positions will be reset after the loop.
|
||||
genTypeInfoAux(m, typ, typ, name, info)
|
||||
var length = sonsLen(typ.n)
|
||||
var length = len(typ.n)
|
||||
var nodePtrs = getTempName(m) & "_" & $length
|
||||
genTNimNodeArray(m, nodePtrs, rope(length))
|
||||
var enumNames, specialCases: Rope
|
||||
@@ -1361,7 +1365,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
of tySet: genSetInfo(m, t, result, info)
|
||||
of tyEnum: genEnumInfo(m, t, result, info)
|
||||
of tyObject:
|
||||
if optNimV2 in m.config.globalOptions:
|
||||
if optTinyRtti in m.config.globalOptions:
|
||||
genObjectInfoV2(m, t, origType, result, info)
|
||||
else:
|
||||
genObjectInfo(m, t, origType, result, info)
|
||||
|
||||
@@ -113,6 +113,9 @@ proc cgFormatValue(result: var string; value: string): void =
|
||||
proc cgFormatValue(result: var string; value: BiggestInt): void =
|
||||
result.addInt value
|
||||
|
||||
proc cgFormatValue(result: var string; value: Int128): void =
|
||||
result.addInt128 value
|
||||
|
||||
# TODO: please document
|
||||
macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||
args.expectKind nnkBracket
|
||||
@@ -261,13 +264,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||
if optEmbedOrigSrc in p.config.globalOptions:
|
||||
add(p.s(cpsStmts), ~"//" & sourceLine(p.config, t.info) & "\L")
|
||||
genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config)
|
||||
if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
if freshLineInfo(p, t.info):
|
||||
linefmt(p, cpsStmts, "#endb($1, $2);$N",
|
||||
[line, makeCString(toFilename(p.config, t.info))])
|
||||
elif ({optLineTrace, optStackTrace} * p.options ==
|
||||
{optLineTrace, optStackTrace}) and
|
||||
if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
|
||||
if freshLineInfo(p, t.info):
|
||||
linefmt(p, cpsStmts, "nimln_($1, $2);$n",
|
||||
@@ -350,7 +347,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
|
||||
s = skipTypes(s.sons[0], skipPtrs)
|
||||
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t, a.lode.info)])
|
||||
of frEmbedded:
|
||||
if optNimV2 in p.config.globalOptions:
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
localError(p.config, p.prc.info,
|
||||
"complex object initialization is not supported with --newruntime")
|
||||
# worst case for performance:
|
||||
@@ -476,19 +473,6 @@ proc deinitGCFrame(p: BProc): Rope =
|
||||
result = ropecg(p.module,
|
||||
"if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n", [])
|
||||
|
||||
proc localDebugInfo(p: BProc, s: PSym, retType: PType) =
|
||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||
# XXX work around a bug: No type information for open arrays possible:
|
||||
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
||||
var a = "&" & s.loc.r
|
||||
if s.kind == skParam and ccgIntroducedPtr(p.config, s, retType): a = s.loc.r
|
||||
lineF(p, cpsInit,
|
||||
"FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n",
|
||||
[p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a,
|
||||
genTypeInfo(p.module, s.loc.t, s.info)])
|
||||
inc(p.maxFrameLen)
|
||||
inc p.blocks[p.blocks.len-1].frameLen
|
||||
|
||||
proc localVarDecl(p: BProc; n: PNode): Rope =
|
||||
let s = n.sym
|
||||
if s.loc.k == locNone:
|
||||
@@ -512,7 +496,6 @@ proc assignLocalVar(p: BProc, n: PNode) =
|
||||
let nl = if optLineDir in p.config.options: "" else: "\L"
|
||||
let decl = localVarDecl(p, n) & ";" & nl
|
||||
line(p, cpsLocals, decl)
|
||||
localDebugInfo(p, n.sym, nil)
|
||||
|
||||
include ccgthreadvars
|
||||
|
||||
@@ -559,17 +542,10 @@ proc assignGlobalVar(p: BProc, n: PNode) =
|
||||
if p.withinLoop > 0:
|
||||
# fixes tests/run/tzeroarray:
|
||||
resetLoc(p, s.loc)
|
||||
if p.module.module.options * {optStackTrace, optEndb} ==
|
||||
{optStackTrace, optEndb}:
|
||||
appcg(p.module, p.module.s[cfsDebugInit],
|
||||
"#dbgRegisterGlobal($1, &$2, $3);$n",
|
||||
[makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
|
||||
s.loc.r, genTypeInfo(p.module, s.typ, n.info)])
|
||||
|
||||
proc assignParam(p: BProc, s: PSym, retType: PType) =
|
||||
assert(s.loc.r != nil)
|
||||
scopeMangledParam(p, s)
|
||||
localDebugInfo(p, s, retType)
|
||||
|
||||
proc fillProcLoc(m: BModule; n: PNode) =
|
||||
let sym = n.sym
|
||||
@@ -686,7 +662,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
[loadlib, genStringLiteral(m, lib.path)])
|
||||
else:
|
||||
var p = newProc(nil, m)
|
||||
p.options = p.options - {optStackTrace, optEndb}
|
||||
p.options = p.options - {optStackTrace}
|
||||
var dest: TLoc
|
||||
initLoc(dest, locTemp, lib.path, OnStack)
|
||||
dest.r = getTempName(m)
|
||||
@@ -781,7 +757,7 @@ proc cgsym(m: BModule, name: string): Rope =
|
||||
rawMessage(m.config, errGenerated, "system module needs: " & name)
|
||||
result = sym.loc.r
|
||||
if m.hcrOn and sym != nil and sym.kind in {skProc..skIterator}:
|
||||
result.addActualPrefixForHCR(m.module, sym)
|
||||
result.addActualSuffixForHCR(m.module, sym)
|
||||
|
||||
proc generateHeaders(m: BModule) =
|
||||
add(m.s[cfsHeaders], "\L#include \"nimbase.h\"\L")
|
||||
@@ -955,11 +931,12 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
|
||||
# assignment this is not good enough! The only pattern we allow for
|
||||
# is 'finally: result = x'
|
||||
result = InitSkippable
|
||||
for it in n:
|
||||
if it.kind == nkFinally:
|
||||
result = allPathsAsgnResult(it.lastSon)
|
||||
allPathsInBranch(n[0])
|
||||
for i in 1..<n.len:
|
||||
if n[i].kind == nkFinally:
|
||||
result = allPathsAsgnResult(n[i].lastSon)
|
||||
else:
|
||||
allPathsInBranch(it.lastSon)
|
||||
allPathsInBranch(n[i].lastSon)
|
||||
else:
|
||||
for i in 0..<safeLen(n):
|
||||
allPathsInBranch(n[i])
|
||||
@@ -1014,23 +991,29 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
#incl(res.loc.flags, lfIndirect)
|
||||
res.loc.storage = OnUnknown
|
||||
|
||||
for i in 1 ..< sonsLen(prc.typ.n):
|
||||
for i in 1 ..< len(prc.typ.n):
|
||||
let param = prc.typ.n.sons[i].sym
|
||||
if param.typ.isCompileTimeOnly: continue
|
||||
assignParam(p, param, prc.typ[0])
|
||||
closureSetup(p, prc)
|
||||
genStmts(p, procBody) # modifies p.locals, p.init, etc.
|
||||
var generatedProc: Rope
|
||||
generatedProc.genCLineDir prc.info, m.config
|
||||
if sfNoReturn in prc.flags:
|
||||
if hasDeclspec in extccomp.CC[p.config.cCompiler].props:
|
||||
header = "__declspec(noreturn) " & header
|
||||
if sfPure in prc.flags:
|
||||
if hasDeclspec in extccomp.CC[p.config.cCompiler].props:
|
||||
header = "__declspec(naked) " & header
|
||||
generatedProc = ropecg(p.module, "$N$1 {$n$2$3$4}$N$N",
|
||||
generatedProc.add ropecg(p.module, "$1 {$n$2$3$4}$N$N",
|
||||
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
|
||||
else:
|
||||
generatedProc = ropecg(p.module, "$N$1 {$N", [header])
|
||||
if m.hcrOn and isReloadable(m, prc):
|
||||
# Add forward declaration for "_actual"-suffixed functions defined in the same module (or inline).
|
||||
# This fixes the use of methods and also the case when 2 functions within the same module
|
||||
# call each other using directly the "_actual" versions (an optimization) - see issue #11608
|
||||
addf(m.s[cfsProcHeaders], "$1;\n", [header])
|
||||
generatedProc.add ropecg(p.module, "$1 {", [header])
|
||||
add(generatedProc, initGCFrame(p))
|
||||
if optStackTrace in prc.options:
|
||||
add(generatedProc, p.s(cpsLocals))
|
||||
@@ -1058,7 +1041,8 @@ proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
|
||||
result = (sfCompileToCpp in m.module.flags and
|
||||
sfCompileToCpp notin sym.getModule().flags and
|
||||
m.config.cmd != cmdCompileToCpp) or (
|
||||
sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and
|
||||
sym.flags * {sfInfixCall, sfCompilerProc, sfMangleCpp} == {} and
|
||||
sym.flags * {sfImportc, sfExportc} != {} and
|
||||
sym.magic == mNone and
|
||||
m.config.cmd == cmdCompileToCpp)
|
||||
|
||||
@@ -1273,7 +1257,7 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
|
||||
|
||||
proc genMainProc(m: BModule) =
|
||||
## this function is called in cgenWriteModules after all modules are closed,
|
||||
## it means raising dependency on the symbols is too late as it will not propogate
|
||||
## it means raising dependency on the symbols is too late as it will not propagate
|
||||
## into other modules, only simple rope manipulations are allowed
|
||||
|
||||
var preMainCode: Rope
|
||||
@@ -1310,7 +1294,6 @@ proc genMainProc(m: BModule) =
|
||||
PreMainBody = "$N" &
|
||||
"void PreMainInner(void) {$N" &
|
||||
"$2" &
|
||||
"$3" &
|
||||
"}$N$N" &
|
||||
PosixCmdLine &
|
||||
"void PreMain(void) {$N" &
|
||||
@@ -1400,17 +1383,11 @@ proc genMainProc(m: BModule) =
|
||||
elif m.config.target.targetOS == osGenode:
|
||||
m.includeHeader("<libc/component.h>")
|
||||
|
||||
if optEndb in m.config.options:
|
||||
for i in 0..<m.config.m.fileInfos.len:
|
||||
m.g.breakpoints.addf("dbgRegisterFilename($1);$N",
|
||||
[m.config.m.fileInfos[i].projPath.string.makeCString])
|
||||
|
||||
let initStackBottomCall =
|
||||
if m.config.target.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope
|
||||
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", [])
|
||||
inc(m.labels)
|
||||
appcg(m, m.s[cfsProcs], PreMainBody, [
|
||||
m.g.mainDatInit, m.g.breakpoints, m.g.otherModsInit])
|
||||
appcg(m, m.s[cfsProcs], PreMainBody, [m.g.mainDatInit, m.g.otherModsInit])
|
||||
|
||||
if m.config.target.targetOS == osWindows and
|
||||
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
@@ -1539,7 +1516,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
|
||||
proc genDatInitCode(m: BModule) =
|
||||
## this function is called in cgenWriteModules after all modules are closed,
|
||||
## it means raising dependency on the symbols is too late as it will not propogate
|
||||
## it means raising dependency on the symbols is too late as it will not propagate
|
||||
## into other modules, only simple rope manipulations are allowed
|
||||
|
||||
var moduleDatInitRequired = m.hcrOn
|
||||
@@ -1583,7 +1560,7 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
|
||||
|
||||
proc genInitCode(m: BModule) =
|
||||
## this function is called in cgenWriteModules after all modules are closed,
|
||||
## it means raising dependency on the symbols is too late as it will not propogate
|
||||
## it means raising dependency on the symbols is too late as it will not propagate
|
||||
## into other modules, only simple rope manipulations are allowed
|
||||
var moduleInitRequired = m.hcrOn
|
||||
let initname = getInitName(m)
|
||||
@@ -1771,7 +1748,7 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
|
||||
result.typeNodesName = getTempName(result)
|
||||
result.nimTypesName = getTempName(result)
|
||||
# no line tracing for the init sections of the system module so that we
|
||||
# don't generate a TFrame which can confuse the stack botton initialization:
|
||||
# don't generate a TFrame which can confuse the stack bottom initialization:
|
||||
if sfSystemModule in module.flags:
|
||||
incl result.flags, preventStackTrace
|
||||
excl(result.preInitProc.options, optStackTrace)
|
||||
@@ -2016,11 +1993,6 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
|
||||
discard cgsym(m, "initThreadVarsEmulation")
|
||||
|
||||
if m.g.breakpoints != nil:
|
||||
discard cgsym(m, "dbgRegisterBreakpoint")
|
||||
if optEndb in m.config.options:
|
||||
discard cgsym(m, "dbgRegisterFilename")
|
||||
|
||||
if m.g.forwardedProcs.len == 0:
|
||||
incl m.flags, objHasKidsValid
|
||||
let disp = generateMethodDispatchers(graph)
|
||||
|
||||
@@ -58,7 +58,7 @@ type
|
||||
id*: int # the ID of the label; positive means that it
|
||||
label*: Rope # generated text for the label
|
||||
# nil if label is not used
|
||||
sections*: TCProcSections # the code beloging
|
||||
sections*: TCProcSections # the code belonging
|
||||
isLoop*: bool # whether block is a loop
|
||||
nestedTryStmts*: int16 # how many try statements is it nested into
|
||||
nestedExceptStmts*: int16 # how many except statements is it nested into
|
||||
@@ -73,7 +73,7 @@ type
|
||||
noSafePoints*: bool # the proc doesn't use safe points in exception handling
|
||||
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
|
||||
currLineInfo*: TLineInfo # AST codegen will make this superfluous
|
||||
nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]
|
||||
nestedTryStmts*: seq[tuple[fin: PNode, inExcept: bool]]
|
||||
# in how many nested try statements we are
|
||||
# (the vars must be volatile then)
|
||||
# bool is true when are in the except part of a try block
|
||||
@@ -117,8 +117,6 @@ type
|
||||
modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
|
||||
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
|
||||
generatedHeader*: BModule
|
||||
breakPointId*: int
|
||||
breakpoints*: Rope # later the breakpoints are inserted into the main proc
|
||||
typeInfoMarker*: TypeCacheWithOwner
|
||||
config*: ConfigRef
|
||||
graph*: ModuleGraph
|
||||
@@ -152,7 +150,7 @@ type
|
||||
initProc*: BProc # code for init procedure
|
||||
preInitProc*: BProc # code executed before the init proc
|
||||
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
|
||||
inHcrInitGuard*: bool # We are currently withing a HCR reloading guard.
|
||||
inHcrInitGuard*: bool # We are currently within a HCR reloading guard.
|
||||
typeStack*: TTypeSeq # used for type generation
|
||||
dataCache*: TNodeTable
|
||||
typeNodes*, nimTypes*: int # used for type info generation
|
||||
|
||||
@@ -48,7 +48,7 @@ proc methodCall*(n: PNode; conf: ConfigRef): PNode =
|
||||
if disp != nil:
|
||||
result.sons[0].sym = disp
|
||||
# change the arguments to up/downcasts to fit the dispatcher's parameters:
|
||||
for i in 1 ..< sonsLen(result):
|
||||
for i in 1 ..< len(result):
|
||||
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true, conf)
|
||||
else:
|
||||
localError(conf, n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
|
||||
@@ -58,10 +58,10 @@ type
|
||||
|
||||
proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
|
||||
if a.name.id != b.name.id: return
|
||||
if sonsLen(a.typ) != sonsLen(b.typ):
|
||||
if len(a.typ) != len(b.typ):
|
||||
return
|
||||
|
||||
for i in 1 ..< sonsLen(a.typ):
|
||||
for i in 1 ..< len(a.typ):
|
||||
var aa = a.typ.sons[i]
|
||||
var bb = b.typ.sons[i]
|
||||
while true:
|
||||
@@ -118,7 +118,7 @@ proc createDispatcher(s: PSym): PSym =
|
||||
disp.ast.sons[bodyPos] = newNodeI(nkEmpty, s.info)
|
||||
disp.loc.r = nil
|
||||
if s.typ.sons[0] != nil:
|
||||
if disp.ast.sonsLen > resultPos:
|
||||
if disp.ast.len > resultPos:
|
||||
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
|
||||
else:
|
||||
# We've encountered a method prototype without a filled-in
|
||||
@@ -136,7 +136,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
|
||||
# from later definitions, particularly the resultPos slot. Also,
|
||||
# the lock level of the dispatcher needs to be updated/checked
|
||||
# against that of the method.
|
||||
if disp.ast.sonsLen > resultPos and meth.ast.sonsLen > resultPos and
|
||||
if disp.ast.len > resultPos and meth.ast.len > resultPos and
|
||||
disp.ast.sons[resultPos].kind == nkEmpty:
|
||||
disp.ast.sons[resultPos] = copyTree(meth.ast.sons[resultPos])
|
||||
|
||||
@@ -198,7 +198,7 @@ proc relevantCol(methods: seq[PSym], col: int): bool =
|
||||
return true
|
||||
|
||||
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
|
||||
for col in 1 ..< sonsLen(a.typ):
|
||||
for col in 1 ..< len(a.typ):
|
||||
if contains(relevantCols, col):
|
||||
var aa = skipTypes(a.typ.sons[col], skipPtrs)
|
||||
var bb = skipTypes(b.typ.sons[col], skipPtrs)
|
||||
@@ -228,7 +228,7 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
|
||||
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
|
||||
var base = methods[0].ast[dispatcherPos].sym
|
||||
result = base
|
||||
var paramLen = sonsLen(base.typ)
|
||||
var paramLen = len(base.typ)
|
||||
var nilchecks = newNodeI(nkStmtList, base.info)
|
||||
var disp = newNodeI(nkIfStmt, base.info)
|
||||
var ands = getSysMagic(g, unknownLineInfo(), "and", mAnd)
|
||||
@@ -288,7 +288,7 @@ proc generateMethodDispatchers*(g: ModuleGraph): PNode =
|
||||
result = newNode(nkStmtList)
|
||||
for bucket in 0 ..< len(g.methods):
|
||||
var relevantCols = initIntSet()
|
||||
for col in 1 ..< sonsLen(g.methods[bucket].methods[0].typ):
|
||||
for col in 1 ..< len(g.methods[bucket].methods[0].typ):
|
||||
if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col)
|
||||
if optMultiMethods notin g.config.globalOptions:
|
||||
# if multi-methods are not enabled, we are interested only in the first field
|
||||
|
||||
@@ -90,9 +90,6 @@
|
||||
# :unrollFinally = true
|
||||
# goto nearestFinally (or -1 if not exists)
|
||||
#
|
||||
# Every finally block calls closureIterEndFinally() upon its successful
|
||||
# completion.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# try:
|
||||
@@ -126,6 +123,7 @@
|
||||
# if :curExc.isNil:
|
||||
# return :tmpResult
|
||||
# else:
|
||||
# closureIterSetupExc(nil)
|
||||
# raise
|
||||
# state = -1 # Goto next state. In this case we just exit
|
||||
# break :stateLoop
|
||||
@@ -174,7 +172,7 @@ proc newStateAssgn(ctx: var Ctx, toValue: PNode): PNode =
|
||||
proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode =
|
||||
# Creates state assignment:
|
||||
# :state = stateNo
|
||||
ctx.newStateAssgn(newIntTypeNode(nkIntLit, stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
|
||||
ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
|
||||
|
||||
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, name), ctx.fn, ctx.fn.info)
|
||||
@@ -359,7 +357,7 @@ proc addElseToExcept(ctx: var Ctx, n: PNode) =
|
||||
block: # :unrollFinally = true
|
||||
branchBody.add(newTree(nkAsgn,
|
||||
ctx.newUnrollFinallyAccess(n.info),
|
||||
newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool))))
|
||||
newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool))))
|
||||
|
||||
block: # :curExc = getCurrentException()
|
||||
branchBody.add(newTree(nkAsgn,
|
||||
@@ -603,7 +601,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
result.add(n)
|
||||
result.add(ctx.newEnvVarAccess(tmp))
|
||||
|
||||
of nkCallKinds:
|
||||
of nkCallKinds, nkChckRange, nkChckRangeF, nkChckRange64:
|
||||
var ns = false
|
||||
for i in 0 ..< n.len:
|
||||
n[i] = ctx.lowerStmtListExprs(n[i], ns)
|
||||
@@ -685,7 +683,8 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
n[0] = ex
|
||||
result.add(n)
|
||||
|
||||
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv:
|
||||
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv,
|
||||
nkDerefExpr, nkHiddenDeref:
|
||||
var ns = false
|
||||
for i in 0 ..< n.len:
|
||||
n[i] = ctx.lowerStmtListExprs(n[i], ns)
|
||||
@@ -759,7 +758,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
n[0] = newSymNode(ctx.g.getSysSym(n[0].info, "true"))
|
||||
n[1] = newBody
|
||||
|
||||
of nkDotExpr:
|
||||
of nkDotExpr, nkCheckedFieldExpr:
|
||||
var ns = false
|
||||
n[0] = ctx.lowerStmtListExprs(n[0], ns)
|
||||
if ns:
|
||||
@@ -809,10 +808,11 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
let retStmt = newTree(nkReturnStmt, asgn)
|
||||
let branch = newTree(nkElifBranch, cmp, retStmt)
|
||||
|
||||
# The C++ backend requires `getCurrentException` here.
|
||||
let raiseStmt = newTree(nkRaiseStmt, ctx.g.callCodegenProc("getCurrentException"))
|
||||
let nullifyExc = newTree(nkCall, newSymNode(ctx.g.getCompilerProc("closureIterSetupExc")), nilnode)
|
||||
nullifyExc.info = info
|
||||
let raiseStmt = newTree(nkRaiseStmt, curExc)
|
||||
raiseStmt.info = info
|
||||
let elseBranch = newTree(nkElse, raiseStmt)
|
||||
let elseBranch = newTree(nkElse, newTree(nkStmtList, nullifyExc, raiseStmt))
|
||||
|
||||
let ifBody = newTree(nkIfStmt, branch, elseBranch)
|
||||
let elifBranch = newTree(nkElifBranch, ctx.newUnrollFinallyAccess(info), ifBody)
|
||||
@@ -832,7 +832,7 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
|
||||
block: # :unrollFinally = true
|
||||
let asgn = newNodeI(nkAsgn, n.info)
|
||||
asgn.add(ctx.newUnrollFinallyAccess(n.info))
|
||||
asgn.add(newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool)))
|
||||
asgn.add(newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool)))
|
||||
result.add(asgn)
|
||||
|
||||
if n[0].kind != nkEmpty:
|
||||
@@ -1162,7 +1162,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
let cond = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(nkIntLit, 0, intTyp))
|
||||
newIntTypeNode(0, intTyp))
|
||||
cond.typ = boolTyp
|
||||
|
||||
let raiseStmt = newTree(nkRaiseStmt, ctx.g.emptyNode)
|
||||
@@ -1174,7 +1174,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
block:
|
||||
let cond = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
|
||||
newIntTypeNode(nkIntLit, 0, intTyp),
|
||||
newIntTypeNode(0, intTyp),
|
||||
ctx.newStateAccess())
|
||||
cond.typ = boolTyp
|
||||
|
||||
@@ -1186,7 +1186,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
let cond = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(nkIntLit, 0, intTyp))
|
||||
newIntTypeNode(0, intTyp))
|
||||
cond.typ = boolTyp
|
||||
|
||||
let negateState = newTree(nkCall,
|
||||
@@ -1287,9 +1287,9 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
|
||||
ctx.fn = fn
|
||||
|
||||
if getEnvParam(fn).isNil:
|
||||
# Lambda lifting was not done yet. Use temporary :state sym, which
|
||||
# Lambda lifting was not done yet. Use temporary :state sym, which will
|
||||
# be handled specially by lambda lifting. Local temp vars (if needed)
|
||||
# should folllow the same logic.
|
||||
# should follow the same logic.
|
||||
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
|
||||
ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
|
||||
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
|
||||
@@ -1310,7 +1310,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
|
||||
# Optimize empty states away
|
||||
ctx.deleteEmptyStates()
|
||||
|
||||
# Make new body by concating the list of states
|
||||
# Make new body by concatenating the list of states
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
for s in ctx.states:
|
||||
assert(s.len == 2)
|
||||
|
||||
@@ -13,6 +13,8 @@ import
|
||||
options, idents, nimconf, scriptconfig, extccomp, commands, msgs,
|
||||
lineinfos, modulegraphs, condsyms, os, pathutils
|
||||
|
||||
from strutils import normalize
|
||||
|
||||
type
|
||||
NimProg* = ref object
|
||||
suggestMode*: bool
|
||||
@@ -72,7 +74,11 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
||||
runNimScriptIfExists(scriptFile)
|
||||
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
|
||||
if fileExists(scriptFile) and scriptFile == conf.projectFull:
|
||||
return false
|
||||
if conf.command == "":
|
||||
conf.command = "e"
|
||||
return false
|
||||
elif conf.command.normalize == "e":
|
||||
return false
|
||||
else:
|
||||
if scriptFile != conf.projectFull:
|
||||
runNimScriptIfExists(scriptFile)
|
||||
@@ -81,7 +87,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
||||
discard
|
||||
|
||||
# now process command line arguments again, because some options in the
|
||||
# command line can overwite the config file's settings
|
||||
# command line can overwrite the config file's settings
|
||||
extccomp.initVars(conf)
|
||||
self.processCmdLine(passCmd2, "", conf)
|
||||
if conf.command == "":
|
||||
|
||||
@@ -266,7 +266,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
||||
of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
|
||||
of "stacktrace": result = contains(conf.options, optStackTrace)
|
||||
of "linetrace": result = contains(conf.options, optLineTrace)
|
||||
of "debugger": result = contains(conf.options, optEndb)
|
||||
of "debugger": result = contains(conf.globalOptions, optCDebug)
|
||||
of "profiler": result = contains(conf.options, optProfiler)
|
||||
of "memtracker": result = contains(conf.options, optMemTracker)
|
||||
of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
|
||||
@@ -380,6 +380,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "nonimblepath", "nobabelpath":
|
||||
expectNoArg(conf, switch, arg, pass, info)
|
||||
disableNimblePath(conf)
|
||||
of "clearnimblepath":
|
||||
expectNoArg(conf, switch, arg, pass, info)
|
||||
clearNimblePath(conf)
|
||||
of "excludepath":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
let path = processPath(conf, arg, info)
|
||||
@@ -387,15 +390,15 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
conf.lazyPaths.keepItIf(it != path)
|
||||
of "nimcache":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.nimcacheDir = processPath(conf, arg, info, true)
|
||||
conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
|
||||
of "out", "o":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
let f = splitFile(arg.expandTilde)
|
||||
let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
|
||||
conf.outFile = RelativeFile f.name & f.ext
|
||||
conf.outDir = toAbsoluteDir f.dir
|
||||
of "outdir":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.outDir = toAbsoluteDir arg.expandTilde
|
||||
conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
|
||||
of "docseesrcurl":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.docSeeSrcUrl = arg
|
||||
@@ -437,30 +440,31 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
processOnOffSwitchG(conf, {optWholeProject}, arg, pass, info)
|
||||
of "gc":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
case arg.normalize
|
||||
of "boehm":
|
||||
conf.selectedGC = gcBoehm
|
||||
defineSymbol(conf.symbols, "boehmgc")
|
||||
of "refc":
|
||||
conf.selectedGC = gcRefc
|
||||
of "v2":
|
||||
message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
|
||||
of "markandsweep":
|
||||
conf.selectedGC = gcMarkAndSweep
|
||||
defineSymbol(conf.symbols, "gcmarkandsweep")
|
||||
of "destructors":
|
||||
conf.selectedGC = gcDestructors
|
||||
defineSymbol(conf.symbols, "gcdestructors")
|
||||
of "go":
|
||||
conf.selectedGC = gcGo
|
||||
defineSymbol(conf.symbols, "gogc")
|
||||
of "none":
|
||||
conf.selectedGC = gcNone
|
||||
defineSymbol(conf.symbols, "nogc")
|
||||
of "stack", "regions":
|
||||
conf.selectedGC= gcRegions
|
||||
defineSymbol(conf.symbols, "gcregions")
|
||||
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
||||
if pass in {passCmd2, passPP}:
|
||||
case arg.normalize
|
||||
of "boehm":
|
||||
conf.selectedGC = gcBoehm
|
||||
defineSymbol(conf.symbols, "boehmgc")
|
||||
of "refc":
|
||||
conf.selectedGC = gcRefc
|
||||
of "v2":
|
||||
message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
|
||||
of "markandsweep":
|
||||
conf.selectedGC = gcMarkAndSweep
|
||||
defineSymbol(conf.symbols, "gcmarkandsweep")
|
||||
of "destructors":
|
||||
conf.selectedGC = gcDestructors
|
||||
defineSymbol(conf.symbols, "gcdestructors")
|
||||
of "go":
|
||||
conf.selectedGC = gcGo
|
||||
defineSymbol(conf.symbols, "gogc")
|
||||
of "none":
|
||||
conf.selectedGC = gcNone
|
||||
defineSymbol(conf.symbols, "nogc")
|
||||
of "stack", "regions":
|
||||
conf.selectedGC= gcRegions
|
||||
defineSymbol(conf.symbols, "gcregions")
|
||||
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
|
||||
of "warnings", "w":
|
||||
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
|
||||
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
|
||||
@@ -473,24 +477,18 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
|
||||
of "debugger":
|
||||
case arg.normalize
|
||||
of "on", "endb":
|
||||
conf.options.incl optEndb
|
||||
defineSymbol(conf.symbols, "endb")
|
||||
of "off":
|
||||
conf.options.excl optEndb
|
||||
undefSymbol(conf.symbols, "endb")
|
||||
of "native", "gdb":
|
||||
incl(conf.globalOptions, optCDebug)
|
||||
conf.options = conf.options + {optLineDir} - {optEndb}
|
||||
of "on", "native", "gdb":
|
||||
conf.globalOptions.incl optCDebug
|
||||
conf.options.incl optLineDir
|
||||
#defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
|
||||
undefSymbol(conf.symbols, "endb")
|
||||
of "off":
|
||||
conf.globalOptions.excl optCDebug
|
||||
else:
|
||||
localError(conf, info, "expected endb|gdb but found " & arg)
|
||||
localError(conf, info, "expected native|gdb|on|off but found " & arg)
|
||||
of "g": # alias for --debugger:native
|
||||
incl(conf.globalOptions, optCDebug)
|
||||
conf.options = conf.options + {optLineDir} - {optEndb}
|
||||
conf.globalOptions.incl optCDebug
|
||||
conf.options.incl optLineDir
|
||||
#defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
|
||||
undefSymbol(conf.symbols, "endb")
|
||||
of "profiler":
|
||||
processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
|
||||
if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
|
||||
@@ -619,22 +617,20 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
processOnOffSwitchG(conf, {optGenMapping}, arg, pass, info)
|
||||
of "os":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd1, passPP}:
|
||||
let theOS = platform.nameToOS(arg)
|
||||
if theOS == osNone:
|
||||
let osList = platform.listOSnames().join(", ")
|
||||
localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
|
||||
elif theOS != conf.target.hostOS:
|
||||
setTarget(conf.target, theOS, conf.target.targetCPU)
|
||||
let theOS = platform.nameToOS(arg)
|
||||
if theOS == osNone:
|
||||
let osList = platform.listOSnames().join(", ")
|
||||
localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
|
||||
else:
|
||||
setTarget(conf.target, theOS, conf.target.targetCPU)
|
||||
of "cpu":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
if pass in {passCmd1, passPP}:
|
||||
let cpu = platform.nameToCPU(arg)
|
||||
if cpu == cpuNone:
|
||||
let cpuList = platform.listCPUnames().join(", ")
|
||||
localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
|
||||
elif cpu != conf.target.hostCPU:
|
||||
setTarget(conf.target, conf.target.targetOS, cpu)
|
||||
let cpu = platform.nameToCPU(arg)
|
||||
if cpu == cpuNone:
|
||||
let cpuList = platform.listCPUnames().join(", ")
|
||||
localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
|
||||
else:
|
||||
setTarget(conf.target, conf.target.targetOS, cpu)
|
||||
of "run", "r":
|
||||
processOnOffSwitchG(conf, {optRun}, arg, pass, info)
|
||||
of "errormax":
|
||||
@@ -763,7 +759,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
if pass in {passCmd2, passPP}:
|
||||
doAssert(conf != nil)
|
||||
incl(conf.features, destructor)
|
||||
incl(conf.globalOptions, optNimV2)
|
||||
incl(conf.globalOptions, optTinyRtti)
|
||||
incl(conf.globalOptions, optOwnedRefs)
|
||||
incl(conf.globalOptions, optSeqDestructors)
|
||||
defineSymbol(conf.symbols, "nimV2")
|
||||
conf.selectedGC = gcDestructors
|
||||
defineSymbol(conf.symbols, "gcdestructors")
|
||||
@@ -788,13 +786,22 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "expandmacro":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.macrosToExpand[arg] = "T"
|
||||
of "oldgensym":
|
||||
processOnOffSwitchG(conf, {optNimV019}, arg, pass, info)
|
||||
of "useversion":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
case arg
|
||||
of "1.0":
|
||||
discard "the default"
|
||||
else:
|
||||
localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
|
||||
of "":
|
||||
conf.projectName = "-"
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
|
||||
else: invalidCmdLineOption(conf, pass, switch, info)
|
||||
|
||||
template gCmdLineInfo*(): untyped = newLineInfo(config, AbsoluteFile"command line", 1, 1)
|
||||
template gCmdLineInfo*(): untyped = newLineInfo(commandLineIdx, 1, 1)
|
||||
|
||||
proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
|
||||
var cmd, arg: string
|
||||
|
||||
@@ -87,6 +87,7 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasDefault")
|
||||
defineSymbol("nimMacrosSizealignof")
|
||||
defineSymbol("nimNoZeroExtendMagic")
|
||||
defineSymbol("nimMacrosGetNodeId")
|
||||
for f in low(Feature)..high(Feature):
|
||||
defineSymbol("nimHas" & $f)
|
||||
|
||||
@@ -97,3 +98,5 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
|
||||
defineSymbol("nimFixedOwned")
|
||||
defineSymbol("nimHasStyleChecks")
|
||||
defineSymbol("nimToOpenArrayCString")
|
||||
defineSymbol("nimHasUsed")
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2019 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
|
||||
lineinfos, parampatterns
|
||||
|
||||
##[
|
||||
This module implements "cursor" detection. A cursor is a local variable
|
||||
that is used for navigation in a datastructure, it does not "own" the
|
||||
data it aliases but it might update the underlying datastructure.
|
||||
|
||||
Two primary examples for cursors that I have in mind and that are critical
|
||||
for optimization:
|
||||
|
||||
1. Local string variable introduced by ``for x in a``::
|
||||
|
||||
var i = 0
|
||||
while i < a.len:
|
||||
let cursor = a[i]
|
||||
use cursor
|
||||
inc i
|
||||
|
||||
2. Local ``ref`` variable for navigation::
|
||||
|
||||
var cursor = listHead
|
||||
while cursor != nil:
|
||||
use cursor
|
||||
cursor = cursor.next
|
||||
|
||||
Cursors are very interesting for the optimizer because they can be copyMem'ed
|
||||
and don't need a destructor.
|
||||
|
||||
More formally, a cursor is a variable that is set on all paths to
|
||||
a *location* or a proc call that produced a ``lent/var`` type. All statements
|
||||
that come after these assignments MUST not mutate what the cursor aliases.
|
||||
|
||||
Mutations *through* the cursor are allowed if the cursor has ref semantics.
|
||||
|
||||
Look at this complex real world example taken from the compiler itself:
|
||||
|
||||
.. code-block:: Nim
|
||||
|
||||
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
||||
var t = typ
|
||||
while true:
|
||||
if t.sym != nil and {sfImportc, sfExportc} * t.sym.flags != {}:
|
||||
return t.sym.loc.r
|
||||
|
||||
if t.kind in irrelevantForBackend:
|
||||
t = t.lastSon
|
||||
else:
|
||||
break
|
||||
let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.lastSon else: typ
|
||||
if typ.loc.r == nil:
|
||||
typ.loc.r = typ.typeName & $sig
|
||||
result = typ.loc.r
|
||||
if result == nil: internalError(m.config, "getTypeName: " & $typ.kind)
|
||||
|
||||
Here `t` is a cursor but without a control flow based analysis we are unlikely
|
||||
to detect it.
|
||||
|
||||
]##
|
||||
|
||||
# Araq: I owe you an implementation. For now use the .cursor pragma. :-/
|
||||
@@ -34,14 +34,14 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
||||
let b = Backend(g.graph.backend)
|
||||
case n.kind
|
||||
of nkImportStmt:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var imported = getModuleName(g.config, n.sons[i])
|
||||
addDependencyAux(b, g.module.name.s, imported)
|
||||
of nkFromStmt, nkImportExceptStmt:
|
||||
var imported = getModuleName(g.config, n.sons[0])
|
||||
addDependencyAux(b, g.module.name.s, imported)
|
||||
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
|
||||
for i in 0 ..< sonsLen(n): discard addDotDependency(c, n.sons[i])
|
||||
for i in 0 ..< len(n): discard addDotDependency(c, n.sons[i])
|
||||
else:
|
||||
discard
|
||||
|
||||
|
||||
@@ -513,7 +513,7 @@ proc genTry(c: var Con; n: PNode) =
|
||||
let f = c.tryStmtFixups[i]
|
||||
c.patch(f)
|
||||
# we also need to produce join instructions
|
||||
# for the 'fork' that might preceed the goto instruction
|
||||
# for the 'fork' that might precede the goto instruction
|
||||
if f.int-1 >= 0 and c.code[f.int-1].kind == fork:
|
||||
c.joinI(TPosition(f.int-1), n)
|
||||
|
||||
@@ -607,14 +607,9 @@ proc aliases(obj, field: PNode): bool =
|
||||
if sameTrees(obj, n): return true
|
||||
case n.kind
|
||||
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
|
||||
nkObjDownConv, nkObjUpConv, nkHiddenDeref, nkDerefExpr:
|
||||
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr, nkBracketExpr,
|
||||
nkHiddenDeref, nkDerefExpr:
|
||||
n = n[0]
|
||||
of nkBracketExpr:
|
||||
let x = n[0]
|
||||
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
|
||||
n = x
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
return false
|
||||
@@ -652,7 +647,7 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
|
||||
while true:
|
||||
case n.kind
|
||||
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
|
||||
nkObjDownConv, nkObjUpConv:
|
||||
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr, nkBracketExpr:
|
||||
n = n[0]
|
||||
of nkHiddenDeref, nkDerefExpr:
|
||||
# We "own" sinkparam[].loc but not ourVar[].location as it is a nasty
|
||||
@@ -660,12 +655,6 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
|
||||
n = n[0]
|
||||
return n.kind == nkSym and n.sym.owner == owner and (isSinkParam(n.sym) or
|
||||
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
|
||||
of nkBracketExpr:
|
||||
let x = n[0]
|
||||
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
|
||||
n = x
|
||||
else:
|
||||
break
|
||||
else:
|
||||
break
|
||||
# XXX Allow closure deref operations here if we know
|
||||
|
||||
@@ -26,6 +26,7 @@ type
|
||||
TSections = array[TSymKind, Rope]
|
||||
TDocumentor = object of rstgen.RstGenerator
|
||||
modDesc: Rope # module description
|
||||
module: PSym
|
||||
modDeprecationMsg: Rope
|
||||
toc, section: TSections
|
||||
indexValFilename: string
|
||||
@@ -115,9 +116,10 @@ proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
|
||||
else:
|
||||
result = getOutFile(conf, filename, ext)
|
||||
|
||||
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, outExt: string = HtmlExt): PDoc =
|
||||
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, outExt: string = HtmlExt, module: PSym = nil): PDoc =
|
||||
declareClosures()
|
||||
new(result)
|
||||
result.module = module
|
||||
result.conf = conf
|
||||
result.cache = cache
|
||||
initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
|
||||
@@ -406,6 +408,7 @@ proc runAllExamples(d: PDoc) =
|
||||
elif isDefined(d.conf, "objc"): "objc"
|
||||
else: "c"
|
||||
if os.execShellCmd(os.getAppFilename() & " " & backend &
|
||||
" --warning[UnusedImport]:off" &
|
||||
" --path:" & quoteShell(d.conf.projectPath) &
|
||||
" --nimcache:" & quoteShell(outputDir) &
|
||||
" -r " & quoteShell(outp)) != 0:
|
||||
@@ -415,12 +418,6 @@ proc runAllExamples(d: PDoc) =
|
||||
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
|
||||
removeFile(outp.changeFileExt(ExeExt))
|
||||
|
||||
proc extractImports(n: PNode; result: PNode) =
|
||||
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
|
||||
result.add copyTree(n)
|
||||
n.kind = nkEmpty
|
||||
return
|
||||
for i in 0..<n.safeLen: extractImports(n[i], result)
|
||||
|
||||
proc prepareExamples(d: PDoc; n: PNode) =
|
||||
var docComment = newTree(nkCommentStmt)
|
||||
@@ -430,12 +427,20 @@ proc prepareExamples(d: PDoc; n: PNode) =
|
||||
docComment,
|
||||
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
|
||||
runnableExamples.info = n.info
|
||||
let imports = newTree(nkStmtList)
|
||||
var savedLastSon = copyTree n.lastSon
|
||||
extractImports(savedLastSon, imports)
|
||||
for imp in imports: runnableExamples.add imp
|
||||
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
|
||||
for a in n.lastSon: runnableExamples.add a
|
||||
testExample(d, runnableExamples)
|
||||
when false:
|
||||
proc extractImports(n: PNode; result: PNode) =
|
||||
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
|
||||
result.add copyTree(n)
|
||||
n.kind = nkEmpty
|
||||
return
|
||||
for i in 0..<n.safeLen: extractImports(n[i], result)
|
||||
let imports = newTree(nkStmtList)
|
||||
var savedLastSon = copyTree n.lastSon
|
||||
extractImports(savedLastSon, imports)
|
||||
for imp in imports: runnableExamples.add imp
|
||||
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
|
||||
|
||||
proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
|
||||
if n.info.fileIndex != orig.info.fileIndex: return
|
||||
@@ -589,7 +594,7 @@ proc docstringSummary(rstText: string): string =
|
||||
##
|
||||
## Most docstrings will contain a one liner summary, so stripping at the
|
||||
## first newline is usually fine. If after that the content is still too big,
|
||||
## it is stripped at the first comma, colon or dot, usual english sentence
|
||||
## it is stripped at the first comma, colon or dot, usual English sentence
|
||||
## separators.
|
||||
##
|
||||
## No guarantees are made on the size of the output, but it should be small.
|
||||
@@ -628,8 +633,12 @@ proc genDeprecationMsg(d: PDoc, n: PNode): Rope =
|
||||
else:
|
||||
doAssert false
|
||||
|
||||
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||
if not isVisible(d, nameNode): return
|
||||
type DocFlags = enum
|
||||
kDefault
|
||||
kForceExport
|
||||
|
||||
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
|
||||
if (docFlags != kForceExport) and not isVisible(d, nameNode): return
|
||||
let
|
||||
name = getName(d, nameNode)
|
||||
nameRope = name.rope
|
||||
@@ -845,7 +854,9 @@ proc documentRaises*(cache: IdentCache; n: PNode) =
|
||||
if p4 != nil: n.sons[pragmasPos].add p4
|
||||
if p5 != nil: n.sons[pragmasPos].add p5
|
||||
|
||||
proc generateDoc*(d: PDoc, n, orig: PNode) =
|
||||
proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
|
||||
template genItemAux(skind) =
|
||||
genItem(d, n, n[namePos], skind, docFlags)
|
||||
case n.kind
|
||||
of nkPragma:
|
||||
let pragmaNode = findPragma(n, wDeprecated)
|
||||
@@ -853,29 +864,29 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
|
||||
of nkCommentStmt: add(d.modDesc, genComment(d, n))
|
||||
of nkProcDef:
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
genItem(d, n, n.sons[namePos], skProc)
|
||||
genItemAux(skProc)
|
||||
of nkFuncDef:
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
genItem(d, n, n.sons[namePos], skFunc)
|
||||
genItemAux(skFunc)
|
||||
of nkMethodDef:
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
genItem(d, n, n.sons[namePos], skMethod)
|
||||
genItemAux(skMethod)
|
||||
of nkIteratorDef:
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
genItem(d, n, n.sons[namePos], skIterator)
|
||||
of nkMacroDef: genItem(d, n, n.sons[namePos], skMacro)
|
||||
of nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate)
|
||||
genItemAux(skIterator)
|
||||
of nkMacroDef: genItemAux(skMacro)
|
||||
of nkTemplateDef: genItemAux(skTemplate)
|
||||
of nkConverterDef:
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
genItem(d, n, n.sons[namePos], skConverter)
|
||||
genItemAux(skConverter)
|
||||
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if n.sons[i].kind != nkCommentStmt:
|
||||
# order is always 'type var let const':
|
||||
genItem(d, n.sons[i], n.sons[i].sons[0],
|
||||
succ(skType, ord(n.kind)-ord(nkTypeSection)))
|
||||
genItem(d, n[i], n[i][0],
|
||||
succ(skType, ord(n.kind)-ord(nkTypeSection)), docFlags)
|
||||
of nkStmtList:
|
||||
for i in 0 ..< sonsLen(n): generateDoc(d, n.sons[i], orig)
|
||||
for i in 0 ..< len(n): generateDoc(d, n.sons[i], orig)
|
||||
of nkWhenStmt:
|
||||
# generate documentation for the first branch only:
|
||||
if not checkForFalse(n.sons[0].sons[0]):
|
||||
@@ -884,7 +895,11 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
|
||||
for it in n: traceDeps(d, it)
|
||||
of nkExportStmt:
|
||||
for it in n:
|
||||
if it.kind == nkSym: exportSym(d, it.sym)
|
||||
if it.kind == nkSym:
|
||||
if d.module != nil and d.module == it.sym.owner:
|
||||
generateDoc(d, it.sym.ast, orig, kForceExport)
|
||||
else:
|
||||
exportSym(d, it.sym)
|
||||
of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
|
||||
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
|
||||
of nkCallKinds:
|
||||
@@ -923,13 +938,13 @@ proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
d.add genJsonItem(d, n, n.sons[namePos], skConverter)
|
||||
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if n.sons[i].kind != nkCommentStmt:
|
||||
# order is always 'type var let const':
|
||||
d.add genJsonItem(d, n.sons[i], n.sons[i].sons[0],
|
||||
succ(skType, ord(n.kind)-ord(nkTypeSection)))
|
||||
of nkStmtList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
generateJson(d, n.sons[i], includeComments)
|
||||
of nkWhenStmt:
|
||||
# generate documentation for the first branch only:
|
||||
@@ -966,13 +981,13 @@ proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
|
||||
when useEffectSystem: documentRaises(d.cache, n)
|
||||
r.add genTagsItem(d, n, n.sons[namePos], skConverter)
|
||||
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if n.sons[i].kind != nkCommentStmt:
|
||||
# order is always 'type var let const':
|
||||
r.add genTagsItem(d, n.sons[i], n.sons[i].sons[0],
|
||||
succ(skType, ord(n.kind)-ord(nkTypeSection)))
|
||||
of nkStmtList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
generateTags(d, n.sons[i], r)
|
||||
of nkWhenStmt:
|
||||
# generate documentation for the first branch only:
|
||||
@@ -1166,6 +1181,9 @@ proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
|
||||
["Index".rope, nil, nil, rope(getDateStr()),
|
||||
rope(getClockStr()), content, nil, nil, nil])
|
||||
# no analytics because context is not available
|
||||
let filename = getOutFile(conf, RelativeFile"theindex", HtmlExt)
|
||||
var outFile = RelativeFile"theindex"
|
||||
if conf.outFile != RelativeFile"":
|
||||
outFile = conf.outFile
|
||||
let filename = getOutFile(conf, outFile, HtmlExt)
|
||||
if not writeRope(code, filename):
|
||||
rawMessage(conf, errCannotOpenFile, filename.string)
|
||||
|
||||
@@ -62,7 +62,7 @@ template myOpenImpl(ext: untyped) {.dirty.} =
|
||||
g.module = module
|
||||
g.config = graph.config
|
||||
var d = newDocumentor(AbsoluteFile toFullPath(graph.config, FileIndex module.position),
|
||||
graph.cache, graph.config, ext)
|
||||
graph.cache, graph.config, ext, module)
|
||||
d.hasToc = true
|
||||
g.doc = d
|
||||
result = g
|
||||
|
||||
@@ -63,9 +63,9 @@ proc importcSymbol*(conf: ConfigRef, sym: PSym): PNode =
|
||||
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
|
||||
globalError(conf, sym.info, "dynlib needs to be a string lit")
|
||||
var theAddr: pointer
|
||||
if (lib.isNil or lib.kind == libHeader) and not gExehandle.isNil:
|
||||
if (lib.isNil or lib.kind == libHeader) and not gExeHandle.isNil:
|
||||
# first try this exe itself:
|
||||
theAddr = gExehandle.symAddr(name)
|
||||
theAddr = gExeHandle.symAddr(name)
|
||||
# then try libc:
|
||||
if theAddr.isNil:
|
||||
let dllhandle = getDll(conf, gDllCache, libcDll, sym.info)
|
||||
@@ -138,13 +138,13 @@ proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer)
|
||||
proc getField(conf: ConfigRef, n: PNode; position: int): PSym =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result = getField(conf, n.sons[i], position)
|
||||
if result != nil: return
|
||||
of nkRecCase:
|
||||
result = getField(conf, n.sons[0], position)
|
||||
if result != nil: return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
result = getField(conf, lastSon(n.sons[i]), position)
|
||||
@@ -158,7 +158,7 @@ proc packObject(conf: ConfigRef, x: PNode, typ: PType, res: pointer) =
|
||||
internalAssert conf, x.kind in {nkObjConstr, nkPar, nkTupleConstr}
|
||||
# compute the field's offsets:
|
||||
discard getSize(conf, typ)
|
||||
for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
|
||||
for i in ord(x.kind == nkObjConstr) ..< len(x):
|
||||
var it = x.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
internalAssert conf, it.sons[0].kind == nkSym
|
||||
@@ -245,7 +245,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode
|
||||
proc unpackObjectAdd(conf: ConfigRef, x: pointer, n, result: PNode) =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
unpackObjectAdd(conf, x, n.sons[i], result)
|
||||
of nkRecCase:
|
||||
globalError(conf, result.info, "case objects cannot be unpacked")
|
||||
@@ -275,7 +275,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
globalError(conf, n.info, "cannot map value from FFI")
|
||||
if typ.n.isNil:
|
||||
globalError(conf, n.info, "cannot unpack unnamed tuple")
|
||||
for i in ord(n.kind == nkObjConstr) ..< sonsLen(n):
|
||||
for i in ord(n.kind == nkObjConstr) ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
internalAssert conf, it.sons[0].kind == nkSym
|
||||
@@ -289,7 +289,7 @@ proc unpackArray(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
if n.isNil:
|
||||
result = newNode(nkBracket)
|
||||
result.typ = typ
|
||||
newSeq(result.sons, lengthOrd(conf, typ).int)
|
||||
newSeq(result.sons, lengthOrd(conf, typ).toInt)
|
||||
else:
|
||||
result = n
|
||||
if result.kind != nkBracket:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## Template evaluation engine. Now hygienic.
|
||||
|
||||
import
|
||||
strutils, options, ast, astalgo, msgs, renderer, lineinfos
|
||||
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents
|
||||
|
||||
type
|
||||
TemplCtx = object
|
||||
@@ -20,6 +20,7 @@ type
|
||||
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
|
||||
# new symbol
|
||||
config: ConfigRef
|
||||
ic: IdentCache
|
||||
|
||||
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
|
||||
result = copyNode(a)
|
||||
@@ -37,7 +38,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
of nkSym:
|
||||
var s = templ.sym
|
||||
if (s.owner == nil and s.kind == skParam) or s.owner == c.owner:
|
||||
if s.kind == skParam and sfGenSym notin s.flags:
|
||||
if s.kind == skParam and {sfGenSym, sfTemplateParam} * s.flags == {sfTemplateParam}:
|
||||
handleParam actual.sons[s.position]
|
||||
elif (s.owner != nil) and (s.kind == skGenericParam or
|
||||
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
|
||||
@@ -52,7 +53,11 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
#if x.kind == skParam and x.owner.kind == skModule:
|
||||
# internalAssert c.config, false
|
||||
idTablePut(c.mapping, s, x)
|
||||
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
|
||||
if sfGenSym in s.flags and optNimV019 notin c.config.globalOptions:
|
||||
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
|
||||
if c.instLines: actual.info else: templ.info)
|
||||
else:
|
||||
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
|
||||
else:
|
||||
result.add copyNode(c, templ, actual)
|
||||
of nkNone..nkIdent, nkType..nkNilLit: # atom
|
||||
@@ -63,7 +68,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
# "declarative" context (bug #9235).
|
||||
if c.isDeclarative:
|
||||
var res = copyNode(c, templ, actual)
|
||||
for i in 0 ..< sonsLen(templ):
|
||||
for i in 0 ..< len(templ):
|
||||
evalTemplateAux(templ.sons[i], actual, c, res)
|
||||
result.add res
|
||||
else:
|
||||
@@ -77,7 +82,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
c.isDeclarative = true
|
||||
isDeclarative = true
|
||||
var res = copyNode(c, templ, actual)
|
||||
for i in 0 ..< sonsLen(templ):
|
||||
for i in 0 ..< len(templ):
|
||||
evalTemplateAux(templ.sons[i], actual, c, res)
|
||||
result.add res
|
||||
if isDeclarative: c.isDeclarative = false
|
||||
@@ -130,7 +135,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
|
||||
else:
|
||||
addSon(result, default.copyTree)
|
||||
|
||||
# add any generic paramaters
|
||||
# add any generic parameters
|
||||
for i in 1 .. genericParams:
|
||||
result.addSon n.sons[givenRegularParams + i]
|
||||
|
||||
@@ -160,7 +165,9 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
|
||||
result.typ = res.typ
|
||||
|
||||
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||
conf: ConfigRef; fromHlo=false): PNode =
|
||||
conf: ConfigRef;
|
||||
ic: IdentCache;
|
||||
fromHlo=false): PNode =
|
||||
inc(conf.evalTemplateCounter)
|
||||
if conf.evalTemplateCounter > evalTemplateLimit:
|
||||
globalError(conf, n.info, errTemplateInstantiationTooNested)
|
||||
@@ -172,6 +179,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||
ctx.owner = tmpl
|
||||
ctx.genSymOwner = genSymOwner
|
||||
ctx.config = conf
|
||||
ctx.ic = ic
|
||||
initIdTable(ctx.mapping)
|
||||
|
||||
let body = tmpl.getBody
|
||||
|
||||
@@ -138,7 +138,7 @@ compiler vcc:
|
||||
optSize: " /O1 /G7 ",
|
||||
compilerExe: "cl",
|
||||
cppCompiler: "cl",
|
||||
compileTmpl: "/c$vccplatform$options $include /Fo$objfile $file",
|
||||
compileTmpl: "/c$vccplatform $options $include /Fo$objfile $file",
|
||||
buildGui: " /link /SUBSYSTEM:WINDOWS ",
|
||||
buildDll: " /LD",
|
||||
buildLib: "lib /OUT:$libfile $objfiles",
|
||||
@@ -404,7 +404,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
|
||||
CC[c].name & fullSuffix
|
||||
result = getConfigVar(conf, fullCCname)
|
||||
if result.len == 0:
|
||||
# not overriden for this cross compilation setting?
|
||||
# not overridden for this cross compilation setting?
|
||||
result = getConfigVar(conf, CC[c].name & fullSuffix)
|
||||
else:
|
||||
result = getConfigVar(conf, CC[c].name & fullSuffix)
|
||||
@@ -757,7 +757,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
|
||||
# way of being able to debug and rebuild the program at the same time. This
|
||||
# is accomplished using the /PDB:<filename> flag (there also exists the
|
||||
# /PDBALTPATH:<filename> flag). The only downside is that the .pdb files are
|
||||
# atleast 300kb big (when linking statically to the runtime - or else 5mb+)
|
||||
# at least 300kb big (when linking statically to the runtime - or else 5mb+)
|
||||
# and will quickly accumulate. There is a hacky solution: we could try to
|
||||
# delete all .pdb files with a pattern and swallow exceptions.
|
||||
#
|
||||
@@ -947,7 +947,9 @@ proc callCCompiler*(conf: ConfigRef) =
|
||||
generateScript(conf, script)
|
||||
|
||||
#from json import escapeJson
|
||||
import json
|
||||
import json, std / sha1
|
||||
|
||||
template hashNimExe(): string = $secureHashFile(os.getAppFilename())
|
||||
|
||||
proc writeJsonBuildInstructions*(conf: ConfigRef) =
|
||||
template lit(x: untyped) = f.write x
|
||||
@@ -960,17 +962,17 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
|
||||
f.write escapeJson(x)
|
||||
|
||||
proc cfiles(conf: ConfigRef; f: File; buf: var string; clist: CfileList, isExternal: bool) =
|
||||
var pastStart = false
|
||||
var i = 0
|
||||
for it in clist:
|
||||
if CfileFlag.Cached in it.flags: continue
|
||||
let compileCmd = getCompileCFileCmd(conf, it)
|
||||
if pastStart: lit "],\L"
|
||||
if i > 0: lit ",\L"
|
||||
lit "["
|
||||
str it.cname.string
|
||||
lit ", "
|
||||
str compileCmd
|
||||
pastStart = true
|
||||
lit "]\L"
|
||||
lit "]"
|
||||
inc i
|
||||
|
||||
proc linkfiles(conf: ConfigRef; f: File; buf, objfiles: var string; clist: CfileList;
|
||||
llist: seq[string]) =
|
||||
@@ -994,6 +996,20 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
|
||||
pastStart = true
|
||||
lit "\L"
|
||||
|
||||
proc depfiles(conf: ConfigRef; f: File) =
|
||||
var i = 0
|
||||
for it in conf.m.fileInfos:
|
||||
let path = it.fullPath.string
|
||||
if isAbsolute(path): # TODO: else?
|
||||
if i > 0: lit "],\L"
|
||||
lit "["
|
||||
str path
|
||||
lit ", "
|
||||
str $secureHashFile(path)
|
||||
inc i
|
||||
lit "]\L"
|
||||
|
||||
|
||||
var buf = newStringOfCap(50)
|
||||
|
||||
let jsonFile = conf.getNimcacheDir / RelativeFile(conf.projectName & ".json")
|
||||
@@ -1009,9 +1025,48 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
|
||||
|
||||
lit "],\L\"linkcmd\": "
|
||||
str getLinkCmd(conf, conf.absOutFile, objfiles)
|
||||
|
||||
if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"):
|
||||
lit ",\L\"cmdline\": "
|
||||
str conf.commandLine
|
||||
lit ",\L\"depfiles\":[\L"
|
||||
depfiles(conf, f)
|
||||
lit "],\L\"nimexe\": \L"
|
||||
str hashNimExe()
|
||||
lit "\L"
|
||||
|
||||
lit "\L}\L"
|
||||
close(f)
|
||||
|
||||
proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile): bool =
|
||||
let jsonFile = toGeneratedFile(conf, projectfile, "json")
|
||||
if not fileExists(jsonFile): return true
|
||||
if not fileExists(conf.absOutFile): return true
|
||||
result = false
|
||||
try:
|
||||
let data = json.parseFile(jsonFile.string)
|
||||
if not data.hasKey("depfiles") or not data.hasKey("cmdline"):
|
||||
return true
|
||||
let oldCmdLine = data["cmdline"].getStr
|
||||
if conf.commandLine != oldCmdLine:
|
||||
return true
|
||||
if hashNimExe() != data["nimexe"].getStr:
|
||||
return true
|
||||
let depfilesPairs = data["depfiles"]
|
||||
doAssert depfilesPairs.kind == JArray
|
||||
for p in depfilesPairs:
|
||||
doAssert p.kind == JArray
|
||||
# >= 2 for forwards compatibility with potential later .json files:
|
||||
doAssert p.len >= 2
|
||||
let depFilename = p[0].getStr
|
||||
let oldHashValue = p[1].getStr
|
||||
let newHashValue = $secureHashFile(depFilename)
|
||||
if oldHashValue != newHashValue:
|
||||
return true
|
||||
except IOError, OSError, ValueError:
|
||||
echo "Warning: JSON processing failed: ", getCurrentExceptionMsg()
|
||||
result = true
|
||||
|
||||
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
let jsonFile = toGeneratedFile(conf, projectfile, "json")
|
||||
try:
|
||||
@@ -1026,7 +1081,7 @@ proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
|
||||
|
||||
add(cmds, c[1].getStr)
|
||||
let (_, name, _) = splitFile(c[0].getStr)
|
||||
add(prettyCmds, "CC: " & name)
|
||||
add(prettyCmds, "CC: " & demanglePackageName(name))
|
||||
|
||||
let prettyCb = proc (idx: int) =
|
||||
when declared(echo):
|
||||
|
||||
@@ -22,7 +22,7 @@ type
|
||||
info: TLineInfo
|
||||
indent, emitPar: int
|
||||
x: string # the current input line
|
||||
outp: PLLStream # the ouput will be parsed by pnimsyn
|
||||
outp: PLLStream # the output will be parsed by pnimsyn
|
||||
subsChar, nimDirective: char
|
||||
emit, conc, toStr: string
|
||||
curly, bracket, par: int
|
||||
|
||||
@@ -20,7 +20,7 @@ proc invalidPragma(conf: ConfigRef; n: PNode) =
|
||||
proc getArg(conf: ConfigRef; n: PNode, name: string, pos: int): PNode =
|
||||
result = nil
|
||||
if n.kind in {nkEmpty..nkNilLit}: return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if n.sons[i].kind == nkExprEqExpr:
|
||||
if n.sons[i].sons[0].kind != nkIdent: invalidPragma(conf, n)
|
||||
if cmpIgnoreStyle(n.sons[i].sons[0].ident.s, name) == 0:
|
||||
|
||||
@@ -40,6 +40,7 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
|
||||
p.inputStream.write(input)
|
||||
p.inputStream.close()
|
||||
result = p.readOutput
|
||||
p.close()
|
||||
readSuccessful = true
|
||||
# only cache successful runs:
|
||||
if result[1] == 0:
|
||||
@@ -54,5 +55,6 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
|
||||
p.inputStream.write(input)
|
||||
p.inputStream.close()
|
||||
result = p.readOutput
|
||||
p.close()
|
||||
except IOError, OSError:
|
||||
result = ("", -1)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## This module implements the 'implies' relation for guards.
|
||||
|
||||
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
|
||||
saturate, modulegraphs, options, lineinfos
|
||||
saturate, modulegraphs, options, lineinfos, int128
|
||||
|
||||
const
|
||||
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
||||
@@ -35,8 +35,8 @@ const
|
||||
someMul = {mMulI, mMulF64}
|
||||
someDiv = {mDivI, mDivF64}
|
||||
someMod = {mModI}
|
||||
someMax = {mMaxI, mMaxF64}
|
||||
someMin = {mMinI, mMinF64}
|
||||
someMax = {mMaxI}
|
||||
someMin = {mMinI}
|
||||
someBinaryOp = someAdd+someSub+someMul+someMax+someMin
|
||||
|
||||
proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit}
|
||||
@@ -436,14 +436,14 @@ proc sameTree*(a, b: PNode): bool =
|
||||
if not result and a.sym.magic != mNone:
|
||||
result = a.sym.magic == b.sym.magic or sameOpr(a.sym, b.sym)
|
||||
of nkIdent: result = a.ident.id == b.ident.id
|
||||
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
|
||||
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
|
||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||
of nkType: result = a.typ == b.typ
|
||||
of nkEmpty, nkNilLit: result = true
|
||||
else:
|
||||
if sonsLen(a) == sonsLen(b):
|
||||
for i in 0 ..< sonsLen(a):
|
||||
if len(a) == len(b):
|
||||
for i in 0 ..< len(a):
|
||||
if not sameTree(a.sons[i], b.sons[i]): return
|
||||
result = true
|
||||
|
||||
@@ -522,7 +522,7 @@ proc geImpliesIn(x, c, aSet: PNode): TImplication =
|
||||
var value = newIntNode(c.kind, c.intVal)
|
||||
let max = lastOrd(nil, x.typ)
|
||||
# don't iterate too often:
|
||||
if max - value.intVal < 1000:
|
||||
if max - getInt(value) < toInt128(1000):
|
||||
var i, pos, neg: int
|
||||
while value.intVal <= max:
|
||||
if inSet(aSet, value): inc pos
|
||||
|
||||
@@ -14,7 +14,7 @@ proc hlo(c: PContext, n: PNode): PNode
|
||||
proc evalPattern(c: PContext, n, orig: PNode): PNode =
|
||||
internalAssert c.config, n.kind == nkCall and n.sons[0].kind == nkSym
|
||||
# we need to ensure that the resulting AST is semchecked. However, it's
|
||||
# aweful to semcheck before macro invocation, so we don't and treat
|
||||
# awful to semcheck before macro invocation, so we don't and treat
|
||||
# templates and macros as immediate in this context.
|
||||
var rule: string
|
||||
if optHints in c.config.options and hintPattern in c.config.notes:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, msgs, options, idents, lookups,
|
||||
semdata, modulepaths, sigmatch, lineinfos
|
||||
semdata, modulepaths, sigmatch, lineinfos, sets
|
||||
|
||||
proc readExceptSet*(c: PContext, n: PNode): IntSet =
|
||||
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
|
||||
@@ -27,11 +27,11 @@ proc importPureEnumField*(c: PContext; s: PSym) =
|
||||
if checkB == nil:
|
||||
strTableAdd(c.pureEnumFields, s)
|
||||
else:
|
||||
# mark as ambigous:
|
||||
# mark as ambiguous:
|
||||
incl(c.ambiguousSymbols, checkB.id)
|
||||
incl(c.ambiguousSymbols, s.id)
|
||||
|
||||
proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
proc rawImportSymbol(c: PContext, s, origin: PSym) =
|
||||
# This does not handle stubs, because otherwise loading on demand would be
|
||||
# pointless in practice. So importing stubs is fine here!
|
||||
# check if we have already a symbol of the same name:
|
||||
@@ -47,7 +47,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
if s.kind == skType:
|
||||
var etyp = s.typ
|
||||
if etyp.kind in {tyBool, tyEnum}:
|
||||
for j in 0 ..< sonsLen(etyp.n):
|
||||
for j in 0 ..< len(etyp.n):
|
||||
var e = etyp.n.sons[j].sym
|
||||
if e.kind != skEnumField:
|
||||
internalError(c.config, s.info, "rawImportSymbol")
|
||||
@@ -63,13 +63,14 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
check = nextIdentIter(it, c.importTable.symbols)
|
||||
if e != nil:
|
||||
if sfPure notin s.flags:
|
||||
rawImportSymbol(c, e)
|
||||
rawImportSymbol(c, e, origin)
|
||||
else:
|
||||
importPureEnumField(c, e)
|
||||
else:
|
||||
# rodgen assures that converters and patterns are no stubs
|
||||
if s.kind == skConverter: addConverter(c, s)
|
||||
if hasPattern(s): addPattern(c, s)
|
||||
if s.owner != origin:
|
||||
c.exportIndirections.incl((origin.id, s.id))
|
||||
|
||||
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||
let ident = lookups.considerQuotedIdent(c, n)
|
||||
@@ -88,10 +89,10 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||
while e != nil:
|
||||
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
|
||||
if s.kind in ExportableSymKinds:
|
||||
rawImportSymbol(c, e)
|
||||
rawImportSymbol(c, e, fromMod)
|
||||
e = nextIdentIter(it, fromMod.tab)
|
||||
else:
|
||||
rawImportSymbol(c, s)
|
||||
rawImportSymbol(c, s, fromMod)
|
||||
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
|
||||
|
||||
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
|
||||
@@ -103,14 +104,14 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
|
||||
if s.kind notin ExportableSymKinds:
|
||||
internalError(c.config, s.info, "importAllSymbols: " & $s.kind & " " & s.name.s)
|
||||
if exceptSet.isNil or s.name.id notin exceptSet:
|
||||
rawImportSymbol(c, s)
|
||||
rawImportSymbol(c, s, fromMod)
|
||||
s = nextIter(i, fromMod.tab)
|
||||
|
||||
proc importAllSymbols*(c: PContext, fromMod: PSym) =
|
||||
var exceptSet: IntSet
|
||||
importAllSymbolsExcept(c, fromMod, exceptSet)
|
||||
|
||||
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
|
||||
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym) =
|
||||
if n.isNil: return
|
||||
case n.kind
|
||||
of nkExportStmt:
|
||||
@@ -120,15 +121,16 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
|
||||
if s.kind == skModule:
|
||||
importAllSymbolsExcept(c, s, exceptSet)
|
||||
elif exceptSet.isNil or s.name.id notin exceptSet:
|
||||
rawImportSymbol(c, s)
|
||||
rawImportSymbol(c, s, fromMod)
|
||||
of nkExportExceptStmt:
|
||||
localError(c.config, n.info, "'export except' not implemented")
|
||||
else:
|
||||
for i in 0..safeLen(n)-1:
|
||||
importForwarded(c, n.sons[i], exceptSet)
|
||||
importForwarded(c, n.sons[i], exceptSet, fromMod)
|
||||
|
||||
proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
|
||||
result = realModule
|
||||
c.unusedImports.add((realModule, n.info))
|
||||
if n.kind != nkImportAs: discard
|
||||
elif n.len != 2 or n.sons[1].kind != nkIdent:
|
||||
localError(c.config, n.info, "module alias must be an identifier")
|
||||
@@ -151,7 +153,11 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
|
||||
err.add toFullPath(c.config, c.graph.importStack[i]) & " imports " &
|
||||
toFullPath(c.config, c.graph.importStack[i+1])
|
||||
c.recursiveDep = err
|
||||
|
||||
discard pushOptionEntry(c)
|
||||
result = importModuleAs(c, n, c.graph.importModuleCallback(c.graph, c.module, f))
|
||||
popOptionEntry(c)
|
||||
|
||||
#echo "set back to ", L
|
||||
c.graph.importStack.setLen(L)
|
||||
# we cannot perform this check reliably because of
|
||||
@@ -185,11 +191,11 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
|
||||
# ``addDecl`` needs to be done before ``importAllSymbols``!
|
||||
addDecl(c, m, it.info) # add symbol to symbol table of module
|
||||
importAllSymbolsExcept(c, m, emptySet)
|
||||
#importForwarded(c, m.ast, emptySet)
|
||||
#importForwarded(c, m.ast, emptySet, m)
|
||||
|
||||
proc evalImport*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkImportStmt, n.info)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
let it = n.sons[i]
|
||||
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
|
||||
let sep = it[0]
|
||||
@@ -219,7 +225,7 @@ proc evalFrom*(c: PContext, n: PNode): PNode =
|
||||
if m != nil:
|
||||
n.sons[0] = newSymNode(m)
|
||||
addDecl(c, m, n.info) # add symbol to symbol table of module
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if n.sons[i].kind != nkNilLit:
|
||||
importSymbol(c, n.sons[i], m)
|
||||
|
||||
@@ -232,4 +238,4 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
|
||||
n.sons[0] = newSymNode(m)
|
||||
addDecl(c, m, n.info) # add symbol to symbol table of module
|
||||
importAllSymbolsExcept(c, m, readExceptSet(c, n))
|
||||
#importForwarded(c, m.ast, exceptSet)
|
||||
#importForwarded(c, m.ast, exceptSet, m)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## Basic type definitions the module graph needs in order to support
|
||||
## incremental compilations.
|
||||
|
||||
const nimIncremental* = true # defined(nimIncremental)
|
||||
const nimIncremental* = defined(nimIncremental)
|
||||
|
||||
import options, lineinfos
|
||||
|
||||
|
||||
@@ -11,136 +11,14 @@
|
||||
## an optimizer that optimizes copies to moves. This is implemented as an
|
||||
## AST to AST transformation so that every backend benefits from it.
|
||||
|
||||
## Rules for destructor injections:
|
||||
##
|
||||
## foo(bar(X(), Y()))
|
||||
## X and Y get destroyed after bar completes:
|
||||
##
|
||||
## foo( (tmpX = X(); tmpY = Y(); tmpBar = bar(tmpX, tmpY);
|
||||
## destroy(tmpX); destroy(tmpY);
|
||||
## tmpBar))
|
||||
## destroy(tmpBar)
|
||||
##
|
||||
## var x = f()
|
||||
## body
|
||||
##
|
||||
## is the same as:
|
||||
##
|
||||
## var x;
|
||||
## try:
|
||||
## move(x, f())
|
||||
## finally:
|
||||
## destroy(x)
|
||||
##
|
||||
## But this really just an optimization that tries to avoid to
|
||||
## introduce too many temporaries, the 'destroy' is caused by
|
||||
## the 'f()' call. No! That is not true for 'result = f()'!
|
||||
##
|
||||
## x = y where y is read only once
|
||||
## is the same as: move(x, y)
|
||||
##
|
||||
## Actually the more general rule is: The *last* read of ``y``
|
||||
## can become a move if ``y`` is the result of a construction.
|
||||
##
|
||||
## We also need to keep in mind here that the number of reads is
|
||||
## control flow dependent:
|
||||
## let x = foo()
|
||||
## while true:
|
||||
## y = x # only one read, but the 2nd iteration will fail!
|
||||
## This also affects recursions! Only usages that do not cross
|
||||
## a loop boundary (scope) and are not used in function calls
|
||||
## are safe.
|
||||
##
|
||||
##
|
||||
## x = f() is the same as: move(x, f())
|
||||
##
|
||||
## x = y
|
||||
## is the same as: copy(x, y)
|
||||
##
|
||||
## Reassignment works under this scheme:
|
||||
## var x = f()
|
||||
## x = y
|
||||
##
|
||||
## is the same as:
|
||||
##
|
||||
## var x;
|
||||
## try:
|
||||
## move(x, f())
|
||||
## copy(x, y)
|
||||
## finally:
|
||||
## destroy(x)
|
||||
##
|
||||
## result = f() must not destroy 'result'!
|
||||
##
|
||||
## The produced temporaries clutter up the code and might lead to
|
||||
## inefficiencies. A better strategy is to collect all the temporaries
|
||||
## in a single object that we put into a single try-finally that
|
||||
## surrounds the proc body. This means the code stays quite efficient
|
||||
## when compiled to C. In fact, we do the same for variables, so
|
||||
## destructors are called when the proc returns, not at scope exit!
|
||||
## This makes certains idioms easier to support. (Taking the slice
|
||||
## of a temporary object.)
|
||||
##
|
||||
## foo(bar(X(), Y()))
|
||||
## X and Y get destroyed after bar completes:
|
||||
##
|
||||
## var tmp: object
|
||||
## foo( (move tmp.x, X(); move tmp.y, Y(); tmp.bar = bar(tmpX, tmpY);
|
||||
## tmp.bar))
|
||||
## destroy(tmp.bar)
|
||||
## destroy(tmp.x); destroy(tmp.y)
|
||||
##
|
||||
## See doc/destructors.rst for a spec of the implemented rewrite rules
|
||||
|
||||
#[
|
||||
From https://github.com/nim-lang/Nim/wiki/Destructors
|
||||
|
||||
Rule Pattern Transformed into
|
||||
---- ------- ----------------
|
||||
1.1 var x: T; stmts var x: T; try stmts
|
||||
finally: `=destroy`(x)
|
||||
2 x = f() `=sink`(x, f())
|
||||
3 x = lastReadOf z `=sink`(x, z); wasMoved(z)
|
||||
3.2 x = path z; body ``x = bitwiseCopy(path z);``
|
||||
do not emit `=destroy(x)`. Note: body
|
||||
must not mutate ``z`` nor ``x``. All
|
||||
assignments to ``x`` must be of the form
|
||||
``path z`` but the ``z`` can differ.
|
||||
Neither ``z`` nor ``x`` can have the
|
||||
flag ``sfAddrTaken`` to ensure no other
|
||||
aliasing is going on.
|
||||
4.1 y = sinkParam `=sink`(y, sinkParam)
|
||||
4.2 x = y `=`(x, y) # a copy
|
||||
5.1 f_sink(g()) f_sink(g())
|
||||
5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read
|
||||
5.3 f_sink(move y) f_sink(y); wasMoved(y) # explicit moves empties 'y'
|
||||
5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp)
|
||||
|
||||
Rule 3.2 describes a "cursor" variable, a variable that is only used as a
|
||||
view into some data structure. See ``compiler/cursors.nim`` for details.
|
||||
|
||||
Note: In order to avoid the very common combination ``reset(x); =sink(x, y)`` for
|
||||
variable definitions we must turn "the first sink/assignment" operation into a
|
||||
copyMem. This is harder than it looks:
|
||||
|
||||
while true:
|
||||
try:
|
||||
if cond: break # problem if we run destroy(x) here :-/
|
||||
var x = f()
|
||||
finally:
|
||||
destroy(x)
|
||||
|
||||
And the C++ optimizers don't sweat to optimize it for us, so we don't have
|
||||
to do it.
|
||||
]#
|
||||
|
||||
import
|
||||
intsets, ast, msgs, renderer, magicsys, types, idents,
|
||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents,
|
||||
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
|
||||
lineinfos, parampatterns, sighashes
|
||||
|
||||
const
|
||||
InterestingSyms = {skVar, skResult, skLet, skForVar, skTemp}
|
||||
|
||||
type
|
||||
Con = object
|
||||
owner: PSym
|
||||
@@ -217,46 +95,9 @@ proc isLastRead(n: PNode; c: var Con): bool =
|
||||
dbg:
|
||||
echo "ugh ", c.otherRead.isNil, " ", result
|
||||
|
||||
when false:
|
||||
let s = n.sym
|
||||
var pcs: seq[int] = @[instr+1]
|
||||
var takenGotos: IntSet
|
||||
var takenForks = initIntSet()
|
||||
while pcs.len > 0:
|
||||
var pc = pcs.pop
|
||||
|
||||
takenGotos = initIntSet()
|
||||
while pc < c.g.len:
|
||||
case c.g[pc].kind
|
||||
of def:
|
||||
if c.g[pc].sym == s:
|
||||
# the path lead to a redefinition of 's' --> abandon it.
|
||||
break
|
||||
inc pc
|
||||
of use:
|
||||
if c.g[pc].sym == s:
|
||||
c.otherRead = c.g[pc].n
|
||||
return false
|
||||
inc pc
|
||||
of goto:
|
||||
# we must leave endless loops eventually:
|
||||
if not takenGotos.containsOrIncl(pc):
|
||||
pc = pc + c.g[pc].dest
|
||||
else:
|
||||
inc pc
|
||||
of fork:
|
||||
# we follow the next instruction but push the dest onto our "work" stack:
|
||||
if not takenForks.containsOrIncl(pc):
|
||||
pcs.add pc + c.g[pc].dest
|
||||
inc pc
|
||||
of InstrKind.join:
|
||||
inc pc
|
||||
#echo c.graph.config $ n.info, " last read here!"
|
||||
return true
|
||||
|
||||
proc initialized(code: ControlFlowGraph; pc: int,
|
||||
init, uninit: var IntSet; comesFrom: int): int =
|
||||
## Computes the set of definitely initialized variables accross all code paths
|
||||
## Computes the set of definitely initialized variables across all code paths
|
||||
## as an IntSet of IDs.
|
||||
var pc = pc
|
||||
while pc < code.len:
|
||||
@@ -290,9 +131,6 @@ proc initialized(code: ControlFlowGraph; pc: int,
|
||||
inc pc
|
||||
return pc
|
||||
|
||||
template interestingSym(s: PSym): bool =
|
||||
s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ)
|
||||
|
||||
template isUnpackedTuple(s: PSym): bool =
|
||||
## we move out all elements of unpacked tuples,
|
||||
## hence unpacked tuples themselves don't need to be destroyed
|
||||
@@ -322,7 +160,7 @@ proc makePtrType(c: Con, baseType: PType): PType =
|
||||
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
|
||||
var op = t.attachedOps[kind]
|
||||
|
||||
if op == nil:
|
||||
if op == nil or op.ast[genericParamsPos].kind != nkEmpty:
|
||||
# give up and find the canonical type instead:
|
||||
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let canon = c.graph.canonTypes.getOrDefault(h)
|
||||
@@ -353,8 +191,8 @@ proc canBeMoved(t: PType): bool {.inline.} =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
result = t.kind != tyRef and t.attachedOps[attachedSink] != nil
|
||||
|
||||
proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
proc genSink(c: Con; dest, ri: PNode): PNode =
|
||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
let k = if t.attachedOps[attachedSink] != nil: attachedSink
|
||||
else: attachedAsgn
|
||||
if t.attachedOps[k] != nil:
|
||||
@@ -365,20 +203,20 @@ proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||
# we generate a fast assignment in this case:
|
||||
result = newTree(nkFastAsgn, dest)
|
||||
|
||||
proc genCopy(c: var Con; t: PType; dest, ri: PNode): PNode =
|
||||
proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode =
|
||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
result = genOp(c, t, attachedAsgn, dest, ri)
|
||||
|
||||
proc genCopy(c: var Con; dest, ri: PNode): PNode =
|
||||
let t = dest.typ
|
||||
if tfHasOwned in t.flags:
|
||||
# try to improve the error message here:
|
||||
if c.otherRead == nil: discard isLastRead(ri, c)
|
||||
checkForErrorPragma(c, t, ri, "=")
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
result = genOp(c, t, attachedAsgn, dest, ri)
|
||||
genCopyNoCheck(c, dest, ri)
|
||||
|
||||
proc genCopyNoCheck(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
result = genOp(c, t, attachedAsgn, dest, ri)
|
||||
|
||||
proc genDestroy(c: Con; t: PType; dest: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
proc genDestroy(c: Con; dest: PNode): PNode =
|
||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
result = genOp(c, t, attachedDestructor, dest, nil)
|
||||
|
||||
proc addTopVar(c: var Con; v: PNode) =
|
||||
@@ -390,20 +228,10 @@ proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
|
||||
result = newSymNode(sym)
|
||||
c.addTopVar(result)
|
||||
|
||||
proc p(n: PNode; c: var Con): PNode
|
||||
|
||||
template recurse(n, dest) =
|
||||
for i in 0..<n.len:
|
||||
dest.add p(n[i], c)
|
||||
|
||||
proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode =
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add(newSymNode(createMagic(c.graph, magicname, m)))
|
||||
result.add n
|
||||
|
||||
proc genWasMoved(n: PNode; c: var Con): PNode =
|
||||
# The mWasMoved builtin does not take the address.
|
||||
result = genMagicCall(n, c, "wasMoved", mWasMoved)
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add(newSymNode(createMagic(c.graph, "wasMoved", mWasMoved)))
|
||||
result.add n #mWasMoved does not take the address
|
||||
|
||||
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
|
||||
result = newNodeI(nkCall, info)
|
||||
@@ -422,9 +250,9 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode =
|
||||
let tempAsNode = newSymNode(temp)
|
||||
|
||||
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
|
||||
vpart.sons[0] = tempAsNode
|
||||
vpart.sons[1] = c.emptyNode
|
||||
vpart.sons[2] = n
|
||||
vpart[0] = tempAsNode
|
||||
vpart[1] = c.emptyNode
|
||||
vpart[2] = n
|
||||
add(v, vpart)
|
||||
|
||||
result.add v
|
||||
@@ -437,6 +265,10 @@ proc sinkParamIsLastReadCheck(c: var Con, s: PNode) =
|
||||
localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s &
|
||||
"` is already consumed at " & toFileLineCol(c. graph.config, s.info))
|
||||
|
||||
proc p(n: PNode; c: var Con): PNode
|
||||
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode
|
||||
|
||||
proc passCopyToSink(n: PNode; c: var Con): PNode =
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let tmp = getTemp(c, n.typ, n.info)
|
||||
@@ -444,7 +276,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
|
||||
# out of loops we need to mark it as 'wasMoved'.
|
||||
result.add genWasMoved(tmp, c)
|
||||
if hasDestructor(n.typ):
|
||||
var m = genCopy(c, n.typ, tmp, n)
|
||||
var m = genCopy(c, tmp, n)
|
||||
m.add p(n, c)
|
||||
result.add m
|
||||
if isLValue(n):
|
||||
@@ -457,7 +289,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
|
||||
|
||||
proc isDangerousSeq(t: PType): bool {.inline.} =
|
||||
let t = t.skipTypes(abstractInst)
|
||||
result = t.kind == tySequence and tfHasOwned notin t.sons[0].flags
|
||||
result = t.kind == tySequence and tfHasOwned notin t[0].flags
|
||||
|
||||
proc containsConstSeq(n: PNode): bool =
|
||||
if n.kind == nkBracket and n.len > 0 and n.typ != nil and isDangerousSeq(n.typ):
|
||||
@@ -467,19 +299,66 @@ proc containsConstSeq(n: PNode): bool =
|
||||
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
||||
result = containsConstSeq(n[1])
|
||||
of nkObjConstr, nkClosure:
|
||||
for i in 1 ..< n.len:
|
||||
for i in 1..<n.len:
|
||||
if containsConstSeq(n[i]): return true
|
||||
of nkCurly, nkBracket, nkPar, nkTupleConstr:
|
||||
for i in 0 ..< n.len:
|
||||
if containsConstSeq(n[i]): return true
|
||||
for son in n:
|
||||
if containsConstSeq(son): return true
|
||||
else: discard
|
||||
|
||||
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||
template pArgIfTyped(argPart: PNode): PNode =
|
||||
# typ is nil if we are in if/case expr branch with noreturn
|
||||
if argPart.typ == nil: p(argPart, c)
|
||||
else: pArg(argPart, c, isSink)
|
||||
template handleNested(n: untyped, processCall: untyped) =
|
||||
case n.kind
|
||||
of nkStmtList, nkStmtListExpr:
|
||||
if n.len == 0: return n
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len-1:
|
||||
result.add p(n[i], c)
|
||||
template node: untyped = n[^1]
|
||||
result.add processCall
|
||||
of nkBlockStmt, nkBlockExpr:
|
||||
result = copyNode(n)
|
||||
result.add n[0]
|
||||
template node: untyped = n[1]
|
||||
result.add processCall
|
||||
of nkIfStmt, nkIfExpr:
|
||||
result = copyNode(n)
|
||||
for son in n:
|
||||
var branch = copyNode(son)
|
||||
if son.kind in {nkElifBranch, nkElifExpr}:
|
||||
template node: untyped = son[1]
|
||||
branch.add p(son[0], c) #The condition
|
||||
branch.add if node.typ == nil: p(node, c) #noreturn
|
||||
else: processCall
|
||||
else:
|
||||
template node: untyped = son[0]
|
||||
branch.add if node.typ == nil: p(node, c) #noreturn
|
||||
else: processCall
|
||||
result.add branch
|
||||
of nkCaseStmt:
|
||||
result = copyNode(n)
|
||||
result.add p(n[0], c)
|
||||
for i in 1..<n.len:
|
||||
var branch: PNode
|
||||
if n[i].kind == nkOfBranch:
|
||||
branch = n[i] # of branch conditions are constants
|
||||
template node: untyped = n[i][^1]
|
||||
branch[^1] = if node.typ == nil: p(node, c) #noreturn
|
||||
else: processCall
|
||||
elif n[i].kind in {nkElifBranch, nkElifExpr}:
|
||||
branch = copyNode(n[i])
|
||||
branch.add p(n[i][0], c) #The condition
|
||||
template node: untyped = n[i][1]
|
||||
branch.add if node.typ == nil: p(node, c) #noreturn
|
||||
else: processCall
|
||||
else:
|
||||
branch = copyNode(n[i])
|
||||
template node: untyped = n[i][0]
|
||||
branch.add if node.typ == nil: p(node, c) #noreturn
|
||||
else: processCall
|
||||
result.add branch
|
||||
else: assert(false)
|
||||
|
||||
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||
if isSink:
|
||||
if arg.kind in nkCallKinds:
|
||||
# recurse but skip the call expression in order to prevent
|
||||
@@ -492,11 +371,11 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||
result.add pArg(arg[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
||||
elif arg.containsConstSeq:
|
||||
# const sequences are not mutable and so we need to pass a copy to the
|
||||
# sink parameter (bug #11524). Note that the string implemenation is
|
||||
# sink parameter (bug #11524). Note that the string implementation is
|
||||
# different and can deal with 'const string sunk into var'.
|
||||
result = passCopyToSink(arg, c)
|
||||
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkCharLit..nkTripleStrLit}:
|
||||
discard "object construction to sink parameter: nothing to do"
|
||||
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr} + nkLiterals:
|
||||
# object construction to sink parameter: nothing to do
|
||||
result = arg
|
||||
elif arg.kind == nkSym and isSinkParam(arg.sym):
|
||||
# Sinked params can be consumed only once. We need to reset the memory
|
||||
@@ -507,204 +386,216 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||
# it is the last read, can be sinked. We need to reset the memory
|
||||
# to disable the destructor which we have not elided
|
||||
result = destructiveMoveVar(arg, c)
|
||||
elif arg.kind in {nkBlockExpr, nkBlockStmt}:
|
||||
result = copyNode(arg)
|
||||
result.add arg[0]
|
||||
result.add pArg(arg[1], c, isSink)
|
||||
elif arg.kind == nkStmtListExpr:
|
||||
result = copyNode(arg)
|
||||
for i in 0..arg.len-2:
|
||||
result.add p(arg[i], c)
|
||||
result.add pArg(arg[^1], c, isSink)
|
||||
elif arg.kind in {nkIfExpr, nkIfStmt}:
|
||||
result = copyNode(arg)
|
||||
for i in 0..<arg.len:
|
||||
var branch = copyNode(arg[i])
|
||||
if arg[i].kind in {nkElifBranch, nkElifExpr}:
|
||||
branch.add p(arg[i][0], c)
|
||||
branch.add pArgIfTyped(arg[i][1])
|
||||
else:
|
||||
branch.add pArgIfTyped(arg[i][0])
|
||||
result.add branch
|
||||
elif arg.kind == nkCaseStmt:
|
||||
result = copyNode(arg)
|
||||
result.add p(arg[0], c)
|
||||
for i in 1..<arg.len:
|
||||
var branch: PNode
|
||||
if arg[i].kind == nkOfBranch:
|
||||
branch = arg[i] # of branch conditions are constants
|
||||
branch[^1] = pArgIfTyped(arg[i][^1])
|
||||
elif arg[i].kind in {nkElifBranch, nkElifExpr}:
|
||||
branch = copyNode(arg[i])
|
||||
branch.add p(arg[i][0], c)
|
||||
branch.add pArgIfTyped(arg[i][1])
|
||||
else:
|
||||
branch = copyNode(arg[i])
|
||||
branch.add pArgIfTyped(arg[i][0])
|
||||
result.add branch
|
||||
elif isAnalysableFieldAccess(arg, c.owner) and isLastRead(arg, c):
|
||||
result = destructiveMoveVar(arg, c)
|
||||
elif arg.kind in {nkStmtListExpr, nkBlockExpr, nkBlockStmt, nkIfExpr, nkIfStmt, nkCaseStmt}:
|
||||
handleNested(arg): pArg(node, c, isSink)
|
||||
else:
|
||||
# an object that is not temporary but passed to a 'sink' parameter
|
||||
# results in a copy.
|
||||
result = passCopyToSink(arg, c)
|
||||
elif arg.kind == nkBracket:
|
||||
# Treat `f([...])` like `f(...)`
|
||||
result = copyNode(arg)
|
||||
for son in arg:
|
||||
result.add pArg(son, c, isSinkTypeForParam(son.typ))
|
||||
elif arg.kind in nkCallKinds and arg.typ != nil and hasDestructor(arg.typ):
|
||||
# produce temp creation
|
||||
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
|
||||
let tmp = getTemp(c, arg.typ, arg.info)
|
||||
let res = p(arg, c)
|
||||
var sinkExpr = genSink(c, tmp, res)
|
||||
sinkExpr.add res
|
||||
result.add sinkExpr
|
||||
result.add tmp
|
||||
c.destroys.add genDestroy(c, tmp)
|
||||
else:
|
||||
result = p(arg, c)
|
||||
|
||||
proc p(n: PNode; c: var Con): PNode =
|
||||
case n.kind
|
||||
of nkCallKinds:
|
||||
let parameters = n[0].typ
|
||||
let L = if parameters != nil: parameters.len else: 0
|
||||
for i in 1..<n.len:
|
||||
n[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
||||
result = n
|
||||
of nkDiscardStmt: #Small optimization
|
||||
if n[0].kind != nkEmpty:
|
||||
n[0] = pArg(n[0], c, false)
|
||||
result = n
|
||||
of nkBracket:
|
||||
result = copyTree(n)
|
||||
for i in 0..<n.len:
|
||||
# everything that is passed to an array constructor is consumed,
|
||||
# so these all act like 'sink' parameters:
|
||||
result[i] = pArg(n[i], c, isSink = true)
|
||||
of nkObjConstr:
|
||||
result = copyTree(n)
|
||||
for i in 1..<n.len:
|
||||
# everything that is passed to an object constructor is consumed,
|
||||
# so these all act like 'sink' parameters:
|
||||
result[i][1] = pArg(n[i][1], c, isSink = true)
|
||||
of nkTupleConstr, nkClosure:
|
||||
result = copyTree(n)
|
||||
for i in ord(n.kind == nkClosure)..<n.len:
|
||||
# everything that is passed to an tuple constructor is consumed,
|
||||
# so these all act like 'sink' parameters:
|
||||
if n[i].kind == nkExprColonExpr:
|
||||
result[i][1] = pArg(n[i][1], c, isSink = true)
|
||||
else:
|
||||
result[i] = pArg(n[i], c, isSink = true)
|
||||
of nkVarSection, nkLetSection:
|
||||
# transform; var x = y to var x; x op y where op is a move or copy
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
for it in n:
|
||||
var ri = it[^1]
|
||||
if it.kind == nkVarTuple and hasDestructor(ri.typ):
|
||||
let x = lowerTupleUnpacking(c.graph, it, c.owner)
|
||||
result.add p(x, c)
|
||||
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
|
||||
for j in 0..<it.len-2:
|
||||
let v = it[j]
|
||||
if v.kind == nkSym:
|
||||
if sfCompileTime in v.sym.flags: continue
|
||||
# move the variable declaration to the top of the frame:
|
||||
c.addTopVar v
|
||||
# make sure it's destroyed at the end of the proc:
|
||||
if not isUnpackedTuple(it[0].sym):
|
||||
c.destroys.add genDestroy(c, v)
|
||||
if ri.kind == nkEmpty and c.inLoop > 0:
|
||||
ri = genDefaultCall(v.typ, c, v.info)
|
||||
if ri.kind != nkEmpty:
|
||||
let r = moveOrCopy(v, ri, c)
|
||||
result.add r
|
||||
else: # keep the var but transform 'ri':
|
||||
var v = copyNode(n)
|
||||
var itCopy = copyNode(it)
|
||||
for j in 0..<it.len-1:
|
||||
itCopy.add it[j]
|
||||
itCopy.add p(it[^1], c)
|
||||
v.add itCopy
|
||||
result.add v
|
||||
of nkAsgn, nkFastAsgn:
|
||||
if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda}:
|
||||
# rule (self-assignment-removal):
|
||||
if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
else:
|
||||
result = moveOrCopy(n[0], n[1], c)
|
||||
else:
|
||||
result = copyNode(n)
|
||||
result.add n[0]
|
||||
result.add p(n[1], c)
|
||||
of nkRaiseStmt:
|
||||
if optOwnedRefs in c.graph.config.globalOptions and n[0].kind != nkEmpty:
|
||||
if n[0].kind in nkCallKinds:
|
||||
let call = p(n[0], c)
|
||||
result = copyNode(n)
|
||||
result.add call
|
||||
else:
|
||||
let tmp = getTemp(c, n[0].typ, n.info)
|
||||
var m = genCopyNoCheck(c, tmp, n[0])
|
||||
m.add p(n[0], c)
|
||||
result = newTree(nkStmtList, genWasMoved(tmp, c), m)
|
||||
var toDisarm = n[0]
|
||||
if toDisarm.kind == nkStmtListExpr: toDisarm = toDisarm.lastSon
|
||||
if toDisarm.kind == nkSym and toDisarm.sym.owner == c.owner:
|
||||
result.add genWasMoved(toDisarm, c)
|
||||
result.add newTree(nkRaiseStmt, tmp)
|
||||
else:
|
||||
result = copyNode(n)
|
||||
result.add p(n[0], c)
|
||||
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
|
||||
nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef,
|
||||
nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt, nkExportStmt,
|
||||
nkPragma, nkCommentStmt, nkBreakStmt:
|
||||
result = n
|
||||
of nkWhileStmt:
|
||||
result = copyNode(n)
|
||||
inc c.inLoop
|
||||
result.add p(n[0], c)
|
||||
result.add p(n[1], c)
|
||||
dec c.inLoop
|
||||
of nkWhen: # This should be a "when nimvm" node.
|
||||
result = copyTree(n)
|
||||
result[1][0] = p(result[1][0], c)
|
||||
of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt, nkIfExpr, nkCaseStmt:
|
||||
handleNested(n): p(node, c)
|
||||
else:
|
||||
result = shallowCopy(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = p(n[i], c)
|
||||
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||
# unfortunately, this needs to be kept consistent with the cases
|
||||
# we handle in the 'case of' statement below:
|
||||
const movableNodeKinds = (nkCallKinds + {nkSym, nkTupleConstr, nkObjConstr,
|
||||
nkBracket, nkBracketExpr, nkNilLit})
|
||||
|
||||
template moveOrCopyIfTyped(riPart: PNode): PNode =
|
||||
# typ is nil if we are in if/case expr branch with noreturn
|
||||
if riPart.typ == nil: p(riPart, c)
|
||||
else: moveOrCopy(dest, riPart, c)
|
||||
|
||||
case ri.kind
|
||||
of nkCallKinds:
|
||||
result = genSink(c, dest.typ, dest, ri)
|
||||
# watch out and no not transform 'ri' twice if it's a call:
|
||||
let ri2 = copyNode(ri)
|
||||
let parameters = ri[0].typ
|
||||
let L = if parameters != nil: parameters.len else: 0
|
||||
ri2.add ri[0]
|
||||
for i in 1..<ri.len:
|
||||
ri2.add pArg(ri[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
||||
#recurse(ri, ri2)
|
||||
result.add ri2
|
||||
result = genSink(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
of nkBracketExpr:
|
||||
if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym):
|
||||
# unpacking of tuple: move out the elements
|
||||
result = genSink(c, dest.typ, dest, ri)
|
||||
result = genSink(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
var snk = genSink(c, dest.typ, dest, ri)
|
||||
var snk = genSink(c, dest, ri)
|
||||
snk.add ri
|
||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||
else:
|
||||
result = genCopy(c, dest.typ, dest, ri)
|
||||
result = genCopy(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
of nkStmtListExpr:
|
||||
result = newNodeI(nkStmtList, ri.info)
|
||||
for i in 0..ri.len-2:
|
||||
result.add p(ri[i], c)
|
||||
result.add moveOrCopy(dest, ri[^1], c)
|
||||
of nkBlockExpr, nkBlockStmt:
|
||||
result = newNodeI(nkBlockStmt, ri.info)
|
||||
result.add ri[0] ## add label
|
||||
result.add moveOrCopy(dest, ri[1], c)
|
||||
of nkIfExpr, nkIfStmt:
|
||||
result = newNodeI(nkIfStmt, ri.info)
|
||||
for i in 0..<ri.len:
|
||||
var branch = copyNode(ri[i])
|
||||
if ri[i].kind in {nkElifBranch, nkElifExpr}:
|
||||
branch.add p(ri[i][0], c)
|
||||
branch.add moveOrCopyIfTyped(ri[i][1])
|
||||
else:
|
||||
branch.add moveOrCopyIfTyped(ri[i][0])
|
||||
result.add branch
|
||||
of nkCaseStmt:
|
||||
result = newNodeI(nkCaseStmt, ri.info)
|
||||
result.add p(ri[0], c)
|
||||
for i in 1..<ri.len:
|
||||
var branch: PNode
|
||||
if ri[i].kind == nkOfBranch:
|
||||
branch = ri[i] # of branch conditions are constants
|
||||
branch[^1] = moveOrCopyIfTyped(ri[i][^1])
|
||||
elif ri[i].kind in {nkElifBranch, nkElifExpr}:
|
||||
branch = copyNode(ri[i])
|
||||
branch.add p(ri[i][0], c)
|
||||
branch.add moveOrCopyIfTyped(ri[i][1])
|
||||
else:
|
||||
branch = copyNode(ri[i])
|
||||
branch.add moveOrCopyIfTyped(ri[i][0])
|
||||
result.add branch
|
||||
of nkBracket:
|
||||
# array constructor
|
||||
if ri.len > 0 and isDangerousSeq(ri.typ):
|
||||
result = genCopy(c, dest.typ, dest, ri)
|
||||
result = genCopy(c, dest, ri)
|
||||
else:
|
||||
result = genSink(c, dest.typ, dest, ri)
|
||||
let ri2 = copyTree(ri)
|
||||
for i in 0..<ri.len:
|
||||
# everything that is passed to an array constructor is consumed,
|
||||
# so these all act like 'sink' parameters:
|
||||
ri2[i] = pArg(ri[i], c, isSink = true)
|
||||
result.add ri2
|
||||
of nkObjConstr:
|
||||
result = genSink(c, dest.typ, dest, ri)
|
||||
let ri2 = copyTree(ri)
|
||||
for i in 1..<ri.len:
|
||||
# everything that is passed to an object constructor is consumed,
|
||||
# so these all act like 'sink' parameters:
|
||||
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
|
||||
result.add ri2
|
||||
of nkTupleConstr, nkClosure:
|
||||
result = genSink(c, dest.typ, dest, ri)
|
||||
let ri2 = copyTree(ri)
|
||||
for i in ord(ri.kind == nkClosure)..<ri.len:
|
||||
# everything that is passed to an tuple constructor is consumed,
|
||||
# so these all act like 'sink' parameters:
|
||||
if ri[i].kind == nkExprColonExpr:
|
||||
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
|
||||
else:
|
||||
ri2[i] = pArg(ri[i], c, isSink = true)
|
||||
result.add ri2
|
||||
of nkNilLit:
|
||||
result = genSink(c, dest.typ, dest, ri)
|
||||
result.add ri
|
||||
result = genSink(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
||||
result = genSink(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
of nkSym:
|
||||
if isSinkParam(ri.sym):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
sinkParamIsLastReadCheck(c, ri)
|
||||
var snk = genSink(c, dest.typ, dest, ri)
|
||||
var snk = genSink(c, dest, ri)
|
||||
snk.add ri
|
||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
|
||||
isLastRead(ri, c) and canBeMoved(dest.typ):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
var snk = genSink(c, dest.typ, dest, ri)
|
||||
var snk = genSink(c, dest, ri)
|
||||
snk.add ri
|
||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||
else:
|
||||
result = genCopy(c, dest.typ, dest, ri)
|
||||
result.add p(ri, c)
|
||||
of nkHiddenSubConv, nkHiddenStdConv:
|
||||
if sameType(ri.typ, ri[1].typ):
|
||||
result = moveOrCopy(dest, ri[1], c)
|
||||
elif ri[1].kind in movableNodeKinds:
|
||||
result = moveOrCopy(dest, ri[1], c)
|
||||
var b = newNodeIT(ri.kind, ri.info, ri.typ)
|
||||
b.add ri[0] # add empty node
|
||||
let L = result.len-1
|
||||
b.add result[L]
|
||||
result[L] = b
|
||||
else:
|
||||
result = genCopy(c, dest.typ, dest, ri)
|
||||
result = genCopy(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
of nkHiddenSubConv, nkHiddenStdConv, nkConv:
|
||||
result = moveOrCopy(dest, ri[1], c)
|
||||
if not sameType(ri.typ, ri[1].typ):
|
||||
let copyRi = copyTree(ri)
|
||||
copyRi[1] = result[^1]
|
||||
result[^1] = copyRi
|
||||
of nkObjDownConv, nkObjUpConv:
|
||||
if ri[0].kind in movableNodeKinds:
|
||||
result = moveOrCopy(dest, ri[0], c)
|
||||
var b = newNodeIT(ri.kind, ri.info, ri.typ)
|
||||
let L = result.len-1
|
||||
b.add result[L]
|
||||
result[L] = b
|
||||
else:
|
||||
result = genCopy(c, dest.typ, dest, ri)
|
||||
result.add p(ri, c)
|
||||
result = moveOrCopy(dest, ri[0], c)
|
||||
let copyRi = copyTree(ri)
|
||||
copyRi[0] = result[^1]
|
||||
result[^1] = copyRi
|
||||
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
|
||||
handleNested(ri): moveOrCopy(dest, node, c)
|
||||
else:
|
||||
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c) and
|
||||
canBeMoved(dest.typ):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
var snk = genSink(c, dest.typ, dest, ri)
|
||||
var snk = genSink(c, dest, ri)
|
||||
snk.add ri
|
||||
result = newTree(nkStmtList, snk, genWasMoved(ri, c))
|
||||
else:
|
||||
# XXX At least string literals can be moved?
|
||||
result = genCopy(c, dest.typ, dest, ri)
|
||||
result = genCopy(c, dest, ri)
|
||||
result.add p(ri, c)
|
||||
|
||||
proc computeUninit(c: var Con) =
|
||||
@@ -717,17 +608,14 @@ proc computeUninit(c: var Con) =
|
||||
proc injectDefaultCalls(n: PNode, c: var Con) =
|
||||
case n.kind
|
||||
of nkVarSection, nkLetSection:
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
let L = it.len-1
|
||||
let ri = it[L]
|
||||
if it.kind == nkIdentDefs and ri.kind == nkEmpty:
|
||||
for it in n:
|
||||
if it.kind == nkIdentDefs and it[^1].kind == nkEmpty:
|
||||
computeUninit(c)
|
||||
for j in 0..L-2:
|
||||
for j in 0..<it.len-2:
|
||||
let v = it[j]
|
||||
doAssert v.kind == nkSym
|
||||
if c.uninit.contains(v.sym.id):
|
||||
it[L] = genDefaultCall(v.sym.typ, c, v.info)
|
||||
it[^1] = genDefaultCall(v.sym.typ, c, v.info)
|
||||
break
|
||||
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
|
||||
nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
|
||||
@@ -736,130 +624,16 @@ proc injectDefaultCalls(n: PNode, c: var Con) =
|
||||
for i in 0..<safeLen(n):
|
||||
injectDefaultCalls(n[i], c)
|
||||
|
||||
proc isCursor(n: PNode): bool {.inline.} =
|
||||
result = n.kind == nkSym and sfCursor in n.sym.flags
|
||||
|
||||
proc keepVar(n, it: PNode, c: var Con): PNode =
|
||||
# keep the var but transform 'ri':
|
||||
result = copyNode(n)
|
||||
var itCopy = copyNode(it)
|
||||
for j in 0..it.len-2:
|
||||
itCopy.add it[j]
|
||||
itCopy.add p(it[it.len-1], c)
|
||||
result.add itCopy
|
||||
|
||||
proc p(n: PNode; c: var Con): PNode =
|
||||
case n.kind
|
||||
of nkVarSection, nkLetSection:
|
||||
discard "transform; var x = y to var x; x op y where op is a move or copy"
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
let L = it.len
|
||||
var ri = it[L-1]
|
||||
if it.kind == nkVarTuple and hasDestructor(ri.typ):
|
||||
let x = lowerTupleUnpacking(c.graph, it, c.owner)
|
||||
result.add p(x, c)
|
||||
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isCursor(it[0]):
|
||||
for j in 0..L-3:
|
||||
let v = it[j]
|
||||
if v.kind == nkSym:
|
||||
if sfCompileTime in v.sym.flags: continue
|
||||
# move the variable declaration to the top of the frame:
|
||||
c.addTopVar v
|
||||
# make sure it's destroyed at the end of the proc:
|
||||
if not isUnpackedTuple(it[0].sym):
|
||||
c.destroys.add genDestroy(c, v.typ, v)
|
||||
if ri.kind == nkEmpty and c.inLoop > 0:
|
||||
ri = genDefaultCall(v.typ, c, v.info)
|
||||
if ri.kind != nkEmpty:
|
||||
let r = moveOrCopy(v, ri, c)
|
||||
result.add r
|
||||
else:
|
||||
result.add keepVar(n, it, c)
|
||||
of nkCallKinds:
|
||||
let parameters = n[0].typ
|
||||
let L = if parameters != nil: parameters.len else: 0
|
||||
for i in 1 ..< n.len:
|
||||
n.sons[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
||||
if n.typ != nil and hasDestructor(n.typ):
|
||||
discard "produce temp creation"
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let tmp = getTemp(c, n.typ, n.info)
|
||||
var sinkExpr = genSink(c, n.typ, tmp, n)
|
||||
sinkExpr.add n
|
||||
result.add sinkExpr
|
||||
result.add tmp
|
||||
c.destroys.add genDestroy(c, n.typ, tmp)
|
||||
else:
|
||||
result = n
|
||||
of nkAsgn, nkFastAsgn:
|
||||
if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda}:
|
||||
# rule (self-assignment-removal):
|
||||
if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
else:
|
||||
result = moveOrCopy(n[0], n[1], c)
|
||||
else:
|
||||
result = copyNode(n)
|
||||
recurse(n, result)
|
||||
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef,
|
||||
nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
|
||||
result = n
|
||||
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
result = copyNode(n)
|
||||
# Destination type
|
||||
result.add n[0]
|
||||
# Analyse the inner expression
|
||||
result.add p(n[1], c)
|
||||
of nkWhen:
|
||||
# This should be a "when nimvm" node.
|
||||
result = copyTree(n)
|
||||
result[1][0] = p(result[1][0], c)
|
||||
of nkRaiseStmt:
|
||||
if optNimV2 in c.graph.config.globalOptions and n[0].kind != nkEmpty:
|
||||
if n[0].kind in nkCallKinds:
|
||||
let call = copyNode(n[0])
|
||||
recurse(n[0], call)
|
||||
result = copyNode(n)
|
||||
result.add call
|
||||
else:
|
||||
let t = n[0].typ
|
||||
let tmp = getTemp(c, t, n.info)
|
||||
var m = genCopyNoCheck(c, t, tmp, n[0])
|
||||
|
||||
m.add p(n[0], c)
|
||||
result = newTree(nkStmtList, genWasMoved(tmp, c), m)
|
||||
var toDisarm = n[0]
|
||||
if toDisarm.kind == nkStmtListExpr: toDisarm = toDisarm.lastSon
|
||||
if toDisarm.kind == nkSym and toDisarm.sym.owner == c.owner:
|
||||
result.add genWasMoved(toDisarm, c)
|
||||
result.add newTree(nkRaiseStmt, tmp)
|
||||
else:
|
||||
result = copyNode(n)
|
||||
recurse(n, result)
|
||||
of nkForStmt, nkParForStmt, nkWhileStmt:
|
||||
inc c.inLoop
|
||||
result = copyNode(n)
|
||||
recurse(n, result)
|
||||
dec c.inLoop
|
||||
else:
|
||||
result = copyNode(n)
|
||||
recurse(n, result)
|
||||
|
||||
proc extractDestroysForTemporaries(c: Con, destroys: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, destroys.info)
|
||||
for i in 0 ..< destroys.len:
|
||||
for i in 0..<destroys.len:
|
||||
if destroys[i][1][0].sym.kind == skTemp:
|
||||
result.add destroys[i]
|
||||
destroys[i] = c.emptyNode
|
||||
|
||||
proc reverseDestroys(destroys: PNode) =
|
||||
var reversed: seq[PNode]
|
||||
proc reverseDestroys(destroys: seq[PNode]): seq[PNode] =
|
||||
for i in countdown(destroys.len - 1, 0):
|
||||
reversed.add(destroys[i])
|
||||
destroys.sons = reversed
|
||||
result.add destroys[i]
|
||||
|
||||
proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||
if sfGeneratedOp in owner.flags or isInlineIterator(owner): return n
|
||||
@@ -876,14 +650,15 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||
if c.g[i].kind in {goto, fork}:
|
||||
c.jumpTargets.incl(i+c.g[i].dest)
|
||||
dbg:
|
||||
echo "injecting into ", n
|
||||
echo "\n### ", owner.name.s, ":\nCFG:"
|
||||
echoCfg(c.g)
|
||||
echo n
|
||||
if owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter}:
|
||||
let params = owner.typ.n
|
||||
for i in 1 ..< params.len:
|
||||
let param = params[i].sym
|
||||
if isSinkTypeForParam(param.typ) and hasDestructor(param.typ.skipTypes({tySink})):
|
||||
c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i])
|
||||
for i in 1..<params.len:
|
||||
let t = params[i].sym.typ
|
||||
if isSinkTypeForParam(t) and hasDestructor(t.skipTypes({tySink})):
|
||||
c.destroys.add genDestroy(c, params[i])
|
||||
|
||||
#if optNimV2 in c.graph.config.globalOptions:
|
||||
# injectDefaultCalls(n, c)
|
||||
@@ -892,7 +667,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||
if c.topLevelVars.len > 0:
|
||||
result.add c.topLevelVars
|
||||
if c.destroys.len > 0:
|
||||
reverseDestroys(c.destroys)
|
||||
c.destroys.sons = reverseDestroys(c.destroys.sons)
|
||||
if owner.kind == skModule:
|
||||
result.add newTryFinally(body, extractDestroysForTemporaries(c, c.destroys))
|
||||
g.globalDestructors.add c.destroys
|
||||
@@ -900,8 +675,6 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||
result.add newTryFinally(body, c.destroys)
|
||||
else:
|
||||
result.add body
|
||||
|
||||
dbg:
|
||||
echo "------------------------------------"
|
||||
echo owner.name.s, " transformed to: "
|
||||
echo ">---------transformed-to--------->"
|
||||
echo result
|
||||
|
||||
@@ -6,10 +6,10 @@ Name: "Nim"
|
||||
Version: "$version"
|
||||
Platforms: """
|
||||
windows: i386;amd64
|
||||
linux: i386;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
|
||||
linux: i386;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
|
||||
macosx: i386;amd64;powerpc64
|
||||
solaris: i386;amd64;sparc;sparc64
|
||||
freebsd: i386;amd64
|
||||
freebsd: i386;amd64;powerpc64
|
||||
netbsd: i386;amd64
|
||||
openbsd: i386;amd64
|
||||
dragonfly: i386;amd64
|
||||
@@ -65,6 +65,7 @@ Files: "compiler"
|
||||
Files: "doc"
|
||||
Files: "doc/html"
|
||||
Files: "tools"
|
||||
Files: "tools/nim-gdb.py"
|
||||
Files: "nimpretty"
|
||||
Files: "testament"
|
||||
Files: "nimsuggest"
|
||||
@@ -87,6 +88,7 @@ Files: "bin/nimble.exe"
|
||||
Files: "bin/vccexe.exe"
|
||||
Files: "bin/nimgrab.exe"
|
||||
Files: "bin/nimpretty.exe"
|
||||
Files: "bin/testament.exe"
|
||||
|
||||
Files: "koch.exe"
|
||||
Files: "finish.exe"
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
## This module is for compiler internal use only. For reliable error
|
||||
## messages and range checks, the compiler needs a data type that can
|
||||
## hold all from ``low(BiggestInt)`` to ``high(BiggestUInt)``, This
|
||||
## type is for that purpose.
|
||||
|
||||
from math import trunc
|
||||
|
||||
type
|
||||
Int128* = object
|
||||
@@ -11,19 +16,13 @@ template sdata(arg: Int128, idx: int): int32 =
|
||||
|
||||
# encoding least significant int first (like LittleEndian)
|
||||
|
||||
type
|
||||
InvalidArgument = object of Exception
|
||||
|
||||
template require(cond: bool) =
|
||||
if unlikely(not cond):
|
||||
raise newException(InvalidArgument, "")
|
||||
|
||||
const
|
||||
Zero* = Int128(udata: [0'u32,0,0,0])
|
||||
One* = Int128(udata: [1'u32,0,0,0])
|
||||
Ten* = Int128(udata: [10'u32,0,0,0])
|
||||
Min = Int128(udata: [0'u32,0,0,0x80000000'u32])
|
||||
Max = Int128(udata: [high(uint32),high(uint32),high(uint32),uint32(high(int32))])
|
||||
NegOne* = Int128(udata: [0xffffffff'u32,0xffffffff'u32,0xffffffff'u32,0xffffffff'u32])
|
||||
|
||||
template low*(t: typedesc[Int128]): Int128 = Min
|
||||
template high*(t: typedesc[Int128]): Int128 = Max
|
||||
@@ -74,11 +73,94 @@ proc toInt64*(arg: Int128): int64 =
|
||||
|
||||
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc toInt64Checked*(arg: Int128; onError: int64): int64 =
|
||||
if isNegative(arg):
|
||||
if arg.sdata(3) != -1 or arg.sdata(2) != -1:
|
||||
return onError
|
||||
else:
|
||||
if arg.sdata(3) != 0 or arg.sdata(2) != 0:
|
||||
return onError
|
||||
return cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc toInt32*(arg: Int128): int32 =
|
||||
if isNegative(arg):
|
||||
assert(arg.sdata(3) == -1, "out of range")
|
||||
assert(arg.sdata(2) == -1, "out of range")
|
||||
assert(arg.sdata(1) == -1, "out of range")
|
||||
else:
|
||||
assert(arg.sdata(3) == 0, "out of range")
|
||||
assert(arg.sdata(2) == 0, "out of range")
|
||||
assert(arg.sdata(1) == 0, "out of range")
|
||||
|
||||
arg.sdata(0)
|
||||
|
||||
proc toInt16*(arg: Int128): int16 =
|
||||
if isNegative(arg):
|
||||
assert(arg.sdata(3) == -1, "out of range")
|
||||
assert(arg.sdata(2) == -1, "out of range")
|
||||
assert(arg.sdata(1) == -1, "out of range")
|
||||
else:
|
||||
assert(arg.sdata(3) == 0, "out of range")
|
||||
assert(arg.sdata(2) == 0, "out of range")
|
||||
assert(arg.sdata(1) == 0, "out of range")
|
||||
|
||||
int16(arg.sdata(0))
|
||||
|
||||
proc toInt8*(arg: Int128): int8 =
|
||||
if isNegative(arg):
|
||||
assert(arg.sdata(3) == -1, "out of range")
|
||||
assert(arg.sdata(2) == -1, "out of range")
|
||||
assert(arg.sdata(1) == -1, "out of range")
|
||||
else:
|
||||
assert(arg.sdata(3) == 0, "out of range")
|
||||
assert(arg.sdata(2) == 0, "out of range")
|
||||
assert(arg.sdata(1) == 0, "out of range")
|
||||
|
||||
int8(arg.sdata(0))
|
||||
|
||||
proc toInt*(arg: Int128): int =
|
||||
when sizeof(int) == 4:
|
||||
cast[int](toInt32(arg))
|
||||
else:
|
||||
cast[int](toInt64(arg))
|
||||
|
||||
proc toUInt64*(arg: Int128): uint64 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
bitconcat(arg.udata[1], arg.udata[0])
|
||||
|
||||
proc toUInt32*(arg: Int128): uint32 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
assert(arg.udata[1] == 0)
|
||||
arg.udata[0]
|
||||
|
||||
proc toUInt16*(arg: Int128): uint16 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
assert(arg.udata[1] == 0)
|
||||
uint16(arg.udata[0])
|
||||
|
||||
proc toUInt8*(arg: Int128): uint8 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
assert(arg.udata[1] == 0)
|
||||
uint8(arg.udata[0])
|
||||
|
||||
proc toUInt*(arg: Int128): uint =
|
||||
when sizeof(int) == 4:
|
||||
cast[uint](toInt32(arg))
|
||||
else:
|
||||
cast[uint](toInt64(arg))
|
||||
|
||||
proc castToInt64*(arg: Int128): int64 =
|
||||
## Conversion to int64 without range check.
|
||||
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc castToUInt64*(arg: Int128): uint64 =
|
||||
## Conversion to uint64 without range check.
|
||||
cast[uint64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc addToHex(result: var string; arg: uint32) =
|
||||
for i in 0 ..< 8:
|
||||
let idx = (arg shr ((7-i) * 4)) and 0xf
|
||||
@@ -206,7 +288,6 @@ proc `shl`*(a: Int128, b: int): Int128 =
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = a.udata[0] shl (b and 31)
|
||||
|
||||
|
||||
proc `+`*(a,b: Int128): Int128 =
|
||||
let tmp0 = uint64(a.udata[0]) + uint64(b.udata[0])
|
||||
result.udata[0] = cast[uint32](tmp0)
|
||||
@@ -254,7 +335,6 @@ proc `*`(a: Int128, b: uint32): Int128 =
|
||||
result.udata[3] = cast[uint32](tmp3) + cast[uint32](tmp2 shr 32)
|
||||
|
||||
proc `*`*(a: Int128, b: int32): Int128 =
|
||||
let isNegative = isNegative(a) xor isNegative(b)
|
||||
result = a * cast[uint32](abs(b))
|
||||
if b < 0:
|
||||
result = -result
|
||||
@@ -275,8 +355,6 @@ proc low64(a: Int128): uint64 =
|
||||
bitconcat(a.udata[1], a.udata[0])
|
||||
|
||||
proc `*`*(lhs,rhs: Int128): Int128 =
|
||||
let isNegative = isNegative(lhs) xor isNegative(rhs)
|
||||
|
||||
let
|
||||
a = cast[uint64](lhs.udata[0])
|
||||
b = cast[uint64](lhs.udata[1])
|
||||
@@ -298,10 +376,6 @@ proc `*`*(lhs,rhs: Int128): Int128 =
|
||||
result = result + toInt128(a32 * b00) shl 32
|
||||
result = result + toInt128(a00 * b32) shl 32
|
||||
|
||||
if isNegative != isNegative(result):
|
||||
echo result
|
||||
assert(false, "overflow")
|
||||
|
||||
proc `*=`*(a: var Int128, b: Int128) =
|
||||
a = a * b
|
||||
|
||||
@@ -319,18 +393,25 @@ proc fastLog2*(a: Int128): int =
|
||||
|
||||
proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
|
||||
assert(divisor != Zero)
|
||||
let isNegative = isNegative(dividend) xor isNegative(divisor)
|
||||
let isNegativeA = isNegative(dividend)
|
||||
let isNegativeB = isNegative(divisor)
|
||||
|
||||
var dividend = abs(dividend)
|
||||
let divisor = abs(divisor)
|
||||
|
||||
if divisor > dividend:
|
||||
result.quotient = Zero
|
||||
result.remainder = dividend
|
||||
if isNegativeA:
|
||||
result.remainder = -dividend
|
||||
else:
|
||||
result.remainder = dividend
|
||||
return
|
||||
|
||||
if divisor == dividend:
|
||||
result.quotient = One
|
||||
if isNegativeA xor isNegativeB:
|
||||
result.quotient = NegOne
|
||||
else:
|
||||
result.quotient = One
|
||||
result.remainder = Zero
|
||||
return
|
||||
|
||||
@@ -351,8 +432,14 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
|
||||
|
||||
denominator = denominator shr 1
|
||||
|
||||
result.quotient = quotient
|
||||
result.remainder = dividend
|
||||
if isNegativeA xor isNegativeB:
|
||||
result.quotient = -quotient
|
||||
else:
|
||||
result.quotient = quotient
|
||||
if isNegativeA:
|
||||
result.remainder = -dividend
|
||||
else:
|
||||
result.remainder = dividend
|
||||
|
||||
proc `div`*(a,b: Int128): Int128 =
|
||||
let (a,b) = divMod(a,b)
|
||||
@@ -362,28 +449,32 @@ proc `mod`*(a,b: Int128): Int128 =
|
||||
let (a,b) = divMod(a,b)
|
||||
return b
|
||||
|
||||
proc `$`*(a: Int128): string =
|
||||
if a == Zero:
|
||||
result = "0"
|
||||
elif a == low(Int128):
|
||||
result = "-170141183460469231731687303715884105728"
|
||||
proc addInt128*(result: var string; value: Int128) =
|
||||
let initialSize = result.len
|
||||
if value == Zero:
|
||||
result.add "0"
|
||||
elif value == low(Int128):
|
||||
result.add "-170141183460469231731687303715884105728"
|
||||
else:
|
||||
let isNegative = isNegative(a)
|
||||
var a = abs(a)
|
||||
while a > Zero:
|
||||
let (quot, rem) = divMod(a, Ten)
|
||||
let isNegative = isNegative(value)
|
||||
var value = abs(value)
|
||||
while value > Zero:
|
||||
let (quot, rem) = divMod(value, Ten)
|
||||
result.add "0123456789"[rem.toInt64]
|
||||
a = quot
|
||||
value = quot
|
||||
if isNegative:
|
||||
result.add '-'
|
||||
|
||||
var i = 0
|
||||
var i = initialSize
|
||||
var j = high(result)
|
||||
while i < j:
|
||||
swap(result[i], result[j])
|
||||
i += 1
|
||||
j -= 1
|
||||
|
||||
proc `$`*(a: Int128): string =
|
||||
result.addInt128(a)
|
||||
|
||||
proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
|
||||
assert(pos < arg.len)
|
||||
assert(arg[pos] in {'-','0'..'9'})
|
||||
@@ -435,6 +526,75 @@ proc `+`*(a: BiggestInt, b: Int128): Int128 =
|
||||
proc `+`*(a: Int128, b: BiggestInt): Int128 =
|
||||
a + toInt128(b)
|
||||
|
||||
proc toFloat64*(arg: Int128): float64 =
|
||||
let isNegative = isNegative(arg)
|
||||
let arg = abs(arg)
|
||||
|
||||
let a = float64(bitconcat(arg.udata[1], arg.udata[0]))
|
||||
let b = float64(bitconcat(arg.udata[3], arg.udata[2]))
|
||||
|
||||
result = a + 18446744073709551616'f64 * b # a + 2^64 * b
|
||||
if isNegative:
|
||||
result = -result
|
||||
|
||||
proc ldexp(x: float64, exp: cint): float64 {.importc: "ldexp", header: "<math.h>".}
|
||||
|
||||
template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
|
||||
|
||||
proc toInt128*(arg: float64): Int128 =
|
||||
let isNegative = arg < 0
|
||||
let v0 = ldexp(abs(arg), -100)
|
||||
let w0 = uint64(trunc(v0))
|
||||
let v1 = ldexp(v0 - float64(w0), 50)
|
||||
let w1 = uint64(trunc(v1))
|
||||
let v2 = ldexp(v1 - float64(w1), 50)
|
||||
let w2 = uint64(trunc(v2))
|
||||
|
||||
let res = bitor(toInt128(w0) shl 100, toInt128(w1) shl 50, toInt128(w2))
|
||||
if isNegative:
|
||||
return -res
|
||||
else:
|
||||
return res
|
||||
|
||||
proc maskUInt64*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0]
|
||||
result.udata[1] = arg.udata[1]
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskUInt32*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0]
|
||||
result.udata[1] = 0
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskUInt16*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0] and 0xffff
|
||||
result.udata[1] = 0
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskUInt8*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0] and 0xff
|
||||
result.udata[1] = 0
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
|
||||
case numbytes
|
||||
of 1:
|
||||
return maskUInt8(arg)
|
||||
of 2:
|
||||
return maskUInt16(arg)
|
||||
of 4:
|
||||
return maskUInt32(arg)
|
||||
of 8:
|
||||
return maskUInt64(arg)
|
||||
else:
|
||||
assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
|
||||
|
||||
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let (a,b) = divMod(Ten,Ten)
|
||||
@@ -514,3 +674,25 @@ when isMainModule:
|
||||
|
||||
doAssert $high(Int128) == "170141183460469231731687303715884105727"
|
||||
doAssert $low(Int128) == "-170141183460469231731687303715884105728"
|
||||
|
||||
var ma = 100'i64
|
||||
var mb = 13
|
||||
|
||||
doAssert toInt128(ma) * toInt128(0) == toInt128(0)
|
||||
doAssert toInt128(-ma) * toInt128(0) == toInt128(0)
|
||||
|
||||
# sign correctness
|
||||
doAssert divMod(toInt128( ma),toInt128( mb)) == (toInt128( ma div mb), toInt128( ma mod mb))
|
||||
doAssert divMod(toInt128(-ma),toInt128( mb)) == (toInt128(-ma div mb), toInt128(-ma mod mb))
|
||||
doAssert divMod(toInt128( ma),toInt128(-mb)) == (toInt128( ma div -mb), toInt128( ma mod -mb))
|
||||
doAssert divMod(toInt128(-ma),toInt128(-mb)) == (toInt128(-ma div -mb), toInt128(-ma mod -mb))
|
||||
|
||||
doAssert divMod(toInt128( mb),toInt128( mb)) == (toInt128( mb div mb), toInt128( mb mod mb))
|
||||
doAssert divMod(toInt128(-mb),toInt128( mb)) == (toInt128(-mb div mb), toInt128(-mb mod mb))
|
||||
doAssert divMod(toInt128( mb),toInt128(-mb)) == (toInt128( mb div -mb), toInt128( mb mod -mb))
|
||||
doAssert divMod(toInt128(-mb),toInt128(-mb)) == (toInt128(-mb div -mb), toInt128(-mb mod -mb))
|
||||
|
||||
doAssert divMod(toInt128( mb),toInt128( ma)) == (toInt128( mb div ma), toInt128( mb mod ma))
|
||||
doAssert divMod(toInt128(-mb),toInt128( ma)) == (toInt128(-mb div ma), toInt128(-mb mod ma))
|
||||
doAssert divMod(toInt128( mb),toInt128(-ma)) == (toInt128( mb div -ma), toInt128( mb mod -ma))
|
||||
doAssert divMod(toInt128(-mb),toInt128(-ma)) == (toInt128(-mb div -ma), toInt128(-mb mod -ma))
|
||||
|
||||
@@ -389,8 +389,6 @@ const # magic checked op; magic unchecked op;
|
||||
["", ""], # BitxorI
|
||||
["nimMin", "nimMin"], # MinI
|
||||
["nimMax", "nimMax"], # MaxI
|
||||
["nimMin", "nimMin"], # MinF64
|
||||
["nimMax", "nimMax"], # MaxF64
|
||||
["", ""], # addU
|
||||
["", ""], # subU
|
||||
["", ""], # mulU
|
||||
@@ -430,11 +428,6 @@ const # magic checked op; magic unchecked op;
|
||||
["", ""], # BitnotI
|
||||
["", ""], # UnaryPlusF64
|
||||
["", ""], # UnaryMinusF64
|
||||
["", ""], # AbsF64
|
||||
["", ""], # ToFloat
|
||||
["", ""], # ToBiggestFloat
|
||||
["", ""], # ToInt
|
||||
["", ""], # ToBiggestInt
|
||||
["nimCharToStr", "nimCharToStr"],
|
||||
["nimBoolToStr", "nimBoolToStr"],
|
||||
["cstrToNimstr", "cstrToNimstr"],
|
||||
@@ -535,7 +528,7 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
xLoc,yLoc: Rope
|
||||
let i = ord(optOverflowCheck notin p.options)
|
||||
useMagic(p, jsMagics[op][i])
|
||||
if sonsLen(n) > 2:
|
||||
if len(n) > 2:
|
||||
gen(p, n.sons[1], x)
|
||||
gen(p, n.sons[2], y)
|
||||
xLoc = x.rdLoc
|
||||
@@ -570,8 +563,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
|
||||
of mMinI: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
|
||||
of mMaxI: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
|
||||
of mMinF64: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
|
||||
of mMaxF64: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
|
||||
of mAddU: applyFormat("", "")
|
||||
of mSubU: applyFormat("", "")
|
||||
of mMulU: applyFormat("", "")
|
||||
@@ -611,11 +602,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
of mBitnotI: applyFormat("~($1)", "~($1)")
|
||||
of mUnaryPlusF64: applyFormat("+($1)", "+($1)")
|
||||
of mUnaryMinusF64: applyFormat("-($1)", "-($1)")
|
||||
of mAbsF64: applyFormat("Math.abs($1)", "Math.abs($1)")
|
||||
of mToFloat: applyFormat("$1", "$1")
|
||||
of mToBiggestFloat: applyFormat("$1", "$1")
|
||||
of mToInt: applyFormat("Math.trunc($1)", "Math.trunc($1)")
|
||||
of mToBiggestInt: applyFormat("Math.trunc($1)", "Math.trunc($1)")
|
||||
of mCharToStr: applyFormat("nimCharToStr($1)", "nimCharToStr($1)")
|
||||
of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)")
|
||||
of mIntToStr: applyFormat("cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")")
|
||||
@@ -666,11 +652,7 @@ proc genLineDir(p: PProc, n: PNode) =
|
||||
if optLineDir in p.options:
|
||||
lineF(p, "// line $2 \"$1\"$n",
|
||||
[rope(toFilename(p.config, n.info)), rope(line)])
|
||||
if {optStackTrace, optEndb} * p.options == {optStackTrace, optEndb} and
|
||||
((p.prc == nil) or sfPure notin p.prc.flags):
|
||||
useMagic(p, "endb")
|
||||
lineF(p, "endb($1);$n", [rope(line)])
|
||||
elif hasFrameInfo(p):
|
||||
if hasFrameInfo(p):
|
||||
lineF(p, "F.line = $1;$n", [rope(line)])
|
||||
|
||||
proc genWhileStmt(p: PProc, n: PNode) =
|
||||
@@ -731,7 +713,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.res = getTemp(p)
|
||||
inc(p.unique)
|
||||
var i = 1
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch
|
||||
if catchBranchesExist:
|
||||
add(p.body, "++excHandler;\L")
|
||||
@@ -749,7 +731,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||
" lastJSError = EXC;$n --excHandler;$n", [])
|
||||
line(p, "framePtr = $1;$n" % [tmpFramePtr])
|
||||
while i < length and n.sons[i].kind == nkExceptBranch:
|
||||
let blen = sonsLen(n.sons[i])
|
||||
let blen = len(n.sons[i])
|
||||
if blen == 1:
|
||||
# general except section:
|
||||
generalCatchBranchExists = true
|
||||
@@ -840,11 +822,11 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if not isEmptyType(n.typ):
|
||||
r.kind = resVal
|
||||
r.res = getTemp(p)
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
let it = n.sons[i]
|
||||
case it.kind
|
||||
of nkOfBranch:
|
||||
for j in 0 .. sonsLen(it) - 2:
|
||||
for j in 0 .. len(it) - 2:
|
||||
let e = it.sons[j]
|
||||
if e.kind == nkRange:
|
||||
var v = copyNode(e.sons[0])
|
||||
@@ -912,7 +894,7 @@ proc genBreakStmt(p: PProc, n: PNode) =
|
||||
proc genAsmOrEmitStmt(p: PProc, n: PNode) =
|
||||
genLineDir(p, n)
|
||||
p.body.add p.indentLine(nil)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
let it = n[i]
|
||||
case it.kind
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -950,9 +932,9 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if not isEmptyType(n.typ):
|
||||
r.kind = resVal
|
||||
r.res = getTemp(p)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
let it = n.sons[i]
|
||||
if sonsLen(it) != 1:
|
||||
if len(it) != 1:
|
||||
if i > 0:
|
||||
lineF(p, "else {$n", [])
|
||||
inc(toClose)
|
||||
@@ -969,7 +951,7 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
|
||||
|
||||
proc generateHeader(p: PProc, typ: PType): Rope =
|
||||
result = nil
|
||||
for i in 1 ..< sonsLen(typ.n):
|
||||
for i in 1 ..< len(typ.n):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
if isCompileTimeOnly(param.typ): continue
|
||||
@@ -982,7 +964,7 @@ proc generateHeader(p: PProc, typ: PType): Rope =
|
||||
add(result, "_Idx")
|
||||
|
||||
proc countJsParams(typ: PType): int =
|
||||
for i in 1 ..< sonsLen(typ.n):
|
||||
for i in 1 ..< len(typ.n):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
var param = typ.n.sons[i].sym
|
||||
if isCompileTimeOnly(param.typ): continue
|
||||
@@ -1157,9 +1139,10 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
|
||||
|
||||
useMagic(p, "raiseFieldError")
|
||||
useMagic(p, "makeNimstrLit")
|
||||
let msg = genFieldError(field, disc)
|
||||
lineF(p, "if ($1[$2.$3]$4undefined) { raiseFieldError(makeNimstrLit($5)); }$n",
|
||||
setx.res, tmp, disc.loc.r, if negCheck: ~"!==" else: ~"===",
|
||||
makeJSString(field.name.s))
|
||||
makeJSString(msg))
|
||||
|
||||
if addrTyp != nil and mapType(p, addrTyp) == etyBaseIndex:
|
||||
r.typ = etyBaseIndex
|
||||
@@ -1173,7 +1156,7 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
|
||||
proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
a, b: TCompRes
|
||||
first: BiggestInt
|
||||
first: Int128
|
||||
r.typ = etyBaseIndex
|
||||
let m = if n.kind == nkHiddenAddr: n.sons[0] else: n
|
||||
gen(p, m.sons[0], a)
|
||||
@@ -1182,11 +1165,11 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let (x, tmp) = maybeMakeTemp(p, m[0], a)
|
||||
r.address = x
|
||||
var typ = skipTypes(m.sons[0].typ, abstractPtrs)
|
||||
if typ.kind == tyArray: first = firstOrd(p.config, typ.sons[0])
|
||||
else: first = 0
|
||||
if typ.kind == tyArray:
|
||||
first = firstOrd(p.config, typ.sons[0])
|
||||
if optBoundsCheck in p.options:
|
||||
useMagic(p, "chckIndx")
|
||||
r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), tmp]
|
||||
r.res = "chckIndx($1, $2, ($3 != null ? $3.length : 0)+$2-1)-$2" % [b.res, rope(first), tmp]
|
||||
elif first != 0:
|
||||
r.res = "($1)-$2" % [b.res, rope(first)]
|
||||
else:
|
||||
@@ -1312,12 +1295,16 @@ proc genCopyForParamIfNeeded(p: PProc, n: PNode) =
|
||||
return
|
||||
owner = owner.up
|
||||
|
||||
proc genVarInit(p: PProc, v: PSym, n: PNode)
|
||||
|
||||
proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var s = n.sym
|
||||
case s.kind
|
||||
of skVar, skLet, skParam, skTemp, skResult, skForVar:
|
||||
if s.loc.r == nil:
|
||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||
if sfCompileTime in s.flags:
|
||||
genVarInit(p, s, if s.ast != nil: s.ast else: newNodeI(nkEmpty, s.info))
|
||||
if s.kind == skParam:
|
||||
genCopyForParamIfNeeded(p, n)
|
||||
let k = mapType(p, s.typ)
|
||||
@@ -1422,13 +1409,13 @@ proc genArgs(p: PProc, n: PNode, r: var TCompRes; start=1) =
|
||||
|
||||
var typ = skipTypes(n.sons[0].typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||
assert(len(typ) == len(typ.n))
|
||||
var emitted = start-1
|
||||
|
||||
for i in start ..< sonsLen(n):
|
||||
for i in start ..< len(n):
|
||||
let it = n.sons[i]
|
||||
var paramType: PNode = nil
|
||||
if i < sonsLen(typ):
|
||||
if i < len(typ):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
paramType = typ.n.sons[i]
|
||||
if paramType.typ.isCompileTimeOnly: continue
|
||||
@@ -1456,7 +1443,7 @@ proc genOtherArg(p: PProc; n: PNode; i: int; typ: PType;
|
||||
" but got only: " & $(n.len-1))
|
||||
let it = n[i]
|
||||
var paramType: PNode = nil
|
||||
if i < sonsLen(typ):
|
||||
if i < len(typ):
|
||||
assert(typ.n.sons[i].kind == nkSym)
|
||||
paramType = typ.n.sons[i]
|
||||
if paramType.typ.isCompileTimeOnly: return
|
||||
@@ -1544,7 +1531,7 @@ proc genEcho(p: PProc, n: PNode, r: var TCompRes) =
|
||||
useMagic(p, "toJSStr") # Used in rawEcho
|
||||
useMagic(p, "rawEcho")
|
||||
add(r.res, "rawEcho(")
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
let it = n.sons[i]
|
||||
if it.typ.isCompileTimeOnly: continue
|
||||
if i > 0: add(r.res, ", ")
|
||||
@@ -1560,11 +1547,11 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope
|
||||
proc createRecordVarAux(p: PProc, rec: PNode, excludedFieldIDs: IntSet, output: var Rope) =
|
||||
case rec.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(rec):
|
||||
for i in 0 ..< len(rec):
|
||||
createRecordVarAux(p, rec.sons[i], excludedFieldIDs, output)
|
||||
of nkRecCase:
|
||||
createRecordVarAux(p, rec.sons[0], excludedFieldIDs, output)
|
||||
for i in 1 ..< sonsLen(rec):
|
||||
for i in 1 ..< len(rec):
|
||||
createRecordVarAux(p, lastSon(rec.sons[i]), excludedFieldIDs, output)
|
||||
of nkSym:
|
||||
# Do not produce code for void types
|
||||
@@ -1611,8 +1598,10 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
result = putToSeq("{}", indirect)
|
||||
of tyBool:
|
||||
result = putToSeq("false", indirect)
|
||||
of tyNil:
|
||||
result = putToSeq("null", indirect)
|
||||
of tyArray:
|
||||
let length = int(lengthOrd(p.config, t))
|
||||
let length = toInt(lengthOrd(p.config, t))
|
||||
let e = elemType(t)
|
||||
let jsTyp = arrayTypeForElemType(e)
|
||||
if jsTyp.len > 0:
|
||||
@@ -1634,7 +1623,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
if indirect: result = "[$1]" % [result]
|
||||
of tyTuple:
|
||||
result = rope("{")
|
||||
for i in 0..<t.sonsLen:
|
||||
for i in 0..<t.len:
|
||||
if i > 0: add(result, ", ")
|
||||
addf(result, "Field$1: $2", [i.rope,
|
||||
createVar(p, t.sons[i], false)])
|
||||
@@ -1735,7 +1724,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||
lineF(p, "}$n")
|
||||
|
||||
proc genVarStmt(p: PProc, n: PNode) =
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkCommentStmt:
|
||||
if a.kind == nkVarTuple:
|
||||
@@ -1747,7 +1736,11 @@ proc genVarStmt(p: PProc, n: PNode) =
|
||||
var v = a.sons[0].sym
|
||||
if lfNoDecl notin v.loc.flags and sfImportc notin v.flags:
|
||||
genLineDir(p, a)
|
||||
genVarInit(p, v, a.sons[2])
|
||||
if sfCompileTime notin v.flags:
|
||||
genVarInit(p, v, a.sons[2])
|
||||
else:
|
||||
# lazy emit, done when it's actually used.
|
||||
if v.ast == nil: v.ast = a[2]
|
||||
|
||||
proc genConstant(p: PProc, c: PSym) =
|
||||
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
|
||||
@@ -1793,15 +1786,15 @@ proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
else:
|
||||
r.res.add("($1 || []).concat(" % [a.res])
|
||||
|
||||
for i in 2 .. sonsLen(n) - 2:
|
||||
for i in 2 .. len(n) - 2:
|
||||
gen(p, n.sons[i], a)
|
||||
if skipTypes(n.sons[i].typ, abstractVarRange).kind == tyChar:
|
||||
r.res.add("[$1]," % [a.res])
|
||||
else:
|
||||
r.res.add("$1 || []," % [a.res])
|
||||
|
||||
gen(p, n.sons[sonsLen(n) - 1], a)
|
||||
if skipTypes(n.sons[sonsLen(n) - 1].typ, abstractVarRange).kind == tyChar:
|
||||
gen(p, n.sons[len(n) - 1], a)
|
||||
if skipTypes(n.sons[len(n) - 1].typ, abstractVarRange).kind == tyChar:
|
||||
r.res.add("[$1])" % [a.res])
|
||||
else:
|
||||
r.res.add("$1 || [])" % [a.res])
|
||||
@@ -1901,6 +1894,15 @@ proc genReset(p: PProc, n: PNode) =
|
||||
lineF(p, "$1 = genericReset($3, $2);$n", [a,
|
||||
genTypeInfo(p, n.sons[1].typ), tmp])
|
||||
|
||||
proc genMove(p: PProc; n: PNode; r: var TCompRes) =
|
||||
var a: TCompRes
|
||||
r.kind = resVal
|
||||
r.res = p.getTemp()
|
||||
gen(p, n[1], a)
|
||||
lineF(p, "$1 = $2;$n", [r.rdLoc, a.rdLoc])
|
||||
genReset(p, n)
|
||||
#lineF(p, "$1 = $2;$n", [dest.rdLoc, src.rdLoc])
|
||||
|
||||
proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
a: TCompRes
|
||||
@@ -2025,7 +2027,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]")
|
||||
of mOf: genOf(p, n, r)
|
||||
of mDefault: genDefault(p, n, r)
|
||||
of mReset: genReset(p, n)
|
||||
of mReset, mWasMoved: genReset(p, n)
|
||||
of mEcho: genEcho(p, n, r)
|
||||
of mNLen..mNError, mSlurp, mStaticExec:
|
||||
localError(p.config, n.info, errXMustBeCompileTime % n.sons[0].sym.name.s)
|
||||
@@ -2048,6 +2050,8 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
gen(p, n.sons[3], z)
|
||||
r.res = "($1.slice($2, $3+1))" % [x.rdLoc, y.rdLoc, z.rdLoc]
|
||||
r.kind = resExpr
|
||||
of mMove:
|
||||
genMove(p, n, r)
|
||||
else:
|
||||
genCall(p, n, r)
|
||||
#else internalError(p.config, e.info, 'genMagic: ' + magicToStr[op]);
|
||||
@@ -2058,7 +2062,7 @@ proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
useMagic(p, "setConstr")
|
||||
r.res = rope("setConstr(")
|
||||
r.kind = resExpr
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if i > 0: add(r.res, ", ")
|
||||
var it = n.sons[i]
|
||||
if it.kind == nkRange:
|
||||
@@ -2080,7 +2084,7 @@ proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var a: TCompRes
|
||||
r.res = rope("[")
|
||||
r.kind = resExpr
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if i > 0: add(r.res, ", ")
|
||||
gen(p, n.sons[i], a)
|
||||
if a.typ == etyBaseIndex:
|
||||
@@ -2097,7 +2101,7 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var a: TCompRes
|
||||
r.res = rope("{")
|
||||
r.kind = resExpr
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if i > 0: add(r.res, ", ")
|
||||
var it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr: it = it.sons[1]
|
||||
@@ -2117,7 +2121,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.kind = resExpr
|
||||
var initList : Rope
|
||||
var fieldIDs = initIntSet()
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if i > 1: add(initList, ", ")
|
||||
var it = n.sons[i]
|
||||
internalAssert p.config, it.kind == nkExprColonExpr
|
||||
@@ -2162,7 +2166,10 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
|
||||
var a, b: TCompRes
|
||||
gen(p, n.sons[0], r)
|
||||
if optRangeCheck in p.options:
|
||||
if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and
|
||||
checkUnsignedConversions notin p.config.legacyFeatures):
|
||||
discard "XXX maybe emit masking instructions here"
|
||||
else:
|
||||
gen(p, n.sons[1], a)
|
||||
gen(p, n.sons[2], b)
|
||||
useMagic(p, "chckRange")
|
||||
@@ -2451,7 +2458,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
# this shows the distinction is nice for backends and should be kept
|
||||
# in the frontend
|
||||
let isExpr = not isEmptyType(n.typ)
|
||||
for i in 0 ..< sonsLen(n) - isExpr.ord:
|
||||
for i in 0 ..< len(n) - isExpr.ord:
|
||||
genStmt(p, n.sons[i])
|
||||
if isExpr:
|
||||
gen(p, lastSon(n), r)
|
||||
@@ -2588,7 +2595,7 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
|
||||
attachProc(p, prc)
|
||||
|
||||
var disp = generateMethodDispatchers(graph)
|
||||
for i in 0..sonsLen(disp)-1:
|
||||
for i in 0..len(disp)-1:
|
||||
let prc = disp.sons[i].sym
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
var p = newProc(globals, m, nil, m.module.options)
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# included from jsgen.nim
|
||||
|
||||
## Type info generation for the JS backend.
|
||||
|
||||
proc rope(arg: Int128): Rope = rope($arg)
|
||||
|
||||
proc genTypeInfo(p: PProc, typ: PType): Rope
|
||||
proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||
var
|
||||
@@ -19,7 +23,7 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
length = sonsLen(n)
|
||||
length = len(n)
|
||||
if length == 1:
|
||||
result = genObjectFields(p, typ, n.sons[0])
|
||||
else:
|
||||
@@ -37,7 +41,7 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||
[mangleName(p.module, field), s,
|
||||
makeJSString(field.name.s)]
|
||||
of nkRecCase:
|
||||
length = sonsLen(n)
|
||||
length = len(n)
|
||||
if (n.sons[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
|
||||
field = n.sons[0].sym
|
||||
s = genTypeInfo(p, field.typ)
|
||||
@@ -46,9 +50,9 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||
u = nil
|
||||
case b.kind
|
||||
of nkOfBranch:
|
||||
if sonsLen(b) < 2:
|
||||
if len(b) < 2:
|
||||
internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
|
||||
for j in 0 .. sonsLen(b) - 2:
|
||||
for j in 0 .. len(b) - 2:
|
||||
if u != nil: add(u, ", ")
|
||||
if b.sons[j].kind == nkRange:
|
||||
addf(u, "[$1, $2]", [rope(getOrdValue(b.sons[j].sons[0])),
|
||||
@@ -101,7 +105,7 @@ proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
|
||||
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
|
||||
|
||||
proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
|
||||
let length = sonsLen(typ.n)
|
||||
let length = len(typ.n)
|
||||
var s: Rope = nil
|
||||
for i in 0 ..< length:
|
||||
if (typ.n.sons[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
|
||||
|
||||
@@ -233,6 +233,10 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
|
||||
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
|
||||
result = conf.cmd == cmdCompileToJS and not isCompileTime
|
||||
|
||||
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo) =
|
||||
createTypeBoundOps(g, nil, refType.lastSon, info)
|
||||
createTypeBoundOps(g, nil, refType, info)
|
||||
|
||||
proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
|
||||
if liftingHarmful(g.config, owner): return n
|
||||
@@ -245,7 +249,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||
var env: PNode
|
||||
if owner.isIterator:
|
||||
let it = getHiddenParam(g, owner)
|
||||
addUniqueField(it.typ.sons[0], hp, g.cache)
|
||||
addUniqueField(it.typ.skipTypes({tyOwned}).sons[0], hp, g.cache)
|
||||
env = indirectAccess(newSymNode(it), hp, hp.info)
|
||||
else:
|
||||
let e = newSym(skLet, iter.name, owner, n.info)
|
||||
@@ -257,13 +261,13 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||
result.add(v)
|
||||
# add 'new' statement:
|
||||
result.add newCall(getSysSym(g, n.info, "internalNew"), env)
|
||||
if optNimV2 in g.config.globalOptions:
|
||||
if optOwnedRefs in g.config.globalOptions:
|
||||
createTypeBoundOps(g, nil, env.typ, n.info)
|
||||
result.add makeClosure(g, iter, env, n.info)
|
||||
|
||||
proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
|
||||
let envParam = getHiddenParam(g, owner)
|
||||
let obj = envParam.typ.skipTypes({tyOwned, tyRef})
|
||||
let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
addField(obj, s, g.cache)
|
||||
|
||||
var access = newSymNode(envParam)
|
||||
@@ -323,7 +327,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
|
||||
c.ownerToType[owner.id] = result
|
||||
|
||||
proc asOwnedRef(c: DetectionPass; t: PType): PType =
|
||||
if optNimV2 in c.graph.config.globalOptions:
|
||||
if optOwnedRefs in c.graph.config.globalOptions:
|
||||
assert t.kind == tyRef
|
||||
result = newType(tyOwned, t.owner)
|
||||
result.flags.incl tfHasOwned
|
||||
@@ -335,16 +339,17 @@ proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
|
||||
info: TLineInfo): PType =
|
||||
var r = c.getEnvTypeForOwner(owner, info)
|
||||
result = newType(tyPtr, owner)
|
||||
rawAddSon(result, r.skipTypes({tyOwned, tyRef}))
|
||||
rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr}))
|
||||
|
||||
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
|
||||
let obj = refObj.skipTypes({tyOwned, tyRef})
|
||||
let obj = refObj.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
# The assumption here is that gcDestructors means we cannot deal
|
||||
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
|
||||
# This seems to be generally correct but since it's a bit risky it's only
|
||||
# enabled for gcDestructors.
|
||||
let fieldType = if false: # c.graph.config.selectedGC == gcDestructors:
|
||||
# This seems to be generally correct but since it's a bit risky it's disabled
|
||||
# for now.
|
||||
let fieldType = if isDefined(c.graph.config, "nimCycleBreaker") or
|
||||
c.graph.config.selectedGC == gcDestructors:
|
||||
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
|
||||
else:
|
||||
c.getEnvTypeForOwner(dep, info)
|
||||
@@ -354,7 +359,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||
let upIdent = getIdent(c.graph.cache, upName)
|
||||
let upField = lookupInRecord(obj.n, upIdent)
|
||||
if upField != nil:
|
||||
if upField.typ.skipTypes({tyOwned, tyRef}) != fieldType.skipTypes({tyOwned, tyRef}):
|
||||
if upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) != fieldType.skipTypes({tyOwned, tyRef, tyPtr}):
|
||||
localError(c.graph.config, dep.info, "internal error: up references do not agree")
|
||||
else:
|
||||
let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
|
||||
@@ -425,8 +430,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
addClosureParam(c, owner, n.info)
|
||||
if interestingIterVar(s):
|
||||
if not c.capturedVars.containsOrIncl(s.id):
|
||||
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef})
|
||||
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef})
|
||||
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
|
||||
if s.name.id == getIdent(c.graph.cache, ":state").id:
|
||||
obj.n[0].sym.id = -s.id
|
||||
@@ -451,8 +456,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
#echo "capturing ", n.info
|
||||
# variable 's' is actually captured:
|
||||
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
|
||||
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef})
|
||||
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef})
|
||||
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
addField(obj, s, c.graph.cache)
|
||||
# create required upFields:
|
||||
var w = owner.skipGenericOwner
|
||||
@@ -477,7 +482,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
w = up
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
|
||||
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt:
|
||||
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
|
||||
discard
|
||||
of nkLambdaKinds, nkIteratorDef:
|
||||
if n.typ != nil:
|
||||
@@ -542,7 +547,7 @@ proc setupEnvVar(owner: PSym; d: DetectionPass;
|
||||
localError d.graph.config, owner.info, "internal error: could not determine closure type"
|
||||
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info)
|
||||
c.envVars[owner.id] = result
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), owner, info)
|
||||
v.flags = {sfShadowed, sfGeneratedOp}
|
||||
v.typ = envVarType
|
||||
@@ -552,7 +557,7 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
|
||||
let p = getHiddenParam(g, owner)
|
||||
result = p.newSymNode
|
||||
if owner.isIterator:
|
||||
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef}).n, getIdent(g.cache, upName))
|
||||
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(g.cache, upName))
|
||||
if upField == nil:
|
||||
localError(g.config, owner.info, "could not find up reference for closure iter")
|
||||
else:
|
||||
@@ -572,20 +577,20 @@ proc rawClosureCreation(owner: PSym;
|
||||
var v = newNodeI(nkVarSection, env.info)
|
||||
addVar(v, env)
|
||||
result.add(v)
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
let unowned = c.unownedEnvVars[owner.id]
|
||||
assert unowned != nil
|
||||
addVar(v, unowned)
|
||||
|
||||
# add 'new' statement:
|
||||
result.add(newCall(getSysSym(d.graph, env.info, "internalNew"), env))
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
let unowned = c.unownedEnvVars[owner.id]
|
||||
assert unowned != nil
|
||||
let env2 = copyTree(env)
|
||||
env2.typ = unowned.typ
|
||||
result.add newAsgnStmt(unowned, env2, env.info)
|
||||
createTypeBoundOps(d.graph, nil, unowned.typ, env.info)
|
||||
createTypeBoundOpsLL(d.graph, unowned.typ, env.info)
|
||||
|
||||
# add assignment statements for captured parameters:
|
||||
for i in 1..<owner.typ.n.len:
|
||||
@@ -595,10 +600,10 @@ proc rawClosureCreation(owner: PSym;
|
||||
# add ``env.param = param``
|
||||
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
|
||||
|
||||
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
|
||||
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
|
||||
if upField != nil:
|
||||
let up = getUpViaParam(d.graph, owner)
|
||||
if up != nil and upField.typ.skipTypes({tyOwned, tyRef}) == up.typ.skipTypes({tyOwned, tyRef}):
|
||||
if up != nil and upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) == up.typ.skipTypes({tyOwned, tyRef, tyPtr}):
|
||||
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
|
||||
up, env.info))
|
||||
#elif oldenv != nil and oldenv.typ == upField.typ:
|
||||
@@ -608,12 +613,12 @@ proc rawClosureCreation(owner: PSym;
|
||||
localError(d.graph.config, env.info, "internal error: cannot create up reference")
|
||||
# we are not in the sem'check phase anymore! so pass 'nil' for the PContext
|
||||
# and hope for the best:
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
createTypeBoundOps(d.graph, nil, env.typ, owner.info)
|
||||
|
||||
proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass;
|
||||
info: TLineInfo; res: PNode) =
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
let unowned = c.unownedEnvVars[owner.id]
|
||||
assert unowned != nil
|
||||
let nilLit = newNodeIT(nkNilLit, info, unowned.typ)
|
||||
@@ -629,7 +634,7 @@ proc closureCreationForIter(iter: PNode;
|
||||
var vnode: PNode
|
||||
if owner.isIterator:
|
||||
let it = getHiddenParam(d.graph, owner)
|
||||
addUniqueField(it.typ.skipTypes({tyOwned, tyRef}), v, d.graph.cache)
|
||||
addUniqueField(it.typ.skipTypes({tyOwned, tyRef, tyPtr}), v, d.graph.cache)
|
||||
vnode = indirectAccess(newSymNode(it), v, v.info)
|
||||
else:
|
||||
vnode = v.newSymNode
|
||||
@@ -637,13 +642,13 @@ proc closureCreationForIter(iter: PNode;
|
||||
addVar(vs, vnode)
|
||||
result.add(vs)
|
||||
result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
createTypeBoundOps(d.graph, nil, vnode.typ, iter.info)
|
||||
|
||||
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
|
||||
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
|
||||
if upField != nil:
|
||||
let u = setupEnvVar(owner, d, c, iter.info)
|
||||
if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}):
|
||||
if u.typ.skipTypes({tyOwned, tyRef, tyPtr}) == upField.typ.skipTypes({tyOwned, tyRef, tyPtr}):
|
||||
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
|
||||
u, iter.info))
|
||||
else:
|
||||
@@ -653,9 +658,9 @@ proc closureCreationForIter(iter: PNode;
|
||||
proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
|
||||
c: var LiftingPass): PNode =
|
||||
var access = setupEnvVar(owner, d, c, n.info)
|
||||
if optNimV2 in d.graph.config.globalOptions:
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
access = c.unownedEnvVars[owner.id]
|
||||
let obj = access.typ.skipTypes({tyOwned, tyRef})
|
||||
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
let field = getFieldFromObj(obj, n.sym)
|
||||
if field != nil:
|
||||
result = rawIndirectAccess(access, field, n.info)
|
||||
@@ -664,7 +669,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
|
||||
result = n
|
||||
|
||||
proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
|
||||
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef}).n.sons[0].sym
|
||||
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n.sons[0].sym
|
||||
|
||||
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
|
||||
c: var LiftingPass): PNode
|
||||
@@ -689,7 +694,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
|
||||
while true:
|
||||
if access.typ == wanted:
|
||||
return makeClosure(d.graph, s, access, n.info)
|
||||
let obj = access.typ.skipTypes({tyOwned, tyRef})
|
||||
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName))
|
||||
if upField == nil:
|
||||
localError(d.graph.config, n.info, "internal error: no environment found")
|
||||
@@ -760,6 +765,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
|
||||
n[0].sons[1] = liftCapturedVars(n[0].sons[1], owner, d, c)
|
||||
else:
|
||||
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
|
||||
of nkTypeOfExpr:
|
||||
result = n
|
||||
else:
|
||||
if owner.isIterator:
|
||||
if nfLL in n.flags:
|
||||
@@ -921,7 +928,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
|
||||
result.add(v)
|
||||
# add 'new' statement:
|
||||
result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode))
|
||||
if optNimV2 in g.config.globalOptions:
|
||||
if optOwnedRefs in g.config.globalOptions:
|
||||
createTypeBoundOps(g, nil, env.typ, body.info)
|
||||
|
||||
elif op.kind == nkStmtListExpr:
|
||||
@@ -933,7 +940,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
|
||||
|
||||
var loopBody = newNodeI(nkStmtList, body.info, 3)
|
||||
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
|
||||
whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(g, body.info, tyBool))
|
||||
whileLoop.sons[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
|
||||
whileLoop.sons[1] = loopBody
|
||||
result.add whileLoop
|
||||
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
|
||||
## Layouter for nimpretty.
|
||||
|
||||
import idents, lexer, lineinfos, llstream, options, msgs, strutils,
|
||||
pathutils
|
||||
from os import changeFileExt
|
||||
from sequtils import delete
|
||||
import idents, lexer, lineinfos, llstream, options, msgs, strutils, pathutils
|
||||
|
||||
const
|
||||
MinLineLen = 15
|
||||
@@ -314,11 +311,11 @@ proc removeSpaces(em: var Emitter) =
|
||||
|
||||
const
|
||||
openPars = {tkParLe, tkParDotLe,
|
||||
tkBracketLe, tkBracketLeColon, tkCurlyDotLe,
|
||||
tkCurlyLe}
|
||||
tkBracketLe, tkBracketDotLe, tkBracketLeColon,
|
||||
tkCurlyDotLe, tkCurlyLe}
|
||||
closedPars = {tkParRi, tkParDotRi,
|
||||
tkBracketRi, tkCurlyDotRi,
|
||||
tkCurlyRi, tkBracketDotRi}
|
||||
tkBracketRi, tkBracketDotRi,
|
||||
tkCurlyDotRi, tkCurlyRi}
|
||||
|
||||
splitters = openPars + {tkComma, tkSemiColon} # do not add 'tkColon' here!
|
||||
oprSet = {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
|
||||
@@ -444,6 +441,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
|
||||
em.indentLevel = tok.indent
|
||||
elif (em.lastTok in (splitters + oprSet) and
|
||||
tok.tokType notin (closedPars - {tkBracketDotRi})):
|
||||
if tok.tokType in openPars and tok.indent > em.indentStack[^1]:
|
||||
while em.indentStack[^1] < tok.indent:
|
||||
em.indentStack.add(em.indentStack[^1] + em.indWidth)
|
||||
# aka: we are in an expression context:
|
||||
let alignment = max(tok.indent - em.indentStack[^1], 0)
|
||||
em.indentLevel = alignment + em.indentStack.high * em.indWidth
|
||||
@@ -499,7 +499,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
|
||||
rememberSplit(splitComma)
|
||||
wrSpace em
|
||||
of openPars:
|
||||
if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker:
|
||||
if tok.strongSpaceA > 0 and not em.endsInWhite and
|
||||
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
|
||||
wrSpace em
|
||||
wr(em, TokTypeToStr[tok.tokType], ltSomeParLe)
|
||||
rememberSplit(splitParLe)
|
||||
|
||||
@@ -134,7 +134,7 @@ type
|
||||
TErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
|
||||
TLexer* = object of TBaseLexer
|
||||
fileIdx*: FileIndex
|
||||
indentAhead*: int # if > 0 an indendation has already been read
|
||||
indentAhead*: int # if > 0 an indentation has already been read
|
||||
# this is needed because scanning comments
|
||||
# needs so much look-ahead
|
||||
currLineIndent*: int
|
||||
@@ -565,7 +565,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
|
||||
case result.tokType
|
||||
of floatTypes:
|
||||
result.fNumber = parseFloat(result.literal)
|
||||
of tkUInt64Lit:
|
||||
of tkUInt64Lit, tkUIntLit:
|
||||
var iNumber: uint64
|
||||
var len: int
|
||||
try:
|
||||
@@ -864,7 +864,9 @@ proc getCharacter(L: var TLexer, tok: var TToken) =
|
||||
inc(L.bufpos) # skip '
|
||||
var c = L.buf[L.bufpos]
|
||||
case c
|
||||
of '\0'..pred(' '), '\'': lexMessage(L, errGenerated, "invalid character literal")
|
||||
of '\0'..pred(' '), '\'':
|
||||
lexMessage(L, errGenerated, "invalid character literal")
|
||||
tok.literal = $c
|
||||
of '\\': getEscapedChar(L, tok)
|
||||
else:
|
||||
tok.literal = $c
|
||||
|
||||
@@ -129,7 +129,7 @@ proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
|
||||
result = newAsgnStmt(x, newOpCall(op, y))
|
||||
|
||||
proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} =
|
||||
result = optNimV2 in c.g.config.globalOptions and
|
||||
result = c.g.config.selectedGC == gcDestructors and
|
||||
({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem)
|
||||
|
||||
proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
|
||||
@@ -142,7 +142,7 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
|
||||
|
||||
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
field: var PSym): bool =
|
||||
if optNimV2 in c.g.config.globalOptions:
|
||||
if c.g.config.selectedGC == gcDestructors:
|
||||
let op = field
|
||||
if field != nil and sfOverriden in field.flags:
|
||||
if sfError in op.flags:
|
||||
@@ -182,8 +182,16 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
body.add newAsgnCall(c.g, op, x, y)
|
||||
result = true
|
||||
|
||||
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode) =
|
||||
proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
|
||||
let t = orig.skipTypes(abstractInst)
|
||||
var op = t.destructor
|
||||
|
||||
if op != nil and sfOverriden in op.flags:
|
||||
if op.ast[genericParamsPos].kind != nkEmpty:
|
||||
# patch generic destructor:
|
||||
op = instantiateGeneric(c, op, t, t.typeInst)
|
||||
t.attachedOps[attachedDestructor] = op
|
||||
|
||||
if op == nil and useNoGc(c, t):
|
||||
op = produceSym(c.g, c.c, t, attachedDestructor, c.info)
|
||||
doAssert op != nil
|
||||
@@ -288,7 +296,7 @@ proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
||||
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
||||
|
||||
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let i = declareCounter(c, body, firstOrd(c.g.config, t))
|
||||
let i = declareCounter(c, body, toInt64(firstOrd(c.g.config, t)))
|
||||
let whileLoop = genWhileLoop(c, i, x)
|
||||
let elemType = t.lastSon
|
||||
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
|
||||
@@ -396,14 +404,14 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if c.kind == attachedDeepCopy:
|
||||
# a big problem is that we don't know the enviroment's type here, so we
|
||||
# a big problem is that we don't know the environment's type here, so we
|
||||
# have to go through some indirection; we delegate this to the codegen:
|
||||
let call = newNodeI(nkCall, c.info, 2)
|
||||
call.typ = t
|
||||
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
|
||||
call.sons[1] = y
|
||||
body.add newAsgnStmt(x, call)
|
||||
elif optNimV2 in c.g.config.globalOptions and
|
||||
elif optOwnedRefs in c.g.config.globalOptions and
|
||||
optRefCheck in c.g.config.options:
|
||||
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
@@ -449,7 +457,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
tyPtr, tyOpt, tyUncheckedArray:
|
||||
defaultOp(c, t, body, x, y)
|
||||
of tyRef:
|
||||
if optNimV2 in c.g.config.globalOptions and
|
||||
if optOwnedRefs in c.g.config.globalOptions and
|
||||
optRefCheck in c.g.config.options:
|
||||
weakrefOp(c, t, body, x, y)
|
||||
else:
|
||||
@@ -461,7 +469,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
defaultOp(c, t, body, x, y)
|
||||
of tyOwned:
|
||||
let base = t.skipTypes(abstractInstOwned)
|
||||
if optNimV2 in c.g.config.globalOptions:
|
||||
if optOwnedRefs in c.g.config.globalOptions:
|
||||
case base.kind
|
||||
of tyRef:
|
||||
ownedRefOp(c, base, body, x, y)
|
||||
@@ -506,7 +514,11 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of tyTuple:
|
||||
fillBodyTup(c, t, body, x, y)
|
||||
of tyVarargs, tyOpenArray:
|
||||
localError(c.g.config, c.info, "cannot copy openArray")
|
||||
if c.kind == attachedDestructor:
|
||||
forallElements(c, t, body, x, y)
|
||||
else:
|
||||
discard "cannot copy openArray"
|
||||
|
||||
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
||||
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
|
||||
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
|
||||
@@ -559,7 +571,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
typ.attachedOps[kind] = result
|
||||
|
||||
var tk: TTypeKind
|
||||
if optNimV2 in g.config.globalOptions:
|
||||
if g.config.selectedGC == gcDestructors:
|
||||
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
|
||||
else:
|
||||
tk = tyNone # no special casing for strings and seqs
|
||||
@@ -626,10 +638,10 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
|
||||
var canon = g.canonTypes.getOrDefault(h)
|
||||
var overwrite = false
|
||||
if canon == nil:
|
||||
let typ = orig.skipTypes({tyGenericInst, tyAlias})
|
||||
let typ = orig.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
g.canonTypes[h] = typ
|
||||
canon = typ
|
||||
elif canon != orig:
|
||||
if canon != orig:
|
||||
overwrite = true
|
||||
|
||||
# multiple cases are to distinguish here:
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import ropes, tables, pathutils
|
||||
|
||||
const
|
||||
explanationsBaseUrl* = "https://nim-lang.org/docs/manual"
|
||||
explanationsBaseUrl* = "https://nim-lang.org/docs"
|
||||
|
||||
type
|
||||
TMsgKind* = enum
|
||||
@@ -33,12 +33,14 @@ type
|
||||
warnFieldXNotSupported, warnCommentXIgnored,
|
||||
warnTypelessParam,
|
||||
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
|
||||
warnUnusedImportX,
|
||||
warnEachIdentIsTuple,
|
||||
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
|
||||
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
|
||||
warnInconsistentSpacing, warnCaseTransition, warnUser,
|
||||
hintSuccess, hintSuccessX, hintCC,
|
||||
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
|
||||
hintLineTooLong, hintXDeclaredButNotUsed,
|
||||
hintConvToBaseNotNeeded,
|
||||
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
|
||||
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
|
||||
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
|
||||
@@ -78,6 +80,7 @@ const
|
||||
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
|
||||
warnWriteToForeignHeap: "write to foreign heap",
|
||||
warnUnsafeCode: "unsafe code: '$1'",
|
||||
warnUnusedImportX: "imported and not used: '$1'",
|
||||
warnEachIdentIsTuple: "each identifier is a tuple",
|
||||
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
|
||||
warnProveField: "cannot prove that field '$1' is accessible",
|
||||
@@ -133,14 +136,15 @@ const
|
||||
"LanguageXNotSupported", "FieldXNotSupported",
|
||||
"CommentXIgnored",
|
||||
"TypelessParam", "UseBase", "WriteToForeignHeap",
|
||||
"UnsafeCode", "EachIdentIsTuple",
|
||||
"UnsafeCode", "UnusedImport", "EachIdentIsTuple",
|
||||
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
|
||||
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
|
||||
"Spacing", "CaseTransition", "User"]
|
||||
|
||||
HintsToStr* = [
|
||||
"Success", "SuccessX", "CC", "LineTooLong",
|
||||
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||
"XDeclaredButNotUsed",
|
||||
"ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
||||
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
|
||||
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro",
|
||||
@@ -240,8 +244,10 @@ type
|
||||
Severity* {.pure.} = enum ## VS Code only supports these three
|
||||
Hint, Warning, Error
|
||||
|
||||
const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
|
||||
# are produced within comments and string literals
|
||||
const
|
||||
trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
|
||||
# are produced within comments and string literals
|
||||
commandLineIdx* = FileIndex(-3)
|
||||
|
||||
type
|
||||
MsgConfig* = object ## does not need to be stored in the incremental cache
|
||||
|
||||
@@ -233,7 +233,7 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
|
||||
addInterfaceDeclAux(c, sym)
|
||||
|
||||
when defined(nimfix):
|
||||
# when we cannot find the identifier, retry with a changed identifer:
|
||||
# when we cannot find the identifier, retry with a changed identifier:
|
||||
proc altSpelling(x: PIdent): PIdent =
|
||||
case x.s[0]
|
||||
of 'A'..'Z': result = getIdent(toLowerAscii(x.s[0]) & x.s.substr(1))
|
||||
@@ -430,7 +430,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
of oimOtherModule:
|
||||
result = nextIdentIter(o.it, o.m.tab).skipAlias(n, c.config)
|
||||
of oimSymChoice:
|
||||
if o.symChoiceIndex < sonsLen(n):
|
||||
if o.symChoiceIndex < len(n):
|
||||
result = n.sons[o.symChoiceIndex].sym
|
||||
incl(o.inSymChoice, result.id)
|
||||
inc o.symChoiceIndex
|
||||
|
||||
@@ -21,8 +21,8 @@ proc newDeref*(n: PNode): PNode {.inline.} =
|
||||
|
||||
proc newTupleAccess*(g: ModuleGraph; tup: PNode, i: int): PNode =
|
||||
if tup.kind == nkHiddenAddr:
|
||||
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar}))
|
||||
result.addSon(newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar}).sons[i]))
|
||||
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent}))
|
||||
result.addSon(newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent}).sons[i]))
|
||||
addSon(result[0], tup[0])
|
||||
var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
|
||||
lit.intVal = i
|
||||
@@ -152,7 +152,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
|
||||
|
||||
proc rawAddField*(obj: PType; field: PSym) =
|
||||
assert field.kind == skField
|
||||
field.position = sonsLen(obj.n)
|
||||
field.position = len(obj.n)
|
||||
addSon(obj.n, newSymNode(field))
|
||||
propagateToOwner(obj, field.typ)
|
||||
|
||||
@@ -179,14 +179,14 @@ proc lookupInRecord(n: PNode, id: int): PSym =
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result = lookupInRecord(n.sons[i], id)
|
||||
if result != nil: return
|
||||
of nkRecCase:
|
||||
if n.sons[0].kind != nkSym: return
|
||||
result = lookupInRecord(n.sons[0], id)
|
||||
if result != nil: return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
result = lookupInRecord(lastSon(n.sons[i]), id)
|
||||
@@ -206,7 +206,7 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) =
|
||||
field.typ = t
|
||||
assert t.kind != tyTyped
|
||||
propagateToOwner(obj, t)
|
||||
field.position = sonsLen(obj.n)
|
||||
field.position = len(obj.n)
|
||||
addSon(obj.n, newSymNode(field))
|
||||
|
||||
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} =
|
||||
@@ -219,7 +219,7 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable
|
||||
field.typ = t
|
||||
assert t.kind != tyTyped
|
||||
propagateToOwner(obj, t)
|
||||
field.position = sonsLen(obj.n)
|
||||
field.position = len(obj.n)
|
||||
addSon(obj.n, newSymNode(field))
|
||||
result = field
|
||||
|
||||
@@ -330,7 +330,7 @@ proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
|
||||
|
||||
proc genHigh*(g: ModuleGraph; n: PNode): PNode =
|
||||
if skipTypes(n.typ, abstractVar).kind == tyArray:
|
||||
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)))
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar))))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
@@ -339,7 +339,7 @@ proc genHigh*(g: ModuleGraph; n: PNode): PNode =
|
||||
|
||||
proc genLen*(g: ModuleGraph; n: PNode): PNode =
|
||||
if skipTypes(n.typ, abstractVar).kind == tyArray:
|
||||
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1)
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
|
||||
@@ -18,7 +18,7 @@ import
|
||||
sem, idents, passes, extccomp,
|
||||
cgen, json, nversion,
|
||||
platform, nimconf, passaux, depends, vm, idgen,
|
||||
parser, modules,
|
||||
modules,
|
||||
modulegraphs, tables, rod, lineinfos, pathutils
|
||||
|
||||
when not defined(leanCompiler):
|
||||
@@ -82,6 +82,13 @@ proc commandCompileToC(graph: ModuleGraph) =
|
||||
semanticPasses(graph)
|
||||
registerPass(graph, cgenPass)
|
||||
|
||||
if {optRun, optForceFullMake} * conf.globalOptions == {optRun} or isDefined(conf, "nimBetterRun"):
|
||||
let proj = changeFileExt(conf.projectFull, "")
|
||||
if not changeDetectedViaJsonBuildInstructions(conf, proj):
|
||||
# nothing changed
|
||||
graph.config.notes = graph.config.mainPackageNotes
|
||||
return
|
||||
|
||||
compileProject(graph)
|
||||
if graph.config.errorCounter > 0:
|
||||
return # issue #9933
|
||||
@@ -143,14 +150,6 @@ const evalPasses = [verbosePass, semPass, evalPass]
|
||||
proc evalNim(graph: ModuleGraph; nodes: PNode, module: PSym) =
|
||||
carryPasses(graph, nodes, module, evalPasses)
|
||||
|
||||
proc commandEval(graph: ModuleGraph; exp: string) =
|
||||
if graph.systemModule == nil:
|
||||
interactivePasses(graph)
|
||||
compileSystemModule(graph)
|
||||
let echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
|
||||
evalNim(graph, echoExp.parseString(graph.cache, graph.config),
|
||||
makeStdinModule(graph))
|
||||
|
||||
proc commandScan(cache: IdentCache, config: ConfigRef) =
|
||||
var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt)
|
||||
var stream = llStreamOpen(f, fmRead)
|
||||
@@ -338,8 +337,11 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
conf.cmd = cmdInteractive
|
||||
commandInteractive(graph)
|
||||
of "e":
|
||||
incl conf.globalOptions, optWasNimscript
|
||||
commandEval(graph, mainCommandArg(conf))
|
||||
if not fileExists(conf.projectFull):
|
||||
rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string)
|
||||
elif not conf.projectFull.string.endsWith(".nims"):
|
||||
rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string)
|
||||
# main NimScript logic handled in cmdlinehelper.nim.
|
||||
of "nop", "help":
|
||||
# prevent the "success" message:
|
||||
conf.cmd = cmdDump
|
||||
|
||||
@@ -64,7 +64,7 @@ type
|
||||
importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.}
|
||||
includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.}
|
||||
recordStmt*: proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.}
|
||||
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
|
||||
cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API
|
||||
cacheCounters*: Table[string, BiggestInt]
|
||||
cacheTables*: Table[string, BTree[string, PNode]]
|
||||
passes*: seq[TPass]
|
||||
@@ -98,7 +98,7 @@ const
|
||||
proc toBase64a(s: cstring, len: int): string =
|
||||
## encodes `s` into base64 representation.
|
||||
result = newStringOfCap(((len + 2) div 3) * 4)
|
||||
result.add '_'
|
||||
result.add "__"
|
||||
var i = 0
|
||||
while i < len - 2:
|
||||
let a = ord(s[i])
|
||||
@@ -215,7 +215,7 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
|
||||
addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false)
|
||||
if g.suggestMode:
|
||||
g.deps.incl m.position.dependsOn(dep.int)
|
||||
# we compute the transitive closure later when quering the graph lazily.
|
||||
# we compute the transitive closure later when querying the graph lazily.
|
||||
# this improves efficiency quite a lot:
|
||||
#invalidTransitiveClosure = true
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
|
||||
setLen(graph.modules, int(fileIdx) + 1)
|
||||
graph.modules[result.position] = result
|
||||
|
||||
incl(result.flags, sfUsed)
|
||||
initStrTable(result.tab)
|
||||
strTableAdd(result.tab, result) # a module knows itself
|
||||
strTableAdd(packSym.tab, result)
|
||||
|
||||
@@ -81,6 +81,7 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
|
||||
pseudoPath = true
|
||||
|
||||
if conf.m.filenameToIndexTbl.hasKey(canon.string):
|
||||
isKnownFile = true
|
||||
result = conf.m.filenameToIndexTbl[canon.string]
|
||||
else:
|
||||
isKnownFile = false
|
||||
@@ -160,19 +161,25 @@ proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
|
||||
if i >=% L: result = unknownLineInfo()
|
||||
else: result = conf.m.msgContext[i].info
|
||||
|
||||
const
|
||||
commandLineDesc = "command line"
|
||||
|
||||
template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
|
||||
if fileIdx.int32 < 0 or conf == nil:
|
||||
"???"
|
||||
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
|
||||
else:
|
||||
conf.m.fileInfos[fileIdx.int32].shortName
|
||||
|
||||
proc toProjPath*(conf: ConfigRef; fileIdx: FileIndex): string =
|
||||
if fileIdx.int32 < 0 or conf == nil: "???"
|
||||
if fileIdx.int32 < 0 or conf == nil:
|
||||
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
|
||||
else: conf.m.fileInfos[fileIdx.int32].projPath.string
|
||||
|
||||
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
|
||||
if fileIdx.int32 < 0 or conf == nil: result = "???"
|
||||
else: result = conf.m.fileInfos[fileIdx.int32].fullPath.string
|
||||
if fileIdx.int32 < 0 or conf == nil:
|
||||
result = (if fileIdx == commandLineIdx: commandLineDesc else: "???")
|
||||
else:
|
||||
result = conf.m.fileInfos[fileIdx.int32].fullPath.string
|
||||
|
||||
proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: AbsoluteFile) =
|
||||
assert fileIdx.int32 >= 0
|
||||
@@ -189,7 +196,7 @@ proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
|
||||
|
||||
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile =
|
||||
if fileIdx.int32 < 0:
|
||||
result = AbsoluteFile"???"
|
||||
result = AbsoluteFile(if fileIdx == commandLineIdx: commandLineDesc else: "???")
|
||||
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isEmpty:
|
||||
result = conf.m.fileInfos[fileIdx.int32].dirtyFile
|
||||
else:
|
||||
|
||||
@@ -7,6 +7,8 @@ define:nimcore
|
||||
#define:nimIncremental
|
||||
#import:"$projectpath/testability"
|
||||
|
||||
#define:staticSqlite
|
||||
|
||||
@if windows:
|
||||
cincludes: "$lib/wrappers/libffi/common"
|
||||
@end
|
||||
|
||||
@@ -40,20 +40,40 @@ proc prependCurDir(f: AbsoluteFile): AbsoluteFile =
|
||||
else:
|
||||
result = f
|
||||
|
||||
proc addCmdPrefix*(result: var string, kind: CmdLineKind) =
|
||||
# consider moving this to std/parseopt
|
||||
case kind
|
||||
of cmdLongOption: result.add "--"
|
||||
of cmdShortOption: result.add "-"
|
||||
of cmdArgument, cmdEnd: discard
|
||||
|
||||
proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
|
||||
var p = parseopt.initOptParser(cmd)
|
||||
var argsCount = 0
|
||||
|
||||
config.commandLine.setLen 0
|
||||
# bugfix: otherwise, config.commandLine ends up duplicated
|
||||
|
||||
while true:
|
||||
parseopt.next(p)
|
||||
case p.kind
|
||||
of cmdEnd: break
|
||||
of cmdLongOption, cmdShortOption:
|
||||
config.commandLine.add " "
|
||||
config.commandLine.addCmdPrefix p.kind
|
||||
config.commandLine.add p.key.quoteShell # quoteShell to be future proof
|
||||
if p.val.len > 0:
|
||||
config.commandLine.add ':'
|
||||
config.commandLine.add p.val.quoteShell
|
||||
|
||||
if p.key == " ":
|
||||
p.key = "-"
|
||||
if processArgument(pass, p, argsCount, config): break
|
||||
else:
|
||||
processSwitch(pass, p, config)
|
||||
of cmdArgument:
|
||||
config.commandLine.add " "
|
||||
config.commandLine.add p.key.quoteShell
|
||||
if processArgument(pass, p, argsCount, config): break
|
||||
if pass == passCmd2:
|
||||
if {optRun, optWasNimscript} * config.globalOptions == {} and
|
||||
|
||||
@@ -69,9 +69,10 @@ proc getPathVersion*(p: string): tuple[name, version: string] =
|
||||
result.version = ""
|
||||
|
||||
const specialSeparator = "-#"
|
||||
var sepIdx = p.find(specialSeparator)
|
||||
let last = p.rfind(p.lastPathPart) # the index where the last path part begins
|
||||
var sepIdx = p.find(specialSeparator, start = last)
|
||||
if sepIdx == -1:
|
||||
sepIdx = p.rfind('-')
|
||||
sepIdx = p.rfind('-', start = last)
|
||||
|
||||
if sepIdx == -1:
|
||||
result.name = p
|
||||
|
||||
@@ -160,8 +160,9 @@ proc checkSymbol(L: TLexer, tok: TToken) =
|
||||
|
||||
proc parseAssignment(L: var TLexer, tok: var TToken;
|
||||
config: ConfigRef; condStack: var seq[bool]) =
|
||||
if tok.ident.s == "-" or tok.ident.s == "--":
|
||||
confTok(L, tok, config, condStack) # skip unnecessary prefix
|
||||
if tok.ident != nil:
|
||||
if tok.ident.s == "-" or tok.ident.s == "--":
|
||||
confTok(L, tok, config, condStack) # skip unnecessary prefix
|
||||
var info = getLineInfo(L, tok) # save for later in case of an error
|
||||
checkSymbol(L, tok)
|
||||
var s = $tok
|
||||
@@ -190,6 +191,12 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
|
||||
checkSymbol(L, tok)
|
||||
add(val, $tok)
|
||||
confTok(L, tok, config, condStack) # skip symbol
|
||||
if tok.tokType in {tkColon, tkEquals}:
|
||||
add(val, $tok) # add the :
|
||||
confTok(L, tok, config, condStack) # skip symbol
|
||||
checkSymbol(L, tok)
|
||||
add(val, $tok) # add the token after it
|
||||
confTok(L, tok, config, condStack) # skip symbol
|
||||
while tok.ident != nil and tok.ident.s == "&":
|
||||
confTok(L, tok, config, condStack)
|
||||
checkSymbol(L, tok)
|
||||
@@ -201,7 +208,7 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
|
||||
else:
|
||||
processSwitch(s, val, passPP, info, config)
|
||||
|
||||
proc readConfigFile(filename: AbsoluteFile; cache: IdentCache;
|
||||
proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache;
|
||||
config: ConfigRef): bool =
|
||||
var
|
||||
L: TLexer
|
||||
|
||||
@@ -46,7 +46,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
|
||||
s = nextIdentIter(it, i.mainModule.tab)
|
||||
|
||||
proc selectRoutine*(i: Interpreter; name: string): PSym =
|
||||
## Selects a declared rountine (proc/func/etc) from the main module.
|
||||
## Selects a declared routine (proc/func/etc) from the main module.
|
||||
## The routine needs to have the export marker ``*``. The only matching
|
||||
## routine is returned and ``nil`` if it is overloaded.
|
||||
result = selectUniqueSymbol(i, name, {skTemplate, skMacro, skFunc,
|
||||
|
||||
@@ -98,7 +98,7 @@ proc handleCmdLine(config: ConfigRef) =
|
||||
gProjectPath = getCurrentDir()
|
||||
loadConfigs(DefaultConfig, config) # load all config files
|
||||
# now process command line arguments again, because some options in the
|
||||
# command line can overwite the config file's settings
|
||||
# command line can overwrite the config file's settings
|
||||
extccomp.initVars()
|
||||
processCmdLine(passCmd2, "", config)
|
||||
mainCommand()
|
||||
|
||||
@@ -17,7 +17,7 @@ proc inSet*(s: PNode, elem: PNode): bool =
|
||||
if s.kind != nkCurly:
|
||||
#internalError(s.info, "inSet")
|
||||
return false
|
||||
for i in 0 ..< sonsLen(s):
|
||||
for i in 0 ..< len(s):
|
||||
if s.sons[i].kind == nkRange:
|
||||
if leValue(s.sons[i].sons[0], elem) and
|
||||
leValue(elem, s.sons[i].sons[1]):
|
||||
@@ -47,7 +47,7 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
|
||||
if s.kind != nkCurly:
|
||||
#internalError(s.info, "SomeInSet")
|
||||
return false
|
||||
for i in 0 ..< sonsLen(s):
|
||||
for i in 0 ..< len(s):
|
||||
if s.sons[i].kind == nkRange:
|
||||
if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
|
||||
leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
|
||||
@@ -59,17 +59,17 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
|
||||
result = false
|
||||
|
||||
proc toBitSet*(conf: ConfigRef; s: PNode, b: var TBitSet) =
|
||||
var first, j: BiggestInt
|
||||
var first, j: Int128
|
||||
first = firstOrd(conf, s.typ.sons[0])
|
||||
bitSetInit(b, int(getSize(conf, s.typ)))
|
||||
for i in 0 ..< sonsLen(s):
|
||||
for i in 0 ..< len(s):
|
||||
if s.sons[i].kind == nkRange:
|
||||
j = getOrdValue(s.sons[i].sons[0], first)
|
||||
while j <= getOrdValue(s.sons[i].sons[1], first):
|
||||
bitSetIncl(b, j - first)
|
||||
bitSetIncl(b, toInt64(j - first))
|
||||
inc(j)
|
||||
else:
|
||||
bitSetIncl(b, getOrdValue(s.sons[i], first) - first)
|
||||
bitSetIncl(b, toInt64(getOrdValue(s.sons[i]) - first))
|
||||
|
||||
proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
||||
var
|
||||
@@ -77,7 +77,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
elemType: PType
|
||||
n: PNode
|
||||
elemType = settype.sons[0]
|
||||
first = firstOrd(conf, elemType)
|
||||
first = firstOrd(conf, elemType).toInt64
|
||||
result = newNodeI(nkCurly, info)
|
||||
result.typ = settype
|
||||
result.info = info
|
||||
@@ -90,7 +90,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
inc(b)
|
||||
if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
|
||||
dec(b)
|
||||
let aa = newIntTypeNode(nkIntLit, a + first, elemType)
|
||||
let aa = newIntTypeNode(a + first, elemType)
|
||||
aa.info = info
|
||||
if a == b:
|
||||
addSon(result, aa)
|
||||
@@ -98,7 +98,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
n = newNodeI(nkRange, info)
|
||||
n.typ = elemType
|
||||
addSon(n, aa)
|
||||
let bb = newIntTypeNode(nkIntLit, b + first, elemType)
|
||||
let bb = newIntTypeNode(b + first, elemType)
|
||||
bb.info = info
|
||||
addSon(n, bb)
|
||||
addSon(result, n)
|
||||
@@ -149,7 +149,7 @@ proc setHasRange*(s: PNode): bool =
|
||||
assert s.kind == nkCurly
|
||||
if s.kind != nkCurly:
|
||||
return false
|
||||
for i in 0 ..< sonsLen(s):
|
||||
for i in 0 ..< len(s):
|
||||
if s.sons[i].kind == nkRange:
|
||||
return true
|
||||
result = false
|
||||
|
||||
@@ -15,6 +15,6 @@ const
|
||||
VersionAsString* = system.NimVersion
|
||||
RodFileVersion* = "1223" # modify this if the rod-format changes!
|
||||
|
||||
NimCompilerApiVersion* = 3 ## Check for the existance of this before accessing it
|
||||
NimCompilerApiVersion* = 3 ## Check for the existence of this before accessing it
|
||||
## as older versions of the compiler API do not
|
||||
## declare this.
|
||||
|
||||
@@ -30,7 +30,6 @@ type # please make sure we have under 32 options
|
||||
optAssert, optLineDir, optWarns, optHints,
|
||||
optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
|
||||
optLineTrace, # line tracing support (includes stack tracing)
|
||||
optEndb, # embedded debugger
|
||||
optByRef, # use pass by ref for objects
|
||||
# (for interfacing with C)
|
||||
optProfiler, # profiler turned on
|
||||
@@ -82,8 +81,13 @@ type # please make sure we have under 32 options
|
||||
optNoNimblePath
|
||||
optHotCodeReloading
|
||||
optDynlibOverrideAll
|
||||
optNimV2
|
||||
optSeqDestructors # active if the implementation uses the new
|
||||
# string/seq implementation based on destructors
|
||||
optTinyRtti # active if we use the new "tiny RTTI"
|
||||
# implementation
|
||||
optOwnedRefs # active if the Nim compiler knows about 'owned'.
|
||||
optMultiMethods
|
||||
optNimV019
|
||||
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
|
||||
@@ -110,7 +114,7 @@ type
|
||||
cmdJsonScript # compile a .json build file
|
||||
TStringSeq* = seq[string]
|
||||
TGCMode* = enum # the selected GC
|
||||
gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
|
||||
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
|
||||
gcRefc, gcV2, gcGo
|
||||
# gcRefc and the GCs that follow it use a write barrier,
|
||||
# as far as usesWriteBarrier() is concerned
|
||||
@@ -138,8 +142,12 @@ type
|
||||
LegacyFeature* = enum
|
||||
allowSemcheckedAstModification,
|
||||
## Allows to modify a NimNode where the type has already been
|
||||
## flaged with nfSem. If you actually do this, it will cause
|
||||
## flagged with nfSem. If you actually do this, it will cause
|
||||
## bugs.
|
||||
checkUnsignedConversions
|
||||
## Historically and especially in version 1.0.0 of the language
|
||||
## conversions to unsigned numbers were checked. In 1.0.4 they
|
||||
## are not anymore.
|
||||
|
||||
SymbolFilesOption* = enum
|
||||
disabledSf, writeOnlySf, readOnlySf, v2Sf
|
||||
@@ -236,6 +244,7 @@ type
|
||||
projectMainIdx*: FileIndex # the canonical path id of the main module
|
||||
command*: string # the main command (e.g. cc, check, scan, etc)
|
||||
commandArgs*: seq[string] # any arguments after the main command
|
||||
commandLine*: string
|
||||
keepComments*: bool # whether the parser needs to keep comments
|
||||
implicitImports*: seq[string] # modules that are to be implicitly imported
|
||||
implicitIncludes*: seq[string] # modules that are to be implicitly included
|
||||
@@ -342,6 +351,7 @@ proc newConfigRef*(): ConfigRef =
|
||||
projectMainIdx: FileIndex(0'i32), # the canonical path id of the main module
|
||||
command: "", # the main command (e.g. cc, check, scan, etc)
|
||||
commandArgs: @[], # any arguments after the main command
|
||||
commandLine: "",
|
||||
keepComments: true, # whether the parser needs to keep comments
|
||||
implicitImports: @[], # modules that are to be implicitly imported
|
||||
implicitIncludes: @[], # modules that are to be implicitly included
|
||||
@@ -395,7 +405,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||
result = conf.target.targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
|
||||
osQnx, osAtari, osAix,
|
||||
osHaiku, osVxWorks, osSolaris, osNetbsd,
|
||||
osFreebsd, osOpenbsd, osDragonfly, osMacosx,
|
||||
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
|
||||
osAndroid, osNintendoSwitch}
|
||||
of "linux":
|
||||
result = conf.target.targetOS in {osLinux, osAndroid}
|
||||
@@ -405,8 +415,10 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
|
||||
result = platform.OS[conf.target.targetOS].props.contains(ospLacksThreadVars)
|
||||
of "msdos": result = conf.target.targetOS == osDos
|
||||
of "mswindows", "win32": result = conf.target.targetOS == osWindows
|
||||
of "macintosh": result = conf.target.targetOS in {osMacos, osMacosx}
|
||||
of "osx": result = conf.target.targetOS == osMacosx
|
||||
of "macintosh":
|
||||
result = conf.target.targetOS in {osMacos, osMacosx, osIos}
|
||||
of "osx", "macosx":
|
||||
result = conf.target.targetOS in {osMacosx, osIos}
|
||||
of "sunos": result = conf.target.targetOS == osSolaris
|
||||
of "nintendoswitch":
|
||||
result = conf.target.targetOS == osNintendoSwitch
|
||||
@@ -469,12 +481,16 @@ proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): Absolute
|
||||
conf.outDir / changeFileExt(filename, ext)
|
||||
|
||||
proc absOutFile*(conf: ConfigRef): AbsoluteFile =
|
||||
conf.outDir / conf.outFile
|
||||
result = conf.outDir / conf.outFile
|
||||
if dirExists(result.string):
|
||||
result.string.add ".out"
|
||||
|
||||
proc prepareToWriteOutput*(conf: ConfigRef): AbsoluteFile =
|
||||
## Create the output directory and returns a full path to the output file
|
||||
createDir conf.outDir
|
||||
return conf.outDir / conf.outFile
|
||||
result = conf.outDir / conf.outFile
|
||||
if dirExists(result.string):
|
||||
result.string.add ".out"
|
||||
|
||||
proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
|
||||
## Gets the prefix dir, usually the parent directory where the binary resides.
|
||||
@@ -532,6 +548,9 @@ proc disableNimblePath*(conf: ConfigRef) =
|
||||
incl conf.globalOptions, optNoNimblePath
|
||||
conf.lazyPaths.setLen(0)
|
||||
|
||||
proc clearNimblePath*(conf: ConfigRef) =
|
||||
conf.lazyPaths.setLen(0)
|
||||
|
||||
include packagehandling
|
||||
|
||||
proc getOsCacheDir(): string =
|
||||
@@ -560,9 +579,7 @@ proc pathSubs*(conf: ConfigRef; p, config: string): string =
|
||||
"projectname", conf.projectName,
|
||||
"projectpath", conf.projectPath.string,
|
||||
"projectdir", conf.projectPath.string,
|
||||
"nimcache", getNimcacheDir(conf).string])
|
||||
if "~/" in result:
|
||||
result = result.replace("~/", home & '/')
|
||||
"nimcache", getNimcacheDir(conf).string]).expandTilde
|
||||
|
||||
proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
|
||||
ext: string): AbsoluteFile =
|
||||
@@ -716,3 +733,13 @@ proc `$`*(c: IdeCmd): string =
|
||||
of ideOutline: "outline"
|
||||
of ideKnown: "known"
|
||||
of ideMsg: "msg"
|
||||
|
||||
proc floatInt64Align*(conf: ConfigRef): int16 =
|
||||
## Returns either 4 or 8 depending on reasons.
|
||||
if conf != nil and conf.target.targetCPU == cpuI386:
|
||||
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
|
||||
if conf.target.targetOS != osWindows:
|
||||
# on i386 for all known POSIX systems, 64bits ints are aligned
|
||||
# to 4bytes (except with -malign-double)
|
||||
return 4
|
||||
return 8
|
||||
|
||||
@@ -39,22 +39,17 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
|
||||
if parents <= 0: break
|
||||
|
||||
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
|
||||
# foo/../bar becomes foo7_7bar
|
||||
result = relativeTo(path, conf.projectPath, '/').string.multiReplace(
|
||||
{"/": "7", "..": "_", "7": "77", "_": "__", ":": "8", "8": "88"})
|
||||
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
|
||||
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@", ":": "@c"})
|
||||
|
||||
proc demanglePackageName*(path: string): string =
|
||||
result = path.multiReplace(
|
||||
{"88": "8", "8": ":", "77": "7", "__": "_", "_7": "../", "7": "/"})
|
||||
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
|
||||
|
||||
proc withPackageName*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
|
||||
let x = getPackageName(conf, path.string)
|
||||
if x.len == 0:
|
||||
result = path
|
||||
let (p, file, ext) = path.splitFile
|
||||
if x == "stdlib":
|
||||
# Hot code reloading now relies on 'stdlib_system' names etc.
|
||||
result = p / RelativeFile((x & '_' & file) & ext)
|
||||
else:
|
||||
let (p, file, ext) = path.splitFile
|
||||
if x == "stdlib":
|
||||
# Hot code reloading now relies on 'stdlib_system' names etc.
|
||||
result = p / RelativeFile((x & '_' & file) & ext)
|
||||
else:
|
||||
result = p / RelativeFile(fakePackageName(conf, path))
|
||||
result = p / RelativeFile(fakePackageName(conf, path))
|
||||
|
||||
@@ -218,20 +218,22 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||
of nkSym:
|
||||
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
|
||||
else: {skVar, skResult, skTemp}
|
||||
if n.sym.kind in kinds:
|
||||
if n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and n.sym.kind == skParam:
|
||||
result = arLValue
|
||||
elif n.sym.kind in kinds:
|
||||
if owner != nil and owner == n.sym.owner and
|
||||
sfGlobal notin n.sym.flags:
|
||||
result = arLocalLValue
|
||||
else:
|
||||
result = arLValue
|
||||
elif n.sym.kind == skParam and n.sym.typ.kind == tyVar:
|
||||
result = arLValue
|
||||
elif n.sym.kind == skType:
|
||||
let t = n.sym.typ.skipTypes({tyTypeDesc})
|
||||
if t.kind == tyVar: result = arStrange
|
||||
of nkDotExpr:
|
||||
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind in {tyVar, tyPtr, tyRef}:
|
||||
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and t.kind == tyLent:
|
||||
result = arLValue
|
||||
@@ -242,7 +244,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||
result = arDiscriminant
|
||||
of nkBracketExpr:
|
||||
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind in {tyVar, tyPtr, tyRef}:
|
||||
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
elif isUnsafeAddr and t.kind == tyLent:
|
||||
result = arLValue
|
||||
|
||||
@@ -26,6 +26,9 @@ when isMainModule:
|
||||
outp.write matches[0], "\L"
|
||||
outp.close
|
||||
|
||||
import ".." / tools / grammar_nanny
|
||||
checkGrammarFile()
|
||||
|
||||
import
|
||||
llstream, lexer, idents, strutils, ast, msgs, options, lineinfos,
|
||||
pathutils
|
||||
@@ -710,7 +713,7 @@ proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode =
|
||||
result = parseCast(p)
|
||||
else:
|
||||
parMessage(p, errExprExpected, p.tok)
|
||||
getTok(p) # we must consume a token here to prevend endless loops!
|
||||
getTok(p) # we must consume a token here to prevent endless loops!
|
||||
result = p.emptyNode
|
||||
|
||||
proc namedParams(p: var TParser, callee: PNode,
|
||||
@@ -750,11 +753,10 @@ proc commandExpr(p: var TParser; r: PNode; mode: TPrimaryMode): PNode =
|
||||
|
||||
proc primarySuffix(p: var TParser, r: PNode,
|
||||
baseIndent: int, mode: TPrimaryMode): PNode =
|
||||
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
|
||||
#| | doBlocks
|
||||
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')'
|
||||
#| | '.' optInd symbol generalizedLit?
|
||||
#| | '[' optInd indexExprList optPar ']'
|
||||
#| | '{' optInd indexExprList optPar '}'
|
||||
#| | '[' optInd exprColonEqExprList optPar ']'
|
||||
#| | '{' optInd exprColonEqExprList optPar '}'
|
||||
#| | &( '`'|IDENT|literal|'cast'|'addr'|'type') expr # command syntax
|
||||
result = r
|
||||
|
||||
@@ -908,7 +910,7 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
|
||||
p.currInd = oldInd
|
||||
|
||||
proc parsePragma(p: var TParser): PNode =
|
||||
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
|
||||
#| pragma = '{.' optInd (exprColonEqExpr comma?)* optPar ('.}' | '}')
|
||||
result = newNodeP(nkPragma, p)
|
||||
inc p.inPragma
|
||||
when defined(nimpretty):
|
||||
@@ -937,8 +939,8 @@ proc parsePragma(p: var TParser): PNode =
|
||||
dec p.em.keepIndents
|
||||
|
||||
proc identVis(p: var TParser; allowDot=false): PNode =
|
||||
#| identVis = symbol opr? # postfix position
|
||||
#| identVisDot = symbol '.' optInd symbol opr?
|
||||
#| identVis = symbol OPR? # postfix position
|
||||
#| identVisDot = symbol '.' optInd symbol OPR?
|
||||
var a = parseSymbol(p)
|
||||
if p.tok.tokType == tkOpr:
|
||||
when defined(nimpretty):
|
||||
@@ -973,7 +975,7 @@ type
|
||||
proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
|
||||
#| declColonEquals = identWithPragma (comma identWithPragma)* comma?
|
||||
#| (':' optInd typeDesc)? ('=' optInd expr)?
|
||||
#| identColonEquals = ident (comma ident)* comma?
|
||||
#| identColonEquals = IDENT (comma IDENT)* comma?
|
||||
#| (':' optInd typeDesc)? ('=' optInd expr)?)
|
||||
var a: PNode
|
||||
result = newNodeP(nkIdentDefs, p)
|
||||
@@ -1006,7 +1008,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
|
||||
|
||||
proc parseTuple(p: var TParser, indentAllowed = false): PNode =
|
||||
#| inlTupleDecl = 'tuple'
|
||||
#| [' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
|
||||
#| '[' optInd (identColonEquals (comma/semicolon)?)* optPar ']'
|
||||
#| extTupleDecl = 'tuple'
|
||||
#| COMMENT? (IND{>} identColonEquals (IND{=} identColonEquals)*)?
|
||||
#| tupleClass = 'tuple'
|
||||
@@ -1104,7 +1106,7 @@ proc optPragmas(p: var TParser): PNode =
|
||||
result = p.emptyNode
|
||||
|
||||
proc parseDoBlock(p: var TParser; info: TLineInfo): PNode =
|
||||
#| doBlock = 'do' paramListArrow pragmas? colcom stmt
|
||||
#| doBlock = 'do' paramListArrow pragma? colcom stmt
|
||||
let params = parseParamList(p, retColon=false)
|
||||
let pragmas = optPragmas(p)
|
||||
colcom(p, result)
|
||||
@@ -1115,7 +1117,7 @@ proc parseDoBlock(p: var TParser; info: TLineInfo): PNode =
|
||||
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
|
||||
|
||||
proc parseProcExpr(p: var TParser; isExpr: bool; kind: TNodeKind): PNode =
|
||||
#| procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
|
||||
#| procExpr = 'proc' paramListColon pragma? ('=' COMMENT? stmt)?
|
||||
# either a proc type or a anonymous proc
|
||||
let info = parLineInfo(p)
|
||||
getTok(p)
|
||||
@@ -1214,11 +1216,11 @@ proc parseExpr(p: var TParser): PNode =
|
||||
#| expr = (blockExpr
|
||||
#| | ifExpr
|
||||
#| | whenExpr
|
||||
#| | caseExpr
|
||||
#| | forExpr
|
||||
#| | caseStmt
|
||||
#| | forExpr
|
||||
#| | tryExpr)
|
||||
#| / simpleExpr
|
||||
case p.tok.tokType:
|
||||
case p.tok.tokType
|
||||
of tkBlock:
|
||||
nimprettyDontTouch:
|
||||
result = parseBlock(p)
|
||||
@@ -1248,7 +1250,7 @@ proc parseTypeClass(p: var TParser): PNode
|
||||
proc primary(p: var TParser, mode: TPrimaryMode): PNode =
|
||||
#| typeKeyw = 'var' | 'out' | 'ref' | 'ptr' | 'shared' | 'tuple'
|
||||
#| | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'
|
||||
#| primary = typeKeyw typeDescK
|
||||
#| primary = typeKeyw optInd typeDesc
|
||||
#| / prefixOperator* identOrLiteral primarySuffix*
|
||||
#| / 'bind' primary
|
||||
if isOperator(p.tok):
|
||||
@@ -1420,8 +1422,7 @@ proc parseExprStmt(p: var TParser): PNode =
|
||||
#| exprStmt = simpleExpr
|
||||
#| (( '=' optInd expr colonBody? )
|
||||
#| / ( expr ^+ comma
|
||||
#| doBlocks
|
||||
#| / macroColon
|
||||
#| postExprBlocks
|
||||
#| ))?
|
||||
var a = simpleExpr(p)
|
||||
if p.tok.tokType == tkEquals:
|
||||
@@ -1468,6 +1469,9 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode =
|
||||
#| importStmt = 'import' optInd expr
|
||||
#| ((comma expr)*
|
||||
#| / 'except' optInd (expr ^+ comma))
|
||||
#| exportStmt = 'export' optInd expr
|
||||
#| ((comma expr)*
|
||||
#| / 'except' optInd (expr ^+ comma))
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p) # skip `import` or `export`
|
||||
optInd(p, result)
|
||||
@@ -1506,7 +1510,7 @@ proc parseIncludeStmt(p: var TParser): PNode =
|
||||
#expectNl(p)
|
||||
|
||||
proc parseFromStmt(p: var TParser): PNode =
|
||||
#| fromStmt = 'from' moduleName 'import' optInd expr (comma expr)*
|
||||
#| fromStmt = 'from' expr 'import' optInd expr (comma expr)*
|
||||
result = newNodeP(nkFromStmt, p)
|
||||
getTok(p) # skip `from`
|
||||
optInd(p, result)
|
||||
@@ -1791,7 +1795,7 @@ type
|
||||
|
||||
proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
defparser: TDefParser): PNode =
|
||||
#| section(p) = COMMENT? p / (IND{>} (p / COMMENT)^+IND{=} DED)
|
||||
#| section(RULE) = COMMENT? RULE / (IND{>} (RULE / COMMENT)^+IND{=} DED)
|
||||
result = newNodeP(kind, p)
|
||||
if kind != nkTypeSection: getTok(p)
|
||||
skipComment(p, result)
|
||||
@@ -1819,7 +1823,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||
parMessage(p, errIdentifierExpected, p.tok)
|
||||
|
||||
proc parseEnum(p: var TParser): PNode =
|
||||
#| enum = 'enum' optInd (symbol optPragmas optInd ('=' optInd expr COMMENT?)? comma?)+
|
||||
#| enum = 'enum' optInd (symbol pragma? optInd ('=' optInd expr COMMENT?)? comma?)+
|
||||
result = newNodeP(nkEnumTy, p)
|
||||
getTok(p)
|
||||
addSon(result, p.emptyNode)
|
||||
@@ -2105,7 +2109,7 @@ proc parseVarTuple(p: var TParser): PNode =
|
||||
eat(p, tkParRi)
|
||||
|
||||
proc parseVariable(p: var TParser): PNode =
|
||||
#| colonBody = colcom stmt doBlocks?
|
||||
#| colonBody = colcom stmt postExprBlocks?
|
||||
#| variable = (varTuple / identColonEquals) colonBody? indAndComment
|
||||
if p.tok.tokType == tkParLe:
|
||||
result = parseVarTuple(p)
|
||||
@@ -2117,7 +2121,7 @@ proc parseVariable(p: var TParser): PNode =
|
||||
indAndComment(p, result)
|
||||
|
||||
proc parseConstant(p: var TParser): PNode =
|
||||
#| constant = (parseVarTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
|
||||
#| constant = (varTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
|
||||
if p.tok.tokType == tkParLe: result = parseVarTuple(p)
|
||||
else:
|
||||
result = newNodeP(nkConstDef, p)
|
||||
|
||||
@@ -97,7 +97,6 @@ proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
|
||||
proc processImplicits(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
|
||||
a: var TPassContextArray; m: PSym) =
|
||||
# XXX fixme this should actually be relative to the config file!
|
||||
let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
|
||||
let relativeTo = toFullPath(graph.config, m.info)
|
||||
for module in items(implicits):
|
||||
# implicit imports should not lead to a module importing itself
|
||||
|
||||
@@ -58,8 +58,8 @@ proc sameTrees*(a, b: PNode): bool =
|
||||
of nkEmpty, nkNilLit: result = true
|
||||
of nkType: result = sameTypeOrNil(a.typ, b.typ)
|
||||
else:
|
||||
if sonsLen(a) == sonsLen(b):
|
||||
for i in 0 ..< sonsLen(a):
|
||||
if len(a) == len(b):
|
||||
for i in 0 ..< len(a):
|
||||
if not sameTrees(a.sons[i], b.sons[i]): return
|
||||
result = true
|
||||
|
||||
@@ -112,7 +112,7 @@ proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
|
||||
rpn: bool): bool =
|
||||
result = true
|
||||
if n.kind in nkCallKinds and matches(c, op.sons[1], n.sons[0]):
|
||||
for i in 1..sonsLen(n)-1:
|
||||
for i in 1..len(n)-1:
|
||||
if not matchStarAux(c, op, n[i], arglist, rpn): return false
|
||||
if rpn: arglist.add(n.sons[0])
|
||||
elif n.kind == nkHiddenStdConv and n.sons[1].kind == nkBracket:
|
||||
@@ -174,35 +174,35 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
|
||||
of nkEmpty, nkNilLit, nkType:
|
||||
result = true
|
||||
else:
|
||||
var plen = sonsLen(p)
|
||||
var plen = len(p)
|
||||
# special rule for p(X) ~ f(...); this also works for stuff like
|
||||
# partial case statements, etc! - Not really ... :-/
|
||||
let v = lastSon(p)
|
||||
if isPatternParam(c, v) and v.sym.typ.kind == tyVarargs:
|
||||
var arglist: PNode
|
||||
if plen <= sonsLen(n):
|
||||
if plen <= len(n):
|
||||
for i in 0 .. plen - 2:
|
||||
if not matches(c, p.sons[i], n.sons[i]): return
|
||||
if plen == sonsLen(n) and lastSon(n).kind == nkHiddenStdConv and
|
||||
if plen == len(n) and lastSon(n).kind == nkHiddenStdConv and
|
||||
lastSon(n).sons[1].kind == nkBracket:
|
||||
# unpack varargs:
|
||||
let n = lastSon(n).sons[1]
|
||||
arglist = newNodeI(nkArgList, n.info, n.len)
|
||||
for i in 0..<n.len: arglist.sons[i] = n.sons[i]
|
||||
else:
|
||||
arglist = newNodeI(nkArgList, n.info, sonsLen(n) - plen + 1)
|
||||
arglist = newNodeI(nkArgList, n.info, len(n) - plen + 1)
|
||||
# f(1, 2, 3)
|
||||
# p(X)
|
||||
for i in 0 .. sonsLen(n) - plen:
|
||||
for i in 0 .. len(n) - plen:
|
||||
arglist.sons[i] = n.sons[i + plen - 1]
|
||||
return bindOrCheck(c, v.sym, arglist)
|
||||
elif plen-1 == sonsLen(n):
|
||||
elif plen-1 == len(n):
|
||||
for i in 0 .. plen - 2:
|
||||
if not matches(c, p.sons[i], n.sons[i]): return
|
||||
arglist = newNodeI(nkArgList, n.info)
|
||||
return bindOrCheck(c, v.sym, arglist)
|
||||
if plen == sonsLen(n):
|
||||
for i in 0 ..< sonsLen(p):
|
||||
if plen == len(n):
|
||||
for i in 0 ..< len(p):
|
||||
if not matches(c, p.sons[i], n.sons[i]): return
|
||||
result = true
|
||||
|
||||
@@ -250,7 +250,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
|
||||
var ctx: TPatternContext
|
||||
ctx.owner = s
|
||||
ctx.c = c
|
||||
ctx.formals = sonsLen(s.typ)-1
|
||||
ctx.formals = len(s.typ)-1
|
||||
var m = matchStmtList(ctx, s.ast.sons[patternPos], n)
|
||||
if isNil(m): return nil
|
||||
# each parameter should have been bound; we simply setup a call and
|
||||
@@ -295,7 +295,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
|
||||
# constraint not fulfilled:
|
||||
if not ok: return nil
|
||||
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
if ctx.subMatch:
|
||||
assert m.len == 3
|
||||
m.sons[1] = result
|
||||
|
||||
@@ -21,7 +21,7 @@ type
|
||||
# conditionals to condsyms (end of module).
|
||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
|
||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxWorks
|
||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
|
||||
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch
|
||||
|
||||
type
|
||||
@@ -139,6 +139,10 @@ const
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
||||
(name: "iOS", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospNeedsPIC, ospPosix}),
|
||||
(name: "Haiku", parDir: "..", dllFrmt: "lib$1.so", altDirSep: ":",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
|
||||
@@ -17,25 +17,24 @@ proc semLocals*(c: PContext, n: PNode): PNode =
|
||||
var tupleType = newTypeS(tyTuple, c)
|
||||
result = newNodeIT(nkPar, n.info, tupleType)
|
||||
tupleType.n = newNodeI(nkRecList, n.info)
|
||||
let owner = getCurrOwner(c)
|
||||
# for now we skip openarrays ...
|
||||
for scope in walkScopes(c.currentScope):
|
||||
if scope == c.topLevelScope: break
|
||||
for it in items(scope.symbols):
|
||||
# XXX parameters' owners are wrong for generics; this caused some pain
|
||||
# for closures too; we should finally fix it.
|
||||
#if it.owner != c.p.owner: return result
|
||||
if it.kind in skLocalVars and
|
||||
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
|
||||
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}:
|
||||
|
||||
var field = newSym(skField, it.name, getCurrOwner(c), n.info)
|
||||
field.typ = it.typ.skipTypes({tyVar})
|
||||
field.position = counter
|
||||
inc(counter)
|
||||
if it.owner == owner:
|
||||
var field = newSym(skField, it.name, owner, n.info)
|
||||
field.typ = it.typ.skipTypes({tyVar})
|
||||
field.position = counter
|
||||
inc(counter)
|
||||
|
||||
addSon(tupleType.n, newSymNode(field))
|
||||
addSonSkipIntLit(tupleType, field.typ)
|
||||
addSon(tupleType.n, newSymNode(field))
|
||||
addSonSkipIntLit(tupleType, field.typ)
|
||||
|
||||
var a = newSymNode(it, result.info)
|
||||
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
|
||||
result.add(a)
|
||||
var a = newSymNode(it, result.info)
|
||||
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
|
||||
result.add(a)
|
||||
|
||||
@@ -19,55 +19,57 @@ const
|
||||
LastCallConv* = wNoconv
|
||||
|
||||
const
|
||||
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
|
||||
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed}
|
||||
## common pragmas for declarations, to a good approximation
|
||||
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
||||
wCompilerProc, wNonReloadable, wCore, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wCodegenDecl,
|
||||
wCompilerProc, wNonReloadable, wCore, wProcVar, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow, wImportCompilerProc, wThread,
|
||||
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
|
||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||
wConstructor, wExportNims, wUsed, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
|
||||
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy}
|
||||
converterPragmas* = procPragmas - {wNoDestroy}
|
||||
methodPragmas* = procPragmas+{wBase}-{wImportCpp, wNoDestroy}
|
||||
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
||||
wDelegator, wExportNims, wUsed, wPragma}
|
||||
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc,
|
||||
wNodecl, wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
|
||||
wExportNims, wUsed}
|
||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
||||
wTags, wLocks, wGcSafe, wExportNims, wUsed}
|
||||
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||
wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore,
|
||||
wDiscardable, wGensym, wInject, wDelegator}
|
||||
iteratorPragmas* = declPragmas + {FirstCallConv..LastCallConv, wNoSideEffect, wSideEffect,
|
||||
wMagic, wBorrow,
|
||||
wDiscardable, wGensym, wInject, wRaises,
|
||||
wTags, wLocks, wGcSafe}
|
||||
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNoSideEffect}
|
||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
|
||||
wBoundChecks, wOverflowChecks, wNilChecks, wStyleChecks, wAssertions,
|
||||
wWarnings, wHints,
|
||||
wLineDir, wStackTrace, wLineTrace, wOptimization, wHint, wWarning, wError,
|
||||
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
|
||||
wBreakpoint, wWatchPoint, wPassl, wPassc,
|
||||
wPassl, wPassc,
|
||||
wDeadCodeElimUnused, # deprecated, always on
|
||||
wDeprecated,
|
||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||
wInjectStmt, wDeprecated, wExperimental, wThis}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wInjectStmt, wExperimental, wThis, wUsed}
|
||||
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
|
||||
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
|
||||
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
|
||||
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl}
|
||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wExtern, wShallow,
|
||||
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
||||
wThread, wAsmNoStackFrame,
|
||||
wRaises, wLocks, wTags, wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
|
||||
typePragmas* = declPragmas + {wMagic, wAcyclic,
|
||||
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
|
||||
wIncompleteStruct, wByCopy, wByRef,
|
||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||
wBorrow, wGcSafe, wExportNims, wPartial, wUsed, wExplain, wPackage}
|
||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
|
||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||
wMagic, wHeader, wDeprecated, wCompilerProc, wCore, wDynlib, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
|
||||
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed, wCursor}
|
||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims,
|
||||
wIntDefine, wStrDefine, wBoolDefine, wUsed, wCompilerProc, wCore}
|
||||
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
|
||||
fieldPragmas* = declPragmas + {
|
||||
wGuard, wBitsize} - {wExportNims, wNodecl} # why exclude these?
|
||||
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
|
||||
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
|
||||
wNoInit, wCompileTime, wGlobal,
|
||||
wGensym, wInject, wCodegenDecl, wGuard, wGoto}
|
||||
constPragmas* = declPragmas + {wHeader, wMagic,
|
||||
wGensym, wInject,
|
||||
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
|
||||
letPragmas* = varPragmas
|
||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
|
||||
wThread, wRaises, wLocks, wTags, wGcSafe}
|
||||
@@ -83,7 +85,8 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode =
|
||||
it[0].ident.id == ord(name):
|
||||
return it[1]
|
||||
|
||||
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
|
||||
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
|
||||
isStatement: bool = false)
|
||||
|
||||
proc recordPragma(c: PContext; n: PNode; key, val: string; val2 = "") =
|
||||
var recorded = newNodeI(nkCommentStmt, n.info)
|
||||
@@ -104,7 +107,7 @@ proc illegalCustomPragma*(c: PContext, n: PNode, s: PSym) =
|
||||
proc pragmaAsm*(c: PContext, n: PNode): char =
|
||||
result = '\0'
|
||||
if n != nil:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
let it = n.sons[i]
|
||||
if it.kind in nkPragmaCallKinds and it.len == 2 and it.sons[0].kind == nkIdent:
|
||||
case whichKeyword(it.sons[0].ident)
|
||||
@@ -345,7 +348,7 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
|
||||
of wLineDir: {optLineDir}
|
||||
of wStackTrace: {optStackTrace}
|
||||
of wLineTrace: {optLineTrace}
|
||||
of wDebugger: {optEndb}
|
||||
of wDebugger: {optNone}
|
||||
of wProfiler: {optProfiler, optMemTracker}
|
||||
of wMemTracker: {optMemTracker}
|
||||
of wByRef: {optByRef}
|
||||
@@ -415,15 +418,8 @@ proc processOption(c: PContext, n: PNode, resOptions: var TOptions) =
|
||||
proc processPush(c: PContext, n: PNode, start: int) =
|
||||
if n.sons[start-1].kind in nkPragmaCallKinds:
|
||||
localError(c.config, n.info, "'push' cannot have arguments")
|
||||
var x = newOptionEntry(c.config)
|
||||
var y = c.optionStack[^1]
|
||||
x.options = c.config.options
|
||||
x.defaultCC = y.defaultCC
|
||||
x.dynlib = y.dynlib
|
||||
x.notes = c.config.notes
|
||||
x.features = c.features
|
||||
c.optionStack.add(x)
|
||||
for i in start ..< sonsLen(n):
|
||||
var x = pushOptionEntry(c)
|
||||
for i in start ..< len(n):
|
||||
if not tryProcessOption(c, n.sons[i], c.config.options):
|
||||
# simply store it somewhere:
|
||||
if x.otherPragmas.isNil:
|
||||
@@ -441,10 +437,7 @@ proc processPop(c: PContext, n: PNode) =
|
||||
if c.optionStack.len <= 1:
|
||||
localError(c.config, n.info, "{.pop.} without a corresponding {.push.}")
|
||||
else:
|
||||
c.config.options = c.optionStack[^1].options
|
||||
c.config.notes = c.optionStack[^1].notes
|
||||
c.features = c.optionStack[^1].features
|
||||
c.optionStack.setLen(c.optionStack.len - 1)
|
||||
popOptionEntry(c)
|
||||
when defined(debugOptions):
|
||||
echo c.config $ n.info, " POP config is now ", c.config.options
|
||||
|
||||
@@ -513,15 +506,6 @@ proc processLink(c: PContext, n: PNode) =
|
||||
extccomp.addExternalFileToLink(c.config, found)
|
||||
recordPragma(c, n, "link", found.string)
|
||||
|
||||
proc pragmaBreakpoint(c: PContext, n: PNode) =
|
||||
discard getOptionalStr(c, n, "")
|
||||
|
||||
proc pragmaWatchpoint(c: PContext, n: PNode) =
|
||||
if n.kind in nkPragmaCallKinds and n.len == 2:
|
||||
n.sons[1] = c.semExpr(c, n.sons[1])
|
||||
else:
|
||||
invalidPragma(c, n)
|
||||
|
||||
proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||
case n.sons[1].kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
@@ -726,7 +710,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
|
||||
proc semCustomPragma(c: PContext, n: PNode): PNode =
|
||||
var callNode: PNode
|
||||
|
||||
if n.kind == nkIdent:
|
||||
if n.kind in {nkIdent, nkSym}:
|
||||
# pragma -> pragma()
|
||||
callNode = newTree(nkCall, n)
|
||||
elif n.kind == nkExprColonExpr:
|
||||
@@ -754,7 +738,8 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
|
||||
result.kind = n.kind
|
||||
|
||||
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
validPragmas: TSpecialWords, comesFromPush: bool) : bool =
|
||||
validPragmas: TSpecialWords,
|
||||
comesFromPush, isStatement: bool) : bool =
|
||||
var it = n.sons[i]
|
||||
var key = if it.kind in nkPragmaCallKinds and it.len > 1: it.sons[0] else: it
|
||||
if key.kind == nkBracketExpr:
|
||||
@@ -774,7 +759,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if c.instCounter > 100:
|
||||
globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s)
|
||||
|
||||
pragma(c, sym, userPragma.ast, validPragmas)
|
||||
pragma(c, sym, userPragma.ast, validPragmas, isStatement)
|
||||
n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
|
||||
i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty
|
||||
dec c.instCounter
|
||||
@@ -784,8 +769,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||
checkPragmaUse(c.config, key.info, k, ident.s)
|
||||
case k
|
||||
of wExportc:
|
||||
of wExportc, wExportCpp:
|
||||
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
if k == wExportCpp:
|
||||
if c.config.cmd != cmdCompileToCpp:
|
||||
localError(c.config, it.info, "exportcpp requires `nim cpp`, got " & $c.config.cmd)
|
||||
else:
|
||||
incl(sym.flags, sfMangleCpp)
|
||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||
of wImportc:
|
||||
let name = getOptionalStr(c, it, "$1")
|
||||
@@ -803,6 +793,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
else: invalidPragma(c, it)
|
||||
of wImportCpp:
|
||||
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
of wImportJs:
|
||||
if c.config.cmd != cmdCompileToJS:
|
||||
localError(c.config, it.info, "`importjs` pragma requires the JavaScript target")
|
||||
let name = getOptionalStr(c, it, "$1")
|
||||
incl(sym.flags, sfImportc)
|
||||
incl(sym.flags, sfInfixCall)
|
||||
if sym.kind in skProcKinds and {'(', '#', '@'} notin name:
|
||||
localError(c.config, n.info, "`importjs` for routines requires a pattern")
|
||||
setExternName(c, sym, name, it.info)
|
||||
of wImportObjC:
|
||||
processImportObjC(c, sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
of wAlign:
|
||||
@@ -816,12 +815,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
if sym.typ == nil: invalidPragma(c, it)
|
||||
var size = expectIntLit(c, it)
|
||||
case size
|
||||
of 1, 2, 4, 8:
|
||||
of 1, 2, 4:
|
||||
sym.typ.size = size
|
||||
if size == 8 and c.config.target.targetCPU == cpuI386:
|
||||
sym.typ.align = 4
|
||||
else:
|
||||
sym.typ.align = int16(size)
|
||||
sym.typ.align = int16 size
|
||||
of 8:
|
||||
sym.typ.size = 8
|
||||
sym.typ.align = floatInt64Align(c.config)
|
||||
else:
|
||||
localError(c.config, it.info, "size may only be 1, 2, 4 or 8")
|
||||
of wNodecl:
|
||||
@@ -848,7 +847,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
of wCompileTime:
|
||||
noVal(c, it)
|
||||
incl(sym.flags, sfCompileTime)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
#incl(sym.loc.flags, lfNoDecl)
|
||||
of wGlobal:
|
||||
noVal(c, it)
|
||||
incl(sym.flags, sfGlobal)
|
||||
@@ -971,7 +970,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
recordPragma(c, it, "warning", s)
|
||||
message(c.config, it.info, warnUser, s)
|
||||
of wError:
|
||||
if sym != nil and (sym.isRoutine or sym.kind == skType) and wUsed in validPragmas:
|
||||
if sym != nil and (sym.isRoutine or sym.kind == skType) and not isStatement:
|
||||
# This is subtle but correct: the error *statement* is only
|
||||
# allowed when 'wUsed' is not in validPragmas. Here this is the easiest way to
|
||||
# distinguish properly between
|
||||
@@ -996,8 +995,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
let s = expectStrLit(c, it)
|
||||
extccomp.addCompileOption(c.config, s)
|
||||
recordPragma(c, it, "passc", s)
|
||||
of wBreakpoint: pragmaBreakpoint(c, it)
|
||||
of wWatchPoint: pragmaWatchpoint(c, it)
|
||||
of wPush:
|
||||
processPush(c, n, i + 1)
|
||||
result = true
|
||||
@@ -1096,11 +1093,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
invalidPragma(c, it)
|
||||
else:
|
||||
sym.flags.incl sfGoto
|
||||
of wCursor:
|
||||
if sym == nil or sym.kind notin {skVar, skLet}:
|
||||
invalidPragma(c, it)
|
||||
else:
|
||||
sym.flags.incl sfCursor
|
||||
of wExportNims:
|
||||
if sym == nil: invalidPragma(c, it)
|
||||
else: magicsys.registerNimScriptSymbol(c.graph, sym)
|
||||
@@ -1142,7 +1134,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
elif comesFromPush and whichKeyword(ident) in {wTags, wRaises}:
|
||||
discard "ignore the .push pragma; it doesn't apply"
|
||||
else:
|
||||
if sym == nil or (sym != nil and sym.kind in {skVar, skLet, skParam,
|
||||
if sym == nil or (sym.kind in {skVar, skLet, skParam,
|
||||
skField, skProc, skFunc, skConverter, skMethod, skType}):
|
||||
n.sons[i] = semCustomPragma(c, it)
|
||||
elif sym != nil:
|
||||
@@ -1172,7 +1164,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
|
||||
pushInfoContext(c.config, n.info)
|
||||
var i = 0
|
||||
while i < o.len:
|
||||
if singlePragma(c, sym, o, i, validPragmas, true):
|
||||
if singlePragma(c, sym, o, i, validPragmas, true, false):
|
||||
internalError(c.config, n.info, "implicitPragmas")
|
||||
inc i
|
||||
popInfoContext(c.config)
|
||||
@@ -1197,14 +1189,16 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
|
||||
|
||||
return false
|
||||
|
||||
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
|
||||
isStatement: bool) =
|
||||
if n == nil: return
|
||||
var i = 0
|
||||
while i < n.len:
|
||||
if singlePragma(c, sym, n, i, validPragmas, false): break
|
||||
if singlePragma(c, sym, n, i, validPragmas, false, isStatement): break
|
||||
inc i
|
||||
|
||||
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
|
||||
isStatement: bool) =
|
||||
if n == nil: return
|
||||
pragmaRec(c, sym, n, validPragmas)
|
||||
pragmaRec(c, sym, n, validPragmas, isStatement)
|
||||
implicitPragmas(c, sym, n, validPragmas)
|
||||
|
||||
@@ -14,8 +14,8 @@ import
|
||||
ast, astalgo, msgs, semdata, types, trees, strutils
|
||||
|
||||
proc equalGenericParams(procA, procB: PNode): bool =
|
||||
if sonsLen(procA) != sonsLen(procB): return false
|
||||
for i in 0 ..< sonsLen(procA):
|
||||
if len(procA) != len(procB): return false
|
||||
for i in 0 ..< len(procA):
|
||||
if procA.sons[i].kind != nkSym:
|
||||
return false
|
||||
if procB.sons[i].kind != nkSym:
|
||||
@@ -29,7 +29,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
|
||||
result = true
|
||||
|
||||
proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
# Searchs for a forward declaration or a "twin" symbol of fn
|
||||
# Searches for a forward declaration or a "twin" symbol of fn
|
||||
# in the symbol table. If the parameter lists are exactly
|
||||
# the same the sym in the symbol table is returned, else nil.
|
||||
var it: TIdentIter
|
||||
@@ -72,8 +72,8 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
of paramsEqual:
|
||||
if (sfExported notin result.flags) and (sfExported in fn.flags):
|
||||
let message = ("public implementation '$1' has non-public " &
|
||||
"forward declaration in $2") %
|
||||
[getProcHeader(c.config, result), c.config$result.info]
|
||||
"forward declaration at $2") %
|
||||
[getProcHeader(c.config, result, getDeclarationPath = false), c.config$result.info]
|
||||
localError(c.config, fn.info, message)
|
||||
return
|
||||
of paramsIncompatible:
|
||||
@@ -95,9 +95,9 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
|
||||
when false:
|
||||
proc paramsFitBorrow(child, parent: PNode): bool =
|
||||
var length = sonsLen(child)
|
||||
var length = len(child)
|
||||
result = false
|
||||
if length == sonsLen(parent):
|
||||
if length == len(parent):
|
||||
for i in 1 ..< length:
|
||||
var m = child.sons[i].sym
|
||||
var n = parent.sons[i].sym
|
||||
@@ -108,7 +108,7 @@ when false:
|
||||
result = true
|
||||
|
||||
proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||
# Searchs for the fn in the symbol table. If the parameter lists are suitable
|
||||
# Searches for the fn in the symbol table. If the parameter lists are suitable
|
||||
# for borrowing the sym in the symbol table is returned, else nil.
|
||||
var it: TIdentIter
|
||||
for scope in walkScopes(startScope):
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
# This module implements the renderer of the standard Nim representation.
|
||||
|
||||
when defined(nimHasUsed):
|
||||
# 'import renderer' is so useful for debugging
|
||||
# that Nim shouldn't produce a warning for that:
|
||||
{.used.}
|
||||
|
||||
import
|
||||
lexer, options, idents, strutils, ast, msgs, lineinfos
|
||||
|
||||
@@ -330,8 +335,7 @@ proc ulitAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
|
||||
if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
|
||||
elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
|
||||
elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
|
||||
else: result = $x
|
||||
# XXX proper unsigned output!
|
||||
else: result = $cast[BiggestUInt](x)
|
||||
|
||||
proc atom(g: TSrcGen; n: PNode): string =
|
||||
when defined(nimpretty):
|
||||
@@ -391,7 +395,7 @@ proc atom(g: TSrcGen; n: PNode): string =
|
||||
proc lcomma(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||
assert(theEnd < 0)
|
||||
result = 0
|
||||
for i in start .. sonsLen(n) + theEnd:
|
||||
for i in start .. len(n) + theEnd:
|
||||
let param = n.sons[i]
|
||||
if nfDefaultParam notin param.flags:
|
||||
inc(result, lsub(g, param))
|
||||
@@ -402,7 +406,7 @@ proc lcomma(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||
proc lsons(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
|
||||
assert(theEnd < 0)
|
||||
result = 0
|
||||
for i in start .. sonsLen(n) + theEnd: inc(result, lsub(g, n.sons[i]))
|
||||
for i in start .. len(n) + theEnd: inc(result, lsub(g, n.sons[i]))
|
||||
|
||||
proc lsub(g: TSrcGen; n: PNode): int =
|
||||
# computes the length of a tree
|
||||
@@ -432,7 +436,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkTableConstr:
|
||||
result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}")
|
||||
of nkClosedSymChoice, nkOpenSymChoice:
|
||||
result = lsons(g, n) + len("()") + sonsLen(n) - 1
|
||||
result = lsons(g, n) + len("()") + len(n) - 1
|
||||
of nkTupleTy: result = lcomma(g, n) + len("tuple[]")
|
||||
of nkTupleClassTy: result = len("tuple")
|
||||
of nkDotExpr: result = lsons(g, n) + 1
|
||||
@@ -444,7 +448,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkDo: result = lsons(g, n) + len("do__:_")
|
||||
of nkConstDef, nkIdentDefs:
|
||||
result = lcomma(g, n, 0, - 3)
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
if n.sons[L - 2].kind != nkEmpty: result = result + lsub(g, n.sons[L - 2]) + 2
|
||||
if n.sons[L - 1].kind != nkEmpty: result = result + lsub(g, n.sons[L - 1]) + 3
|
||||
of nkVarTuple: result = lcomma(g, n, 0, - 3) + len("() = ") + lsub(g, lastSon(n))
|
||||
@@ -453,7 +457,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkChckRange: result = len("chckRange") + 2 + lcomma(g, n)
|
||||
of nkObjDownConv, nkObjUpConv:
|
||||
result = 2
|
||||
if sonsLen(n) >= 1: result = result + lsub(g, n.sons[0])
|
||||
if len(n) >= 1: result = result + lsub(g, n.sons[0])
|
||||
result = result + lcomma(g, n, 1)
|
||||
of nkExprColonExpr: result = lsons(g, n) + 2
|
||||
of nkInfix: result = lsons(g, n) + 2
|
||||
@@ -487,16 +491,16 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkIteratorTy: result = lsons(g, n) + len("iterator_")
|
||||
of nkSharedTy: result = lsons(g, n) + len("shared_")
|
||||
of nkEnumTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + len("enum_")
|
||||
else:
|
||||
result = len("enum")
|
||||
of nkEnumFieldDef: result = lsons(g, n) + 3
|
||||
of nkVarSection, nkLetSection:
|
||||
if sonsLen(n) > 1: result = MaxLineLen + 1
|
||||
if len(n) > 1: result = MaxLineLen + 1
|
||||
else: result = lsons(g, n) + len("var_")
|
||||
of nkUsingStmt:
|
||||
if sonsLen(n) > 1: result = MaxLineLen + 1
|
||||
if len(n) > 1: result = MaxLineLen + 1
|
||||
else: result = lsons(g, n) + len("using_")
|
||||
of nkReturnStmt:
|
||||
if n.len > 0 and n[0].kind == nkAsgn:
|
||||
@@ -552,7 +556,7 @@ proc hasCom(n: PNode): bool =
|
||||
case n.kind
|
||||
of nkEmpty..nkNilLit: discard
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if hasCom(n.sons[i]): return true
|
||||
|
||||
proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
|
||||
@@ -561,8 +565,8 @@ proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
|
||||
|
||||
proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
|
||||
theEnd: int = - 1, separator = tkComma) =
|
||||
for i in start .. sonsLen(n) + theEnd:
|
||||
var c = i < sonsLen(n) + theEnd
|
||||
for i in start .. len(n) + theEnd:
|
||||
var c = i < len(n) + theEnd
|
||||
var sublen = lsub(g, n.sons[i]) + ord(c)
|
||||
if not fits(g, sublen) and (ind + sublen < MaxLineLen): optNL(g, ind)
|
||||
let oldLen = g.tokens.len
|
||||
@@ -596,15 +600,15 @@ proc gsemicolon(g: var TSrcGen, n: PNode, start: int = 0, theEnd: int = - 1) =
|
||||
|
||||
proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
|
||||
theEnd: int = - 1) =
|
||||
for i in start .. sonsLen(n) + theEnd: gsub(g, n.sons[i], c)
|
||||
for i in start .. len(n) + theEnd: gsub(g, n.sons[i], c)
|
||||
|
||||
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType,
|
||||
k: string) =
|
||||
if sonsLen(n) == 0: return # empty var sections are possible
|
||||
if len(n) == 0: return # empty var sections are possible
|
||||
putWithSpace(g, kind, k)
|
||||
gcoms(g)
|
||||
indentNL(g)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
optNL(g)
|
||||
gsub(g, n.sons[i], c)
|
||||
gcoms(g)
|
||||
@@ -614,7 +618,7 @@ proc longMode(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): bool =
|
||||
result = n.comment.len > 0
|
||||
if not result:
|
||||
# check further
|
||||
for i in start .. sonsLen(n) + theEnd:
|
||||
for i in start .. len(n) + theEnd:
|
||||
if (lsub(g, n.sons[i]) > MaxLineLen):
|
||||
result = true
|
||||
break
|
||||
@@ -659,7 +663,7 @@ proc gif(g: var TSrcGen, n: PNode) =
|
||||
incl(c.flags, rfLongMode)
|
||||
gcoms(g) # a good place for comments
|
||||
gstmts(g, n.sons[0].sons[1], c)
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
for i in 1 ..< length:
|
||||
optNL(g)
|
||||
gsub(g, n.sons[i], c)
|
||||
@@ -708,7 +712,7 @@ proc gtry(g: var TSrcGen, n: PNode) =
|
||||
|
||||
proc gfor(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
putWithSpace(g, tkFor, "for")
|
||||
initContext(c)
|
||||
if longMode(g, n) or
|
||||
@@ -726,7 +730,7 @@ proc gfor(g: var TSrcGen, n: PNode) =
|
||||
proc gcase(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
initContext(c)
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
if length == 0: return
|
||||
var last = if n.sons[length-1].kind == nkElse: -2 else: -1
|
||||
if longMode(g, n, 0, last): incl(c.flags, rfLongMode)
|
||||
@@ -740,13 +744,18 @@ proc gcase(g: var TSrcGen, n: PNode) =
|
||||
if longMode(g, n.sons[length - 1]): incl(c.flags, rfLongMode)
|
||||
gsub(g, n.sons[length - 1], c)
|
||||
|
||||
proc genSymSuffix(result: var string, s: PSym) {.inline.} =
|
||||
if sfGenSym in s.flags:
|
||||
result.add '_'
|
||||
result.addInt s.id
|
||||
|
||||
proc gproc(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
if n.sons[namePos].kind == nkSym:
|
||||
let s = n.sons[namePos].sym
|
||||
put(g, tkSymbol, renderDefinitionName(s))
|
||||
if sfGenSym in s.flags:
|
||||
put(g, tkIntLit, $s.id)
|
||||
var ret = renderDefinitionName(s)
|
||||
ret.genSymSuffix(s)
|
||||
put(g, tkSymbol, ret)
|
||||
else:
|
||||
gsub(g, n.sons[namePos])
|
||||
|
||||
@@ -840,12 +849,12 @@ proc gident(g: var TSrcGen, n: PNode) =
|
||||
t = tkSymbol
|
||||
else:
|
||||
t = tkOpr
|
||||
put(g, t, s, if n.kind == nkSym and renderSyms in g.flags: n.sym else: nil)
|
||||
if n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags or n.sym.kind == skTemp):
|
||||
s.genSymSuffix(n.sym)
|
||||
when defined(debugMagics):
|
||||
put(g, tkIntLit, $n.sym.id & $n.sym.magic)
|
||||
else:
|
||||
put(g, tkIntLit, $n.sym.id)
|
||||
s.add '_'
|
||||
s.add $n.sym.magic
|
||||
put(g, t, s, if n.kind == nkSym and renderSyms in g.flags: n.sym else: nil)
|
||||
|
||||
proc doParamsAux(g: var TSrcGen, params: PNode) =
|
||||
if params.len > 1:
|
||||
@@ -957,7 +966,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
put(g, tkColon, ":")
|
||||
gsub(g, n, n.len-1)
|
||||
else:
|
||||
if sonsLen(n) >= 1: accentedName(g, n[0])
|
||||
if len(n) >= 1: accentedName(g, n[0])
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n, 1)
|
||||
put(g, tkParRi, ")")
|
||||
@@ -1037,14 +1046,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
gcomma(g, n)
|
||||
put(g, tkParRi, ")")
|
||||
of nkObjDownConv, nkObjUpConv:
|
||||
if sonsLen(n) >= 1: gsub(g, n.sons[0])
|
||||
if len(n) >= 1: gsub(g, n.sons[0])
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n, 1)
|
||||
put(g, tkParRi, ")")
|
||||
of nkClosedSymChoice, nkOpenSymChoice:
|
||||
if renderIds in g.flags:
|
||||
put(g, tkParLe, "(")
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if i > 0: put(g, tkOpr, "|")
|
||||
if n.sons[i].kind == nkSym:
|
||||
let s = n[i].sym
|
||||
@@ -1106,7 +1115,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
gsub(g, n, bodyPos)
|
||||
of nkConstDef, nkIdentDefs:
|
||||
gcomma(g, n, 0, -3)
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
if L >= 2 and n.sons[L - 2].kind != nkEmpty:
|
||||
putWithSpace(g, tkColon, ":")
|
||||
gsub(g, n, L - 2)
|
||||
@@ -1191,19 +1200,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
if n.len > 0: gsub(g, n.sons[0])
|
||||
put(g, tkParRi, ")")
|
||||
of nkRefTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkRef, "ref")
|
||||
gsub(g, n.sons[0])
|
||||
else:
|
||||
put(g, tkRef, "ref")
|
||||
of nkPtrTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkPtr, "ptr")
|
||||
gsub(g, n.sons[0])
|
||||
else:
|
||||
put(g, tkPtr, "ptr")
|
||||
of nkVarTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkVar, "var")
|
||||
gsub(g, n.sons[0])
|
||||
else:
|
||||
@@ -1234,7 +1243,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
gsub(g, n.sons[2])
|
||||
of nkObjectTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkObject, "object")
|
||||
gsub(g, n.sons[0])
|
||||
gsub(g, n.sons[1])
|
||||
@@ -1244,7 +1253,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
put(g, tkObject, "object")
|
||||
of nkRecList:
|
||||
indentNL(g)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
optNL(g)
|
||||
gsub(g, n.sons[i], c)
|
||||
gcoms(g)
|
||||
@@ -1254,14 +1263,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
putWithSpace(g, tkOf, "of")
|
||||
gsub(g, n, 0)
|
||||
of nkProcTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkProc, "proc")
|
||||
gsub(g, n, 0)
|
||||
gsub(g, n, 1)
|
||||
else:
|
||||
put(g, tkProc, "proc")
|
||||
of nkIteratorTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkIterator, "iterator")
|
||||
gsub(g, n, 0)
|
||||
gsub(g, n, 1)
|
||||
@@ -1274,7 +1283,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
gsub(g, n.sons[0])
|
||||
put(g, tkBracketRi, "]")
|
||||
of nkEnumTy:
|
||||
if sonsLen(n) > 0:
|
||||
if len(n) > 0:
|
||||
putWithSpace(g, tkEnum, "enum")
|
||||
gsub(g, n.sons[0])
|
||||
gcoms(g)
|
||||
@@ -1332,7 +1341,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
incl(a.flags, rfInConstExpr)
|
||||
gsection(g, n, a, tkConst, "const")
|
||||
of nkVarSection, nkLetSection, nkUsingStmt:
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
if L == 0: return
|
||||
if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
|
||||
elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
|
||||
@@ -1543,7 +1552,7 @@ proc renderModule*(n: PNode, infile, outfile: string,
|
||||
g: TSrcGen
|
||||
initSrcGen(g, renderFlags, conf)
|
||||
g.fid = fid
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
gsub(g, n.sons[i])
|
||||
optNL(g)
|
||||
case n.sons[i].kind
|
||||
@@ -1576,3 +1585,15 @@ proc getTokSym*(r: TSrcGen): PSym =
|
||||
result = r.tokens[r.idx-1].sym
|
||||
else:
|
||||
result = nil
|
||||
|
||||
proc quoteExpr*(a: string): string {.inline.} =
|
||||
## can be used for quoting expressions in error msgs.
|
||||
"'" & a & "'"
|
||||
|
||||
proc genFieldError*(field: PSym, disc: PSym): string =
|
||||
## this needs to be in a module accessible by jsgen, ccgexprs, and vm to
|
||||
## provide this error msg FieldError; msgs would be better but it does not
|
||||
## import ast
|
||||
result = field.name.s.quoteExpr & " is not accessible using discriminant " &
|
||||
disc.name.s.quoteExpr & " of type " &
|
||||
disc.owner.name.s.quoteExpr
|
||||
|
||||
@@ -156,7 +156,7 @@ proc encodeNode(g: ModuleGraph; fInfo: TLineInfo, n: PNode,
|
||||
encodeVInt(n.sym.id, result)
|
||||
pushSym(w, n.sym)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
encodeNode(g, n.info, n.sons[i], result)
|
||||
add(result, ')')
|
||||
|
||||
@@ -223,6 +223,9 @@ proc encodeType(g: ModuleGraph, t: PType, result: var string) =
|
||||
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
|
||||
add(result, '\14')
|
||||
encodeVInt(t.lockLevel.int16, result)
|
||||
if t.paddingAtEnd != 0:
|
||||
add(result, '\15')
|
||||
encodeVInt(t.paddingAtEnd, result)
|
||||
for a in t.attachedOps:
|
||||
add(result, '\16')
|
||||
if a == nil:
|
||||
@@ -241,7 +244,7 @@ proc encodeType(g: ModuleGraph, t: PType, result: var string) =
|
||||
add(result, '\21')
|
||||
encodeVInt(t.typeInst.uniqueId, result)
|
||||
pushType(w, t.typeInst)
|
||||
for i in 0 ..< sonsLen(t):
|
||||
for i in 0 ..< len(t):
|
||||
if t.sons[i] == nil:
|
||||
add(result, "^()")
|
||||
else:
|
||||
@@ -422,9 +425,7 @@ proc storeRemaining*(g: ModuleGraph; module: PSym) =
|
||||
transitiveClosure(g)
|
||||
var nimid = 0
|
||||
for x in items(g.config.m.fileInfos):
|
||||
# don't store the "command line" entry:
|
||||
if nimid != 0:
|
||||
storeFilename(g, x.fullPath, FileIndex(nimid))
|
||||
storeFilename(g, x.fullPath, FileIndex(nimid))
|
||||
inc nimid
|
||||
|
||||
# ---------------- decoder -----------------------------------
|
||||
@@ -633,6 +634,10 @@ proc loadType(g; id: int; info: TLineInfo): PType =
|
||||
else:
|
||||
result.lockLevel = UnspecifiedLockLevel
|
||||
|
||||
if b.s[b.pos] == '\15':
|
||||
inc(b.pos)
|
||||
result.paddingAtEnd = decodeVInt(b.s, b.pos).int16
|
||||
|
||||
for a in low(result.attachedOps)..high(result.attachedOps):
|
||||
if b.s[b.pos] == '\16':
|
||||
inc(b.pos)
|
||||
|
||||
@@ -62,9 +62,15 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||
cbos listDirs:
|
||||
listDirs(a, {pcDir})
|
||||
cbos removeDir:
|
||||
os.removeDir getString(a, 0)
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
os.removeDir getString(a, 0)
|
||||
cbos removeFile:
|
||||
os.removeFile getString(a, 0)
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
os.removeFile getString(a, 0)
|
||||
cbos createDir:
|
||||
os.createDir getString(a, 0)
|
||||
|
||||
@@ -76,20 +82,35 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||
cbos getCurrentDir:
|
||||
setResult(a, os.getCurrentDir())
|
||||
cbos moveFile:
|
||||
os.moveFile(getString(a, 0), getString(a, 1))
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
os.moveFile(getString(a, 0), getString(a, 1))
|
||||
cbos moveDir:
|
||||
os.moveDir(getString(a, 0), getString(a, 1))
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
os.moveDir(getString(a, 0), getString(a, 1))
|
||||
cbos copyFile:
|
||||
os.copyFile(getString(a, 0), getString(a, 1))
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
os.copyFile(getString(a, 0), getString(a, 1))
|
||||
cbos copyDir:
|
||||
os.copyDir(getString(a, 0), getString(a, 1))
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
os.copyDir(getString(a, 0), getString(a, 1))
|
||||
cbos getLastModificationTime:
|
||||
setResult(a, getLastModificationTime(getString(a, 0)).toUnix)
|
||||
cbos findExe:
|
||||
setResult(a, os.findExe(getString(a, 0)))
|
||||
|
||||
cbos rawExec:
|
||||
setResult(a, osproc.execCmd getString(a, 0))
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
setResult(a, osproc.execCmd getString(a, 0))
|
||||
|
||||
cbconf getEnv:
|
||||
setResult(a, os.getEnv(a.getString 0, a.getString 1))
|
||||
@@ -97,6 +118,8 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||
setResult(a, os.existsEnv(a.getString 0))
|
||||
cbconf putEnv:
|
||||
os.putEnv(a.getString 0, a.getString 1)
|
||||
cbconf delEnv:
|
||||
os.delEnv(a.getString 0)
|
||||
cbconf dirExists:
|
||||
setResult(a, os.dirExists(a.getString 0))
|
||||
cbconf fileExists:
|
||||
@@ -162,11 +185,17 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||
cbconf cppDefine:
|
||||
options.cppDefine(conf, a.getString(0))
|
||||
cbexc stdinReadLine, EOFError:
|
||||
setResult(a, "")
|
||||
setResult(a, stdin.readLine())
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
setResult(a, "")
|
||||
setResult(a, stdin.readLine())
|
||||
cbexc stdinReadAll, EOFError:
|
||||
setResult(a, "")
|
||||
setResult(a, stdin.readAll())
|
||||
if defined(nimsuggest) or graph.config.cmd == cmdCheck:
|
||||
discard
|
||||
else:
|
||||
setResult(a, "")
|
||||
setResult(a, stdin.readAll())
|
||||
|
||||
proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
freshDefines=true; conf: ConfigRef) =
|
||||
@@ -185,6 +214,12 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
|
||||
conf.searchPaths.add(conf.libpath)
|
||||
|
||||
let oldGlobalOptions = conf.globalOptions
|
||||
let oldSelectedGC = conf.selectedGC
|
||||
undefSymbol(conf.symbols, "nimv2")
|
||||
conf.globalOptions.excl {optTinyRtti, optOwnedRefs, optSeqDestructors}
|
||||
conf.selectedGC = gcUnselected
|
||||
|
||||
var m = graph.makeModule(scriptName)
|
||||
incl(m.flags, sfMainModule)
|
||||
graph.vm = setupVM(m, cache, scriptName.string, graph)
|
||||
@@ -192,6 +227,14 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
graph.compileSystemModule() # TODO: see why this unsets hintConf in conf.notes
|
||||
discard graph.processModule(m, llStreamOpen(scriptName, fmRead))
|
||||
|
||||
# watch out, "newruntime" can be set within NimScript itself and then we need
|
||||
# to remember this:
|
||||
if optOwnedRefs in oldGlobalOptions:
|
||||
conf.globalOptions.incl {optTinyRtti, optOwnedRefs, optSeqDestructors}
|
||||
defineSymbol(conf.symbols, "nimv2")
|
||||
if conf.selectedGC == gcUnselected:
|
||||
conf.selectedGC = oldSelectedGC
|
||||
|
||||
# ensure we load 'system.nim' again for the real non-config stuff!
|
||||
resetSystemArtifacts(graph)
|
||||
# do not remove the defined symbols
|
||||
|
||||
@@ -77,14 +77,12 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
|
||||
discard safeSemExpr(c, n)
|
||||
|
||||
proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode =
|
||||
result = arg
|
||||
let x = result.skipConv
|
||||
let x = arg.skipConv
|
||||
if x.kind in {nkPar, nkTupleConstr, nkCurly} and formal.kind != tyUntyped:
|
||||
changeType(c, x, formal, check=true)
|
||||
else:
|
||||
result = skipHiddenSubConv(result)
|
||||
#result.typ = takeType(formal, arg.typ)
|
||||
#echo arg.info, " picked ", result.typ.typeToString
|
||||
result = arg
|
||||
result = skipHiddenSubConv(result)
|
||||
|
||||
|
||||
proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
if arg.typ.isNil:
|
||||
@@ -405,7 +403,13 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
if s.typ.sons[0] == nil:
|
||||
result = semStmt(c, result, flags)
|
||||
else:
|
||||
case s.typ.sons[0].kind
|
||||
var retType = s.typ.sons[0]
|
||||
if retType.kind == tyTypeDesc and tfUnresolved in retType.flags and
|
||||
retType.len == 1:
|
||||
# bug #11941: template fails(T: type X, v: auto): T
|
||||
# does not mean we expect a tyTypeDesc.
|
||||
retType = retType[0]
|
||||
case retType.kind
|
||||
of tyUntyped:
|
||||
# Not expecting a type here allows templates like in ``tmodulealias.in``.
|
||||
result = semExpr(c, result, flags)
|
||||
@@ -423,7 +427,6 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
else:
|
||||
var retType = s.typ.sons[0]
|
||||
if s.ast[genericParamsPos] != nil and retType.isMetaType:
|
||||
# The return type may depend on the Macro arguments
|
||||
# e.g. template foo(T: typedesc): seq[T]
|
||||
@@ -444,13 +447,14 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
|
||||
const
|
||||
errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"
|
||||
errFloatToString = "cannot convert '$1' to '$2'"
|
||||
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
pushInfoContext(c.config, nOrig.info, sym.detailedInfo)
|
||||
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c.config, info, sym, c.graph.usageSym)
|
||||
markUsed(c, info, sym)
|
||||
onUse(info, sym)
|
||||
if sym == c.p.owner:
|
||||
globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s)
|
||||
@@ -571,7 +575,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
||||
if c.lastGenericIdx < c.generics.len:
|
||||
var a = newNodeI(nkStmtList, n.info)
|
||||
addCodeForGenerics(c, a)
|
||||
if sonsLen(a) > 0:
|
||||
if len(a) > 0:
|
||||
# a generic has been added to `a`:
|
||||
if result.kind != nkEmpty: addSon(a, result)
|
||||
result = a
|
||||
@@ -612,12 +616,18 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
#if c.config.cmd == cmdIdeTools: findSuggest(c, n)
|
||||
rod.storeNode(c.graph, c.module, result)
|
||||
|
||||
proc reportUnusedModules(c: PContext) =
|
||||
for i in 0..high(c.unusedImports):
|
||||
if sfUsed notin c.unusedImports[i][0].flags:
|
||||
message(c.config, c.unusedImports[i][1], warnUnusedImportX, c.unusedImports[i][0].name.s)
|
||||
|
||||
proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
if c.config.cmd == cmdIdeTools and not c.suggestionsMade:
|
||||
suggestSentinel(c)
|
||||
closeScope(c) # close module's scope
|
||||
rawCloseScope(c) # imported symbols; don't check for unused ones!
|
||||
reportUnusedModules(c)
|
||||
result = newNode(nkStmtList)
|
||||
if n != nil:
|
||||
internalError(c.config, n.info, "n is not nil") #result := n;
|
||||
|
||||
@@ -176,6 +176,8 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
filterOnlyFirst = true
|
||||
break
|
||||
|
||||
var maybeWrongSpace = false
|
||||
|
||||
var candidates = ""
|
||||
var skipped = 0
|
||||
for err in errors:
|
||||
@@ -196,6 +198,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
case err.firstMismatch.kind
|
||||
of kUnknownNamedParam: candidates.add("\n unknown named parameter: " & $nArg[0])
|
||||
of kAlreadyGiven: candidates.add("\n named param already provided: " & $nArg[0])
|
||||
of kPositionalAlreadyGiven: candidates.add("\n positional param was already given as named param")
|
||||
of kExtraArg: candidates.add("\n extra argument given")
|
||||
of kMissingParam: candidates.add("\n missing parameter: " & nameParam)
|
||||
of kTypeMismatch, kVarNeeded:
|
||||
@@ -215,13 +218,19 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
candidates.add typeToString(got)
|
||||
doAssert wanted != nil
|
||||
if got != nil: effectProblem(wanted, got, candidates)
|
||||
of kUnknown: internalAssert(c.config, false)
|
||||
of kUnknown: discard "do not break 'nim check'"
|
||||
candidates.add "\n"
|
||||
if err.firstMismatch.arg == 1 and nArg.kind == nkTupleConstr and
|
||||
n.kind == nkCommand:
|
||||
maybeWrongSpace = true
|
||||
for diag in err.diagnostics:
|
||||
candidates.add(diag & "\n")
|
||||
if skipped > 0:
|
||||
candidates.add($skipped & " other mismatching symbols have been " &
|
||||
"suppressed; compile with --showAllMismatches:on to see them\n")
|
||||
if maybeWrongSpace:
|
||||
candidates.add("maybe misplaced space between " & renderTree(n[0]) & " and '(' \n")
|
||||
|
||||
result = (prefer, candidates)
|
||||
|
||||
const
|
||||
@@ -284,7 +293,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||
assert result.startsWith "sk"
|
||||
result = result[2..^1].toLowerAscii
|
||||
result &= "\n found '$1' of kind '$2'" % [getSymRepr(c.config, sym), sym.kind.toHumanStr]
|
||||
sym = nextOverloadIter(o, c, n)
|
||||
sym = nextOverloadIter(o, c, f)
|
||||
|
||||
let ident = considerQuotedIdent(c, f, n).s
|
||||
if nfDotField in n.flags and nfExplicitCall notin n.flags:
|
||||
@@ -295,7 +304,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
|
||||
# in a concept, eg:
|
||||
# ExplainedConcept {.explain.} = concept x
|
||||
# x.foo is int
|
||||
# We coudl use: `(c.config $ n.sons[1].info)` to get more context.
|
||||
# We could use: `(c.config $ n.sons[1].info)` to get more context.
|
||||
discard
|
||||
else:
|
||||
typeHint = " for type " & getProcHeader(c.config, sym)
|
||||
@@ -396,7 +405,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
elif c.config.errorCounter == 0:
|
||||
# don't cascade errors
|
||||
var args = "("
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if i > 1: add(args, ", ")
|
||||
add(args, typeToString(n.sons[i].typ))
|
||||
add(args, ")")
|
||||
@@ -474,7 +483,7 @@ proc semResolvedCall(c: PContext, x: TCandidate,
|
||||
assert x.state == csMatch
|
||||
var finalCallee = x.calleeSym
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c.config, info, finalCallee, c.graph.usageSym)
|
||||
markUsed(c, info, finalCallee)
|
||||
onUse(info, finalCallee)
|
||||
assert finalCallee.ast != nil
|
||||
if x.hasFauxMatch:
|
||||
@@ -568,7 +577,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
# binding has to stay 'nil' for this to work!
|
||||
initCandidate(c, m, s, nil)
|
||||
|
||||
for i in 1..sonsLen(n)-1:
|
||||
for i in 1..len(n)-1:
|
||||
let formal = s.ast.sons[genericParamsPos].sons[i-1].typ
|
||||
var arg = n[i].typ
|
||||
# try transforming the argument into a static one before feeding it into
|
||||
@@ -584,16 +593,16 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
var newInst = generateInstance(c, s, m.bindings, n.info)
|
||||
newInst.typ.flags.excl tfUnresolved
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c.config, info, s, c.graph.usageSym)
|
||||
markUsed(c, info, s)
|
||||
onUse(info, s)
|
||||
result = newSymNode(newInst, info)
|
||||
|
||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
assert n.kind == nkBracketExpr
|
||||
for i in 1..sonsLen(n)-1:
|
||||
for i in 1..len(n)-1:
|
||||
let e = semExpr(c, n.sons[i])
|
||||
if e.typ == nil:
|
||||
localError(c.config, e.info, "expression has no type")
|
||||
n.sons[i].typ = errorType(c)
|
||||
else:
|
||||
n.sons[i].typ = e.typ.skipTypes({tyTypeDesc})
|
||||
var s = s
|
||||
@@ -631,7 +640,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = explicitGenericInstError(c, n)
|
||||
|
||||
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
|
||||
# Searchs for the fn in the symbol table. If the parameter lists are suitable
|
||||
# Searches for the fn in the symbol table. If the parameter lists are suitable
|
||||
# for borrowing the sym in the symbol table is returned, else nil.
|
||||
# New approach: generate fn(x, y, z) where x, y, z have the proper types
|
||||
# and use the overloading resolution mechanism:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
intsets, options, ast, astalgo, msgs, idents, renderer,
|
||||
magicsys, vmdef, modulegraphs, lineinfos
|
||||
magicsys, vmdef, modulegraphs, lineinfos, sets
|
||||
|
||||
type
|
||||
TOptionEntry* = object # entries to put on a stack for pragma parsing
|
||||
@@ -71,7 +71,8 @@ type
|
||||
TExprFlags* = set[TExprFlag]
|
||||
|
||||
PContext* = ref TContext
|
||||
TContext* = object of TPassContext # a context represents a module
|
||||
TContext* = object of TPassContext # a context represents the module
|
||||
# that is currently being compiled
|
||||
enforceVoidContext*: PType
|
||||
module*: PSym # the module sym belonging to the context
|
||||
currentScope*: PScope # current scope
|
||||
@@ -136,6 +137,8 @@ type
|
||||
# the generic type has been constructed completely. See
|
||||
# tests/destructor/topttree.nim for an example that
|
||||
# would otherwise fail.
|
||||
unusedImports*: seq[(PSym, TLineInfo)]
|
||||
exportIndirections*: HashSet[(int, int)]
|
||||
|
||||
template config*(c: PContext): ConfigRef = c.graph.config
|
||||
|
||||
@@ -209,13 +212,28 @@ proc newOptionEntry*(conf: ConfigRef): POptionEntry =
|
||||
result.dynlib = nil
|
||||
result.notes = conf.notes
|
||||
|
||||
proc pushOptionEntry*(c: PContext): POptionEntry =
|
||||
new(result)
|
||||
var prev = c.optionStack[^1]
|
||||
result.options = c.config.options
|
||||
result.defaultCC = prev.defaultCC
|
||||
result.dynlib = prev.dynlib
|
||||
result.notes = c.config.notes
|
||||
result.features = c.features
|
||||
c.optionStack.add(result)
|
||||
|
||||
proc popOptionEntry*(c: PContext) =
|
||||
c.config.options = c.optionStack[^1].options
|
||||
c.config.notes = c.optionStack[^1].notes
|
||||
c.features = c.optionStack[^1].features
|
||||
c.optionStack.setLen(c.optionStack.len - 1)
|
||||
|
||||
proc newContext*(graph: ModuleGraph; module: PSym): PContext =
|
||||
new(result)
|
||||
result.enforceVoidContext = PType(kind: tyTyped)
|
||||
result.ambiguousSymbols = initIntSet()
|
||||
result.optionStack = @[]
|
||||
result.optionStack = @[newOptionEntry(graph.config)]
|
||||
result.libs = @[]
|
||||
result.optionStack.add(newOptionEntry(graph.config))
|
||||
result.module = module
|
||||
result.friendModules = @[module]
|
||||
result.converters = @[]
|
||||
@@ -365,7 +383,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
|
||||
if n.typ != nil and n.typ.n == nil:
|
||||
result.flags.incl tfUnresolved
|
||||
result.n = newNode(nkRange, n.info, @[
|
||||
newIntTypeNode(nkIntLit, 0, intType),
|
||||
newIntTypeNode(0, intType),
|
||||
makeStaticExpr(c, nMinusOne(c, n))])
|
||||
|
||||
template rangeHasUnresolvedStatic*(t: PType): bool =
|
||||
@@ -389,8 +407,8 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
|
||||
info: TLineInfo; intType: PType = nil): PType =
|
||||
let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt)
|
||||
var n = newNodeI(nkRange, info)
|
||||
addSon(n, newIntTypeNode(nkIntLit, first, intType))
|
||||
addSon(n, newIntTypeNode(nkIntLit, last, intType))
|
||||
addSon(n, newIntTypeNode(first, intType))
|
||||
addSon(n, newIntTypeNode(last, intType))
|
||||
result = newTypeS(tyRange, c)
|
||||
result.n = n
|
||||
addSonSkipIntLit(result, intType) # basetype of range
|
||||
@@ -407,10 +425,10 @@ proc illFormedAstLocal*(n: PNode; conf: ConfigRef) =
|
||||
localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
|
||||
|
||||
proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) =
|
||||
if sonsLen(n) != length: illFormedAst(n, conf)
|
||||
if len(n) != length: illFormedAst(n, conf)
|
||||
|
||||
proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) =
|
||||
if sonsLen(n) < length: illFormedAst(n, conf)
|
||||
if len(n) < length: illFormedAst(n, conf)
|
||||
|
||||
proc isTopLevel*(c: PContext): bool {.inline.} =
|
||||
result = c.currentScope.depthLevel <= 2
|
||||
|
||||
@@ -25,12 +25,12 @@ const
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c.config, info, s, c.graph.usageSym)
|
||||
markUsed(c, info, s)
|
||||
onUse(info, s)
|
||||
# Note: This is n.info on purpose. It prevents template from creating an info
|
||||
# context when called from an another template
|
||||
pushInfoContext(c.config, n.info, s.detailedInfo)
|
||||
result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in flags)
|
||||
result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, efFromHlo in flags)
|
||||
if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
|
||||
popInfoContext(c.config)
|
||||
|
||||
@@ -149,7 +149,7 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
|
||||
(srcBaseTyp.kind in IntegralTypes):
|
||||
if targetTyp.isOrdinalType:
|
||||
if src.kind in nkCharLit..nkUInt64Lit and
|
||||
src.intVal notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp):
|
||||
src.getInt notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp):
|
||||
result = convNotInRange
|
||||
elif src.kind in nkFloatLit..nkFloat64Lit and
|
||||
(classify(src.floatVal) in {fcNan, fcNegInf, fcInf} or
|
||||
@@ -225,7 +225,7 @@ proc isOwnedSym(c: PContext; n: PNode): bool =
|
||||
result = s != nil and sfSystemModule in s.owner.flags and s.name.s == "owned"
|
||||
|
||||
proc semConv(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) != 2:
|
||||
if len(n) != 2:
|
||||
localError(c.config, n.info, "a type conversion takes exactly one argument")
|
||||
return n
|
||||
|
||||
@@ -301,11 +301,11 @@ proc semConv(c: PContext, n: PNode): PNode =
|
||||
localError(c.config, n.info, errGenerated, value & " can't be converted to " &
|
||||
result.typ.typeToString)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(op):
|
||||
for i in 0 ..< len(op):
|
||||
let it = op.sons[i]
|
||||
let status = checkConvertible(c, result.typ, it)
|
||||
if status in {convOK, convNotNeedeed}:
|
||||
markUsed(c.config, n.info, it.sym, c.graph.usageSym)
|
||||
markUsed(c, n.info, it.sym)
|
||||
onUse(n.info, it.sym)
|
||||
markIndirect(c, it.sym)
|
||||
return it
|
||||
@@ -331,7 +331,7 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
const
|
||||
opToStr: array[mLow..mHigh, string] = ["low", "high"]
|
||||
if sonsLen(n) != 2:
|
||||
if len(n) != 2:
|
||||
localError(c.config, n.info, errXExpectsTypeOrValue % opToStr[m])
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
|
||||
@@ -341,7 +341,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
of tyArray:
|
||||
n.typ = typ.sons[0] # indextype
|
||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32, tyFloat..tyFloat64:
|
||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt..tyUInt64, tyFloat..tyFloat64:
|
||||
n.typ = n.sons[1].typ.skipTypes({tyTypeDesc})
|
||||
of tyGenericParam:
|
||||
# prepare this for resolving in semtypinst:
|
||||
@@ -369,7 +369,7 @@ proc fixupStaticType(c: PContext, n: PNode) =
|
||||
|
||||
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
internalAssert c.config,
|
||||
n.sonsLen == 3 and
|
||||
n.len == 3 and
|
||||
n[1].typ != nil and
|
||||
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
||||
|
||||
@@ -408,7 +408,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.typ = n.typ
|
||||
|
||||
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) != 3:
|
||||
if len(n) != 3:
|
||||
localError(c.config, n.info, "'is' operator takes 2 arguments")
|
||||
|
||||
let boolType = getSysType(c.graph, n.info, tyBool)
|
||||
@@ -452,9 +452,9 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
const flags = {efDetermineType}
|
||||
for i in 1 ..< n.sonsLen:
|
||||
for i in 1 ..< n.len:
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||
if a.kind == nkExprEqExpr and len(a) == 2:
|
||||
let info = a.sons[0].info
|
||||
a.sons[0] = newIdentNode(considerQuotedIdent(c, a.sons[0], a), info)
|
||||
a.sons[1] = semExprWithType(c, a.sons[1], flags)
|
||||
@@ -470,22 +470,22 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
addSon(result, newIdentNode(par, n.info))
|
||||
for i in 0 ..< sonsLen(n): addSon(result, n.sons[i])
|
||||
for i in 0 ..< len(n): addSon(result, n.sons[i])
|
||||
result = semExpr(c, result)
|
||||
|
||||
proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
case n.kind
|
||||
of nkCurly, nkBracket:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
changeType(c, n.sons[i], elemType(newType), check)
|
||||
of nkPar, nkTupleConstr:
|
||||
let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
if tup.kind != tyTuple:
|
||||
if tup.kind == tyObject: return
|
||||
globalError(c.config, n.info, "no tuple type for constructor")
|
||||
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
|
||||
elif len(n) > 0 and n.sons[0].kind == nkExprColonExpr:
|
||||
# named tuple?
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var m = n.sons[i].sons[0]
|
||||
if m.kind != nkSym:
|
||||
globalError(c.config, m.info, "invalid tuple constructor")
|
||||
@@ -499,7 +499,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
else:
|
||||
changeType(c, n.sons[i].sons[1], tup.sons[i], check)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
changeType(c, n.sons[i], tup.sons[i], check)
|
||||
when false:
|
||||
var m = n.sons[i]
|
||||
@@ -513,43 +513,61 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
|
||||
localError(c.config, n.info, "cannot convert " & $value &
|
||||
" to " & typeToString(newType))
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if check and not floatRangeCheck(n.floatVal, newType):
|
||||
localError(c.config, n.info, errFloatToString % [$n.floatVal, typeToString(newType)])
|
||||
else: discard
|
||||
n.typ = newType
|
||||
|
||||
proc arrayConstrType(c: PContext, n: PNode): PType =
|
||||
var typ = newTypeS(tyArray, c)
|
||||
rawAddSon(typ, nil) # index type
|
||||
if sonsLen(n) == 0:
|
||||
if len(n) == 0:
|
||||
rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||
else:
|
||||
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
|
||||
addSonSkipIntLit(typ, t)
|
||||
typ.sons[0] = makeRangeType(c, 0, sonsLen(n) - 1, n.info)
|
||||
typ.sons[0] = makeRangeType(c, 0, len(n) - 1, n.info)
|
||||
result = typ
|
||||
|
||||
proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = newNodeI(nkBracket, n.info)
|
||||
result.typ = newTypeS(tyArray, c)
|
||||
rawAddSon(result.typ, nil) # index type
|
||||
if sonsLen(n) == 0:
|
||||
var
|
||||
firstIndex, lastIndex: Int128
|
||||
indexType = getSysType(c.graph, n.info, tyInt)
|
||||
lastValidIndex = lastOrd(c.config, indexType)
|
||||
if len(n) == 0:
|
||||
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||
lastIndex = toInt128(-1)
|
||||
else:
|
||||
var x = n.sons[0]
|
||||
var lastIndex: BiggestInt = 0
|
||||
var indexType = getSysType(c.graph, n.info, tyInt)
|
||||
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||
if x.kind == nkExprColonExpr and len(x) == 2:
|
||||
var idx = semConstExpr(c, x.sons[0])
|
||||
lastIndex = getOrdValue(idx)
|
||||
indexType = idx.typ
|
||||
x = x.sons[1]
|
||||
if not isOrdinalType(idx.typ):
|
||||
localError(c.config, idx.info, "expected ordinal value for array " &
|
||||
"index, got '$1'" % renderTree(idx))
|
||||
else:
|
||||
firstIndex = getOrdValue(idx)
|
||||
lastIndex = firstIndex
|
||||
indexType = idx.typ
|
||||
lastValidIndex = lastOrd(c.config, indexType)
|
||||
x = x.sons[1]
|
||||
|
||||
let yy = semExprWithType(c, x)
|
||||
var typ = yy.typ
|
||||
addSon(result, yy)
|
||||
#var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal})
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if lastIndex == lastValidIndex:
|
||||
let validIndex = makeRangeType(c, toInt64(firstIndex), toInt64(lastValidIndex), n.info,
|
||||
indexType)
|
||||
localError(c.config, n.info, "size of array exceeds range of index " &
|
||||
"type '$1' by $2 elements" % [typeToString(validIndex), $(n.len-i)])
|
||||
|
||||
x = n.sons[i]
|
||||
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||
if x.kind == nkExprColonExpr and len(x) == 2:
|
||||
var idx = semConstExpr(c, x.sons[0])
|
||||
idx = fitNode(c, indexType, idx, x.info)
|
||||
if lastIndex+1 != getOrdValue(idx):
|
||||
@@ -565,7 +583,8 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
addSonSkipIntLit(result.typ, typ)
|
||||
for i in 0 ..< result.len:
|
||||
result.sons[i] = fitNode(c, typ, result.sons[i], result.sons[i].info)
|
||||
result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
|
||||
result.typ.sons[0] = makeRangeType(c, toInt64(firstIndex), toInt64(lastIndex), n.info,
|
||||
indexType)
|
||||
|
||||
proc fixAbstractType(c: PContext, n: PNode) =
|
||||
for i in 1 ..< n.len:
|
||||
@@ -664,8 +683,8 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams:
|
||||
# BUGFIX: check for L-Value still needs to be done for the arguments!
|
||||
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
|
||||
for i in 1 ..< sonsLen(n):
|
||||
if i < sonsLen(t) and t.sons[i] != nil and
|
||||
for i in 1 ..< len(n):
|
||||
if i < len(t) and t.sons[i] != nil and
|
||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||
let it = n[i]
|
||||
if isAssignable(c, it) notin {arLValue, arLocalLValue}:
|
||||
@@ -680,13 +699,13 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
localError(c.config, n.info, errXStackEscape % renderTree(n[1], {renderNoComments}))
|
||||
|
||||
return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
let n = if n.kind == nkHiddenDeref: n[0] else: n
|
||||
if n.sons[i].kind == nkHiddenCallConv:
|
||||
# we need to recurse explicitly here as converters can create nested
|
||||
# calls and then they wouldn't be analysed otherwise
|
||||
analyseIfAddressTakenInCall(c, n.sons[i])
|
||||
if i < sonsLen(t) and
|
||||
if i < len(t) and
|
||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||
if n.sons[i].kind != nkHiddenAddr:
|
||||
n.sons[i] = analyseIfAddressTaken(c, n.sons[i])
|
||||
@@ -868,7 +887,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = n0
|
||||
result.kind = nkCall
|
||||
result.flags.incl nfExplicitCall
|
||||
for i in 1 ..< sonsLen(n): addSon(result, n.sons[i])
|
||||
for i in 1 ..< len(n): addSon(result, n.sons[i])
|
||||
return semExpr(c, result, flags)
|
||||
else:
|
||||
n.sons[0] = n0
|
||||
@@ -899,7 +918,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else:
|
||||
var hasErrorType = false
|
||||
var msg = "type mismatch: got <"
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if i > 1: add(msg, ", ")
|
||||
let nt = n.sons[i].typ
|
||||
add(msg, typeToString(nt))
|
||||
@@ -987,7 +1006,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||
result = nil
|
||||
case r.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(r):
|
||||
for i in 0 ..< len(r):
|
||||
result = lookupInRecordAndBuildCheck(c, n, r.sons[i], field, check)
|
||||
if result != nil: return
|
||||
of nkRecCase:
|
||||
@@ -997,19 +1016,19 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||
if result != nil: return
|
||||
let setType = createSetType(c, r.sons[0].typ)
|
||||
var s = newNodeIT(nkCurly, r.info, setType)
|
||||
for i in 1 ..< sonsLen(r):
|
||||
for i in 1 ..< len(r):
|
||||
var it = r.sons[i]
|
||||
case it.kind
|
||||
of nkOfBranch:
|
||||
result = lookupInRecordAndBuildCheck(c, n, lastSon(it), field, check)
|
||||
if result == nil:
|
||||
for j in 0..sonsLen(it)-2: addSon(s, copyTree(it.sons[j]))
|
||||
for j in 0..len(it)-2: addSon(s, copyTree(it.sons[j]))
|
||||
else:
|
||||
if check == nil:
|
||||
check = newNodeI(nkCheckedFieldExpr, n.info)
|
||||
addSon(check, c.graph.emptyNode) # make space for access node
|
||||
s = newNodeIT(nkCurly, n.info, setType)
|
||||
for j in 0 .. sonsLen(it) - 2: addSon(s, copyTree(it.sons[j]))
|
||||
for j in 0 .. len(it) - 2: addSon(s, copyTree(it.sons[j]))
|
||||
var inExpr = newNodeIT(nkCall, n.info, getSysType(c.graph, n.info, tyBool))
|
||||
addSon(inExpr, newSymNode(c.graph.opContains, n.info))
|
||||
addSon(inExpr, s)
|
||||
@@ -1090,7 +1109,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
let s = getGenSym(c, sym)
|
||||
case s.kind
|
||||
of skConst:
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
let typ = skipTypes(s.typ, abstractInst-{tyTypeDesc})
|
||||
case typ.kind
|
||||
@@ -1122,7 +1141,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
of skMacro:
|
||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
||||
(n.kind notin nkCallKinds and s.requiredParams > 0):
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
else:
|
||||
@@ -1132,13 +1151,13 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
(n.kind notin nkCallKinds and s.requiredParams > 0) or
|
||||
sfCustomPragma in sym.flags:
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c.config, info, s, c.graph.usageSym)
|
||||
markUsed(c, info, s)
|
||||
onUse(info, s)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
else:
|
||||
result = semTemplateExpr(c, n, s, flags)
|
||||
of skParam:
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
if s.typ != nil and s.typ.kind == tyStatic and s.typ.n != nil:
|
||||
# XXX see the hack in sigmatch.nim ...
|
||||
@@ -1162,7 +1181,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if s.magic == mNimvm:
|
||||
localError(c.config, n.info, "illegal context for 'nimvm' magic")
|
||||
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
# We cannot check for access to outer vars for example because it's still
|
||||
@@ -1180,7 +1199,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
n.typ = s.typ
|
||||
return n
|
||||
of skType:
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
|
||||
return s.typ.n
|
||||
@@ -1202,7 +1221,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if f != nil and fieldVisible(c, f):
|
||||
# is the access to a public field or in the same module or in a friend?
|
||||
doAssert f == s
|
||||
markUsed(c.config, n.info, f, c.graph.usageSym)
|
||||
markUsed(c, n.info, f)
|
||||
onUse(n.info, f)
|
||||
result = newNodeIT(nkDotExpr, n.info, f.typ)
|
||||
result.add makeDeref(newSymNode(p.selfSym))
|
||||
@@ -1215,12 +1234,13 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if ty.sons[0] == nil: break
|
||||
ty = skipTypes(ty.sons[0], skipPtrs)
|
||||
# old code, not sure if it's live code:
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
else:
|
||||
let info = getCallLineInfo(n)
|
||||
markUsed(c.config, info, s, c.graph.usageSym)
|
||||
#if efInCall notin flags:
|
||||
markUsed(c, info, s)
|
||||
onUse(info, s)
|
||||
result = newSymNode(s, info)
|
||||
|
||||
@@ -1242,7 +1262,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
if result.kind == nkSym: result = semSym(c, n, s, flags)
|
||||
else:
|
||||
markUsed(c.config, n.sons[1].info, s, c.graph.usageSym)
|
||||
markUsed(c, n.sons[1].info, s)
|
||||
result = semSym(c, n, s, flags)
|
||||
onUse(n.sons[1].info, s)
|
||||
return
|
||||
@@ -1306,7 +1326,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = newSymNode(f)
|
||||
result.info = n.info
|
||||
result.typ = ty
|
||||
markUsed(c.config, n.info, f, c.graph.usageSym)
|
||||
markUsed(c, n.info, f)
|
||||
onUse(n.info, f)
|
||||
return
|
||||
of tyObject, tyTuple:
|
||||
@@ -1341,7 +1361,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else: true
|
||||
if not visibilityCheckNeeded or fieldVisible(c, f):
|
||||
# is the access to a public field or in the same module or in a friend?
|
||||
markUsed(c.config, n.sons[1].info, f, c.graph.usageSym)
|
||||
markUsed(c, n.sons[1].info, f)
|
||||
onUse(n.sons[1].info, f)
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
n.sons[1] = newSymNode(f) # we now have the correct field
|
||||
@@ -1355,7 +1375,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
elif ty.kind == tyTuple and ty.n != nil:
|
||||
f = getSymFromList(ty.n, i)
|
||||
if f != nil:
|
||||
markUsed(c.config, n.sons[1].info, f, c.graph.usageSym)
|
||||
markUsed(c, n.sons[1].info, f)
|
||||
onUse(n.sons[1].info, f)
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
n.sons[1] = newSymNode(f)
|
||||
@@ -1404,7 +1424,7 @@ proc semDeref(c: PContext, n: PNode): PNode =
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
## returns nil if not a built-in subscript operator; also called for the
|
||||
## checking of assignments
|
||||
if sonsLen(n) == 1:
|
||||
if len(n) == 1:
|
||||
let x = semDeref(c, n)
|
||||
if x == nil: return nil
|
||||
result = newNodeIT(nkDerefExpr, x.info, x.typ)
|
||||
@@ -1431,7 +1451,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
tyUncheckedArray:
|
||||
if n.len != 2: return nil
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
n.sons[i] = semExprWithType(c, n.sons[i],
|
||||
flags*{efInTypeof, efDetermineType})
|
||||
# Arrays index type is dictated by the range's type
|
||||
@@ -1462,7 +1482,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias, tySink}).kind in
|
||||
{tyInt..tyInt64}:
|
||||
let idx = getOrdValue(n.sons[1])
|
||||
if idx >= 0 and idx < len(arr): n.typ = arr.sons[int(idx)]
|
||||
if idx >= 0 and idx < len(arr): n.typ = arr.sons[toInt(idx)]
|
||||
else: localError(c.config, n.info, "invalid index value for tuple subscript")
|
||||
result = n
|
||||
else:
|
||||
@@ -1541,11 +1561,11 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
|
||||
of nkBracketExpr:
|
||||
if len(n) == 1: return n.sons[0]
|
||||
else: discard
|
||||
let valid = isAssignable(c, n)
|
||||
let valid = isAssignable(c, n, isLent)
|
||||
if valid != arLValue:
|
||||
if valid == arLocalLValue:
|
||||
localError(c.config, n.info, errXStackEscape % renderTree(n, {renderNoComments}))
|
||||
elif not isLent:
|
||||
else:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
|
||||
result.add(n)
|
||||
@@ -1761,21 +1781,21 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||
var t = skipTypes(restype, {tyGenericInst, tyAlias, tySink})
|
||||
case t.kind
|
||||
of tyVar, tyLent:
|
||||
if t.kind == tyVar: t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
t.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
if n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||
n.sons[0] = n.sons[0].sons[1]
|
||||
n.sons[0] = takeImplicitAddr(c, n.sons[0], t.kind == tyLent)
|
||||
of tyTuple:
|
||||
for i in 0..<t.sonsLen:
|
||||
var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
|
||||
for i in 0..<t.len:
|
||||
let e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink})
|
||||
if e.kind in {tyVar, tyLent}:
|
||||
if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892
|
||||
if n.sons[0].kind in {nkPar, nkTupleConstr}:
|
||||
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i], e.kind == tyLent)
|
||||
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
||||
n.sons[0].sons[1].kind in {nkPar, nkTupleConstr}:
|
||||
var a = n.sons[0].sons[1]
|
||||
a.sons[i] = takeImplicitAddr(c, a.sons[i], false)
|
||||
a.sons[i] = takeImplicitAddr(c, a.sons[i], e.kind == tyLent)
|
||||
else:
|
||||
localError(c.config, n.sons[0].info, errXExpected, "tuple constructor")
|
||||
else: discard
|
||||
@@ -1876,7 +1896,6 @@ proc expectString(c: PContext, n: PNode): string =
|
||||
|
||||
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
|
||||
result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info)
|
||||
result.flags = {sfGenSym}
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
let macroCall = n[1]
|
||||
@@ -1886,7 +1905,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
if expandedSym.kind == skError: return n
|
||||
|
||||
macroCall.sons[0] = newSymNode(expandedSym, macroCall.info)
|
||||
markUsed(c.config, n.info, expandedSym, c.graph.usageSym)
|
||||
markUsed(c, n.info, expandedSym)
|
||||
onUse(n.info, expandedSym)
|
||||
|
||||
if isCallExpr(macroCall):
|
||||
@@ -1911,7 +1930,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
let info = macroCall.sons[0].info
|
||||
macroCall.sons[0] = newSymNode(cand, info)
|
||||
markUsed(c.config, info, cand, c.graph.usageSym)
|
||||
markUsed(c, info, cand)
|
||||
onUse(info, cand)
|
||||
|
||||
# we just perform overloading resolution here:
|
||||
@@ -1927,7 +1946,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
if sonsLen(n) == 2:
|
||||
if len(n) == 2:
|
||||
n.sons[0] = newSymNode(magicSym, n.info)
|
||||
result = semExpandToAst(c, n)
|
||||
else:
|
||||
@@ -2000,7 +2019,14 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
|
||||
var tmpl = semTemplateDef(c, dummyTemplate)
|
||||
quotes[0] = tmpl[namePos]
|
||||
# This adds a call to newIdentNode("result") as the first argument to the template call
|
||||
quotes[1] = newNode(nkCall, n.info, @[newIdentNode(getIdent(c.cache, "newIdentNode"), n.info), newStrNode(nkStrLit, "result")])
|
||||
let identNodeSym = getCompilerProc(c.graph, "newIdentNode")
|
||||
# so that new Nim compilers can compile old macros.nim versions, we check for 'nil'
|
||||
# here and provide the old fallback solution:
|
||||
let identNode = if identNodeSym == nil:
|
||||
newIdentNode(getIdent(c.cache, "newIdentNode"), n.info)
|
||||
else:
|
||||
identNodeSym.newSymNode
|
||||
quotes[1] = newNode(nkCall, n.info, @[identNode, newStrNode(nkStrLit, "result")])
|
||||
result = newNode(nkCall, n.info, @[
|
||||
createMagic(c.graph, "getAst", mExpandToAst).newSymNode,
|
||||
newNode(nkCall, n.info, quotes)])
|
||||
@@ -2012,7 +2038,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
let oldErrorMax = c.config.errorMax
|
||||
let oldCompilesId = c.compilesContextId
|
||||
# if this is a nested 'when compiles', do not increase the ID so that
|
||||
# generic instantations can still be cached for this level.
|
||||
# generic instantiations can still be cached for this level.
|
||||
if c.compilesContextId == 0:
|
||||
inc c.compilesContextIdGenerator
|
||||
c.compilesContextId = c.compilesContextIdGenerator
|
||||
@@ -2057,14 +2083,14 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
|
||||
proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# we replace this node by a 'true' or 'false' node:
|
||||
if sonsLen(n) != 2: return semDirectOp(c, n, flags)
|
||||
if len(n) != 2: return semDirectOp(c, n, flags)
|
||||
|
||||
result = newIntNode(nkIntLit, ord(tryExpr(c, n[1], flags) != nil))
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
if len(n) == 3:
|
||||
# XXX ugh this is really a hack: shallowCopy() can be overloaded only
|
||||
# with procs that take not 2 parameters:
|
||||
result = newNodeI(nkFastAsgn, n.info)
|
||||
@@ -2101,7 +2127,7 @@ proc setMs(n: PNode, s: PSym): PNode =
|
||||
n.sons[0].info = n.info
|
||||
|
||||
proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) != 2:
|
||||
if len(n) != 2:
|
||||
localError(c.config, n.info, errXExpectsTypeOrValue % "sizeof")
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
|
||||
@@ -2114,30 +2140,42 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
case s.magic # magics that need special treatment
|
||||
of mAddr:
|
||||
markUsed(c, n.info, s)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result[0] = newSymNode(s, n[0].info)
|
||||
result[1] = semAddrArg(c, n.sons[1], s.name.s == "unsafeAddr")
|
||||
result.typ = makePtrType(c, result[1].typ)
|
||||
of mTypeOf:
|
||||
markUsed(c, n.info, s)
|
||||
result = semTypeOf(c, n)
|
||||
#of mArrGet: result = semArrGet(c, n, flags)
|
||||
#of mArrPut: result = semArrPut(c, n, flags)
|
||||
#of mAsgn: result = semAsgnOpr(c, n)
|
||||
of mDefined: result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
||||
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
of mIs: result = semIs(c, setMs(n, s), flags)
|
||||
#of mOf: result = semOf(c, setMs(n, s))
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||
of mQuoteAst: result = semQuoteAst(c, n)
|
||||
of mDefined:
|
||||
markUsed(c, n.info, s)
|
||||
result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope:
|
||||
markUsed(c, n.info, s)
|
||||
result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles:
|
||||
markUsed(c, n.info, s)
|
||||
result = semCompiles(c, setMs(n, s), flags)
|
||||
of mIs:
|
||||
markUsed(c, n.info, s)
|
||||
result = semIs(c, setMs(n, s), flags)
|
||||
of mShallowCopy:
|
||||
markUsed(c, n.info, s)
|
||||
result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst:
|
||||
markUsed(c, n.info, s)
|
||||
result = semExpandToAst(c, n, s, flags)
|
||||
of mQuoteAst:
|
||||
markUsed(c, n.info, s)
|
||||
result = semQuoteAst(c, n)
|
||||
of mAstToStr:
|
||||
markUsed(c, n.info, s)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
of mParallel:
|
||||
markUsed(c, n.info, s)
|
||||
if parallel notin c.features:
|
||||
localError(c.config, n.info, "use the {.experimental.} pragma to enable 'parallel'")
|
||||
result = setMs(n, s)
|
||||
@@ -2147,6 +2185,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
result.sons[1] = semStmt(c, x, {})
|
||||
dec c.inParallelStmt
|
||||
of mSpawn:
|
||||
markUsed(c, n.info, s)
|
||||
when defined(leanCompiler):
|
||||
localError(c.config, n.info, "compiler was built without 'spawn' support")
|
||||
result = n
|
||||
@@ -2164,10 +2203,12 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
else:
|
||||
result.add c.graph.emptyNode
|
||||
of mProcCall:
|
||||
markUsed(c, n.info, s)
|
||||
result = setMs(n, s)
|
||||
result.sons[1] = semExpr(c, n.sons[1])
|
||||
result.typ = n[1].typ
|
||||
of mPlugin:
|
||||
markUsed(c, n.info, s)
|
||||
# semDirectOp with conditional 'afterCallActions':
|
||||
let nOrig = n.copyTree
|
||||
#semLazyOpAux(c, n)
|
||||
@@ -2184,6 +2225,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
if callee.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
of mRunnableExamples:
|
||||
markUsed(c, n.info, s)
|
||||
if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList:
|
||||
when false:
|
||||
# some of this dead code was moved to `prepareExamples`
|
||||
@@ -2200,8 +2242,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
result = setMs(n, s)
|
||||
else:
|
||||
result = c.graph.emptyNode
|
||||
of mSizeOf: result =
|
||||
semSizeof(c, setMs(n, s))
|
||||
of mSizeOf:
|
||||
markUsed(c, n.info, s)
|
||||
result = semSizeof(c, setMs(n, s))
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
@@ -2230,7 +2273,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
whenNimvm = exprNode.sym.magic == mNimvm
|
||||
if whenNimvm: n.flags.incl nfLL
|
||||
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
case it.kind
|
||||
of nkElifBranch, nkElifExpr:
|
||||
@@ -2268,12 +2311,12 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkCurly, n.info)
|
||||
result.typ = newTypeS(tySet, c)
|
||||
if sonsLen(n) == 0:
|
||||
if len(n) == 0:
|
||||
rawAddSon(result.typ, newTypeS(tyEmpty, c))
|
||||
else:
|
||||
# only semantic checking for all elements, later type checking:
|
||||
var typ: PType = nil
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if isRange(n.sons[i]):
|
||||
checkSonsLen(n.sons[i], 3, c.config)
|
||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
|
||||
@@ -2297,7 +2340,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||
elif lengthOrd(c.config, typ) > MaxSetElements:
|
||||
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
|
||||
addSonSkipIntLit(result.typ, typ)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var m: PNode
|
||||
let info = n.sons[i].info
|
||||
if isRange(n.sons[i]):
|
||||
@@ -2316,7 +2359,7 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
|
||||
var lastKey = 0
|
||||
for i in 0..n.len-1:
|
||||
var x = n.sons[i]
|
||||
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||
if x.kind == nkExprColonExpr and len(x) == 2:
|
||||
for j in lastKey ..< i:
|
||||
var pair = newNodeI(nkTupleConstr, x.info)
|
||||
pair.add(n.sons[j])
|
||||
@@ -2338,7 +2381,7 @@ type
|
||||
paNone, paSingle, paTupleFields, paTuplePositions
|
||||
|
||||
proc checkPar(c: PContext; n: PNode): TParKind =
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
if length == 0:
|
||||
result = paTuplePositions # ()
|
||||
elif length == 1:
|
||||
@@ -2364,12 +2407,10 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var typ = newTypeS(tyTuple, c)
|
||||
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
||||
var ids = initIntSet()
|
||||
for i in 0 ..< sonsLen(n):
|
||||
if n[i].kind != nkExprColonExpr or n[i][0].kind notin {nkSym, nkIdent}:
|
||||
for i in 0 ..< len(n):
|
||||
if n[i].kind != nkExprColonExpr:
|
||||
illFormedAst(n.sons[i], c.config)
|
||||
var id: PIdent
|
||||
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
|
||||
else: id = n.sons[i].sons[0].sym.name
|
||||
let id = considerQuotedIdent(c, n[i][0])
|
||||
if containsOrIncl(ids, id.id):
|
||||
localError(c.config, n.sons[i].info, errFieldInitTwice % id.s)
|
||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
|
||||
@@ -2392,7 +2433,7 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = n # we don't modify n, but compute the type:
|
||||
result.kind = nkTupleConstr
|
||||
var typ = newTypeS(tyTuple, c) # leave typ.n nil!
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor})
|
||||
addSonSkipIntLit(typ, n.sons[i].typ)
|
||||
result.typ = typ
|
||||
@@ -2434,11 +2475,11 @@ proc semExportExcept(c: PContext, n: PNode): PNode =
|
||||
var s = initTabIter(i, exported.tab)
|
||||
while s != nil:
|
||||
if s.kind in ExportableSymKinds+{skModule} and
|
||||
s.name.id notin exceptSet:
|
||||
s.name.id notin exceptSet and sfError notin s.flags:
|
||||
strTableAdd(c.module.tab, s)
|
||||
result.add newSymNode(s, n.info)
|
||||
s = nextIter(i, exported.tab)
|
||||
markUsed(c.config, n.info, exported, c.graph.usageSym)
|
||||
markUsed(c, n.info, exported)
|
||||
|
||||
proc semExport(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkExportStmt, n.info)
|
||||
@@ -2458,14 +2499,16 @@ proc semExport(c: PContext, n: PNode): PNode =
|
||||
strTableAdd(c.module.tab, it)
|
||||
result.add newSymNode(it, a.info)
|
||||
it = nextIter(ti, s.tab)
|
||||
markUsed(c, n.info, s)
|
||||
else:
|
||||
while s != nil:
|
||||
if s.kind == skEnumField:
|
||||
localError(c.config, a.info, errGenerated, "cannot export: " & renderTree(a) &
|
||||
"; enum field cannot be exported individually")
|
||||
if s.kind in ExportableSymKinds+{skModule}:
|
||||
if s.kind in ExportableSymKinds+{skModule} and sfError notin s.flags:
|
||||
result.add(newSymNode(s, a.info))
|
||||
strTableAdd(c.module.tab, s)
|
||||
markUsed(c, n.info, s)
|
||||
s = nextOverloadIter(o, c, a)
|
||||
|
||||
proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
@@ -2520,7 +2563,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
# if isGenericRoutine(result.sym):
|
||||
# localError(c.config, n.info, errInstantiateXExplicitly, s.name.s)
|
||||
# "procs literals" are 'owned'
|
||||
if optNimV2 in c.config.globalOptions:
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
else:
|
||||
result = semSym(c, n, s, flags)
|
||||
@@ -2712,7 +2755,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkUsingStmt: result = semUsing(c, n)
|
||||
of nkAsmStmt: result = semAsm(c, n)
|
||||
of nkYieldStmt: result = semYield(c, n)
|
||||
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
|
||||
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas, true)
|
||||
of nkIteratorDef: result = semIterator(c, n)
|
||||
of nkProcDef: result = semProc(c, n)
|
||||
of nkFuncDef: result = semFunc(c, n)
|
||||
|
||||
@@ -27,7 +27,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
of nkIdent, nkSym:
|
||||
result = n
|
||||
let ident = considerQuotedIdent(c.c, n)
|
||||
var L = sonsLen(forLoop)
|
||||
var L = len(forLoop)
|
||||
if c.replaceByFieldName:
|
||||
if ident.id == considerQuotedIdent(c.c, forLoop[0]).id:
|
||||
let fieldName = if c.tupleType.isNil: c.field.name.s
|
||||
@@ -54,8 +54,8 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
|
||||
localError(c.c.config, n.info,
|
||||
"'continue' not supported in a 'fields' loop")
|
||||
result = copyNode(n)
|
||||
newSons(result, sonsLen(n))
|
||||
for i in 0 ..< sonsLen(n):
|
||||
newSons(result, len(n))
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = instFieldLoopBody(c, n.sons[i], forLoop)
|
||||
|
||||
type
|
||||
@@ -120,9 +120,9 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
var stmts = newNodeI(nkStmtList, n.info)
|
||||
result.sons[1] = stmts
|
||||
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
var call = n.sons[length-2]
|
||||
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
|
||||
if length-2 != len(call)-1 + ord(m==mFieldPairs):
|
||||
localError(c.config, n.info, errWrongNumberOfVariables)
|
||||
return result
|
||||
|
||||
@@ -139,7 +139,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
inc(c.p.nestedLoopCounter)
|
||||
if tupleTypeA.kind == tyTuple:
|
||||
var loopBody = n.sons[length-1]
|
||||
for i in 0..sonsLen(tupleTypeA)-1:
|
||||
for i in 0..len(tupleTypeA)-1:
|
||||
openScope(c)
|
||||
var fc: TFieldInstCtx
|
||||
fc.tupleType = tupleTypeA
|
||||
|
||||
@@ -15,7 +15,12 @@ import
|
||||
platform, math, msgs, idents, renderer, types,
|
||||
commands, magicsys, modulegraphs, strtabs, lineinfos
|
||||
|
||||
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
proc errorType*(g: ModuleGraph): PType =
|
||||
## creates a type representing an error state
|
||||
result = newType(tyError, g.owners[^1])
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode {.deprecated: "intVal should be Int128".} =
|
||||
case skipTypes(n.typ, abstractVarRange).kind
|
||||
of tyInt:
|
||||
result = newIntNode(nkIntLit, intVal)
|
||||
@@ -35,8 +40,20 @@ proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
result.typ = n.typ
|
||||
result.info = n.info
|
||||
|
||||
proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newIntTypeNode(intVal, n.typ)
|
||||
# See bug #6989. 'pred' et al only produce an int literal type if the
|
||||
# original type was 'int', not a distinct int etc.
|
||||
if n.typ.kind == tyInt:
|
||||
# access cache for the int lit type
|
||||
result.typ = getIntLitType(g, result)
|
||||
result.info = n.info
|
||||
|
||||
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newFloatNode(nkFloatLit, floatVal)
|
||||
if n.typ.skipTypes(abstractInst).kind == tyFloat32:
|
||||
result = newFloatNode(nkFloat32Lit, floatVal)
|
||||
else:
|
||||
result = newFloatNode(nkFloatLit, floatVal)
|
||||
result.typ = n.typ
|
||||
result.info = n.info
|
||||
|
||||
@@ -50,65 +67,30 @@ proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode
|
||||
# expression
|
||||
proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode
|
||||
|
||||
proc checkInRange(conf: ConfigRef; n: PNode, res: BiggestInt): bool =
|
||||
if res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ):
|
||||
result = true
|
||||
proc checkInRange(conf: ConfigRef; n: PNode, res: Int128): bool =
|
||||
res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ)
|
||||
|
||||
proc foldAdd(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a +% b
|
||||
if ((res xor a) >= 0'i64 or (res xor b) >= 0'i64) and
|
||||
checkInRange(g.config, n, res):
|
||||
proc foldAdd(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a + b
|
||||
if checkInRange(g.config, n, res):
|
||||
result = newIntNodeT(res, n, g)
|
||||
|
||||
proc foldSub*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a -% b
|
||||
if ((res xor a) >= 0'i64 or (res xor not b) >= 0'i64) and
|
||||
checkInRange(g.config, n, res):
|
||||
proc foldSub(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a - b
|
||||
if checkInRange(g.config, n, res):
|
||||
result = newIntNodeT(res, n, g)
|
||||
|
||||
proc foldUnarySub(a: BiggestInt, n: PNode, g: ModuleGraph): PNode =
|
||||
proc foldUnarySub(a: Int128, n: PNode, g: ModuleGraph): PNode =
|
||||
if a != firstOrd(g.config, n.typ):
|
||||
result = newIntNodeT(-a, n, g)
|
||||
|
||||
proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
proc foldAbs(a: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
if a != firstOrd(g.config, n.typ):
|
||||
result = newIntNodeT(abs(a), n, g)
|
||||
|
||||
proc foldMod*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64:
|
||||
result = newIntNodeT(a mod b, n, g)
|
||||
|
||||
proc foldModU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64:
|
||||
result = newIntNodeT(a %% b, n, g)
|
||||
|
||||
proc foldDiv*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64 and (a != firstOrd(g.config, n.typ) or b != -1'i64):
|
||||
result = newIntNodeT(a div b, n, g)
|
||||
|
||||
proc foldDivU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64:
|
||||
result = newIntNodeT(a /% b, n, g)
|
||||
|
||||
proc foldMul*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a *% b
|
||||
let floatProd = toBiggestFloat(a) * toBiggestFloat(b)
|
||||
let resAsFloat = toBiggestFloat(res)
|
||||
|
||||
# Fast path for normal case: small multiplicands, and no info
|
||||
# is lost in either method.
|
||||
if resAsFloat == floatProd and checkInRange(g.config, n, res):
|
||||
return newIntNodeT(res, n, g)
|
||||
|
||||
# Somebody somewhere lost info. Close enough, or way off? Note
|
||||
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
|
||||
# The difference either is or isn't significant compared to the
|
||||
# true value (of which floatProd is a good approximation).
|
||||
|
||||
# abs(diff)/abs(prod) <= 1/32 iff
|
||||
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
||||
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd) and
|
||||
checkInRange(g.config, n, res):
|
||||
proc foldMul(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a * b
|
||||
if checkInRange(g.config, n, res):
|
||||
return newIntNodeT(res, n, g)
|
||||
|
||||
proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
|
||||
@@ -119,10 +101,10 @@ proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
|
||||
var t = skipTypes(a.typ, abstractRange)
|
||||
case t.kind
|
||||
of tyChar:
|
||||
result = $chr(int(x) and 0xff)
|
||||
result = $chr(toInt64(x) and 0xff)
|
||||
of tyEnum:
|
||||
var n = t.n
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
if n.sons[i].kind != nkSym: internalError(g.config, a.info, "ordinalValToString")
|
||||
var field = n.sons[i].sym
|
||||
if field.position == x:
|
||||
@@ -176,7 +158,7 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
|
||||
result.n = n
|
||||
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
||||
|
||||
proc fitLiteral(c: ConfigRef, n: PNode): PNode =
|
||||
proc fitLiteral(c: ConfigRef, n: PNode): PNode {.deprecated: "no substitute".} =
|
||||
# Trim the literal value in order to make it fit in the destination type
|
||||
if n == nil:
|
||||
# `n` may be nil if the overflow check kicks in
|
||||
@@ -188,58 +170,68 @@ proc fitLiteral(c: ConfigRef, n: PNode): PNode =
|
||||
|
||||
let typ = n.typ.skipTypes(abstractRange)
|
||||
if typ.kind in tyUInt..tyUInt32:
|
||||
result.intVal = result.intVal and lastOrd(c, typ, fixedUnsigned=true)
|
||||
result.intVal = result.intVal and castToInt64(lastOrd(c, typ))
|
||||
|
||||
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
template doAndFit(op: untyped): untyped =
|
||||
# Implements wrap-around behaviour for unsigned types
|
||||
fitLiteral(g.config, op)
|
||||
# b and c may be nil
|
||||
result = nil
|
||||
case m
|
||||
of mOrd: result = newIntNodeT(getOrdValue(a), n, g)
|
||||
of mChr: result = newIntNodeT(getInt(a), n, g)
|
||||
of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, g)
|
||||
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
|
||||
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
|
||||
of mUnaryMinusF64: result = newFloatNodeT(-getFloat(a), n, g)
|
||||
of mNot: result = newIntNodeT(One - getInt(a), n, g)
|
||||
of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
|
||||
of mBitnotI: result = doAndFit(newIntNodeT(not getInt(a), n, g))
|
||||
of mBitnotI:
|
||||
if n.typ.isUnsigned:
|
||||
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, g)
|
||||
else:
|
||||
result = newIntNodeT(bitnot(getInt(a)), n, g)
|
||||
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
|
||||
of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
|
||||
if a.kind == nkNilLit:
|
||||
result = newIntNodeT(0, n, g)
|
||||
result = newIntNodeT(Zero, n, g)
|
||||
elif a.kind in {nkStrLit..nkTripleStrLit}:
|
||||
result = newIntNodeT(len a.strVal, n, g)
|
||||
result = newIntNodeT(toInt128(a.strVal.len), n, g)
|
||||
else:
|
||||
result = newIntNodeT(sonsLen(a), n, g)
|
||||
result = newIntNodeT(toInt128(len(a)), n, g)
|
||||
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
|
||||
of mToFloat, mToBiggestFloat:
|
||||
result = newFloatNodeT(toFloat(int(getInt(a))), n, g)
|
||||
# XXX: Hides overflow/underflow
|
||||
of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n, g)
|
||||
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n, g)
|
||||
of mAbsI: result = foldAbs(getInt(a), n, g)
|
||||
of mUnaryLt: result = doAndFit(foldSub(getOrdValue(a), 1, n, g))
|
||||
of mSucc: result = doAndFit(foldAdd(getOrdValue(a), getInt(b), n, g))
|
||||
of mPred: result = doAndFit(foldSub(getOrdValue(a), getInt(b), n, g))
|
||||
of mUnaryLt: result = foldSub(getOrdValue(a), One, n, g)
|
||||
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g)
|
||||
of mPred: result = foldSub(getOrdValue(a), getInt(b), n, g)
|
||||
of mAddI: result = foldAdd(getInt(a), getInt(b), n, g)
|
||||
of mSubI: result = foldSub(getInt(a), getInt(b), n, g)
|
||||
of mMulI: result = foldMul(getInt(a), getInt(b), n, g)
|
||||
of mMinI:
|
||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n, g)
|
||||
else: result = newIntNodeT(getInt(a), n, g)
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
result = newIntNodeT(if argA < argB: argA else: argB, n, g)
|
||||
of mMaxI:
|
||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(a), n, g)
|
||||
else: result = newIntNodeT(getInt(b), n, g)
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
result = newIntNodeT(if argA > argB: argA else: argB, n, g)
|
||||
of mShlI:
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n, g)
|
||||
of tyInt16: result = newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n, g)
|
||||
of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n, g)
|
||||
of tyInt64, tyInt:
|
||||
result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)
|
||||
of tyUInt..tyUInt64:
|
||||
result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g))
|
||||
of tyInt8: result = newIntNodeT(toInt8(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt16: result = newIntNodeT(toInt16(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt32: result = newIntNodeT(toInt32(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt64: result = newIntNodeT(toInt64(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt:
|
||||
if g.config.target.intSize == 4:
|
||||
result = newIntNodeT(toInt128(toInt32(getInt(a)) shl getInt64(b)), n, g)
|
||||
else:
|
||||
result = newIntNodeT(toInt128(toInt64(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt:
|
||||
if g.config.target.intSize == 4:
|
||||
result = newIntNodeT(BiggestInt(toUInt32(getInt(a)) shl getInt64(b)), n, g)
|
||||
else:
|
||||
result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl getInt64(b)), n, g)
|
||||
else: internalError(g.config, n.info, "constant folding for shl")
|
||||
of mShrI:
|
||||
var a = cast[uint64](getInt(a))
|
||||
@@ -263,25 +255,27 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
result = newIntNodeT(c, n, g)
|
||||
of mAshrI:
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g)
|
||||
of tyInt16: result = newIntNodeT(ashr(int16(getInt(a)), int16(getInt(b))), n, g)
|
||||
of tyInt32: result = newIntNodeT(ashr(int32(getInt(a)), int32(getInt(b))), n, g)
|
||||
of tyInt8: result = newIntNodeT(ashr(int8(getInt64(a)), int8(getInt64(b))), n, g)
|
||||
of tyInt16: result = newIntNodeT(ashr(int16(getInt64(a)), int16(getInt64(b))), n, g)
|
||||
of tyInt32: result = newIntNodeT(ashr(int32(getInt64(a)), int32(getInt64(b))), n, g)
|
||||
of tyInt64, tyInt:
|
||||
result = newIntNodeT(ashr(getInt(a), getInt(b)), n, g)
|
||||
result = newIntNodeT(ashr(getInt64(a), getInt64(b)), n, g)
|
||||
else: internalError(g.config, n.info, "constant folding for ashr")
|
||||
of mDivI: result = foldDiv(getInt(a), getInt(b), n, g)
|
||||
of mModI: result = foldMod(getInt(a), getInt(b), n, g)
|
||||
of mDivI:
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
|
||||
result = newIntNodeT(argA div argB, n, g)
|
||||
of mModI:
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
|
||||
result = newIntNodeT(argA mod argB, n, g)
|
||||
of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
|
||||
of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g)
|
||||
of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
|
||||
of mDivF64:
|
||||
result = newFloatNodeT(getFloat(a) / getFloat(b), n, g)
|
||||
of mMaxF64:
|
||||
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(a), n, g)
|
||||
else: result = newFloatNodeT(getFloat(b), n, g)
|
||||
of mMinF64:
|
||||
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n, g)
|
||||
else: result = newFloatNodeT(getFloat(a), n, g)
|
||||
of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n, g)
|
||||
of mLtI, mLtB, mLtEnum, mLtCh:
|
||||
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n, g)
|
||||
@@ -296,17 +290,32 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n, g)
|
||||
of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n, g)
|
||||
of mLtU, mLtU64:
|
||||
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n, g)
|
||||
result = newIntNodeT(ord(`<%`(getOrdValue64(a), getOrdValue64(b))), n, g)
|
||||
of mLeU, mLeU64:
|
||||
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n, g)
|
||||
of mBitandI, mAnd: result = doAndFit(newIntNodeT(a.getInt and b.getInt, n, g))
|
||||
of mBitorI, mOr: result = doAndFit(newIntNodeT(getInt(a) or getInt(b), n, g))
|
||||
of mBitxorI, mXor: result = doAndFit(newIntNodeT(a.getInt xor b.getInt, n, g))
|
||||
of mAddU: result = doAndFit(newIntNodeT(`+%`(getInt(a), getInt(b)), n, g))
|
||||
of mSubU: result = doAndFit(newIntNodeT(`-%`(getInt(a), getInt(b)), n, g))
|
||||
of mMulU: result = doAndFit(newIntNodeT(`*%`(getInt(a), getInt(b)), n, g))
|
||||
of mModU: result = doAndFit(foldModU(getInt(a), getInt(b), n, g))
|
||||
of mDivU: result = doAndFit(foldDivU(getInt(a), getInt(b), n, g))
|
||||
result = newIntNodeT(ord(`<=%`(getOrdValue64(a), getOrdValue64(b))), n, g)
|
||||
of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, g)
|
||||
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g)
|
||||
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g)
|
||||
of mAddU:
|
||||
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
|
||||
result = newIntNodeT(val, n, g)
|
||||
of mSubU:
|
||||
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
|
||||
result = newIntNodeT(val, n, g)
|
||||
# echo "subU: ", val, " n: ", n, " result: ", val
|
||||
of mMulU:
|
||||
let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size))
|
||||
result = newIntNodeT(val, n, g)
|
||||
of mModU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA mod argB, n, g)
|
||||
of mDivU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA div argB, n, g)
|
||||
of mLeSet: result = newIntNodeT(ord(containsSets(g.config, a, b)), n, g)
|
||||
of mEqSet: result = newIntNodeT(ord(equalSets(g.config, a, b)), n, g)
|
||||
of mLtSet:
|
||||
@@ -332,10 +341,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mBoolToStr:
|
||||
if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
|
||||
else: result = newStrNodeT("true", n, g)
|
||||
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n, g)
|
||||
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(toInt64(getOrdValue(b)))), n, g)
|
||||
of mCopyStrLast:
|
||||
result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
|
||||
int(getOrdValue(c))), n, g)
|
||||
result = newStrNodeT(substr(getStr(a), toInt(getOrdValue(b)),
|
||||
toInt(getOrdValue(c))), n, g)
|
||||
of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
|
||||
of mCStrToStr, mCharToStr:
|
||||
if a.kind == nkBracket:
|
||||
@@ -362,7 +371,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
|
||||
proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
result = nil
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it.len == 2:
|
||||
var e = getConstExpr(c, it.sons[0], g)
|
||||
@@ -380,27 +389,27 @@ proc leValueConv*(a, b: PNode): bool =
|
||||
case a.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
case b.kind
|
||||
of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
|
||||
of nkCharLit..nkUInt64Lit: result = a.getInt <= b.getInt
|
||||
of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int
|
||||
else: result = false #internalError(a.info, "leValueConv")
|
||||
of nkFloatLit..nkFloat128Lit:
|
||||
case b.kind
|
||||
of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
|
||||
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
|
||||
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat64(b.getInt)
|
||||
else: result = false # internalError(a.info, "leValueConv")
|
||||
else: result = false # internalError(a.info, "leValueConv")
|
||||
|
||||
proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
if sonsLen(n) <= 1: return
|
||||
if len(n) <= 1: return
|
||||
|
||||
var s = n.sons[0].sym
|
||||
var a = getConstExpr(m, n.sons[1], g)
|
||||
var b, c: PNode
|
||||
if a == nil: return
|
||||
if sonsLen(n) > 2:
|
||||
if len(n) > 2:
|
||||
b = getConstExpr(m, n.sons[2], g)
|
||||
if b == nil: return
|
||||
if sonsLen(n) > 3:
|
||||
if len(n) > 3:
|
||||
c = getConstExpr(m, n.sons[3], g)
|
||||
if c == nil: return
|
||||
result = evalOp(s.magic, n, a, b, c, g)
|
||||
@@ -415,57 +424,42 @@ proc getAppType(n: PNode; g: ModuleGraph): PNode =
|
||||
else:
|
||||
result = newStrNodeT("console", n, g)
|
||||
|
||||
proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) =
|
||||
var err = false
|
||||
if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}:
|
||||
err = value <% firstOrd(g.config, n.typ) or value >% lastOrd(g.config, n.typ, fixedUnsigned=true)
|
||||
else:
|
||||
err = value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ)
|
||||
if err:
|
||||
proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) =
|
||||
if value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ):
|
||||
localError(g.config, n.info, "cannot convert " & $value &
|
||||
" to " & typeToString(n.typ))
|
||||
|
||||
proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
|
||||
let dstTyp = skipTypes(n.typ, abstractRange)
|
||||
let srcTyp = skipTypes(a.typ, abstractRange)
|
||||
let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
|
||||
let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
|
||||
|
||||
# XXX range checks?
|
||||
# if srcTyp.kind == tyUInt64 and "FFFFFF" in $n:
|
||||
# echo "n: ", n, " a: ", a
|
||||
# echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check
|
||||
# echo getInt(a)
|
||||
# echo high(int64)
|
||||
# writeStackTrace()
|
||||
case dstTyp.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
case srcTyp.kind
|
||||
of tyFloat..tyFloat64:
|
||||
result = newIntNodeT(int(getFloat(a)), n, g)
|
||||
of tyChar:
|
||||
result = newIntNodeT(getOrdValue(a), n, g)
|
||||
of tyUInt..tyUInt64, tyInt..tyInt64:
|
||||
let toSigned = dstTyp.kind in tyInt..tyInt64
|
||||
result = newIntNodeT(BiggestInt(getFloat(a)), n, g)
|
||||
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
|
||||
var val = a.getOrdValue
|
||||
|
||||
if dstTyp.kind in {tyInt, tyInt64, tyUInt, tyUInt64}:
|
||||
# No narrowing needed
|
||||
discard
|
||||
elif dstTyp.kind in {tyInt..tyInt64}:
|
||||
# Signed type: Overflow check (if requested) and conversion
|
||||
if check: rangeCheck(n, val, g)
|
||||
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
|
||||
let valSign = val < 0
|
||||
val = abs(val) and mask
|
||||
if valSign: val = -val
|
||||
else:
|
||||
# Unsigned type: Conversion
|
||||
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
|
||||
val = val and mask
|
||||
|
||||
if check: rangeCheck(n, val, g)
|
||||
result = newIntNodeT(val, n, g)
|
||||
if dstTyp.kind in {tyUInt..tyUInt64}:
|
||||
result.kind = nkUIntLit
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
if check and result.kind in {nkCharLit..nkUInt64Lit}:
|
||||
rangeCheck(n, result.intVal, g)
|
||||
rangeCheck(n, getInt(result), g)
|
||||
of tyFloat..tyFloat64:
|
||||
case srcTyp.kind
|
||||
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
||||
result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g)
|
||||
result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
@@ -490,16 +484,16 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
var y = getConstExpr(m, n.sons[1], g)
|
||||
if y == nil: return
|
||||
|
||||
var idx = getOrdValue(y)
|
||||
var idx = toInt64(getOrdValue(y))
|
||||
case x.kind
|
||||
of nkPar, nkTupleConstr:
|
||||
if idx >= 0 and idx < sonsLen(x):
|
||||
result = x.sons[int(idx)]
|
||||
if idx >= 0 and idx < len(x):
|
||||
result = x.sons[idx]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
else:
|
||||
localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)-1) & $n)
|
||||
localError(g.config, n.info, formatErrorIndexBound(idx, len(x)-1) & $n)
|
||||
of nkBracket:
|
||||
idx = idx - firstOrd(g.config, x.typ)
|
||||
idx = idx - toInt64(firstOrd(g.config, x.typ))
|
||||
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
|
||||
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -518,7 +512,7 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
|
||||
|
||||
var field = n.sons[1].sym
|
||||
for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
|
||||
for i in ord(x.kind == nkObjConstr) ..< len(x):
|
||||
var it = x.sons[i]
|
||||
if it.kind != nkExprColonExpr:
|
||||
# lookup per index:
|
||||
@@ -533,7 +527,7 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
proc foldConStrStr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||
result.strVal = ""
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
let a = getConstExpr(m, n.sons[i], g)
|
||||
if a == nil: return nil
|
||||
result.strVal.add(getStrOrChar(a))
|
||||
@@ -635,12 +629,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
var a = getArrayConstr(m, n.sons[1], g)
|
||||
if a.kind == nkBracket:
|
||||
# we can optimize it away:
|
||||
result = newIntNodeT(sonsLen(a)-1, n, g)
|
||||
result = newIntNodeT(len(a)-1, n, g)
|
||||
of mLengthOpenArray:
|
||||
var a = getArrayConstr(m, n.sons[1], g)
|
||||
if a.kind == nkBracket:
|
||||
# we can optimize it away! This fixes the bug ``len(134)``.
|
||||
result = newIntNodeT(sonsLen(a), n, g)
|
||||
result = newIntNodeT(len(a), n, g)
|
||||
else:
|
||||
result = magicCall(m, n, g)
|
||||
of mLengthArray:
|
||||
@@ -689,7 +683,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
addSon(result, b)
|
||||
#of nkObjConstr:
|
||||
# result = copyTree(n)
|
||||
# for i in 1 ..< sonsLen(n):
|
||||
# for i in 1 ..< len(n):
|
||||
# var a = getConstExpr(m, n.sons[i].sons[1])
|
||||
# if a == nil: return nil
|
||||
# result.sons[i].sons[1] = a
|
||||
@@ -697,7 +691,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
of nkPar, nkTupleConstr:
|
||||
# tuple constructor
|
||||
result = copyNode(n)
|
||||
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
||||
if (len(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
||||
for i, expr in n.pairs:
|
||||
let exprNew = copyNode(expr) # nkExprColonExpr
|
||||
exprNew.add expr[0]
|
||||
@@ -729,8 +723,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var a = getConstExpr(m, n.sons[1], g)
|
||||
if a == nil: return
|
||||
# XXX: we should enable `check` for other conversion types too
|
||||
result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv)
|
||||
result = foldConv(n, a, g, check=true)
|
||||
of nkCast:
|
||||
var a = getConstExpr(m, n.sons[1], g)
|
||||
if a == nil: return
|
||||
|
||||
@@ -282,7 +282,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
# in threads.nim: the subtle preprocessing here binds 'globalsSlot' which
|
||||
# is not exported and yet the generic 'threadProcWrapper' works correctly.
|
||||
let flags = if mixinContext: flags+{withinMixin} else: flags
|
||||
for i in first ..< sonsLen(result):
|
||||
for i in first ..< safeLen(result):
|
||||
result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
|
||||
of nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
@@ -316,13 +316,13 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
withBracketExpr ctx, a.sons[0]:
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
|
||||
of nkIfStmt:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
|
||||
of nkWhenStmt:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
# bug #8603: conditions of 'when' statements are not
|
||||
# in a 'mixin' context:
|
||||
let it = n[i]
|
||||
@@ -333,22 +333,22 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
n.sons[i] = semGenericStmt(c, it, flags+{withinMixin}, ctx)
|
||||
of nkWhileStmt:
|
||||
openScope(c)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
|
||||
closeScope(c)
|
||||
of nkCaseStmt:
|
||||
openScope(c)
|
||||
n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
checkMinSonsLen(a, 1, c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
for j in 0 .. L-2:
|
||||
a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx)
|
||||
a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
|
||||
closeScope(c)
|
||||
of nkForStmt, nkParForStmt:
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
openScope(c)
|
||||
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
|
||||
for i in 0 .. L - 3:
|
||||
@@ -372,10 +372,10 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
of nkTryStmt, nkHiddenTryStmt:
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx)
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
checkMinSonsLen(a, 1, c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
openScope(c)
|
||||
for j in 0 .. L-2:
|
||||
if a.sons[j].isInfixAs():
|
||||
@@ -387,28 +387,28 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
closeScope(c)
|
||||
|
||||
of nkVarSection, nkLetSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
|
||||
a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
|
||||
for j in 0 .. L-3:
|
||||
addTempDecl(c, getIdentNode(c, a.sons[j]), skVar)
|
||||
of nkGenericParams:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
|
||||
# do not perform symbol lookup for default expressions
|
||||
for j in 0 .. L-3:
|
||||
addTempDecl(c, getIdentNode(c, a.sons[j]), skType)
|
||||
of nkConstSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkConstDef): illFormedAst(a, c.config)
|
||||
@@ -417,13 +417,13 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx)
|
||||
a.sons[2] = semGenericStmt(c, a.sons[2], flags, ctx)
|
||||
of nkTypeSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkTypeDef): illFormedAst(a, c.config)
|
||||
checkSonsLen(a, 3, c.config)
|
||||
addTempDecl(c, getIdentNode(c, a.sons[0]), skType)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkTypeDef): illFormedAst(a, c.config)
|
||||
@@ -436,10 +436,10 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
else:
|
||||
a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
|
||||
of nkEnumTy:
|
||||
if n.sonsLen > 0:
|
||||
if n.len > 0:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var a: PNode
|
||||
case n.sons[i].kind
|
||||
of nkEnumFieldDef: a = n.sons[i].sons[0]
|
||||
@@ -452,11 +452,11 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
|
||||
a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
|
||||
for j in 0 .. L-3:
|
||||
@@ -489,7 +489,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
result.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
|
||||
|
||||
when defined(nimsuggest):
|
||||
|
||||
@@ -211,7 +211,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
|
||||
param.typ = makeTypeDesc(c, header[i+1])
|
||||
|
||||
# this scope was not created by the user,
|
||||
# unused params shoudn't be reported.
|
||||
# unused params shouldn't be reported.
|
||||
param.flags.incl sfUsed
|
||||
addDecl(c, param)
|
||||
|
||||
@@ -387,7 +387,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
if c.inGenericContext == 0:
|
||||
instantiateBody(c, n, fn.typ.n, result, fn)
|
||||
sideEffectsCheck(c, result)
|
||||
if result.magic != mSlice:
|
||||
if result.magic notin {mSlice, mTypeOf}:
|
||||
# 'toOpenArray' is special and it is allowed to return 'openArray':
|
||||
paramsTypeCheck(c, result.typ)
|
||||
else:
|
||||
|
||||
@@ -16,14 +16,14 @@ proc ithField(n: PNode, field: var int): PSym =
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result = ithField(n.sons[i], field)
|
||||
if result != nil: return
|
||||
of nkRecCase:
|
||||
if n.sons[0].kind != nkSym: return
|
||||
result = ithField(n.sons[0], field)
|
||||
if result != nil: return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
result = ithField(lastSon(n.sons[i]), field)
|
||||
|
||||
@@ -141,6 +141,14 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
return typeWithSonsResult(tyAnd, @[operand, operand2])
|
||||
of "not":
|
||||
return typeWithSonsResult(tyNot, @[operand])
|
||||
of "typeToString":
|
||||
var prefer = preferTypeName
|
||||
if traitCall.sons.len >= 2:
|
||||
let preferStr = traitCall.sons[2].strVal
|
||||
prefer = parseEnum[TPreferedDesc](preferStr)
|
||||
result = newStrNode(nkStrLit, operand.typeToString(prefer))
|
||||
result.typ = newType(tyString, context)
|
||||
result.info = traitCall.info
|
||||
of "name", "$":
|
||||
result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
|
||||
result.typ = newType(tyString, context)
|
||||
@@ -172,7 +180,7 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
let t = n.sons[1].typ
|
||||
internalAssert c.config, t != nil and t.kind == tyTypeDesc
|
||||
if t.sonsLen > 0:
|
||||
if t.len > 0:
|
||||
# This is either a type known to sem or a typedesc
|
||||
# param to a regular proc (again, known at instantiation)
|
||||
result = evalTypeTrait(c, n, t, getCurrOwner(c))
|
||||
@@ -186,7 +194,9 @@ proc semOrd(c: PContext, n: PNode): PNode =
|
||||
if isOrdinalType(parType, allowEnumWithHoles=true):
|
||||
discard
|
||||
elif parType.kind == tySet:
|
||||
result.typ = makeRangeType(c, firstOrd(c.config, parType), lastOrd(c.config, parType), n.info)
|
||||
let a = toInt64(firstOrd(c.config, parType))
|
||||
let b = toInt64(lastOrd(c.config, parType))
|
||||
result.typ = makeRangeType(c, a, b, n.info)
|
||||
else:
|
||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
||||
result.typ = errorType(c)
|
||||
@@ -269,11 +279,11 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
|
||||
a.setResult opBindSym(c, scope, a.getNode(0), a.getInt(1).int, a.getNode(2))
|
||||
|
||||
let
|
||||
# altough we use VM callback here, it is not
|
||||
# although we use VM callback here, it is not
|
||||
# executed like 'normal' VM callback
|
||||
idx = vm.registerCallback("bindSymImpl", bindSymWrapper)
|
||||
# dummy node to carry idx information to VM
|
||||
idxNode = newIntTypeNode(nkIntLit, idx, c.graph.getSysType(TLineInfo(), tyInt))
|
||||
idxNode = newIntTypeNode(idx, c.graph.getSysType(TLineInfo(), tyInt))
|
||||
|
||||
result = copyNode(n)
|
||||
for x in n: result.add x
|
||||
@@ -283,7 +293,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
|
||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
|
||||
proc semOf(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
if len(n) == 3:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
|
||||
@@ -100,7 +100,7 @@ proc allPossibleValues(c: PContext, t: PType): IntSet =
|
||||
for field in t.n.sons:
|
||||
result.incl(field.sym.position)
|
||||
else:
|
||||
for i in firstOrd(c.config, t) .. lastOrd(c.config, t):
|
||||
for i in toInt64(firstOrd(c.config, t)) .. toInt64(lastOrd(c.config, t)):
|
||||
result.incl(i.int)
|
||||
|
||||
proc branchVals(c: PContext, caseNode: PNode, caseIdx: int,
|
||||
@@ -113,6 +113,13 @@ proc branchVals(c: PContext, caseNode: PNode, caseIdx: int,
|
||||
for i in 1 .. caseNode.len-2:
|
||||
processBranchVals(caseNode[i], excl)
|
||||
|
||||
proc rangeTypVals(rangeTyp: PType): IntSet =
|
||||
assert rangeTyp.kind == tyRange
|
||||
let (a, b) = (rangeTyp.n.sons[0].intVal, rangeTyp.n.sons[1].intVal)
|
||||
result = initIntSet()
|
||||
for it in a .. b:
|
||||
result.incl(it.int)
|
||||
|
||||
proc formatUnsafeBranchVals(t: PType, diffVals: IntSet): string =
|
||||
if diffVals.len <= 32:
|
||||
var strs: seq[string]
|
||||
@@ -228,9 +235,9 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||
template badDiscriminatorError =
|
||||
let fields = fieldsPresentInBranch(selectedBranch)
|
||||
localError(c.config, initExpr.info,
|
||||
("you must provide a compile-time value for the discriminator '$1' " &
|
||||
"in order to prove that it's safe to initialize $2.") %
|
||||
[discriminator.sym.name.s, fields])
|
||||
("cannot prove that it's safe to initialize $1 with " &
|
||||
"the runtime value for the discriminator '$2' ") %
|
||||
[fields, discriminator.sym.name.s])
|
||||
mergeInitStatus(result, initNone)
|
||||
|
||||
template wrongBranchError(i) =
|
||||
@@ -241,30 +248,45 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||
"are in conflict with this value.",
|
||||
[discriminator.sym.name.s, discriminatorVal.renderTree, fields])
|
||||
|
||||
template valuesInConflictError(valsDiff) =
|
||||
localError(c.config, discriminatorVal.info, ("possible values " &
|
||||
"$2are in conflict with discriminator values for " &
|
||||
"selected object branch $1.") % [$selectedBranch,
|
||||
formatUnsafeBranchVals(recNode.sons[0].typ, valsDiff)])
|
||||
|
||||
let branchNode = recNode[selectedBranch]
|
||||
let flags = flags*{efAllowDestructor} + {efPreferStatic,
|
||||
efPreferNilResult}
|
||||
var discriminatorVal = semConstrField(c, flags,
|
||||
discriminator.sym, initExpr)
|
||||
|
||||
if discriminatorVal != nil:
|
||||
discriminatorVal = discriminatorVal.skipHidden
|
||||
if discriminatorVal.kind notin nkLiterals and (
|
||||
not isOrdinalType(discriminatorVal.typ, true) or
|
||||
lengthOrd(c.config, discriminatorVal.typ) > MaxSetElements or
|
||||
lengthOrd(c.config, recNode.sons[0].typ) > MaxSetElements):
|
||||
localError(c.config, discriminatorVal.info,
|
||||
"branch initialization with a runtime discriminator only " &
|
||||
"supports ordinal types with 2^16 elements or less.")
|
||||
|
||||
if discriminatorVal == nil:
|
||||
badDiscriminatorError()
|
||||
elif discriminatorVal.kind == nkSym:
|
||||
let (ctorCase, ctorIdx) = findUsefulCaseContext(c, discriminatorVal)
|
||||
if ctorCase == nil:
|
||||
badDiscriminatorError()
|
||||
if discriminatorVal.typ.kind == tyRange:
|
||||
let rangeVals = rangeTypVals(discriminatorVal.typ)
|
||||
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
|
||||
let diff = rangeVals - recBranchVals
|
||||
if diff.len != 0:
|
||||
valuesInConflictError(diff)
|
||||
else:
|
||||
badDiscriminatorError()
|
||||
elif discriminatorVal.sym.kind notin {skLet, skParam} or
|
||||
discriminatorVal.sym.typ.kind == tyVar:
|
||||
localError(c.config, discriminatorVal.info,
|
||||
"runtime discriminator must be immutable if branch fields are " &
|
||||
"initialized, a 'let' binding is required.")
|
||||
elif not isOrdinalType(discriminatorVal.sym.typ, true) or
|
||||
lengthOrd(c.config, discriminatorVal.sym.typ) > MaxSetElements:
|
||||
localError(c.config, discriminatorVal.info,
|
||||
"branch initialization with a runtime discriminator only " &
|
||||
"supports ordinal types with 2^16 elements or less.")
|
||||
elif ctorCase[ctorIdx].kind == nkElifBranch:
|
||||
localError(c.config, discriminatorVal.info, "branch initialization " &
|
||||
"with a runtime discriminator is not supported inside of an " &
|
||||
@@ -275,20 +297,27 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||
recBranchVals = branchVals(c, recNode, selectedBranch, false)
|
||||
branchValsDiff = ctorBranchVals - recBranchVals
|
||||
if branchValsDiff.len != 0:
|
||||
localError(c.config, discriminatorVal.info, ("possible values " &
|
||||
"$2are in conflict with discriminator values for " &
|
||||
"selected object branch $1.") % [$selectedBranch,
|
||||
formatUnsafeBranchVals(recNode.sons[0].typ, branchValsDiff)])
|
||||
valuesInConflictError(branchValsDiff)
|
||||
else:
|
||||
var failedBranch = -1
|
||||
if branchNode.kind != nkElse:
|
||||
if not branchNode.caseBranchMatchesExpr(discriminatorVal):
|
||||
wrongBranchError(selectedBranch)
|
||||
failedBranch = selectedBranch
|
||||
else:
|
||||
# With an else clause, check that all other branches don't match:
|
||||
for i in 1 .. (recNode.len - 2):
|
||||
if recNode[i].caseBranchMatchesExpr(discriminatorVal):
|
||||
wrongBranchError(i)
|
||||
failedBranch = i
|
||||
break
|
||||
if failedBranch != -1:
|
||||
if discriminatorVal.typ.kind == tyRange:
|
||||
let rangeVals = rangeTypVals(discriminatorVal.typ)
|
||||
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
|
||||
let diff = rangeVals - recBranchVals
|
||||
if diff.len != 0:
|
||||
valuesInConflictError(diff)
|
||||
else:
|
||||
wrongBranchError(failedBranch)
|
||||
|
||||
# When a branch is selected with a partial match, some of the fields
|
||||
# that were not initialized may be mandatory. We must check for this:
|
||||
@@ -310,7 +339,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||
result = initPartial
|
||||
if discriminatorVal.kind == nkIntLit:
|
||||
# When the discriminator is a compile-time value, we also know
|
||||
# which brach will be selected:
|
||||
# which branch will be selected:
|
||||
let matchedBranch = recNode.pickCaseBranch discriminatorVal
|
||||
if matchedBranch != nil: checkMissingFields matchedBranch
|
||||
else:
|
||||
@@ -351,7 +380,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned})
|
||||
if t.kind == tyRef:
|
||||
t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink, tyOwned})
|
||||
if optNimV2 in c.config.globalOptions:
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
# we have to watch out, there are also 'owned proc' types that can be used
|
||||
# multiple times as long as they don't have closures.
|
||||
|
||||
@@ -380,7 +380,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||
# Collect the exceptions caught by the except branches
|
||||
for i in 1 ..< n.len:
|
||||
let b = n.sons[i]
|
||||
let blen = sonsLen(b)
|
||||
let blen = len(b)
|
||||
if b.kind == nkExceptBranch:
|
||||
inc branches
|
||||
if blen == 1:
|
||||
@@ -398,7 +398,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||
# Add any other exception raised in the except bodies
|
||||
for i in 1 ..< n.len:
|
||||
let b = n.sons[i]
|
||||
let blen = sonsLen(b)
|
||||
let blen = len(b)
|
||||
if b.kind == nkExceptBranch:
|
||||
setLen(tracked.init, oldState)
|
||||
track(tracked, b.sons[blen-1])
|
||||
@@ -430,7 +430,7 @@ proc isForwardedProc(n: PNode): bool =
|
||||
result = n.kind == nkSym and sfForward in n.sym.flags
|
||||
|
||||
proc trackPragmaStmt(tracked: PEffects, n: PNode) =
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if whichPragma(it) == wEffects:
|
||||
# list the computed effects up to here:
|
||||
@@ -575,7 +575,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType; caller: PNode)
|
||||
notNilCheck(tracked, n, paramType)
|
||||
|
||||
proc breaksBlock(n: PNode): bool =
|
||||
# sematic check doesn't allow statements after raise, break, return or
|
||||
# semantic check doesn't allow statements after raise, break, return or
|
||||
# call to noreturn proc, so it is safe to check just the last statements
|
||||
var it = n
|
||||
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||
@@ -751,6 +751,9 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
discard
|
||||
else:
|
||||
message(tracked.config, arg.info, warnProveInit, $arg)
|
||||
# check required for 'nim check':
|
||||
if n[1].typ.len > 0:
|
||||
createTypeBoundOps(tracked.graph, tracked.c, n[1].typ.lastSon, n.info)
|
||||
for i in 0 ..< safeLen(n):
|
||||
track(tracked, n.sons[i])
|
||||
of nkDotExpr:
|
||||
|
||||
@@ -157,7 +157,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
result = n
|
||||
var typ = commonTypeBegin
|
||||
var hasElse = false
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it.len == 2:
|
||||
openScope(c)
|
||||
@@ -208,7 +208,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
n[0] = semExprBranchScope(c, n[0])
|
||||
typ = commonType(typ, n[0].typ)
|
||||
|
||||
var last = sonsLen(n) - 1
|
||||
var last = len(n) - 1
|
||||
var catchAllExcepts = 0
|
||||
|
||||
for i in 1 .. last:
|
||||
@@ -292,6 +292,8 @@ proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
|
||||
result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal)
|
||||
result.info = n.info
|
||||
result.typ = typ
|
||||
if not floatRangeCheck(result.floatVal, typ):
|
||||
localError(c.config, n.info, errFloatToString % [$result.floatVal, typeToString(typ)])
|
||||
else:
|
||||
changeType(c, r1, typ, check=true)
|
||||
result = r1
|
||||
@@ -361,13 +363,13 @@ proc isDiscardUnderscore(v: PSym): bool =
|
||||
proc semUsing(c: PContext; n: PNode): PNode =
|
||||
result = c.graph.emptyNode
|
||||
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "using")
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var length = sonsLen(a)
|
||||
var length = len(a)
|
||||
if a.sons[length-2].kind != nkEmpty:
|
||||
let typ = semTypeNode(c, a.sons[length-2], nil)
|
||||
for j in 0 .. length-3:
|
||||
@@ -414,7 +416,7 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
|
||||
if obj.kind == tyObject and tfPartial in obj.flags:
|
||||
let field = newSym(skField, getIdent(c.cache, y.s), obj.sym, n[1].info)
|
||||
field.typ = skipIntLit(typ)
|
||||
field.position = sonsLen(obj.n)
|
||||
field.position = len(obj.n)
|
||||
addSon(obj.n, newSymNode(field))
|
||||
n.sons[0] = makeDeref x
|
||||
n.sons[1] = newSymNode(field)
|
||||
@@ -435,13 +437,13 @@ proc setVarType(c: PContext; v: PSym, typ: PType) =
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var length = sonsLen(a)
|
||||
var length = len(a)
|
||||
|
||||
var typ: PType = nil
|
||||
if a.sons[length-2].kind != nkEmpty:
|
||||
@@ -500,7 +502,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if a.kind == nkVarTuple:
|
||||
if tup.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
elif length-2 != sonsLen(tup):
|
||||
elif length-2 != len(tup):
|
||||
localError(c.config, a.info, errWrongNumberOfVariables)
|
||||
b = newNodeI(nkVarTuple, a.info)
|
||||
newSons(b, length)
|
||||
@@ -581,13 +583,13 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
proc semConst(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
inc c.inStaticContext
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var length = sonsLen(a)
|
||||
var length = len(a)
|
||||
|
||||
var typ: PType = nil
|
||||
if a.sons[length-2].kind != nkEmpty:
|
||||
@@ -630,7 +632,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
if a.kind == nkVarTuple:
|
||||
if typ.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
elif length-2 != sonsLen(typ):
|
||||
elif length-2 != len(typ):
|
||||
localError(c.config, a.info, errWrongNumberOfVariables)
|
||||
b = newNodeI(nkVarTuple, a.info)
|
||||
newSons(b, length)
|
||||
@@ -673,28 +675,33 @@ proc symForVar(c: PContext, n: PNode): PSym =
|
||||
|
||||
proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
result = n
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
let iterBase = n.sons[length-2].typ
|
||||
var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink})
|
||||
var iterAfterVarLent = iter.skipTypes({tyLent, tyVar})
|
||||
# length == 3 means that there is one for loop variable
|
||||
# and thus no tuple unpacking:
|
||||
if iter.kind != tyTuple or length == 3:
|
||||
if iterAfterVarLent.kind != tyTuple or length == 3:
|
||||
if length == 3:
|
||||
if n.sons[0].kind == nkVarTuple:
|
||||
var mutable = false
|
||||
if iter.kind == tyVar:
|
||||
iter = iter.skipTypes({tyVar})
|
||||
mutable = true
|
||||
if sonsLen(n[0])-1 != sonsLen(iter):
|
||||
if len(n[0])-1 != len(iterAfterVarLent):
|
||||
localError(c.config, n[0].info, errWrongNumberOfVariables)
|
||||
for i in 0 ..< sonsLen(n[0])-1:
|
||||
for i in 0 ..< len(n[0])-1:
|
||||
var v = symForVar(c, n[0][i])
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
if mutable:
|
||||
v.typ = newTypeS(tyVar, c)
|
||||
v.typ.sons.add iter[i]
|
||||
else:
|
||||
v.typ = iter.sons[i]
|
||||
case iter.kind
|
||||
of tyVar:
|
||||
v.typ = newTypeS(tyVar, c)
|
||||
v.typ.sons.add iterAfterVarLent[i]
|
||||
if tfVarIsPtr in iter.flags:
|
||||
v.typ.flags.incl tfVarIsPtr
|
||||
of tyLent:
|
||||
v.typ = newTypeS(tyLent, c)
|
||||
v.typ.sons.add iterAfterVarLent[i]
|
||||
if tfVarIsPtr in iter.flags:
|
||||
v.typ.flags.incl tfVarIsPtr
|
||||
else:
|
||||
v.typ = iter.sons[i]
|
||||
n.sons[0][i] = newSymNode(v)
|
||||
if sfGenSym notin v.flags: addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
@@ -710,23 +717,33 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
else:
|
||||
localError(c.config, n.info, errWrongNumberOfVariables)
|
||||
elif length-2 != sonsLen(iter):
|
||||
elif length-2 != len(iterAfterVarLent):
|
||||
localError(c.config, n.info, errWrongNumberOfVariables)
|
||||
else:
|
||||
for i in 0 .. length - 3:
|
||||
if n.sons[i].kind == nkVarTuple:
|
||||
var mutable = false
|
||||
if iter[i].kind == tyVar:
|
||||
iter[i] = iter[i].skipTypes({tyVar})
|
||||
mutable = true
|
||||
if sonsLen(n[i])-1 != sonsLen(iter[i]):
|
||||
var isLent = false
|
||||
iter[i] = case iter[i].kind
|
||||
of tyVar:
|
||||
mutable = true
|
||||
iter[i].skipTypes({tyVar})
|
||||
of tyLent:
|
||||
isLent = true
|
||||
iter[i].skipTypes({tyLent})
|
||||
else: iter[i]
|
||||
|
||||
if len(n[i])-1 != len(iter[i]):
|
||||
localError(c.config, n[i].info, errWrongNumberOfVariables)
|
||||
for j in 0 ..< sonsLen(n[i])-1:
|
||||
for j in 0 ..< len(n[i])-1:
|
||||
var v = symForVar(c, n[i][j])
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
if mutable:
|
||||
v.typ = newTypeS(tyVar, c)
|
||||
v.typ.sons.add iter[i][j]
|
||||
elif isLent:
|
||||
v.typ = newTypeS(tyLent, c)
|
||||
v.typ.sons.add iter[i][j]
|
||||
else:
|
||||
v.typ = iter[i][j]
|
||||
n.sons[i][j] = newSymNode(v)
|
||||
@@ -735,7 +752,19 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
else:
|
||||
var v = symForVar(c, n.sons[i])
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
v.typ = iter.sons[i]
|
||||
case iter.kind
|
||||
of tyVar:
|
||||
v.typ = newTypeS(tyVar, c)
|
||||
v.typ.sons.add iterAfterVarLent[i]
|
||||
if tfVarIsPtr in iter.flags:
|
||||
v.typ.flags.incl tfVarIsPtr
|
||||
of tyLent:
|
||||
v.typ = newTypeS(tyLent, c)
|
||||
v.typ.sons.add iterAfterVarLent[i]
|
||||
if tfVarIsPtr in iter.flags:
|
||||
v.typ.flags.incl tfVarIsPtr
|
||||
else:
|
||||
v.typ = iter.sons[i]
|
||||
n.sons[i] = newSymNode(v)
|
||||
if sfGenSym notin v.flags:
|
||||
if not isDiscardUnderscore(v): addDecl(c, v)
|
||||
@@ -763,7 +792,8 @@ proc isTrivalStmtExpr(n: PNode): bool =
|
||||
return false
|
||||
result = true
|
||||
|
||||
proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string): PNode =
|
||||
proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string;
|
||||
flags: TExprFlags): PNode =
|
||||
if selector.kind in nkCallKinds:
|
||||
# we transform
|
||||
# n := for a, b, c in m(x, y, z): Y
|
||||
@@ -792,14 +822,14 @@ proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string): PNode
|
||||
callExpr.add newSymNode(match)
|
||||
callExpr.add n
|
||||
case match.kind
|
||||
of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, {})
|
||||
of skTemplate: result = semTemplateExpr(c, callExpr, match, {})
|
||||
of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, flags)
|
||||
of skTemplate: result = semTemplateExpr(c, callExpr, match, flags)
|
||||
else: result = nil
|
||||
|
||||
proc handleForLoopMacro(c: PContext; n: PNode): PNode =
|
||||
result = handleStmtMacro(c, n, n[^2], "ForLoopStmt")
|
||||
proc handleForLoopMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
result = handleStmtMacro(c, n, n[^2], "ForLoopStmt", flags)
|
||||
|
||||
proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
|
||||
proc handleCaseStmtMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
# n[0] has been sem'checked and has a type. We use this to resolve
|
||||
# 'match(n[0])' but then we pass 'n' to the 'match' macro. This seems to
|
||||
# be the best solution.
|
||||
@@ -812,15 +842,15 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
|
||||
errors, false)
|
||||
if r.state == csMatch:
|
||||
var match = r.calleeSym
|
||||
markUsed(c.config, n[0].info, match, c.graph.usageSym)
|
||||
markUsed(c, n[0].info, match)
|
||||
onUse(n[0].info, match)
|
||||
|
||||
# but pass 'n' to the 'match' macro, not 'n[0]':
|
||||
r.call.sons[1] = n
|
||||
let toExpand = semResolvedCall(c, r, r.call, {})
|
||||
case match.kind
|
||||
of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, {})
|
||||
of skTemplate: result = semTemplateExpr(c, toExpand, match, {})
|
||||
of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, flags)
|
||||
of skTemplate: result = semTemplateExpr(c, toExpand, match, flags)
|
||||
else: result = nil
|
||||
# this would be the perfectly consistent solution with 'for loop macros',
|
||||
# but it kinda sucks for pattern matching as the matcher is not attached to
|
||||
@@ -830,9 +860,9 @@ proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
|
||||
|
||||
proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
checkMinSonsLen(n, 3, c.config)
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
if forLoopMacros in c.features:
|
||||
result = handleForLoopMacro(c, n)
|
||||
result = handleForLoopMacro(c, n, flags)
|
||||
if result != nil: return result
|
||||
openScope(c)
|
||||
result = n
|
||||
@@ -895,12 +925,12 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
popCaseContext(c)
|
||||
closeScope(c)
|
||||
if caseStmtMacros in c.features:
|
||||
result = handleCaseStmtMacro(c, n)
|
||||
result = handleCaseStmtMacro(c, n, flags)
|
||||
if result != nil:
|
||||
return result
|
||||
localError(c.config, n.sons[0].info, errSelectorMustBeOfCertainTypes)
|
||||
return
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
setCaseContextIdx(c, i)
|
||||
var x = n.sons[i]
|
||||
when defined(nimsuggest):
|
||||
@@ -910,7 +940,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
of nkOfBranch:
|
||||
checkMinSonsLen(x, 2, c.config)
|
||||
semCaseBranch(c, n, x, i, covered)
|
||||
var last = sonsLen(x)-1
|
||||
var last = len(x)-1
|
||||
x.sons[last] = semExprBranchScope(c, x.sons[last])
|
||||
typ = commonType(typ, x.sons[last])
|
||||
of nkElifBranch:
|
||||
@@ -971,7 +1001,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
|
||||
|
||||
proc addGenericParamListToScope(c: PContext, n: PNode) =
|
||||
if n.kind != nkGenericParams: illFormedAst(n, c.config)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkSym: addDecl(c, a.sym)
|
||||
else: illFormedAst(a, c.config)
|
||||
@@ -988,7 +1018,7 @@ proc typeSectionTypeName(c: PContext; n: PNode): PNode =
|
||||
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
||||
# process the symbols on the left side for the whole type section, before
|
||||
# we even look at the type definitions on the right
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
when defined(nimsuggest):
|
||||
if c.config.cmd == cmdIdeTools:
|
||||
@@ -1120,7 +1150,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
|
||||
discard traverseSubTypes(c, body)
|
||||
|
||||
proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind != nkTypeDef: illFormedAst(a, c.config)
|
||||
@@ -1157,7 +1187,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
if body != nil:
|
||||
body.sym = s
|
||||
body.size = -1 # could not be computed properly
|
||||
s.typ.sons[sonsLen(s.typ) - 1] = body
|
||||
s.typ.sons[len(s.typ) - 1] = body
|
||||
if tfCovariant in s.typ.flags:
|
||||
checkCovariantParamsUsages(c, s.typ)
|
||||
# XXX: This is a temporary limitation:
|
||||
@@ -1247,7 +1277,7 @@ proc checkForMetaFields(c: PContext; n: PNode) =
|
||||
internalAssert c.config, false
|
||||
|
||||
proc typeSectionFinalPass(c: PContext, n: PNode) =
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
let name = typeSectionTypeName(c, a.sons[0])
|
||||
@@ -1345,7 +1375,7 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
|
||||
s.typ = semProcTypeNode(c, n, genericParams, nil, s.kind)
|
||||
|
||||
proc addParams(c: PContext, n: PNode, kind: TSymKind) =
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
|
||||
else: illFormedAst(n, c.config)
|
||||
|
||||
@@ -1420,8 +1450,13 @@ proc semProcAnnotation(c: PContext, prc: PNode;
|
||||
continue
|
||||
|
||||
doAssert r.sons[0].kind == nkSym
|
||||
# Expand the macro here
|
||||
result = semMacroExpr(c, r, r, r.sons[0].sym, {})
|
||||
let m = r.sons[0].sym
|
||||
case m.kind
|
||||
of skMacro: result = semMacroExpr(c, r, r, m, {})
|
||||
of skTemplate: result = semTemplateExpr(c, r, m, {})
|
||||
else:
|
||||
prc.sons[pragmasPos] = n
|
||||
continue
|
||||
|
||||
doAssert result != nil
|
||||
|
||||
@@ -1469,7 +1504,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[paramsPos], gp, s)
|
||||
# paramsTypeCheck(c, s.typ)
|
||||
if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
|
||||
if len(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
|
||||
# we have a list of implicit type parameters:
|
||||
n.sons[genericParamsPos] = gp
|
||||
else:
|
||||
@@ -1497,7 +1532,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
closeScope(c) # close scope for parameters
|
||||
popOwner(c)
|
||||
result.typ = s.typ
|
||||
if optNimV2 in c.config.globalOptions:
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
|
||||
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
|
||||
@@ -1534,7 +1569,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
|
||||
popProcCon(c)
|
||||
popOwner(c)
|
||||
closeScope(c)
|
||||
if optNimV2 in c.config.globalOptions and result.typ != nil:
|
||||
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
# alternative variant (not quite working):
|
||||
# var prc = arg[0].sym
|
||||
@@ -1593,7 +1628,9 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
else: break
|
||||
if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
|
||||
obj = canonType(c, obj)
|
||||
if obj.destructor.isNil:
|
||||
if obj.attachedOps[attachedDestructor] == s:
|
||||
discard "forward declared destructor"
|
||||
elif obj.destructor.isNil and tfCheckedForDestructor notin obj.flags:
|
||||
obj.attachedOps[attachedDestructor] = s
|
||||
else:
|
||||
prevDestructor(c, obj.destructor, obj, n.info)
|
||||
@@ -1658,7 +1695,9 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
obj = canonType(c, obj)
|
||||
#echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj)
|
||||
let k = if name == "=": attachedAsgn else: attachedSink
|
||||
if obj.attachedOps[k].isNil:
|
||||
if obj.attachedOps[k] == s:
|
||||
discard "forward declared op"
|
||||
elif obj.attachedOps[k].isNil and tfCheckedForDestructor notin obj.flags:
|
||||
obj.attachedOps[k] = s
|
||||
else:
|
||||
prevDestructor(c, obj.attachedOps[k], obj, n.info)
|
||||
@@ -1691,7 +1730,7 @@ type
|
||||
|
||||
proc hasObjParam(s: PSym): bool =
|
||||
var t = s.typ
|
||||
for col in 1 ..< sonsLen(t):
|
||||
for col in 1 ..< len(t):
|
||||
if skipTypes(t.sons[col], skipPtrs).kind == tyObject:
|
||||
return true
|
||||
|
||||
@@ -1705,7 +1744,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
|
||||
var foundObj = false
|
||||
# we start at 1 for now so that tparsecombnum continues to compile.
|
||||
# XXX Revisit this problem later.
|
||||
for col in 1 ..< sonsLen(tt):
|
||||
for col in 1 ..< len(tt):
|
||||
let t = tt.sons[col]
|
||||
if t != nil and t.kind == tyGenericInvocation:
|
||||
var x = skipTypes(t.sons[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
|
||||
@@ -1778,7 +1817,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
# process parameters:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[paramsPos], gp, s)
|
||||
if sonsLen(gp) > 0:
|
||||
if len(gp) > 0:
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
# we have a list of implicit type parameters:
|
||||
n.sons[genericParamsPos] = gp
|
||||
@@ -1878,7 +1917,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
else:
|
||||
pushProcCon(c, s)
|
||||
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
|
||||
if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
|
||||
if not usePseudoGenerics and s.magic == mNone: paramsTypeCheck(c, s.typ)
|
||||
|
||||
c.p.wasForwarded = proto != nil
|
||||
maybeAddResult(c, s, n)
|
||||
@@ -1904,6 +1943,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
discard
|
||||
popProcCon(c)
|
||||
else:
|
||||
if s.kind in {skProc, skFunc} and s.typ[0] != nil and s.typ[0].kind == tyUntyped:
|
||||
# `auto` is represented as `tyUntyped` at this point in compilation.
|
||||
localError(c.config, n[paramsPos][0].info, "return type 'auto' cannot be used in forward declarations")
|
||||
|
||||
if s.kind == skMethod: semMethodPrototype(c, s, n)
|
||||
if proto != nil: localError(c.config, n.info, errImplOfXexpected % proto.name.s)
|
||||
if {sfImportc, sfBorrow, sfError} * s.flags == {} and s.magic == mNone:
|
||||
@@ -1918,7 +1961,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if isAnon:
|
||||
n.kind = nkLambda
|
||||
result.typ = s.typ
|
||||
if optNimV2 in c.config.globalOptions:
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
if isTopLevel(c) and s.kind != skIterator and
|
||||
s.typ.callConv == ccClosure:
|
||||
@@ -1998,7 +2041,7 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: localError(c.config, n.info, errXNeedsReturnType % "converter")
|
||||
if sonsLen(t) != 2: localError(c.config, n.info, "a converter takes exactly one argument")
|
||||
if len(t) != 2: localError(c.config, n.info, "a converter takes exactly one argument")
|
||||
addConverter(c, s)
|
||||
|
||||
proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
@@ -2032,9 +2075,11 @@ proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
|
||||
proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
addSon(result, n)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var imp: PNode
|
||||
let it = n.sons[i]
|
||||
if it.kind == nkInfix and it.len == 3 and it[0].ident.s != "/":
|
||||
localError(c.config, it.info, "Cannot use '" & it[0].ident.s & "' in 'include'.")
|
||||
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
|
||||
let sep = it[0]
|
||||
let dir = it[1]
|
||||
@@ -2111,7 +2156,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
||||
result = n
|
||||
result.kind = nkStmtList
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
var voidContext = false
|
||||
var last = length-1
|
||||
# by not allowing for nkCommentStmt etc. we ensure nkStmtListExpr actually
|
||||
|
||||
@@ -34,7 +34,7 @@ type
|
||||
spNone, spGenSym, spInject
|
||||
|
||||
proc symBinding(n: PNode): TSymBinding =
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||
if key.kind == nkIdent:
|
||||
@@ -47,7 +47,8 @@ type
|
||||
TSymChoiceRule = enum
|
||||
scClosed, scOpen, scForceOpen
|
||||
|
||||
proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
|
||||
proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
isField = false): PNode =
|
||||
var
|
||||
a: PSym
|
||||
o: TOverloadIter
|
||||
@@ -63,9 +64,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
|
||||
# XXX this makes more sense but breaks bootstrapping for now:
|
||||
# (s.kind notin routineKinds or s.magic != mNone):
|
||||
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
|
||||
result = newSymNode(s, info)
|
||||
markUsed(c.config, info, s, c.graph.usageSym)
|
||||
onUse(info, s)
|
||||
if not isField or sfGenSym notin s.flags:
|
||||
result = newSymNode(s, info)
|
||||
markUsed(c, info, s)
|
||||
onUse(info, s)
|
||||
else:
|
||||
result = n
|
||||
else:
|
||||
# semantic checking requires a type; ``fitNode`` deals with it
|
||||
# appropriately
|
||||
@@ -74,8 +78,9 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
|
||||
result = newNodeIT(kind, info, newTypeS(tyNone, c))
|
||||
a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
if a.kind != skModule:
|
||||
if a.kind != skModule and (not isField or sfGenSym notin s.flags):
|
||||
incl(a.flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, a)
|
||||
addSon(result, newSymNode(a, info))
|
||||
onUse(info, a)
|
||||
a = nextOverloadIter(o, c, n)
|
||||
@@ -119,6 +124,8 @@ type
|
||||
owner: PSym
|
||||
cursorInBody: bool # only for nimsuggest
|
||||
scopeN: int
|
||||
noGenSym: int
|
||||
inTemplateHeader: int
|
||||
|
||||
template withBracketExpr(ctx, x, body: untyped) =
|
||||
body
|
||||
@@ -138,9 +145,12 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
|
||||
illFormedAst(n, c.c.config)
|
||||
result = n
|
||||
|
||||
template oldCheck(cx: TemplCtx; cond: bool): bool =
|
||||
(optNimV019 notin cx.c.config.globalOptions or cond)
|
||||
|
||||
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
||||
result = n.kind == nkSym and n.sym.kind == skParam and
|
||||
n.sym.owner == c.owner and sfGenSym notin n.sym.flags
|
||||
n.sym.owner == c.owner and sfTemplateParam in n.sym.flags
|
||||
|
||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
||||
|
||||
@@ -197,7 +207,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||
else:
|
||||
replaceIdentBySym(c.c, n, ident)
|
||||
else:
|
||||
if (n.kind == nkPragmaExpr and sonsLen(n) >= 2 and n.sons[1].kind == nkPragma):
|
||||
if (n.kind == nkPragmaExpr and len(n) >= 2 and n.sons[1].kind == nkPragma):
|
||||
let pragmaNode = n.sons[1]
|
||||
for i in 0..<pragmaNode.sons.len:
|
||||
openScope(c)
|
||||
@@ -225,11 +235,17 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||
styleCheckDef(c.c.config, n.info, local)
|
||||
onDef(n.info, local)
|
||||
replaceIdentBySym(c.c, n, newSymNode(local, n.info))
|
||||
if k == skParam and c.inTemplateHeader > 0:
|
||||
local.flags.incl sfTemplateParam
|
||||
else:
|
||||
replaceIdentBySym(c.c, n, ident)
|
||||
|
||||
proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode =
|
||||
incl(s.flags, sfUsed)
|
||||
# bug #12885; ideally sem'checking is performed again afterwards marking
|
||||
# the symbol as used properly, but the nfSem mechanism currently prevents
|
||||
# that from happening, so we mark the module as used here already:
|
||||
markOwnerModuleAsUsed(c, s)
|
||||
# we do not call onUse here, as the identifier is not really
|
||||
# resolved here. We will fixup the used identifiers later.
|
||||
case s.kind
|
||||
@@ -237,15 +253,23 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||
# Introduced in this pass! Leave it as an identifier.
|
||||
result = n
|
||||
of OverloadableSyms:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
result = symChoice(c, n, s, scOpen, isField)
|
||||
of skGenericParam:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else: result = newSymNodeTypeDesc(s, n.info)
|
||||
of skParam:
|
||||
result = n
|
||||
of skType:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else: result = newSymNodeTypeDesc(s, n.info)
|
||||
else:
|
||||
result = newSymNode(s, n.info)
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else: result = newSymNode(s, n.info)
|
||||
# Issue #12832
|
||||
when defined(nimsuggest):
|
||||
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
|
||||
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
|
||||
styleCheckUse(c.config, n.info, s)
|
||||
|
||||
proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -279,7 +303,14 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
|
||||
n.sons[namePos] = semRoutineInTemplName(c, n.sons[namePos])
|
||||
# open scope for parameters
|
||||
openScope(c)
|
||||
for i in patternPos..miscPos:
|
||||
for i in patternPos..paramsPos-1:
|
||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||
|
||||
if k == skTemplate: inc(c.inTemplateHeader)
|
||||
n.sons[paramsPos] = semTemplBody(c, n.sons[paramsPos])
|
||||
if k == skTemplate: dec(c.inTemplateHeader)
|
||||
|
||||
for i in paramsPos+1..miscPos:
|
||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||
# open scope for locals
|
||||
inc c.scopeN
|
||||
@@ -292,12 +323,12 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
|
||||
closeScope(c)
|
||||
|
||||
proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) =
|
||||
for i in start ..< sonsLen(n):
|
||||
for i in start ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a, c.c.config)
|
||||
checkMinSonsLen(a, 3, c.c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
when defined(nimsuggest):
|
||||
inc c.c.inTypeContext
|
||||
a.sons[L-2] = semTemplBody(c, a.sons[L-2])
|
||||
@@ -322,22 +353,23 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
if n.ident.id in c.toInject: return n
|
||||
let s = qualifiedLookUp(c.c, n, {})
|
||||
if s != nil:
|
||||
if s.owner == c.owner and s.kind == skParam:
|
||||
if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
|
||||
# oldCheck(c, sfGenSym notin s.flags or c.noGenSym == 0):
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
onUse(n.info, s)
|
||||
elif contains(c.toBind, s.id):
|
||||
result = symChoice(c.c, n, s, scClosed)
|
||||
result = symChoice(c.c, n, s, scClosed, c.noGenSym > 0)
|
||||
elif contains(c.toMixin, s.name.id):
|
||||
result = symChoice(c.c, n, s, scForceOpen)
|
||||
elif s.owner == c.owner and sfGenSym in s.flags:
|
||||
result = symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
|
||||
elif s.owner == c.owner and sfGenSym in s.flags and c.noGenSym == 0:
|
||||
# template tmp[T](x: var seq[T]) =
|
||||
# var yz: T
|
||||
incl(s.flags, sfUsed)
|
||||
result = newSymNode(s, n.info)
|
||||
onUse(n.info, s)
|
||||
else:
|
||||
result = semTemplSymbol(c.c, n, s)
|
||||
result = semTemplSymbol(c.c, n, s, c.noGenSym > 0)
|
||||
of nkBind:
|
||||
result = semTemplBody(c, n.sons[0])
|
||||
of nkBindStmt:
|
||||
@@ -348,7 +380,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
of nkEmpty, nkSym..nkNilLit, nkComesFrom:
|
||||
discard
|
||||
of nkIfStmt:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it.len == 2:
|
||||
openScope(c)
|
||||
@@ -359,27 +391,27 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
n.sons[i] = semTemplBodyScope(c, it)
|
||||
of nkWhileStmt:
|
||||
openScope(c)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||
closeScope(c)
|
||||
of nkCaseStmt:
|
||||
openScope(c)
|
||||
n.sons[0] = semTemplBody(c, n.sons[0])
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
checkMinSonsLen(a, 1, c.c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
for j in 0 .. L-2:
|
||||
a.sons[j] = semTemplBody(c, a.sons[j])
|
||||
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
||||
closeScope(c)
|
||||
of nkForStmt, nkParForStmt:
|
||||
var L = sonsLen(n)
|
||||
var L = len(n)
|
||||
openScope(c)
|
||||
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
|
||||
for i in 0 .. L - 3:
|
||||
if n[i].kind == nkVarTuple:
|
||||
for j in 0 ..< sonsLen(n[i])-1:
|
||||
for j in 0 ..< len(n[i])-1:
|
||||
addLocalDecl(c, n[i][j], skForVar)
|
||||
else:
|
||||
addLocalDecl(c, n.sons[i], skForVar)
|
||||
@@ -404,10 +436,10 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
of nkTryStmt, nkHiddenTryStmt:
|
||||
checkMinSonsLen(n, 2, c.c.config)
|
||||
n.sons[0] = semTemplBodyScope(c, n.sons[0])
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
checkMinSonsLen(a, 1, c.c.config)
|
||||
var L = sonsLen(a)
|
||||
var L = len(a)
|
||||
openScope(c)
|
||||
for j in 0 .. L-2:
|
||||
if a.sons[j].isInfixAs():
|
||||
@@ -424,7 +456,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
n.sons[0] = semTemplBody(c, n.sons[0])
|
||||
semTemplSomeDecl(c, n, skParam, 1)
|
||||
of nkConstSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkConstDef): illFormedAst(a, c.c.config)
|
||||
@@ -433,13 +465,13 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
a.sons[1] = semTemplBody(c, a.sons[1])
|
||||
a.sons[2] = semTemplBody(c, a.sons[2])
|
||||
of nkTypeSection:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
|
||||
checkSonsLen(a, 3, c.c.config)
|
||||
addLocalDecl(c, a.sons[0], skType)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
|
||||
@@ -524,12 +556,27 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
onUse(n.info, s)
|
||||
return newSymNode(s, n.info)
|
||||
elif contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
return symChoice(c.c, n, s, scClosed, c.noGenSym > 0)
|
||||
elif contains(c.toMixin, s.name.id):
|
||||
return symChoice(c.c, n, s, scForceOpen)
|
||||
return symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0)
|
||||
else:
|
||||
return symChoice(c.c, n, s, scOpen)
|
||||
result = semTemplBodySons(c, n)
|
||||
return symChoice(c.c, n, s, scOpen, c.noGenSym > 0)
|
||||
if n.kind == nkDotExpr:
|
||||
result = n
|
||||
result.sons[0] = semTemplBody(c, n.sons[0])
|
||||
if optNimV019 notin c.c.config.globalOptions: inc c.noGenSym
|
||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||
if optNimV019 notin c.c.config.globalOptions: dec c.noGenSym
|
||||
else:
|
||||
result = semTemplBodySons(c, n)
|
||||
of nkExprColonExpr, nkExprEqExpr:
|
||||
if n.len == 2:
|
||||
if optNimV019 notin c.c.config.globalOptions: inc c.noGenSym
|
||||
result.sons[0] = semTemplBody(c, n.sons[0])
|
||||
if optNimV019 notin c.c.config.globalOptions: dec c.noGenSym
|
||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||
else:
|
||||
result = semTemplBodySons(c, n)
|
||||
else:
|
||||
result = semTemplBodySons(c, n)
|
||||
|
||||
@@ -558,7 +605,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||
if s != nil and contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
result = n
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
|
||||
|
||||
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
@@ -600,9 +647,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
# body by the absence of the sfGenSym flag:
|
||||
for i in 1 .. s.typ.n.len-1:
|
||||
let param = s.typ.n.sons[i].sym
|
||||
param.flags.incl sfTemplateParam
|
||||
param.flags.excl sfGenSym
|
||||
if param.typ.kind != tyUntyped: allUntyped = false
|
||||
if sonsLen(gp) > 0:
|
||||
if len(gp) > 0:
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
# we have a list of implicit type parameters:
|
||||
n.sons[genericParamsPos] = gp
|
||||
@@ -715,7 +763,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||
if stupidStmtListExpr(n):
|
||||
result = semPatternBody(c, n.lastSon)
|
||||
else:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = semPatternBody(c, n.sons[i])
|
||||
of nkCallKinds:
|
||||
let s = qualifiedLookUp(c.c, n.sons[0], {})
|
||||
@@ -748,7 +796,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||
return
|
||||
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = semPatternBody(c, n.sons[i])
|
||||
else:
|
||||
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
||||
@@ -764,7 +812,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||
of nkPar:
|
||||
if n.len == 1: return semPatternBody(c, n.sons[0])
|
||||
else: discard
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
result.sons[i] = semPatternBody(c, n.sons[i])
|
||||
|
||||
proc semPattern(c: PContext, n: PNode): PNode =
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
# this module does the semantic checking of type declarations
|
||||
# included from sem.nim
|
||||
|
||||
import math
|
||||
|
||||
const
|
||||
errStringOrIdentNodeExpected = "string or ident node expected"
|
||||
errStringLiteralExpected = "string literal expected"
|
||||
@@ -52,8 +54,8 @@ proc newConstraint(c: PContext, k: TTypeKind): PType =
|
||||
result.addSonSkipIntLit(newTypeS(k, c))
|
||||
|
||||
proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
if n.sonsLen == 0: return newConstraint(c, tyEnum)
|
||||
elif n.sonsLen == 1:
|
||||
if n.len == 0: return newConstraint(c, tyEnum)
|
||||
elif n.len == 1:
|
||||
# don't create an empty tyEnum; fixes #3052
|
||||
return errorType(c)
|
||||
var
|
||||
@@ -69,13 +71,13 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
base = semTypeNode(c, n.sons[0].sons[0], nil)
|
||||
if base.kind != tyEnum:
|
||||
localError(c.config, n.sons[0].info, "inheritance only works with an enum")
|
||||
counter = lastOrd(c.config, base) + 1
|
||||
counter = toInt64(lastOrd(c.config, base)) + 1
|
||||
rawAddSon(result, base)
|
||||
let isPure = result.sym != nil and sfPure in result.sym.flags
|
||||
var symbols: TStrTable
|
||||
if isPure: initStrTable(symbols)
|
||||
var hasNull = false
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
if n.sons[i].kind == nkEmpty: continue
|
||||
case n.sons[i].kind
|
||||
of nkEnumFieldDef:
|
||||
@@ -88,12 +90,12 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
var strVal: PNode = nil
|
||||
case skipTypes(v.typ, abstractInst-{tyTypeDesc}).kind
|
||||
of tyTuple:
|
||||
if sonsLen(v) == 2:
|
||||
if len(v) == 2:
|
||||
strVal = v.sons[1] # second tuple part is the string value
|
||||
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
|
||||
if not isOrdinalType(v.sons[0].typ, allowEnumWithHoles=true):
|
||||
localError(c.config, v.sons[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v.sons[0].typ, preferDesc))
|
||||
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
|
||||
x = toInt64(getOrdValue(v.sons[0])) # first tuple part is the ordinal
|
||||
else:
|
||||
localError(c.config, strVal.info, errStringLiteralExpected)
|
||||
else:
|
||||
@@ -104,7 +106,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
else:
|
||||
if not isOrdinalType(v.typ, allowEnumWithHoles=true):
|
||||
localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
|
||||
x = getOrdValue(v)
|
||||
x = toInt64(getOrdValue(v))
|
||||
if i != 1:
|
||||
if x != counter: incl(result.flags, tfEnumHasHoles)
|
||||
if x < counter:
|
||||
@@ -141,7 +143,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
|
||||
proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tySet, prev, c)
|
||||
if sonsLen(n) == 2 and n.sons[1].kind != nkEmpty:
|
||||
if len(n) == 2 and n.sons[1].kind != nkEmpty:
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
addSonSkipIntLit(result, base)
|
||||
if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
|
||||
@@ -155,7 +157,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
addSonSkipIntLit(result, errorType(c))
|
||||
|
||||
proc semContainerArg(c: PContext; n: PNode, kindStr: string; result: PType) =
|
||||
if sonsLen(n) == 2:
|
||||
if len(n) == 2:
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
if base.kind == tyVoid:
|
||||
localError(c.config, n.info, errTIsNotAConcreteType % typeToString(base))
|
||||
@@ -171,17 +173,17 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
|
||||
proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyVarargs, prev, c)
|
||||
if sonsLen(n) == 2 or sonsLen(n) == 3:
|
||||
if len(n) == 2 or len(n) == 3:
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
addSonSkipIntLit(result, base)
|
||||
if sonsLen(n) == 3:
|
||||
if len(n) == 3:
|
||||
result.n = newIdentNode(considerQuotedIdent(c, n.sons[2]), n.sons[2].info)
|
||||
else:
|
||||
localError(c.config, n.info, errXExpectsOneTypeParam % "varargs")
|
||||
addSonSkipIntLit(result, errorType(c))
|
||||
|
||||
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
|
||||
if sonsLen(n) == 1:
|
||||
if len(n) == 1:
|
||||
result = newOrPrevType(tyVar, prev, c)
|
||||
var base = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
|
||||
if base.kind == tyVar:
|
||||
@@ -223,7 +225,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
if not hasUnknownTypes:
|
||||
if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})):
|
||||
localError(c.config, n.info, "type mismatch")
|
||||
elif not rangeT[0].isOrdinalType and rangeT[0].kind notin tyFloat..tyFloat128 or
|
||||
elif not isOrdinalType(rangeT[0]) and rangeT[0].kind notin tyFloat..tyFloat128 or
|
||||
rangeT[0].kind == tyBool:
|
||||
localError(c.config, n.info, "ordinal or float type expected")
|
||||
elif enumHasHoles(rangeT[0]):
|
||||
@@ -236,6 +238,10 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
else:
|
||||
result.n.addSon semConstExpr(c, range[i])
|
||||
|
||||
if (result.n[0].kind in {nkFloatLit..nkFloat64Lit} and classify(result.n[0].floatVal) == fcNan) or
|
||||
(result.n[1].kind in {nkFloatLit..nkFloat64Lit} and classify(result.n[1].floatVal) == fcNan):
|
||||
localError(c.config, n.info, "NaN is not a valid start or end for a range")
|
||||
|
||||
if weakLeValue(result.n[0], result.n[1]) == impNo:
|
||||
localError(c.config, n.info, "range is empty")
|
||||
|
||||
@@ -243,7 +249,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
|
||||
proc semRange(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = nil
|
||||
if sonsLen(n) == 2:
|
||||
if len(n) == 2:
|
||||
if isRange(n[1]):
|
||||
result = semRangeAux(c, n[1], prev)
|
||||
let n = result.n
|
||||
@@ -309,7 +315,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base: PType
|
||||
if sonsLen(n) == 3:
|
||||
if len(n) == 3:
|
||||
# 3 = length(array indx base)
|
||||
let indx = semArrayIndex(c, n[1])
|
||||
var indxB = indx
|
||||
@@ -335,7 +341,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
|
||||
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyOrdinal, prev, c)
|
||||
if sonsLen(n) == 2:
|
||||
if len(n) == 2:
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
if base.kind != tyGenericParam:
|
||||
if not isOrdinalType(base):
|
||||
@@ -353,7 +359,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
if result.isNil:
|
||||
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
|
||||
if result != nil:
|
||||
markUsed(c.config, n.info, result, c.graph.usageSym)
|
||||
markUsed(c, n.info, result)
|
||||
onUse(n.info, result)
|
||||
|
||||
if result.kind == skParam and result.typ.kind == tyTypeDesc:
|
||||
@@ -408,7 +414,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
result = errorSym(c, n)
|
||||
|
||||
proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
if sonsLen(n) == 0:
|
||||
if len(n) == 0:
|
||||
localError(c.config, n.info, errTypeExpected)
|
||||
result = newOrPrevType(tyTuple, prev, c)
|
||||
for it in n:
|
||||
@@ -420,11 +426,11 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
result.n = newNodeI(nkRecList, n.info)
|
||||
var check = initIntSet()
|
||||
var counter = 0
|
||||
for i in ord(n.kind == nkBracketExpr) ..< sonsLen(n):
|
||||
for i in ord(n.kind == nkBracketExpr) ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
|
||||
checkMinSonsLen(a, 3, c.config)
|
||||
var length = sonsLen(a)
|
||||
var length = len(a)
|
||||
if a.sons[length - 2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a.sons[length - 2], nil)
|
||||
else:
|
||||
@@ -454,7 +460,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
allowed: TSymFlags): PSym =
|
||||
# identifier with visibility
|
||||
if n.kind == nkPostfix:
|
||||
if sonsLen(n) == 2:
|
||||
if len(n) == 2:
|
||||
# for gensym'ed identifiers the identifier may already have been
|
||||
# transformed to a symbol and we need to use that here:
|
||||
result = newSymG(kind, n.sons[1], c)
|
||||
@@ -491,7 +497,7 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||
proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
|
||||
let ex = t[branchIndex][currentEx].skipConv
|
||||
for i in 1 .. branchIndex:
|
||||
for j in 0 .. sonsLen(t.sons[i]) - 2:
|
||||
for j in 0 .. len(t.sons[i]) - 2:
|
||||
if i == branchIndex and j == currentEx: break
|
||||
if overlap(t.sons[i].sons[j].skipConv, ex):
|
||||
localError(c.config, ex.info, errDuplicateCaseLabel)
|
||||
@@ -507,7 +513,7 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var Int128): PNode =
|
||||
result.add(at)
|
||||
result.add(bt)
|
||||
if emptyRange(ac, bc): localError(c.config, b.info, "range is empty")
|
||||
else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
|
||||
else: covered = covered + getOrdValue(bc) + 1 - getOrdValue(ac)
|
||||
|
||||
proc semCaseBranchRange(c: PContext, t, b: PNode,
|
||||
covered: var Int128): PNode =
|
||||
@@ -528,7 +534,7 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
|
||||
|
||||
proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||
covered: var Int128) =
|
||||
let lastIndex = sonsLen(branch) - 2
|
||||
let lastIndex = len(branch) - 2
|
||||
for i in 0..lastIndex:
|
||||
var b = branch.sons[i]
|
||||
if b.kind == nkRange:
|
||||
@@ -538,7 +544,7 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||
else:
|
||||
# constant sets and arrays are allowed:
|
||||
var r = semConstExpr(c, b)
|
||||
if r.kind in {nkCurly, nkBracket} and len(r) == 0 and sonsLen(branch)==2:
|
||||
if r.kind in {nkCurly, nkBracket} and len(r) == 0 and len(branch)==2:
|
||||
# discarding ``{}`` and ``[]`` branches silently
|
||||
delSon(branch, 0)
|
||||
return
|
||||
@@ -564,13 +570,13 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||
checkForOverlap(c, t, i, branchIndex)
|
||||
|
||||
# Elements added above needs to be checked for overlaps.
|
||||
for i in lastIndex.succ..(sonsLen(branch) - 2):
|
||||
for i in lastIndex.succ..(len(branch) - 2):
|
||||
checkForOverlap(c, t, i, branchIndex)
|
||||
|
||||
proc toCover(c: PContext, t: PType): Int128 =
|
||||
let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
|
||||
if t2.kind == tyEnum and enumHasHoles(t2):
|
||||
result = toInt128(sonsLen(t2.n))
|
||||
result = toInt128(len(t2.n))
|
||||
else:
|
||||
# <----
|
||||
let t = skipTypes(t, abstractVar-{tyTypeDesc})
|
||||
@@ -582,7 +588,7 @@ proc toCover(c: PContext, t: PType): Int128 =
|
||||
elif t.kind in {tyInt, tyUInt}:
|
||||
result = toInt128(1) shl (c.config.target.intSize * 8)
|
||||
else:
|
||||
result = toInt128(lengthOrd(c.config, t))
|
||||
result = lengthOrd(c.config, t)
|
||||
|
||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
father: PNode, rectype: PType, hasCaseFields = false)
|
||||
@@ -629,7 +635,13 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
errorUndeclaredIdentifier(c, n.sons[0].info, typ.sym.name.s)
|
||||
elif not isOrdinalType(typ):
|
||||
localError(c.config, n.sons[0].info, "selector must be of an ordinal type, float or string")
|
||||
for i in 1 ..< sonsLen(n):
|
||||
if firstOrd(c.config, typ) != 0:
|
||||
localError(c.config, n.info, "low(" & $a.sons[0].sym.name.s &
|
||||
") must be 0 for discriminant")
|
||||
elif lengthOrd(c.config, typ) > 0x00007FFF:
|
||||
localError(c.config, n.info, "len($1) must be less than 32768" % a.sons[0].sym.name.s)
|
||||
|
||||
for i in 1 ..< len(n):
|
||||
var b = copyTree(n.sons[i])
|
||||
addSon(a, b)
|
||||
case n.sons[i].kind
|
||||
@@ -642,7 +654,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
localError(c.config, b.info, "invalid else, all cases are already covered")
|
||||
chckCovered = false
|
||||
else: illFormedAst(n, c.config)
|
||||
delSon(b, sonsLen(b) - 1)
|
||||
delSon(b, len(b) - 1)
|
||||
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype, hasCaseFields = true)
|
||||
if chckCovered and covered != toCover(c, a.sons[0].typ):
|
||||
if a.sons[0].typ.kind == tyEnum:
|
||||
@@ -658,7 +670,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
case n.kind
|
||||
of nkRecWhen:
|
||||
var branch: PNode = nil # the branch to take
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n, c.config)
|
||||
var idx = 1
|
||||
@@ -695,12 +707,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
of nkRecList:
|
||||
# attempt to keep the nesting at a sane level:
|
||||
var a = if father.kind == nkRecList: father else: copyNode(n)
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
|
||||
if a != father: addSon(father, a)
|
||||
of nkIdentDefs:
|
||||
checkMinSonsLen(n, 3, c.config)
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
var a: PNode
|
||||
if father.kind != nkRecList and length>=4: a = newNodeI(nkRecList, n.info)
|
||||
else: a = newNodeI(nkEmpty, n.info)
|
||||
@@ -715,7 +727,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
propagateToOwner(rectype, typ)
|
||||
var fieldOwner = if c.inGenericContext > 0: c.getCurrOwner
|
||||
else: rectype.sym
|
||||
for i in 0 .. sonsLen(n)-3:
|
||||
for i in 0 .. len(n)-3:
|
||||
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
||||
suggestSym(c.config, n.sons[i].info, f, c.graph.usageSym)
|
||||
f.typ = typ
|
||||
@@ -750,13 +762,13 @@ proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
|
||||
of nkRecCase:
|
||||
if (n.sons[0].kind != nkSym): internalError(c.config, n.info, "addInheritedFieldsAux")
|
||||
addInheritedFieldsAux(c, check, pos, n.sons[0])
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
case n.sons[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
addInheritedFieldsAux(c, check, pos, lastSon(n.sons[i]))
|
||||
else: internalError(c.config, n.info, "addInheritedFieldsAux(record case branch)")
|
||||
of nkRecList, nkRecWhen, nkElifBranch, nkElse:
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
addInheritedFieldsAux(c, check, pos, n.sons[i])
|
||||
of nkSym:
|
||||
incl(check, n.sym.name.id)
|
||||
@@ -773,12 +785,12 @@ proc skipGenericInvocation(t: PType): PType {.inline.} =
|
||||
proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
|
||||
obj: PType) =
|
||||
assert obj.kind == tyObject
|
||||
if (sonsLen(obj) > 0) and (obj.sons[0] != nil):
|
||||
if (len(obj) > 0) and (obj.sons[0] != nil):
|
||||
addInheritedFields(c, check, pos, obj.sons[0].skipGenericInvocation)
|
||||
addInheritedFieldsAux(c, check, pos, obj.n)
|
||||
|
||||
proc semObjectNode(c: PContext, n: PNode, prev: PType; isInheritable: bool): PType =
|
||||
if n.sonsLen == 0:
|
||||
if n.len == 0:
|
||||
return newConstraint(c, tyObject)
|
||||
var check = initIntSet()
|
||||
var pos = 0
|
||||
@@ -844,6 +856,7 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
localError(c.config, n.info, "type '$1 void' is not allowed" % kindToStr[kind])
|
||||
result = newOrPrevType(kind, prev, c)
|
||||
var isNilable = false
|
||||
var isOwned = false
|
||||
# check every except the last is an object:
|
||||
for i in isCall .. n.len-2:
|
||||
let ni = n[i]
|
||||
@@ -851,16 +864,24 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
|
||||
isNilable = true
|
||||
else:
|
||||
let region = semTypeNode(c, ni, nil)
|
||||
if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
|
||||
if region.kind == tyOwned:
|
||||
isOwned = true
|
||||
elif region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
|
||||
tyError, tyObject}:
|
||||
message c.config, n[i].info, errGenerated, "region needs to be an object type"
|
||||
addSonSkipIntLit(result, region)
|
||||
else:
|
||||
message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated")
|
||||
addSonSkipIntLit(result, region)
|
||||
addSonSkipIntLit(result, region)
|
||||
addSonSkipIntLit(result, t)
|
||||
if tfPartial in result.flags:
|
||||
if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial)
|
||||
#if not isNilable: result.flags.incl tfNotNil
|
||||
if isOwned and optOwnedRefs in c.config.globalOptions:
|
||||
let t = newTypeS(tyOwned, c)
|
||||
t.flags.incl tfHasOwned
|
||||
t.rawAddSonNoPropagationOfTypeFlags result
|
||||
result = t
|
||||
|
||||
proc findEnforcedStaticType(t: PType): PType =
|
||||
# This handles types such as `static[T] and Foo`,
|
||||
@@ -899,63 +920,59 @@ template shouldHaveMeta(t) =
|
||||
internalAssert c.config, tfHasMeta in t.flags
|
||||
# result.lastSon.flags.incl tfHasMeta
|
||||
|
||||
proc addImplicitGeneric(c: PContext; typeClass: PType, typId: PIdent;
|
||||
info: TLineInfo; genericParams: PNode;
|
||||
paramName: string): PType =
|
||||
if genericParams == nil:
|
||||
# This happens with anonymous proc types appearing in signatures
|
||||
# XXX: we need to lift these earlier
|
||||
return
|
||||
let finalTypId = if typId != nil: typId
|
||||
else: getIdent(c.cache, paramName & ":type")
|
||||
# is this a bindOnce type class already present in the param list?
|
||||
for i in 0 ..< genericParams.len:
|
||||
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||
return genericParams.sons[i].typ
|
||||
|
||||
let owner = if typeClass.sym != nil: typeClass.sym
|
||||
else: getCurrOwner(c)
|
||||
var s = newSym(skType, finalTypId, owner, info)
|
||||
if sfExplain in owner.flags: s.flags.incl sfExplain
|
||||
if typId == nil: s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
typeClass.flags.incl tfImplicitTypeParam
|
||||
s.position = genericParams.len
|
||||
genericParams.addSon(newSymNode(s))
|
||||
result = typeClass
|
||||
addDecl(c, s)
|
||||
|
||||
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
paramType: PType, paramName: string,
|
||||
info: TLineInfo, anon = false): PType =
|
||||
if paramType == nil: return # (e.g. proc return type)
|
||||
|
||||
proc addImplicitGenericImpl(c: PContext; typeClass: PType, typId: PIdent): PType =
|
||||
if genericParams == nil:
|
||||
# This happens with anonymous proc types appearing in signatures
|
||||
# XXX: we need to lift these earlier
|
||||
return
|
||||
let finalTypId = if typId != nil: typId
|
||||
else: getIdent(c.cache, paramName & ":type")
|
||||
# is this a bindOnce type class already present in the param list?
|
||||
for i in 0 ..< genericParams.len:
|
||||
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||
return genericParams.sons[i].typ
|
||||
|
||||
let owner = if typeClass.sym != nil: typeClass.sym
|
||||
else: getCurrOwner(c)
|
||||
var s = newSym(skType, finalTypId, owner, info)
|
||||
if sfExplain in owner.flags: s.flags.incl sfExplain
|
||||
if typId == nil: s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
typeClass.flags.incl tfImplicitTypeParam
|
||||
s.position = genericParams.len
|
||||
genericParams.addSon(newSymNode(s))
|
||||
result = typeClass
|
||||
addDecl(c, s)
|
||||
|
||||
# XXX: There are codegen errors if this is turned into a nested proc
|
||||
template liftingWalk(typ: PType, anonFlag = false): untyped =
|
||||
template recurse(typ: PType, anonFlag = false): untyped =
|
||||
liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
|
||||
#proc liftingWalk(paramType: PType, anon = false): PType =
|
||||
|
||||
var paramTypId = if not anon and paramType.sym != nil: paramType.sym.name
|
||||
else: nil
|
||||
|
||||
template maybeLift(typ: PType): untyped =
|
||||
let lifted = liftingWalk(typ)
|
||||
(if lifted != nil: lifted else: typ)
|
||||
|
||||
template addImplicitGeneric(e): untyped =
|
||||
addImplicitGenericImpl(c, e, paramTypId)
|
||||
|
||||
case paramType.kind:
|
||||
of tyAnything:
|
||||
result = addImplicitGenericImpl(c, newTypeS(tyGenericParam, c), nil)
|
||||
result = addImplicitGeneric(c, newTypeS(tyGenericParam, c), nil, info, genericParams, paramName)
|
||||
|
||||
of tyStatic:
|
||||
if paramType.base.kind != tyNone and paramType.n != nil:
|
||||
# this is a concrete static value
|
||||
return
|
||||
if tfUnresolved in paramType.flags: return # already lifted
|
||||
let base = paramType.base.maybeLift
|
||||
|
||||
let lifted = recurse(paramType.base)
|
||||
let base = (if lifted != nil: lifted else: paramType.base)
|
||||
if base.isMetaType and procKind == skMacro:
|
||||
localError(c.config, info, errMacroBodyDependsOnGenericTypes % paramName)
|
||||
result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
|
||||
result = addImplicitGeneric(c, c.newTypeWithSons(tyStatic, @[base]),
|
||||
paramTypId, info, genericParams, paramName)
|
||||
if result != nil: result.flags.incl({tfHasStatic, tfUnresolved})
|
||||
|
||||
of tyTypeDesc:
|
||||
@@ -968,15 +985,15 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
paramTypId = nil
|
||||
let t = c.newTypeWithSons(tyTypeDesc, @[paramType.base])
|
||||
incl t.flags, tfCheckedForDestructor
|
||||
result = addImplicitGeneric(t)
|
||||
result = addImplicitGeneric(c, t, paramTypId, info, genericParams, paramName)
|
||||
|
||||
of tyDistinct:
|
||||
if paramType.sonsLen == 1:
|
||||
if paramType.len == 1:
|
||||
# disable the bindOnce behavior for the type class
|
||||
result = liftingWalk(paramType.base, true)
|
||||
result = recurse(paramType.base, true)
|
||||
|
||||
of tyAlias, tyOwned:
|
||||
result = liftingWalk(paramType.base)
|
||||
result = recurse(paramType.base)
|
||||
|
||||
of tySequence, tySet, tyArray, tyOpenArray,
|
||||
tyVar, tyLent, tyPtr, tyRef, tyProc:
|
||||
@@ -989,12 +1006,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
|
||||
let typ = c.newTypeWithSons(tyBuiltInTypeClass,
|
||||
@[newTypeS(paramType.kind, c)])
|
||||
result = addImplicitGeneric(typ)
|
||||
result = addImplicitGeneric(c, typ, paramTypId, info, genericParams, paramName)
|
||||
else:
|
||||
for i in 0 ..< paramType.len:
|
||||
if paramType.sons[i] == paramType:
|
||||
globalError(c.config, info, errIllegalRecursionInTypeX % typeToString(paramType))
|
||||
var lifted = liftingWalk(paramType.sons[i])
|
||||
var lifted = recurse(paramType.sons[i])
|
||||
if lifted != nil:
|
||||
paramType.sons[i] = lifted
|
||||
result = paramType
|
||||
@@ -1003,7 +1020,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
result = newTypeS(tyGenericInvocation, c)
|
||||
result.rawAddSon(paramType)
|
||||
|
||||
for i in 0 .. paramType.sonsLen - 2:
|
||||
for i in 0 .. paramType.len - 2:
|
||||
if paramType.sons[i].kind == tyStatic:
|
||||
var staticCopy = paramType.sons[i].exactReplica
|
||||
staticCopy.flags.incl tfInferrableStatic
|
||||
@@ -1014,29 +1031,29 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
if paramType.lastSon.kind == tyUserTypeClass:
|
||||
result.kind = tyUserTypeClassInst
|
||||
result.rawAddSon paramType.lastSon
|
||||
return addImplicitGeneric(result)
|
||||
return addImplicitGeneric(c, result, paramTypId, info, genericParams, paramName)
|
||||
|
||||
let x = instGenericContainer(c, paramType.sym.info, result,
|
||||
allowMetaTypes = true)
|
||||
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, x])
|
||||
#result = newTypeS(tyCompositeTypeClass, c)
|
||||
#for i in 0..<x.len: result.rawAddSon(x.sons[i])
|
||||
result = addImplicitGeneric(result)
|
||||
result = addImplicitGeneric(c, result, paramTypId, info, genericParams, paramName)
|
||||
|
||||
of tyGenericInst:
|
||||
if paramType.lastSon.kind == tyUserTypeClass:
|
||||
var cp = copyType(paramType, getCurrOwner(c), false)
|
||||
cp.kind = tyUserTypeClassInst
|
||||
return addImplicitGeneric(cp)
|
||||
return addImplicitGeneric(c, cp, paramTypId, info, genericParams, paramName)
|
||||
|
||||
for i in 1 .. paramType.len-2:
|
||||
var lifted = liftingWalk(paramType.sons[i])
|
||||
var lifted = recurse(paramType.sons[i])
|
||||
if lifted != nil:
|
||||
paramType.sons[i] = lifted
|
||||
result = paramType
|
||||
result.lastSon.shouldHaveMeta
|
||||
|
||||
let liftBody = liftingWalk(paramType.lastSon, true)
|
||||
let liftBody = recurse(paramType.lastSon, true)
|
||||
if liftBody != nil:
|
||||
result = liftBody
|
||||
result.flags.incl tfHasMeta
|
||||
@@ -1044,7 +1061,8 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
|
||||
of tyGenericInvocation:
|
||||
for i in 1 ..< paramType.len:
|
||||
let lifted = liftingWalk(paramType.sons[i])
|
||||
#if paramType[i].kind != tyTypeDesc:
|
||||
let lifted = recurse(paramType.sons[i])
|
||||
if lifted != nil: paramType.sons[i] = lifted
|
||||
|
||||
let body = paramType.base
|
||||
@@ -1056,14 +1074,16 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
if body.lastSon.kind == tyUserTypeClass:
|
||||
let expanded = instGenericContainer(c, info, paramType,
|
||||
allowMetaTypes = true)
|
||||
result = liftingWalk(expanded, true)
|
||||
result = recurse(expanded, true)
|
||||
|
||||
of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass,
|
||||
tyAnd, tyOr, tyNot:
|
||||
result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), false))
|
||||
result = addImplicitGeneric(c,
|
||||
copyType(paramType, getCurrOwner(c), false), paramTypId,
|
||||
info, genericParams, paramName)
|
||||
|
||||
of tyGenericParam:
|
||||
markUsed(c.config, paramType.sym.info, paramType.sym, c.graph.usageSym)
|
||||
markUsed(c, paramType.sym.info, paramType.sym)
|
||||
onUse(paramType.sym.info, paramType.sym)
|
||||
if tfWildcard in paramType.flags:
|
||||
paramType.flags.excl tfWildcard
|
||||
@@ -1071,8 +1091,6 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
|
||||
else: discard
|
||||
|
||||
# result = liftingWalk(paramType)
|
||||
|
||||
proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
|
||||
if n.kind == nkCurlyExpr:
|
||||
result = semTypeNode(c, n.sons[0], nil)
|
||||
@@ -1119,7 +1137,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
typ: PType = nil
|
||||
def: PNode = nil
|
||||
constraint: PNode = nil
|
||||
length = sonsLen(a)
|
||||
length = len(a)
|
||||
hasType = a.sons[length-2].kind != nkEmpty
|
||||
hasDefault = a.sons[length-1].kind != nkEmpty
|
||||
|
||||
@@ -1230,6 +1248,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
# 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
|
||||
# compiler is hardly aware of 'auto':
|
||||
r = newTypeS(tyUntyped, c)
|
||||
elif r.kind == tyStatic:
|
||||
# type allowed should forbid this type
|
||||
discard
|
||||
else:
|
||||
if r.sym == nil or sfAnon notin r.sym.flags:
|
||||
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
||||
@@ -1266,7 +1287,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
|
||||
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
for i in 0 .. length - 2:
|
||||
n.sons[i] = semStmt(c, n.sons[i], {})
|
||||
if length > 0:
|
||||
@@ -1331,7 +1352,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
else: addSonSkipIntLit(result, typ)
|
||||
|
||||
if t.kind == tyForward:
|
||||
for i in 1 ..< sonsLen(n):
|
||||
for i in 1 ..< len(n):
|
||||
var elem = semGenericParamInInvocation(c, n.sons[i])
|
||||
addToResult(elem)
|
||||
return
|
||||
@@ -1356,7 +1377,10 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
|
||||
for i in 1 ..< m.call.len:
|
||||
var typ = m.call[i].typ
|
||||
if typ.kind == tyTypeDesc and typ.sons[0].kind == tyNone:
|
||||
# is this a 'typedesc' *parameter*? If so, use the typedesc type,
|
||||
# unstripped.
|
||||
if m.call[i].kind == nkSym and m.call[i].sym.kind == skParam and
|
||||
typ.kind == tyTypeDesc and containsGenericType(typ):
|
||||
isConcrete = false
|
||||
addToResult(typ)
|
||||
else:
|
||||
@@ -1440,7 +1464,7 @@ template modifierTypeKindOfNode(n: PNode): TTypeKind =
|
||||
else: tyNone
|
||||
|
||||
proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
# if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
|
||||
# if n.len == 0: return newConstraint(c, tyTypeClass)
|
||||
let
|
||||
pragmas = n[1]
|
||||
inherited = n[2]
|
||||
@@ -1551,7 +1575,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = semTypeof(c, n.sons[0], prev)
|
||||
if result.kind == tyTypeDesc: result.flags.incl tfExplicit
|
||||
of nkPar:
|
||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||
if len(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||
else:
|
||||
result = semAnonTuple(c, n, prev)
|
||||
of nkTupleConstr: result = semAnonTuple(c, n, prev)
|
||||
@@ -1620,7 +1644,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = semTypeof(c, n[1], prev)
|
||||
elif op.s == "typeof" and n[0].kind == nkSym and n[0].sym.magic == mTypeOf:
|
||||
result = semTypeof2(c, n, prev)
|
||||
elif op.s == "owned" and optNimV2 notin c.config.globalOptions and n.len == 2:
|
||||
elif op.s == "owned" and optOwnedRefs notin c.config.globalOptions and n.len == 2:
|
||||
result = semTypeExpr(c, n[1], prev)
|
||||
else:
|
||||
if c.inGenericContext > 0 and n.kind == nkCall:
|
||||
@@ -1644,7 +1668,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of mSet: result = semSet(c, n, prev)
|
||||
of mOrdinal: result = semOrdinal(c, n, prev)
|
||||
of mSeq:
|
||||
if c.config.selectedGC == gcDestructors and optNimV2 notin c.config.globalOptions:
|
||||
if false: # c.config.selectedGC == gcDestructors and optNimV2 notin c.config.globalOptions:
|
||||
let s = c.graph.sysTypes[tySequence]
|
||||
assert s != nil
|
||||
assert prev == nil
|
||||
@@ -1751,7 +1775,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
else:
|
||||
assignType(prev, t)
|
||||
result = prev
|
||||
markUsed(c.config, n.info, n.sym, c.graph.usageSym)
|
||||
markUsed(c, n.info, n.sym)
|
||||
onUse(n.info, n.sym)
|
||||
else:
|
||||
if s.kind != skError:
|
||||
@@ -1768,7 +1792,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkDistinctTy: result = semDistinct(c, n, prev)
|
||||
of nkStaticTy: result = semStaticType(c, n[0], prev)
|
||||
of nkIteratorTy:
|
||||
if n.sonsLen == 0:
|
||||
if n.len == 0:
|
||||
result = newTypeS(tyBuiltInTypeClass, c)
|
||||
let child = newTypeS(tyProc, c)
|
||||
child.flags.incl tfIterator
|
||||
@@ -1781,7 +1805,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
else:
|
||||
result.callConv = ccClosure
|
||||
of nkProcTy:
|
||||
if n.sonsLen == 0:
|
||||
if n.len == 0:
|
||||
result = newConstraint(c, tyProc)
|
||||
else:
|
||||
result = semProcTypeWithScope(c, n, prev, skProc)
|
||||
@@ -1790,7 +1814,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkStmtListType: result = semStmtListType(c, n, prev)
|
||||
of nkBlockType: result = semBlockType(c, n, prev)
|
||||
else:
|
||||
localError(c.config, n.info, errTypeExpected)
|
||||
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
n.typ = result
|
||||
dec c.inTypeContext
|
||||
@@ -1810,13 +1834,8 @@ proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
|
||||
|
||||
# FIXME: proper support for clongdouble should be added.
|
||||
# long double size can be 8, 10, 12, 16 bytes depending on platform & compiler
|
||||
if conf.target.targetCPU == cpuI386 and size == 8:
|
||||
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
|
||||
if conf.target.targetOS != osWindows:
|
||||
if kind in {tyFloat64, tyFloat, tyInt, tyUInt, tyInt64, tyUInt64}:
|
||||
# on i386 for all known POSIX systems, 64bits ints are aligned
|
||||
# to 4bytes (except with -malign-double)
|
||||
m.typ.align = 4
|
||||
if kind in {tyFloat64, tyFloat, tyInt, tyUInt, tyInt64, tyUInt64} and size == 8:
|
||||
m.typ.align = int16(conf.floatInt64Align)
|
||||
|
||||
proc setMagicIntegral(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
|
||||
setMagicType(conf, m, kind, size)
|
||||
@@ -1915,7 +1934,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
if n.kind != nkGenericParams:
|
||||
illFormedAst(n, c.config)
|
||||
return
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkIdentDefs: illFormedAst(n, c.config)
|
||||
let L = a.len
|
||||
|
||||
@@ -76,13 +76,13 @@ type
|
||||
c*: PContext
|
||||
typeMap*: ptr LayeredIdTable # map PType to PType
|
||||
symMap*: TIdTable # map PSym to PSym
|
||||
localCache*: TIdTable # local cache for remembering alraedy replaced
|
||||
localCache*: TIdTable # local cache for remembering already replaced
|
||||
# types during instantiation of meta types
|
||||
# (they are not stored in the global cache)
|
||||
info*: TLineInfo
|
||||
allowMetaTypes*: bool # allow types such as seq[Number]
|
||||
# i.e. the result contains unresolved generics
|
||||
skipTypedesc*: bool # wether we should skip typeDescs
|
||||
skipTypedesc*: bool # whether we should skip typeDescs
|
||||
isReturnType*: bool
|
||||
owner*: PSym # where this instantiation comes from
|
||||
recursionLimit: int
|
||||
@@ -169,7 +169,7 @@ proc replaceObjBranches(cl: TReplTypeVars, n: PNode): PNode =
|
||||
discard
|
||||
of nkRecWhen:
|
||||
var branch: PNode = nil # the branch to take
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n, cl.c.config)
|
||||
case it.kind
|
||||
@@ -189,7 +189,7 @@ proc replaceObjBranches(cl: TReplTypeVars, n: PNode): PNode =
|
||||
else:
|
||||
result = newNodeI(nkRecList, n.info)
|
||||
else:
|
||||
for i in 0..<n.sonsLen:
|
||||
for i in 0..<n.len:
|
||||
n.sons[i] = replaceObjBranches(cl, n.sons[i])
|
||||
|
||||
proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
|
||||
@@ -209,7 +209,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
|
||||
result = newNode(nkRecList, n.info)
|
||||
of nkRecWhen:
|
||||
var branch: PNode = nil # the branch to take
|
||||
for i in 0 ..< sonsLen(n):
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n, cl.c.config)
|
||||
case it.kind
|
||||
@@ -234,7 +234,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
|
||||
result = if cl.allowMetaTypes: n
|
||||
else: cl.c.semExpr(cl.c, n)
|
||||
else:
|
||||
var length = sonsLen(n)
|
||||
var length = len(n)
|
||||
if length > 0:
|
||||
newSons(result, length)
|
||||
if start > 0:
|
||||
@@ -249,7 +249,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
return s
|
||||
|
||||
# XXX: Bound symbols in default parameter expressions may reach here.
|
||||
# We cannot process them, becase `sym.n` may point to a proc body with
|
||||
# We cannot process them, because `sym.n` may point to a proc body with
|
||||
# cyclic references that will lead to an infinite recursion.
|
||||
# Perhaps we should not use a black-list here, but a whitelist instead
|
||||
# (e.g. skGenericParam and skType).
|
||||
@@ -260,12 +260,32 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
|
||||
#result = PSym(idTableGet(cl.symMap, s))
|
||||
#if result == nil:
|
||||
#[
|
||||
|
||||
We cannot naively check for symbol recursions, because otherwise
|
||||
object types A, B whould share their fields!
|
||||
|
||||
import tables
|
||||
|
||||
type
|
||||
Table[S, T] = object
|
||||
x: S
|
||||
y: T
|
||||
|
||||
G[T] = object
|
||||
inodes: Table[int, T] # A
|
||||
rnodes: Table[T, int] # B
|
||||
|
||||
var g: G[string]
|
||||
|
||||
]#
|
||||
result = copySym(s)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
#idTablePut(cl.symMap, s, result)
|
||||
result.owner = s.owner
|
||||
result.typ = replaceTypeVarsT(cl, s.typ)
|
||||
result.ast = replaceTypeVarsN(cl, s.ast)
|
||||
if result.kind != skType:
|
||||
result.ast = replaceTypeVarsN(cl, s.ast)
|
||||
|
||||
proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
|
||||
result = cl.typeMap.lookup(t)
|
||||
@@ -311,7 +331,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||
when defined(reportCacheHits):
|
||||
echo "Generic instantiation cached ", typeToString(result), " for ", typeToString(t)
|
||||
return
|
||||
for i in 1 ..< sonsLen(t):
|
||||
for i in 1 ..< len(t):
|
||||
var x = t.sons[i]
|
||||
if x.kind in {tyGenericParam}:
|
||||
x = lookupTypeVar(cl, x)
|
||||
@@ -351,14 +371,14 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||
var typeMapLayer = newTypeMapLayer(cl)
|
||||
cl.typeMap = addr(typeMapLayer)
|
||||
|
||||
for i in 1 ..< sonsLen(t):
|
||||
for i in 1 ..< len(t):
|
||||
var x = replaceTypeVarsT(cl, t.sons[i])
|
||||
assert x.kind != tyGenericInvocation
|
||||
header.sons[i] = x
|
||||
propagateToOwner(header, x)
|
||||
cl.typeMap.put(body.sons[i-1], x)
|
||||
|
||||
for i in 1 ..< sonsLen(t):
|
||||
for i in 1 ..< len(t):
|
||||
# if one of the params is not concrete, we cannot do anything
|
||||
# but we already raised an error!
|
||||
rawAddSon(result, header.sons[i])
|
||||
@@ -426,11 +446,11 @@ proc eraseVoidParams*(t: PType) =
|
||||
if t.sons[0] != nil and t.sons[0].kind == tyVoid:
|
||||
t.sons[0] = nil
|
||||
|
||||
for i in 1 ..< t.sonsLen:
|
||||
for i in 1 ..< t.len:
|
||||
# don't touch any memory unless necessary
|
||||
if t.sons[i].kind == tyVoid:
|
||||
var pos = i
|
||||
for j in i+1 ..< t.sonsLen:
|
||||
for j in i+1 ..< t.len:
|
||||
if t.sons[j].kind != tyVoid:
|
||||
t.sons[pos] = t.sons[j]
|
||||
t.n.sons[pos] = t.n.sons[j]
|
||||
@@ -440,7 +460,7 @@ proc eraseVoidParams*(t: PType) =
|
||||
break
|
||||
|
||||
proc skipIntLiteralParams*(t: PType) =
|
||||
for i in 0 ..< t.sonsLen:
|
||||
for i in 0 ..< t.len:
|
||||
let p = t.sons[i]
|
||||
if p == nil: continue
|
||||
let skipped = p.skipIntLit
|
||||
@@ -553,7 +573,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
bailout()
|
||||
result = instCopyType(cl, t)
|
||||
idTablePut(cl.localCache, t, result)
|
||||
for i in 1 ..< result.sonsLen:
|
||||
for i in 1 ..< result.len:
|
||||
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
|
||||
propagateToOwner(result, result.lastSon)
|
||||
|
||||
@@ -566,10 +586,10 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
#if not cl.allowMetaTypes:
|
||||
idTablePut(cl.localCache, t, result)
|
||||
|
||||
for i in 0 ..< sonsLen(result):
|
||||
for i in 0 ..< len(result):
|
||||
if result.sons[i] != nil:
|
||||
if result.sons[i].kind == tyGenericBody:
|
||||
localError(cl.c.config, t.sym.info,
|
||||
localError(cl.c.config, if t.sym != nil: t.sym.info else: cl.info,
|
||||
"cannot instantiate '" &
|
||||
typeToString(result.sons[i], preferDesc) &
|
||||
"' inside of type definition: '" &
|
||||
@@ -597,20 +617,6 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
eraseVoidParams(result)
|
||||
skipIntLiteralParams(result)
|
||||
|
||||
of tySequence:
|
||||
if cl.isReturnType and cl.c.config.selectedGC == gcDestructors and
|
||||
result.attachedOps[attachedDestructor].isNil and
|
||||
result[0].kind != tyEmpty and optNimV2 notin cl.c.config.globalOptions:
|
||||
let s = cl.c.graph.sysTypes[tySequence]
|
||||
var old = copyType(s, s.owner, keepId=false)
|
||||
# Remove the 'T' parameter from tySequence:
|
||||
old.sons.setLen 0
|
||||
old.n = nil
|
||||
old.flags = {tfHasAsgn}
|
||||
old.addSonSkipIntLit result[0]
|
||||
result.attachedOps = old.attachedOps
|
||||
cl.c.typesWithOps.add((result, old))
|
||||
|
||||
else: discard
|
||||
else:
|
||||
# If this type doesn't refer to a generic type we may still want to run it
|
||||
@@ -673,10 +679,10 @@ proc recomputeFieldPositions*(t: PType; obj: PNode; currPosition: var int) =
|
||||
recomputeFieldPositions(b, b.n, currPosition)
|
||||
case obj.kind
|
||||
of nkRecList:
|
||||
for i in 0 ..< sonsLen(obj): recomputeFieldPositions(nil, obj.sons[i], currPosition)
|
||||
for i in 0 ..< len(obj): recomputeFieldPositions(nil, obj.sons[i], currPosition)
|
||||
of nkRecCase:
|
||||
recomputeFieldPositions(nil, obj.sons[0], currPosition)
|
||||
for i in 1 ..< sonsLen(obj):
|
||||
for i in 1 ..< len(obj):
|
||||
recomputeFieldPositions(nil, lastSon(obj.sons[i]), currPosition)
|
||||
of nkSym:
|
||||
obj.sym.position = currPosition
|
||||
@@ -685,6 +691,10 @@ proc recomputeFieldPositions*(t: PType; obj: PNode; currPosition: var int) =
|
||||
|
||||
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
|
||||
t: PType): PType =
|
||||
# Given `t` like Foo[T]
|
||||
# pt: Table with type mappings: T -> int
|
||||
# Desired result: Foo[int]
|
||||
# proc (x: T = 0); T -> int ----> proc (x: int = 0)
|
||||
var typeMap = initLayeredTypeMap(pt)
|
||||
var cl = initTypeVars(p, addr(typeMap), info, nil)
|
||||
pushInfoContext(p.config, info)
|
||||
|
||||
@@ -93,7 +93,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||
|
||||
case t.kind
|
||||
of tyGenericInvocation:
|
||||
for i in 0 ..< sonsLen(t):
|
||||
for i in 0 ..< len(t):
|
||||
c.hashType t.sons[i], flags
|
||||
of tyDistinct:
|
||||
if CoDistinct in flags:
|
||||
@@ -180,15 +180,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||
of tyTuple:
|
||||
c &= char(t.kind)
|
||||
if t.n != nil and CoType notin flags:
|
||||
assert(sonsLen(t.n) == sonsLen(t))
|
||||
for i in 0 ..< sonsLen(t.n):
|
||||
assert(len(t.n) == len(t))
|
||||
for i in 0 ..< len(t.n):
|
||||
assert(t.n.sons[i].kind == nkSym)
|
||||
c &= t.n.sons[i].sym.name.s
|
||||
c &= ':'
|
||||
c.hashType(t.sons[i], flags+{CoIgnoreRange})
|
||||
c &= ','
|
||||
else:
|
||||
for i in 0 ..< sonsLen(t): c.hashType t.sons[i], flags+{CoIgnoreRange}
|
||||
for i in 0 ..< len(t): c.hashType t.sons[i], flags+{CoIgnoreRange}
|
||||
of tyRange:
|
||||
if CoIgnoreRange notin flags:
|
||||
c &= char(t.kind)
|
||||
|
||||
@@ -21,7 +21,7 @@ when (defined(booting) or defined(nimsuggest)) and not defined(leanCompiler):
|
||||
type
|
||||
MismatchKind* = enum
|
||||
kUnknown, kAlreadyGiven, kUnknownNamedParam, kTypeMismatch, kVarNeeded,
|
||||
kMissingParam, kExtraArg
|
||||
kMissingParam, kExtraArg, kPositionalAlreadyGiven
|
||||
|
||||
MismatchInfo* = object
|
||||
kind*: MismatchKind # reason for mismatch
|
||||
@@ -107,7 +107,8 @@ type
|
||||
const
|
||||
isNilConversion = isConvertible # maybe 'isIntConv' fits better?
|
||||
|
||||
proc markUsed*(conf: ConfigRef; info: TLineInfo, s: PSym; usageSym: var PSym)
|
||||
proc markUsed*(c: PContext; info: TLineInfo, s: PSym)
|
||||
proc markOwnerModuleAsUsed*(c: PContext; s: PSym)
|
||||
|
||||
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
|
||||
|
||||
@@ -133,11 +134,14 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PType) =
|
||||
initIdTable(c.bindings)
|
||||
|
||||
proc put(c: var TCandidate, key, val: PType) {.inline.} =
|
||||
## Given: proc foo[T](x: T); foo(4)
|
||||
## key: 'T'
|
||||
## val: 'int' (typeof(4))
|
||||
when false:
|
||||
let old = PType(idTableGet(c.bindings, key))
|
||||
if old != nil:
|
||||
echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old)
|
||||
if typeToString(old) == "seq[string]":
|
||||
if typeToString(old) == "float32":
|
||||
writeStackTrace()
|
||||
if c.c.module.name.s == "temp3":
|
||||
echo "binding ", key, " -> ", val
|
||||
@@ -166,7 +170,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||
initIdTable(c.bindings)
|
||||
if binding != nil and callee.kind in routineKinds:
|
||||
var typeParams = callee.ast[genericParamsPos]
|
||||
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
||||
for i in 1..min(len(typeParams), len(binding)-1):
|
||||
var formalTypeParam = typeParams.sons[i-1].typ
|
||||
var bound = binding[i].typ
|
||||
if bound != nil:
|
||||
@@ -333,7 +337,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
|
||||
n.sons[i] = arg
|
||||
if arg.typ != nil and arg.typ.kind == tyError: return
|
||||
add(result, argTypeToString(arg, prefer))
|
||||
if i != sonsLen(n) - 1: add(result, ", ")
|
||||
if i != len(n) - 1: add(result, ", ")
|
||||
|
||||
proc typeRel*(c: var TCandidate, f, aOrig: PType,
|
||||
flags: TTypeRelFlags = {}): TTypeRelation
|
||||
@@ -377,10 +381,10 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
if k == f.kind: result = isSubrange
|
||||
elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
|
||||
tyUInt..tyUInt64} and
|
||||
isIntLit(ab) and ab.n.intVal >= firstOrd(nil, f) and
|
||||
ab.n.intVal <= lastOrd(nil, f):
|
||||
isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
|
||||
getInt(ab.n) <= lastOrd(nil, f):
|
||||
# passing 'nil' to firstOrd/lastOrd here as type checking rules should
|
||||
# not depent on the target integer size configurations!
|
||||
# not depend on the target integer size configurations!
|
||||
# integer literal in the proper range; we want ``i16 + 4`` to stay an
|
||||
# ``int16`` operation so we declare the ``4`` pseudo-equal to int16
|
||||
result = isFromIntLit
|
||||
@@ -396,27 +400,30 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
f.kind in {tyUInt8..tyUInt32} and a[0].kind in {tyUInt8..tyInt32}) and
|
||||
a.n[0].intVal >= firstOrd(nil, f) and a.n[1].intVal <= lastOrd(nil, f):
|
||||
# passing 'nil' to firstOrd/lastOrd here as type checking rules should
|
||||
# not depent on the target integer size configurations!
|
||||
# not depend on the target integer size configurations!
|
||||
result = isConvertible
|
||||
else: result = isNone
|
||||
|
||||
proc isConvertibleToRange(f, a: PType): bool =
|
||||
# be less picky for tyRange, as that it is used for array indexing:
|
||||
if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
|
||||
a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
|
||||
case f.kind
|
||||
of tyInt, tyInt64: result = true
|
||||
of tyInt8: result = a.kind in {tyInt8, tyInt}
|
||||
of tyInt16: result = a.kind in {tyInt8, tyInt16, tyInt}
|
||||
of tyInt32: result = a.kind in {tyInt8, tyInt16, tyInt32, tyInt}
|
||||
of tyUInt, tyUInt64: result = true
|
||||
of tyUInt8: result = a.kind in {tyUInt8, tyUInt}
|
||||
of tyUInt16: result = a.kind in {tyUInt8, tyUInt16, tyUInt}
|
||||
of tyUInt32: result = a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
|
||||
of tyInt8: result = isIntLit(a) or a.kind in {tyInt8}
|
||||
of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
|
||||
of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
|
||||
# This is wrong, but seems like there's a lot of code that relies on it :(
|
||||
of tyInt, tyUInt, tyUInt64: result = true
|
||||
of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
|
||||
of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
|
||||
of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
|
||||
of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
|
||||
#of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
|
||||
#of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64}
|
||||
else: result = false
|
||||
elif f.kind in {tyFloat..tyFloat128} and
|
||||
a.kind in {tyFloat..tyFloat128}:
|
||||
result = true
|
||||
elif f.kind in {tyFloat..tyFloat128}:
|
||||
# `isIntLit` is correct and should be used above as well, see PR:
|
||||
# https://github.com/nim-lang/Nim/pull/11197
|
||||
result = isIntLit(a) or a.kind in {tyFloat..tyFloat128}
|
||||
|
||||
proc handleFloatRange(f, a: PType): TTypeRelation =
|
||||
if a.kind == f.kind:
|
||||
@@ -436,7 +443,7 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
|
||||
proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
|
||||
if fGenericOrigin != nil and last.kind == tyGenericInst and
|
||||
last.len-1 == fGenericOrigin.len:
|
||||
for i in 1 ..< sonsLen(fGenericOrigin):
|
||||
for i in 1 ..< len(fGenericOrigin):
|
||||
let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
|
||||
if x == nil:
|
||||
put(c, fGenericOrigin.sons[i], last.sons[i])
|
||||
@@ -514,16 +521,16 @@ proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
result = isNone
|
||||
if sameType(f, a):
|
||||
result = isEqual
|
||||
elif sonsLen(a) == sonsLen(f):
|
||||
elif len(a) == len(f):
|
||||
result = isEqual
|
||||
let firstField = if f.kind == tyTuple: 0
|
||||
else: 1
|
||||
for i in firstField ..< sonsLen(f):
|
||||
for i in firstField ..< len(f):
|
||||
var m = typeRel(c, f.sons[i], a.sons[i])
|
||||
if m < isSubtype: return isNone
|
||||
result = minRel(result, m)
|
||||
if f.n != nil and a.n != nil:
|
||||
for i in 0 ..< sonsLen(f.n):
|
||||
for i in 0 ..< len(f.n):
|
||||
# check field names:
|
||||
if f.n.sons[i].kind != nkSym: return isNone
|
||||
elif a.n.sons[i].kind != nkSym: return isNone
|
||||
@@ -603,7 +610,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
case a.kind
|
||||
of tyProc:
|
||||
if sonsLen(f) != sonsLen(a): return
|
||||
if len(f) != len(a): return
|
||||
result = isEqual # start with maximum; also correct for no
|
||||
# params at all
|
||||
|
||||
@@ -613,7 +620,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
|
||||
# Note: We have to do unification for the parameters before the
|
||||
# return type!
|
||||
for i in 1 ..< f.sonsLen:
|
||||
for i in 1 ..< f.len:
|
||||
checkParam(f.sons[i], a.sons[i])
|
||||
|
||||
if f.sons[0] != nil:
|
||||
@@ -873,7 +880,7 @@ proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool =
|
||||
of mUnaryMinusI:
|
||||
return inferStaticParam(c, lhs[1], -rhs)
|
||||
|
||||
of mUnaryPlusI, mToInt, mToBiggestInt:
|
||||
of mUnaryPlusI:
|
||||
return inferStaticParam(c, lhs[1], rhs)
|
||||
|
||||
else: discard
|
||||
@@ -902,10 +909,10 @@ proc inferStaticsInRange(c: var TCandidate,
|
||||
allowUnresolved = true)
|
||||
let upperBound = tryResolvingStaticExpr(c, inferred.n[1],
|
||||
allowUnresolved = true)
|
||||
template doInferStatic(e: PNode, r: BiggestInt) =
|
||||
template doInferStatic(e: PNode, r: Int128) =
|
||||
var exp = e
|
||||
var rhs = r
|
||||
if inferStaticParam(c, exp, rhs):
|
||||
if inferStaticParam(c, exp, toInt64(rhs)):
|
||||
return isGeneric
|
||||
else:
|
||||
failureToInferStaticParam(c.c.config, exp)
|
||||
@@ -918,7 +925,7 @@ proc inferStaticsInRange(c: var TCandidate,
|
||||
return isNone
|
||||
doInferStatic(upperBound, lengthOrd(c.c.config, concrete) + lowerBound.intVal - 1)
|
||||
elif upperBound.kind == nkIntLit:
|
||||
doInferStatic(lowerBound, upperBound.intVal + 1 - lengthOrd(c.c.config, concrete))
|
||||
doInferStatic(lowerBound, getInt(upperBound) + 1 - lengthOrd(c.c.config, concrete))
|
||||
|
||||
template subtypeCheck() =
|
||||
if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in {
|
||||
@@ -939,7 +946,7 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
|
||||
of tyGenericInst:
|
||||
let body = f.base
|
||||
return body == a.base and
|
||||
a.sonsLen == 3 and
|
||||
a.len == 3 and
|
||||
tfWeakCovariant notin body.sons[0].flags and
|
||||
baseTypesCheck(f.sons[1], a.sons[1])
|
||||
else:
|
||||
@@ -1412,7 +1419,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
# YYYY
|
||||
result = isEqual
|
||||
|
||||
for i in 1 .. rootf.sonsLen-2:
|
||||
for i in 1 .. rootf.len-2:
|
||||
let ff = rootf.sons[i]
|
||||
let aa = roota.sons[i]
|
||||
let res = typeRel(c, ff, aa, nextFlags)
|
||||
@@ -1493,8 +1500,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
# simply no match for now:
|
||||
discard
|
||||
elif x.kind == tyGenericInst and f.sons[0] == x.sons[0] and
|
||||
sonsLen(x) - 1 == sonsLen(f):
|
||||
for i in 1 ..< sonsLen(f):
|
||||
len(x) - 1 == len(f):
|
||||
for i in 1 ..< len(f):
|
||||
if x.sons[i].kind == tyGenericParam:
|
||||
internalError(c.c.graph.config, "wrong instantiated type!")
|
||||
elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype:
|
||||
@@ -1502,7 +1509,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
if f.sons[i].kind != tyTypeDesc: return
|
||||
result = isGeneric
|
||||
elif x.kind == tyGenericInst and isGenericSubtype(c, x, f, depth, f) and
|
||||
(sonsLen(x) - 1 == sonsLen(f)):
|
||||
(len(x) - 1 == len(f)):
|
||||
# do not recurse here in order to not K bind twice for this code:
|
||||
#
|
||||
# type
|
||||
@@ -1534,7 +1541,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
# var it1 = internalFind(root, 312) # cannot instantiate: 'D'
|
||||
#
|
||||
# we steal the generic parameters from the tyGenericBody:
|
||||
for i in 1 ..< sonsLen(f):
|
||||
for i in 1 ..< len(f):
|
||||
let x = PType(idTableGet(c.bindings, genericBody.sons[i-1]))
|
||||
if x == nil:
|
||||
discard "maybe fine (for eg. a==tyNil)"
|
||||
@@ -1639,7 +1646,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
let roota = a.skipGenericAlias
|
||||
let rootf = f.lastSon.skipGenericAlias
|
||||
if a.kind == tyGenericInst and roota.base == rootf.base:
|
||||
for i in 1 .. rootf.sonsLen-2:
|
||||
for i in 1 .. rootf.len-2:
|
||||
let ff = rootf.sons[i]
|
||||
let aa = roota.sons[i]
|
||||
result = typeRel(c, ff, aa)
|
||||
@@ -1654,8 +1661,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
of tyGenericParam:
|
||||
var x = PType(idTableGet(c.bindings, f))
|
||||
if x == nil:
|
||||
if c.callee.kind == tyGenericBody and
|
||||
f.kind == tyGenericParam and not c.typedescMatched:
|
||||
if c.callee.kind == tyGenericBody and not c.typedescMatched:
|
||||
# XXX: The fact that generic types currently use tyGenericParam for
|
||||
# their parameters is really a misnomer. tyGenericParam means "match
|
||||
# any value" and what we need is "match any type", which can be encoded
|
||||
@@ -1664,7 +1670,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
if tfWildcard in a.flags:
|
||||
result = isGeneric
|
||||
elif a.kind == tyTypeDesc:
|
||||
if f.sonsLen == 0:
|
||||
if f.len == 0:
|
||||
result = isGeneric
|
||||
else:
|
||||
internalAssert c.c.graph.config, a.len > 0
|
||||
@@ -1686,7 +1692,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
result = isNone
|
||||
else:
|
||||
# check if 'T' has a constraint as in 'proc p[T: Constraint](x: T)'
|
||||
if f.sonsLen > 0 and f.sons[0].kind != tyNone:
|
||||
if f.len > 0 and f.sons[0].kind != tyNone:
|
||||
let oldInheritancePenalty = c.inheritancePenalty
|
||||
result = typeRel(c, f.sons[0], a, flags + {trDontBind})
|
||||
if doBind and result notin {isNone, isGeneric}:
|
||||
@@ -1700,6 +1706,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
c.inheritancePenalty = oldInheritancePenalty - c.inheritancePenalty -
|
||||
100 * ord(result == isEqual)
|
||||
result = isGeneric
|
||||
elif a.kind == tyTypeDesc:
|
||||
# somewhat special typing rule, the following is illegal:
|
||||
# proc p[T](x: T)
|
||||
# p(int)
|
||||
result = isNone
|
||||
else:
|
||||
result = isGeneric
|
||||
|
||||
@@ -1889,7 +1900,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
dest = generateTypeInstance(c, m.bindings, arg, dest)
|
||||
let fdest = typeRel(m, f, dest)
|
||||
if fdest in {isEqual, isGeneric} and not (dest.kind == tyLent and f.kind == tyVar):
|
||||
markUsed(c.config, arg.info, c.converters[i], c.graph.usageSym)
|
||||
markUsed(c, arg.info, c.converters[i])
|
||||
var s = newSymNode(c.converters[i])
|
||||
s.typ = c.converters[i].typ
|
||||
s.info = arg.info
|
||||
@@ -2218,7 +2229,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||
else: result = nil
|
||||
else:
|
||||
# only one valid interpretation found:
|
||||
markUsed(m.c.config, arg.info, arg.sons[best].sym, m.c.graph.usageSym)
|
||||
markUsed(m.c, arg.info, arg.sons[best].sym)
|
||||
onUse(arg.info, arg.sons[best].sym)
|
||||
result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
|
||||
argOrig)
|
||||
@@ -2294,7 +2305,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
arg: PNode # current prepared argument
|
||||
formal: PSym # current routine parameter
|
||||
|
||||
defer:
|
||||
template noMatch() =
|
||||
m.state = csNoMatch
|
||||
m.firstMismatch.arg = a
|
||||
m.firstMismatch.formal = formal
|
||||
|
||||
@@ -2304,19 +2316,19 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
# better match over other routines with no such restriction:
|
||||
inc(m.genericMatches, 100)
|
||||
else:
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
|
||||
if formal.typ.kind == tyVar:
|
||||
let argConverter = if arg.kind == nkHiddenDeref: arg[0] else: arg
|
||||
if argConverter.kind == nkHiddenCallConv:
|
||||
if argConverter.typ.kind != tyVar:
|
||||
m.state = csNoMatch
|
||||
m.firstMismatch.kind = kVarNeeded
|
||||
noMatch()
|
||||
return
|
||||
elif not n.isLValue:
|
||||
m.state = csNoMatch
|
||||
m.firstMismatch.kind = kVarNeeded
|
||||
noMatch()
|
||||
return
|
||||
|
||||
m.state = csMatch # until proven otherwise
|
||||
@@ -2352,12 +2364,12 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
prepareNamedParam(n.sons[a], c)
|
||||
if n.sons[a].sons[0].kind != nkIdent:
|
||||
localError(c.config, n.sons[a].info, "named parameter has to be an identifier")
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
|
||||
formal = getNamedParamFromList(m.callee.n, n.sons[a].sons[0].ident)
|
||||
if formal == nil:
|
||||
# no error message!
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
if containsOrIncl(marker, formal.position):
|
||||
m.firstMismatch.kind = kAlreadyGiven
|
||||
@@ -2366,7 +2378,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
# bug #3836 of why that is not sound (other overload with
|
||||
# different parameter names could match later on):
|
||||
when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
m.baseTypeMatch = false
|
||||
m.typedescMatched = false
|
||||
@@ -2376,7 +2388,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
n.sons[a].sons[1], n.sons[a].sons[1])
|
||||
m.firstMismatch.kind = kTypeMismatch
|
||||
if arg == nil:
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
checkConstraint(n.sons[a].sons[1])
|
||||
if m.baseTypeMatch:
|
||||
@@ -2417,23 +2429,24 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
incrIndexType(container.typ)
|
||||
checkConstraint(n.sons[a])
|
||||
else:
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
else:
|
||||
m.firstMismatch.kind = kExtraArg
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
else:
|
||||
if m.callee.n.sons[f].kind != nkSym:
|
||||
internalError(c.config, n.sons[a].info, "matches")
|
||||
noMatch()
|
||||
return
|
||||
formal = m.callee.n.sons[f].sym
|
||||
m.firstMismatch.kind = kTypeMismatch
|
||||
if containsOrIncl(marker, formal.position) and container.isNil:
|
||||
m.firstMismatch.kind = kAlreadyGiven
|
||||
# already in namedParams: (see above remark)
|
||||
m.firstMismatch.kind = kPositionalAlreadyGiven
|
||||
# positional param already in namedParams: (see above remark)
|
||||
when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
|
||||
if formal.typ.isVarargsUntyped:
|
||||
@@ -2450,7 +2463,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
|
||||
n.sons[a], nOrig.sons[a])
|
||||
if arg == nil:
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
if m.baseTypeMatch:
|
||||
assert formal.typ.kind == tyVarargs
|
||||
@@ -2479,10 +2492,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||
# this assertion can be off
|
||||
localError(c.config, n.sons[a].info, "cannot convert $1 to $2" % [
|
||||
typeToString(n.sons[a].typ), typeToString(formal.typ) ])
|
||||
m.state = csNoMatch
|
||||
noMatch()
|
||||
return
|
||||
checkConstraint(n.sons[a])
|
||||
inc(a)
|
||||
# for some edge cases (see tdont_return_unowned_from_owned test case)
|
||||
m.firstMismatch.arg = a
|
||||
m.firstMismatch.formal = formal
|
||||
|
||||
proc semFinishOperands*(c: PContext, n: PNode) =
|
||||
# this needs to be called to ensure that after overloading resolution every
|
||||
@@ -2510,7 +2526,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
if m.state == csNoMatch: return
|
||||
# check that every formal parameter got a value:
|
||||
var f = 1
|
||||
while f < sonsLen(m.callee.n):
|
||||
while f < len(m.callee.n):
|
||||
var formal = m.callee.n.sons[f].sym
|
||||
if not containsOrIncl(marker, formal.position):
|
||||
if formal.ast == nil:
|
||||
@@ -2538,18 +2554,23 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
formal.name.s)
|
||||
if nfDefaultRefsParam in formal.ast.flags:
|
||||
m.call.flags.incl nfDefaultRefsParam
|
||||
var def = copyTree(formal.ast)
|
||||
if def.kind == nkNilLit:
|
||||
def = implicitConv(nkHiddenStdConv, formal.typ, def, m, c)
|
||||
var defaultValue = copyTree(formal.ast)
|
||||
if defaultValue.kind == nkNilLit:
|
||||
defaultValue = implicitConv(nkHiddenStdConv, formal.typ, defaultValue, m, c)
|
||||
# proc foo(x: T = 0.0)
|
||||
# foo()
|
||||
if {tfImplicitTypeParam, tfGenericTypeParam} * formal.typ.flags != {}:
|
||||
put(m, formal.typ, def.typ)
|
||||
def.flags.incl nfDefaultParam
|
||||
setSon(m.call, formal.position + 1, def)
|
||||
let existing = PType(idTableGet(m.bindings, formal.typ))
|
||||
if existing == nil or existing.kind == tyTypeDesc:
|
||||
# see bug #11600:
|
||||
put(m, formal.typ, defaultValue.typ)
|
||||
defaultValue.flags.incl nfDefaultParam
|
||||
setSon(m.call, formal.position + 1, defaultValue)
|
||||
inc(f)
|
||||
# forget all inferred types if the overload matching failed
|
||||
if m.state == csNoMatch:
|
||||
for t in m.inferredTypes:
|
||||
if t.sonsLen > 1: t.sons.setLen 1
|
||||
if t.len > 1: t.sons.setLen 1
|
||||
|
||||
proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
|
||||
var m: TCandidate
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user