Compare commits

...

632 Commits

Author SHA1 Message Date
Arne Döring
193b3c66bb fix #12426 (#12462)
(cherry picked from commit ec20fd3544)
2019-10-22 07:21:24 +02:00
Andreas Rumpf
0b134412f8 fixes #12310 [backport] (#12470)
(cherry picked from commit 38b3590e40)
2019-10-21 07:32:38 +02:00
ducdetronquito
1526ae8791 Namespace unittest enums to avoid name conflicts (#12468) [backport]
* [backport] Fixes: #12465 - Unittest - Namespace the usage of TestStatus enum to avoid name conflicts.

(cherry picked from commit df4c339cfc)
2019-10-21 07:32:38 +02:00
Andreas Rumpf
b914573d18 fixes #12420 [backport] (#12456)
(cherry picked from commit 832b0a0232)
2019-10-21 07:32:38 +02:00
Juan Carlos
f579d29b68 Fixes #8802 (#12439)
* Fix #8802

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12439#discussion_r335905397

(cherry picked from commit f5b4d9a2e5)
2019-10-21 07:32:38 +02:00
Juan Carlos
f79f7fed98 Fixes #10824 (#12437)
(cherry picked from commit 4d1f69c7d2)
2019-10-17 22:27:54 +02:00
Juan Carlos
e0c4015bbe Fix #10804 (#12438)
(cherry picked from commit 2cfd58de48)
2019-10-17 22:27:38 +02:00
Miran
7b500cbfad [backport] fix type's case in random.nim (#12445)
(cherry picked from commit a5ab502f08)
2019-10-17 22:25:51 +02:00
Andreas Rumpf
53e4692665 [backport] add back a check that got accidentically removed; fixes #12379 (#12444)
(cherry picked from commit 81125e2029)
2019-10-17 22:25:51 +02:00
Miran
b0e595b3cf [backport] fix #12418, fix random.randomize on JS backend (#12432)
(cherry picked from commit 5f5ac8ce16)
2019-10-17 22:25:51 +02:00
Yuriy Glukhov
4e3c997d40 Fixed yield in nkCheckedFieldExpr (#12429) [backport]
(cherry picked from commit 1aed455e7c)
2019-10-17 22:25:51 +02:00
Alexander Ivanov
f16bb4d85b Fixes semCustomPragma when nkSym (#12414) [backport]
(cherry picked from commit 990aadc43c)
2019-10-12 08:00:44 +02:00
genotrance
8f1dea614e Fixes #12286 - require explicit disabling of boehm interior pointer checking (#12406) [backport]
(cherry picked from commit 9e62876647)
2019-10-12 08:00:44 +02:00
Arne Döring
63d710f5a1 fix #12332 (#12402) [backport]
(cherry picked from commit 0a29c05a1b)
2019-10-12 08:00:44 +02:00
Andreas Rumpf
2ebd47089a fixes a koch regression that made 'koch boot --listcmd' not work anymore [backport] (#12400)
(cherry picked from commit d783c0f7ff)
2019-10-12 08:00:43 +02:00
Araq
535f0b9c9d fixes #12244 [backport]
(cherry picked from commit 7f904e2c66)
2019-10-12 08:00:43 +02:00
awr1
813b371758 [backport] Mention "lambdas" and => in the manual (#12397) [ci skip]
(so that "lambda" can be CTRL+F'd)

(cherry picked from commit 3b1760df72)
2019-10-12 08:00:43 +02:00
Andreas Rumpf
a09379f5fd fixes #12366 [backport] (#12393)
(cherry picked from commit f728614ef8)
2019-10-12 08:00:43 +02:00
narimiran
e9f7455bd6 bump version to 1.0.2 2019-10-09 06:42:54 +02:00
Andrew Smith
e03b1b79ae Updated the code example in the os module to use better grammar. (#12328)
(cherry picked from commit 0d94ee15c0)
2019-10-09 06:39:41 +02:00
Jasper Jenkins
0ea770c8f0 Macro docs additions (#12270)
* small macros doc additions

* more changes

* fixes [ci skip]

* capitalization, couple additions

* nkNodeKind to nnkNodeKind

(cherry picked from commit c20778d2d3)
2019-10-09 06:39:16 +02:00
Nindaleth
8a0012de42 fix a few dead links and a missing sentence in documentation (#12387)
(cherry picked from commit 84c956d9da)
2019-10-09 06:36:39 +02:00
treeform
1d4916b481 Easier build instructions for windows - just run build_all.bat. (#12276)
* Easier build instructions for windows.

* title letter

* Update build_all.bat to be like build_all.sh

(cherry picked from commit dbcffcfccb)
2019-10-09 06:36:19 +02:00
Ray Imber
2de758e68a Documentation improvements around the db interface (#12362)
Added more details about the limits and reasoning behind the API.
Came about from this discussion on IRC: https://irclogs.nim-lang.org/04-10-2019.html#16:58:04

(cherry picked from commit 7c23522b29)
2019-10-09 06:35:37 +02:00
pietroppeter
c8c9699850 [doc/tut1] removed discard discussion in comments (#12352)
(cherry picked from commit 89c37fada7)
2019-10-09 06:34:06 +02:00
kraptor
5df7f3fd5c Fix reference to parseSpec proc in readme (#12359)
(cherry picked from commit 412011eb96)
2019-10-09 06:33:45 +02:00
Andreas Rumpf
44d45b763c fixes #12315 [backport]; refs #12314 (#12385)
(cherry picked from commit f30da2f266)
2019-10-09 06:28:27 +02:00
alaviss
f7c150766a nimsuggest: fix tcp socket leak for epc backend (#12384) [backport]
Same as e9fa4c9b9c, but for the epc
backend which is used by emacs and vscode plugin.

Since the EPC backend only deal with one connection per nimsuggest
instance, only one socket is leaked, thus not as servere as with the tcp
backend.

(cherry picked from commit edb24b7ce0)
2019-10-09 06:28:27 +02:00
alaviss
4ae143ca60 nimsuggest: fix tcp socket leak (#12377) [backport]
A new socket is created for each iteration and leak immediately thanks
to the accept() call replacing the created socket with the client socket.

This commit fixes that.

(cherry picked from commit e9fa4c9b9c)
2019-10-09 06:28:27 +02:00
Leorize
0a8dcd5e11 azure: disable failing tests
(cherry picked from commit 73c8391fd3)
2019-10-08 11:43:16 +02:00
Leorize
929aa99665 testament: add azure integration
(cherry picked from commit acebcd7899)
2019-10-08 11:41:44 +02:00
Leorize
bae10d44fa azure-pipelines: add pipelines for linux, mac and win
This is the equivalent to the current AppVeyor + Travis setup.

(cherry picked from commit 880df4de62)
2019-10-08 11:41:38 +02:00
Andreas Rumpf
4632e8b26e fixes #12323 [backport]
(cherry picked from commit a60f18d025)
2019-10-07 18:40:07 +02:00
Andreas Rumpf
97e2e06b00 VM: no special casing for big endian machines; refs #9690 [backport] (#12364)
(cherry picked from commit 5be8e0b088)
2019-10-07 18:40:07 +02:00
Miran
b827431499 [backport] bundle nimpretty on Windows (#12358)
(cherry picked from commit 2909e41370)
2019-10-04 17:53:27 +02:00
Andrew Owen
99d448deeb [backport] Fix typo in docs (#12356) [ci skip]
(cherry picked from commit 64acc9dbfb)
2019-10-04 17:53:27 +02:00
Andreas Rumpf
9afd19b236 fixes #12291 [backport] (#12338)
(cherry picked from commit c51857f434)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
0d0cf86401 fixes #12336 [backport]
(cherry picked from commit 98e76a1058)
2019-10-03 09:32:46 +02:00
Tomohiro
5785444520 Fix how relativePath handle case sensitiviy (#12312) [backport]
(cherry picked from commit 64d5e25821)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
1b3f5eed70 fixes #12240 [backport] (#12308)
(cherry picked from commit 6dd4cbc3af)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
517538dcf8 fixes #12264 [backport] (#12302)
(cherry picked from commit dd082b6ec8)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
59916007cc fixes #12281 [backport]
(cherry picked from commit 72acf5de94)
2019-10-03 09:32:46 +02:00
Andreas Rumpf
a5bcbe6dff fixes #12294 [backport]
(cherry picked from commit 1964589a29)
2019-10-03 09:32:46 +02:00
narimiran
cd3d4b5e05 [backport] run nimpretty on the remaining files
(cherry picked from commit 5732bb41ef)
2019-09-30 18:43:36 +02:00
narimiran
ac2181c5b9 [backport] run nimpretty on os-related stuff
(cherry picked from commit 34d0be2ec1)
2019-09-30 18:43:36 +02:00
narimiran
4675aae90b [backport] run nimpretty on string stuff
(cherry picked from commit dcf3181bd1)
2019-09-30 18:43:36 +02:00
narimiran
a0402b2012 [backport] run nimpretty on web stuff
(cherry picked from commit 0ca9cc7419)
2019-09-30 18:43:36 +02:00
narimiran
cbdc48ec66 [backport] run nimpretty on hashes
(cherry picked from commit 15895ebc3f)
2019-09-30 18:43:36 +02:00
narimiran
f19edae1b8 [backport] run nimpretty on parsers
(cherry picked from commit b17ed2ca9c)
2019-09-30 18:43:36 +02:00
narimiran
c5b9a44894 [backport] run nimpretty on numbers stuff
(cherry picked from commit 6c994b2498)
2019-09-30 18:43:36 +02:00
narimiran
3009eafc89 [backport] run nimpretty on async
(cherry picked from commit aa513d78e7)
2019-09-30 18:43:35 +02:00
Araq
1e97abec96 JS: gensym is stricter for 'this'; refs #12246 [backport]
(cherry picked from commit 63bcbea700)
2019-09-30 18:43:35 +02:00
Araq
95a655a975 different fix for #12279 [backport]
(cherry picked from commit c5a1149e00)
2019-09-30 18:43:35 +02:00
Araq
39f5a2b218 fixes #12279 [backport]
(cherry picked from commit 86de2cddf6)
2019-09-30 18:43:35 +02:00
narimiran
6c1f389d72 [backport] fix nimpretty removing space before pragma
(cherry picked from commit f804245087)
2019-09-30 18:43:35 +02:00
narimiran
1ae9cac3a4 [backport] fix #12278, don't expose internal PCRE documentation
(cherry picked from commit e0cd52365c)
2019-09-30 18:43:35 +02:00
Federico Ceratto
fa7f5742d3 Fix spellings (#12277) [backport]
(cherry picked from commit 39290cf88c)
2019-09-30 18:43:35 +02:00
Endeg
c8314b7c9c Fix #12242, replacing ":" with "@c" in packages [backport] (#12265)
(cherry picked from commit 657e09e79d)
2019-09-30 18:40:12 +02:00
Jjp137
52ea15cc24 threadpool: fix link in docs [ci skip] (#12258) [backport]
[backport]

(cherry picked from commit e065e51245)
2019-09-30 18:40:00 +02:00
Andreas Rumpf
7926440ae3 fixes the --verbosity:2 regression [backport]
(cherry picked from commit 13960066cb)
2019-09-30 18:39:48 +02:00
narimiran
bda6e071cd nightly version is 1.0.1 2019-09-30 18:38:14 +02:00
narimiran
f7a8fc46c0 Revert "improvements for httpcore (#12228)"
This reverts commit b865c2a54b.
2019-09-23 19:06:55 +02:00
narimiran
5b43c98897 version 1.0 2019-09-23 14:42:19 +02:00
Andreas Rumpf
f388817a79 update the Nimble version we ship with Nim (#12236) 2019-09-23 14:24:36 +02:00
Andreas Rumpf
b865c2a54b improvements for httpcore (#12228)
* improvements for httpcore
* further improvements, now stable API but needs extensions later on
2019-09-23 12:38:35 +02:00
Ray Imber
6e681b546f fixes #9026 adds a readLineImpl to streams so that FileStreams can be fast (#12234) 2019-09-23 08:25:26 +02:00
PMunch
2565d3d102 Fix issue with long wait for passed timer [bugfix] (#12221)
* Fix issue with long wait for passed timer [bugfix]

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

* Refactor logic into

* Add test case based on original issue

* Use longer timeouts to be more lenient in checking

* Revert to short timeouts, but widen the accepted range

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

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

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

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

* add doc comment.

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

* Change to androidNDK and add docs.

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

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

* spacing

* only do 64bts on x86

* add amd64

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

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

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

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

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

* Fix test

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

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

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

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

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

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

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

* remove previous fix and fix differently after all

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

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

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

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

* Add build support for FreeBSD PowerPC64

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

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

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

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

* Reimplement isExported using VM callback mechanism

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

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

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

* Improve wording in comment

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

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

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

* Async test for HTTP/1.1 without Content-Length

* Apply suggestions from code review

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

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

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

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

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

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

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

* more tests and fixes

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

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

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

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

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

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

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

* tests/assert: enable excessiveStackTrace

* tests/assert: add test case for #11545

* tfailedassert_stacktrace: disable excessiveStackTrace

* assertions: weird workaround for failing tests

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

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

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

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

* ccgstmt: use quotedFilename() for raiseExceptionEx

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

Fixes #11572

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

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

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

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

* compiler/msgs: use toMsgFilename for toFileLineCol

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

* compiler/msgs: remove toFileLine

unused proc

* compiler/msgs: cleanup toMsgFilename

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

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

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

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

View File

@@ -56,6 +56,7 @@ addons:
- boehmgc
- make
- sfml
update: true
install:
- if [[ $CPU = i386 ]]; then echo -e "#!/bin/bash\n$(which gcc) -m32 \"\$@\"" > bin/gcc; fi

View File

@@ -1,14 +1,11 @@
version: '{build}'
environment:
DLLS_URL: https://nim-lang.org/download/dlls.zip
DLLS_ARCHIVE: dlls.zip
MINGW_DIR: mingw64
MINGW_URL: https://nim-lang.org/download/mingw64-6.3.0.7z
MINGW_ARCHIVE: mingw64-6.3.0.7z
OPENBLAS_URL: https://sourceforge.net/projects/openblas/files/v0.3.5/OpenBLAS%200.3.5%20version.zip/download
OPENBLAS_ARCHIVE: OpenBLAS-0.3.5.zip
SQLITE_URL: http://www.sqlite.org/2017/sqlite-dll-win64-x64-3160200.zip
SQLITE_ARCHIVE: sqlite-dll-win64-x64-3160200.zip
platform: x64
matrix:
- NIM_TEST_PACKAGES: false
@@ -16,33 +13,19 @@ environment:
cache:
- '%MINGW_ARCHIVE%'
- '%SQLITE_ARCHIVE%'
- '%OPENBLAS_ARCHIVE%'
- '%DLLS_ARCHIVE%'
matrix:
#allow_failures:
# - NIM_TEST_PACKAGES: true
fast_finish: true
install:
- ps: Install-Product node 8 # node 8 or later is required to test js async stuff
- MKDIR %CD%\DIST
- MKDIR %CD%\DIST\PCRE
- nuget install pcre -Verbosity quiet -Version 8.33.0.1 -OutputDirectory %CD%\DIST\PCRE
- IF not exist "%SQLITE_ARCHIVE%" appveyor DownloadFile "%SQLITE_URL%" -FileName "%SQLITE_ARCHIVE%"
- 7z x -y "%SQLITE_ARCHIVE%" -o"%CD%\DIST"> nul
- IF not exist "%DLLS_ARCHIVE%" appveyor DownloadFile "%DLLS_URL%" -FileName "%DLLS_ARCHIVE%"
- 7z x -y "%DLLS_ARCHIVE%" -o"%CD%\BIN"> nul
- IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%"
- 7z x -y "%MINGW_ARCHIVE%" -o"%CD%\DIST"> nul
- IF not exist "%OPENBLAS_ARCHIVE%" appveyor DownloadFile "%OPENBLAS_URL%" -FileName "%OPENBLAS_ARCHIVE%"
- 7z x -y "%OPENBLAS_ARCHIVE%" -o"%CD%\DIST"> nul
- SET PATH=%CD%\DIST\%MINGW_DIR%\BIN;%CD%\BIN;%PATH%
- IF "%PLATFORM%" == "x64" ( copy C:\OpenSSL-Win64\libeay32.dll %CD%\BIN\libeay64.dll & copy C:\OpenSSL-Win64\libeay32.dll %CD%\BIN\libeay32.dll & copy C:\OpenSSL-Win64\libssl32.dll %CD%\BIN\libssl64.dll & copy C:\OpenSSL-Win64\libssl32.dll %CD%\BIN\libssl32.dll )
ELSE ( copy C:\OpenSSL-Win32\libeay32.dll %CD%\BIN\libeay32.dll & copy C:\OpenSSL-Win32\libssl32.dll %CD%\BIN\libssl32.dll )
- IF "%PLATFORM%" == "x64" ( copy %CD%\DIST\sqlite3.dll %CD%\BIN\sqlite3_64.dll ) ELSE ( copy %CD%\DIST\sqlite3.dll %CD%\BIN\sqlite3_32.dll )
- IF "%PLATFORM%" == "x64" ( copy %CD%\DIST\PCRE\pcre.redist.8.33.0.1\build\native\bin\v100\x64\Release\dynamic\utf8\pcre8.dll %CD%\bin\pcre64.dll ) ELSE ( copy %CD%\DIST\PCRE\pcre.redist.8.33.0.1\build\native\bin\v100\Win32\Release\dynamic\utf8\pcre8.dll %CD%\bin\pcre32.dll )
- git clone --depth 1 https://github.com/nim-lang/csources
- cd csources
- IF "%PLATFORM%" == "x64" ( build64.bat ) else ( build.bat )
- build64.bat
- cd ..
build_script:

148
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,148 @@
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-16.04'
CPU: amd64
Linux_i386:
vmImage: 'ubuntu-16.04'
CPU: i386
OSX_amd64:
vmImage: 'macOS-10.14'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-10.14'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64:
vmImage: 'windows-2019'
CPU: amd64
Windows_amd64_pkg:
vmImage: 'windows-2019'
CPU: amd64
NIM_TEST_PACKAGES: true
pool:
vmImage: $(vmImage)
workspace:
clean: all
steps:
- bash: git config --global core.autocrlf false
displayName: 'Disable auto conversion to CRLF by git (Windows-only)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- checkout: self
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
displayName: 'Checkout csources'
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install node.js 8.x'
- bash: |
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev
displayName: 'Install dependencies (amd64 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
- bash: |
sudo dpkg --add-architecture i386
# Downgrade llvm, libgcc and libstdc++:
# - llvm has to be downgraded to have 32bit version installed for sfml.
# - libgcc and libstdc++ have to be downgraded as an optimization to
# prevent the use of the toolchain ppa, which has a terrible download
# speed.
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
Package: libllvm6.0 libgcc1 libstdc++6
Pin: origin "azure.archive.ubuntu.com"
Pin-Priority: 1001
Package: *
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
Pin-Priority: 100
EOF
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386
cat << EOF > bin/gcc
#!/bin/bash
exec $(which gcc) -m32 "\$@"
EOF
cat << EOF > bin/g++
#!/bin/bash
exec $(which g++) -m32 "\$@"
EOF
chmod 755 bin/gcc
chmod 755 bin/g++
displayName: 'Install dependencies (i386 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'i386'))
- bash: brew install boehmgc make sfml
displayName: 'Install dependencies (OSX)'
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64-6.3.0.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/dist/mingw64/bin'
displayName: 'Install dependencies (Windows)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/bin'
displayName: 'Add build binaries to PATH'
- bash: |
echo 'PATH:' "$PATH"
echo '##[section]gcc version'
gcc -v
echo '##[section]nodejs version'
node -v
echo '##[section]make version'
make -v
displayName: 'System information'
- bash: |
ncpu=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
;;
'Darwin')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
displayName: 'Build csources'
- bash: nim c koch
displayName: 'Build koch'
# set result to omit the "bash exited with error code '1'" message
- bash: |
./koch runCI || echo '##vso[task.complete result=Failed]'
displayName: 'Run CI'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

16
build_all.bat Normal file
View File

@@ -0,0 +1,16 @@
@echo off
rem build development version of the compiler; can be rerun safely
if not exist csources (
git clone --depth 1 https://github.com/nim-lang/csources.git
)
if not exist bin\nim.exe (
cd csources
if PROCESSOR_ARCHITECTURE == AMD64 (
SET ARCH=64
)
CALL build.bat
cd ..
)
bin\nim.exe c --skipUserCfg --skipParentCfg koch
koch.exe boot -d:release
koch.exe tools

View File

@@ -1,25 +1,32 @@
## v0.20.2 - 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
## Changes affecting backwards compatibility
### Language additions
### Breaking changes in the standard library
### Breaking changes in the compiler
## Library additions
## Library changes
## Language additions
## Language changes
### Language changes
### Tool changes
@@ -30,4 +37,5 @@
### Bugfixes
## Bugfixes

View File

@@ -0,0 +1,55 @@
# v0.20.2 - 2019-07-17
## Changes affecting backwards compatibility
- All `strutils.rfind` procs now take `start` and `last` like `strutils.find`
with the same data slice/index meaning. This is backwards compatible for
calls *not* changing the `rfind` `start` parameter from its default. (#11487)
In the unlikely case that you were using `rfind X, start=N`, or `rfind X, N`,
then you need to change that to `rfind X, last=N` or `rfind X, 0, N`. (This
should minimize gotchas porting code from other languages like Python or C++.)
- On Windows stderr/stdout/stdin are not opened as binary files anymore. Use the switch
`-d:nimBinaryStdFiles` for a transition period.
### Breaking changes in the standard library
- Mac OS X / BSD: TSa_Family is now the ``uint8`` type, so type
conversions like ``x.sin_family = uint16 toInt(nativesockets.AF_INET)``
need to be changed into ``x.sin_family = TSa_Family toInt(nativesockets.AF_INET)``.
### Breaking changes in the compiler
## Library additions
- `toOpenArray` is now available for the JS target.
## Library changes
- Fix async IO operations stalling even after socket is closed. (#11232)
- More informative error message for `streams.openFileStream`. (#11438)
## Language additions
## Language changes
### Tool changes
### Compiler changes
- Better error message for IndexError for empty containers. (#11476)
- Fix regression in semfold for old right shift. (#11477)
- Fix for passing tuples as static params to macros. (#11423)
## Bugfixes

View File

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

View File

@@ -1,27 +1,33 @@
## v0.XX.0 - XX/XX/2018
### Changes affecting backwards compatibility
- Example item: ``Foo`` changed to ``Bar``.
#### Breaking changes in the standard library
# vx.xx.x - yyyy-mm-dd
#### Breaking changes in the compiler
## Changes affecting backwards compatibility
### Library additions
### Library changes
- Example item: `Foo` changed to `Bar`.
### Language additions
### Breaking changes in the standard library
### Language changes
### Breaking changes in the compiler
## Library additions
- `set[T].len` is now an alias for `set[T].card` (cardinality)
## Library changes
## Language additions
## Language changes
### Tool changes
### Compiler changes
### Bugfixes
## Bugfixes

View File

@@ -10,7 +10,7 @@
## Simple alias analysis for the HLO and the code generators.
import
ast, astalgo, types, trees, intsets, msgs
ast, astalgo, types, trees, intsets
type
TAnalysisResult* = enum
@@ -22,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
@@ -186,7 +186,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
if res != arNo:
result = res
if res == arYes: break
of nkCall:
of nkCallKinds:
result = arNo
for i in 1 ..< b.len:
let res = isPartOf(a, b[i])

View File

@@ -71,7 +71,7 @@ iterator parseTableCells*(s: string, delim = '\t'): Cell =
proc alignTable*(s: string, delim = '\t', fill = ' ', sep = " "): string =
## formats a `delim`-delimited `s` representing a table; each cell is aligned
## to a width that's computed for each column; consecutive columns are
## delimted by `sep`, and alignment space is filled using `fill`.
## delimited by `sep`, and alignment space is filled using `fill`.
## More customized formatting can be done by calling `parseTableCells` directly.
for cell in parseTableCells(s, delim):
result.add cell.text

View File

@@ -10,8 +10,9 @@
# abstract syntax tree + symbol table
import
lineinfos, hashes, nversion, options, strutils, std / sha1, ropes, idents,
intsets, idgen
lineinfos, hashes, options, ropes, idents, idgen, int128
export int128
type
TCallingConvention* = enum
@@ -184,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
@@ -227,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
@@ -238,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
@@ -270,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
@@ -279,6 +281,9 @@ type
sfNonReloadable # symbol will be left as-is when hot code reloading is on -
# meaning that it won't be renamed and/or changed in any way
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]
@@ -530,8 +535,8 @@ 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.
@@ -605,7 +610,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,
@@ -618,13 +622,7 @@ type
mXor, mEqCString, mEqProc,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
mZe8ToI, mZe8ToI64,
mZe16ToI, mZe16ToI64,
mZe32ToI64, mZeIToI64,
mToU8, mToU16, mToU32,
mToFloat, mToBiggestFloat,
mToInt, mToBiggestInt,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
@@ -668,7 +666,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
@@ -681,7 +680,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,
@@ -692,13 +690,7 @@ const
mEqB, mLeB, mLtB,
mEqRef, mEqProc, mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64, mAbsF64,
mZe8ToI, mZe8ToI64,
mZe16ToI, mZe16ToI64,
mZe32ToI64, mZeIToI64,
mToU8, mToU16, mToU32,
mToFloat, mToBiggestFloat,
mToInt, mToBiggestInt,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
@@ -764,7 +756,9 @@ type
lfImportCompilerProc, # ``importc`` of a compilerproc
lfSingleUse # no location yet and will only be used once
lfEnforceDeref # a copyMem is required to dereference if this a
# ptr array due to C array limitations. See #1181, #6422, #11171
# ptr array due to C array limitations.
# See #1181, #6422, #11171
lfPrepareForMutation # string location is about to be mutated (V2)
TStorageLoc* = enum
OnUnknown, # location is unknown (stack, heap or static)
OnStatic, # in a static section
@@ -859,7 +853,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
@@ -906,6 +899,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
@@ -1029,7 +1023,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:
@@ -1053,8 +1049,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
@@ -1062,7 +1056,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 =
@@ -1240,10 +1234,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
@@ -1310,7 +1342,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:
@@ -1319,21 +1351,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
@@ -1351,8 +1368,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)
@@ -1428,14 +1445,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
@@ -1474,14 +1483,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
@@ -1514,7 +1523,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)
@@ -1555,7 +1564,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
@@ -1576,12 +1585,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
@@ -1599,30 +1608,43 @@ proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
case n.kind
of nkEmpty..nkNilLit: result = n.kind in kinds
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if n.kind in kinds or containsNode(n.sons[i], kinds): return true
proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
case n.kind
of nkEmpty..nkNilLit: result = n.kind == kind
else:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
return true
result = false
proc getInt*(a: PNode): BiggestInt =
proc getInt*(a: PNode): Int128 =
case a.kind
of nkCharLit..nkUInt64Lit: result = a.intVal
of nkCharLit, nkUIntLit..nkUInt64Lit:
result = toInt128(cast[uint64](a.intVal))
of nkInt8Lit..nkInt64Lit:
result = toInt128(a.intVal)
of nkIntLit:
# XXX: enable this assert
# assert a.typ.kind notin {tyChar, tyUint..tyUInt64}
result = toInt128(a.intVal)
else:
raiseRecoverableError("cannot extract number from invalid AST node")
proc getInt64*(a: PNode): int64 {.deprecated: "use getInt".} =
case a.kind
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
result = a.intVal
else:
raiseRecoverableError("cannot extract number from invalid AST node")
#internalError(a.info, "getInt")
#doAssert false, "getInt"
#result = 0
proc getFloat*(a: PNode): BiggestFloat =
case a.kind
of nkFloatLiterals: result = a.floatVal
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
result = BiggestFloat a.intVal
else:
raiseRecoverableError("cannot extract number from invalid AST node")
#doAssert false, "getFloat"

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,9 @@ proc intLiteral(i: BiggestInt): Rope =
else:
result = ~"(IL64(-9223372036854775807) - IL64(1))"
proc intLiteral(i: Int128): Rope =
intLiteral(toInt64(i))
proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
case n.kind
of nkCharLit..nkUInt64Lit:
@@ -76,7 +79,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
# with the new semantics for 'nil' strings, we can map "" to nil and
# save tons of allocations:
if n.strVal.len == 0 and optNilSeqs notin p.options and
p.config.selectedGc != gcDestructors:
p.config.selectedGC != gcDestructors:
result = genNilStringLiteral(p.module, n.info)
else:
result = genStringLiteral(p.module, n)
@@ -93,26 +96,30 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
proc genLiteral(p: BProc, n: PNode): Rope =
result = genLiteral(p, n, n.typ)
proc bitSetToWord(s: TBitSet, size: int): BiggestInt =
proc bitSetToWord(s: TBitSet, size: int): BiggestUInt =
result = 0
for j in 0 ..< size:
if j < len(s): result = result or (ze64(s[j]) shl (j * 8))
if j < len(s): result = result or (BiggestUInt(s[j]) shl (j * 8))
proc genRawSetData(cs: TBitSet, size: int): Rope =
if size > 8:
result = "{$n" % []
var res = "{\n"
for i in 0 ..< size:
res.add "0x"
res.add "0123456789abcdef"[cs[i] div 16]
res.add "0123456789abcdef"[cs[i] mod 16]
if i < size - 1:
# not last iteration?
if (i + 1) mod 8 == 0:
addf(result, "0x$1,$n", [rope(toHex(ze64(cs[i]), 2))])
# not last iteration
if i mod 8 == 7:
res.add ",\n"
else:
addf(result, "0x$1, ", [rope(toHex(ze64(cs[i]), 2))])
res.add ", "
else:
addf(result, "0x$1}$n", [rope(toHex(ze64(cs[i]), 2))])
res.add "}\n"
result = rope(res)
else:
result = intLiteral(bitSetToWord(cs, size))
# result := rope('0x' + ToHex(bitSetToWord(cs, size), size * 2))
result = intLiteral(cast[BiggestInt](bitSetToWord(cs, size)))
proc genSetNode(p: BProc, n: PNode): Rope =
var cs: TBitSet
@@ -356,7 +363,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
else:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
tyInt..tyUInt64, tyRange, tyVar, tyLent:
tyInt..tyUInt64, tyRange, tyVar, tyLent, tyNil:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
else: internalError(p.config, "genAssignment: " & $ty.kind)
@@ -581,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))")
@@ -635,28 +640,6 @@ proc genIsNil(p: BProc, e: PNode, d: var TLoc) =
unaryExpr(p, e, d, "($1 == 0)")
proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
const
unArithTab: array[mNot..mToBiggestInt, string] = [
"!($1)", # Not
"$1", # UnaryPlusI
"($3)((NU$2) ~($1))", # BitnotI
"$1", # UnaryPlusF64
"-($1)", # UnaryMinusF64
"($1 < 0? -($1) : ($1))", # AbsF64; BUGFIX: fabs() makes problems
# for Tiny C, so we don't use it
"(($3)(NU)(NU8)($1))", # mZe8ToI
"(($3)(NU64)(NU8)($1))", # mZe8ToI64
"(($3)(NU)(NU16)($1))", # mZe16ToI
"(($3)(NU64)(NU16)($1))", # mZe16ToI64
"(($3)(NU64)(NU32)($1))", # mZe32ToI64
"(($3)(NU64)(NU)($1))", # mZeIToI64
"(($3)(NU8)(NU)($1))", # ToU8
"(($3)(NU16)(NU)($1))", # ToU16
"(($3)(NU32)(NU64)($1))", # ToU32
"((double) ($1))", # ToFloat
"((double) ($1))", # ToBiggestFloat
"float64ToInt32($1)", # ToInt
"float64ToInt64($1)"] # ToBiggestInt
var
a: TLoc
t: PType
@@ -667,7 +650,6 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
template applyFormat(frmt: untyped) =
putIntoDest(p, d, e, frmt % [rdLoc(a), rope(getSize(p.config, t) * 8),
getSimpleTypeDesc(p.module, e.typ)])
case op
of mNot:
applyFormat("!($1)")
@@ -679,35 +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 mZe8ToI:
applyFormat("(($3)(NU)(NU8)($1))")
of mZe8ToI64:
applyFormat("(($3)(NU64)(NU8)($1))")
of mZe16ToI:
applyFormat("(($3)(NU)(NU16)($1))")
of mZe16ToI64:
applyFormat("(($3)(NU64)(NU16)($1))")
of mZe32ToI64:
applyFormat("(($3)(NU64)(NU32)($1))")
of mZeIToI64:
applyFormat("(($3)(NU64)(NU)($1))")
of mToU8:
applyFormat("(($3)(NU8)(NU)($1))")
of mToU16:
applyFormat("(($3)(NU16)(NU)($1))")
of mToU32:
applyFormat("(($3)(NU32)(NU64)($1))")
of mToFloat:
applyFormat("((double) ($1))")
of mToBiggestFloat:
applyFormat("((double) ($1))")
of mToInt:
applyFormat("float64ToInt32($1)")
of mToBiggestInt:
applyFormat("float64ToInt64($1)")
else:
assert false, $op
@@ -844,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)
@@ -859,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",
@@ -978,6 +932,10 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
if d.k == locNone: d.storage = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
a.r = ropecg(p.module, "(*$1)", [a.r])
if lfPrepareForMutation in d.flags and ty.kind == tyString and
p.config.selectedGC == gcDestructors:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
putIntoDest(p, d, n,
ropecg(p.module, "$1$3[$2]", [rdLoc(a), rdCharLoc(b), dataField(p)]), a.storage)
@@ -1069,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:
@@ -1102,7 +1060,7 @@ proc gcUsage(conf: ConfigRef; n: PNode) =
if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree)
proc strLoc(p: BProc; d: TLoc): Rope =
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
result = byRefLoc(p, d)
else:
result = rdLoc(d)
@@ -1129,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:
@@ -1168,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:
@@ -1235,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
@@ -1252,7 +1212,7 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
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:
@@ -1343,11 +1303,17 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
let seqtype = skipTypes(e.typ, abstractVarRange)
var a: TLoc
initLocExpr(p, e.sons[1], a)
putIntoDest(p, d, e, ropecg(p.module,
"($1)#nimNewSeqOfCap($2, $3)", [
getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype, e.info), a.rdLoc]))
gcUsage(p.config, e)
if p.config.selectedGC == gcDestructors:
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false)
linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
[d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype)])
else:
putIntoDest(p, d, e, ropecg(p.module,
"($1)#nimNewSeqOfCap($2, $3)", [
getTypeDesc(p.module, seqtype),
genTypeInfo(p.module, seqtype, e.info), a.rdLoc]))
gcUsage(p.config, e)
proc genConstExpr(p: BProc, n: PNode): Rope
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
@@ -1436,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",
@@ -1446,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
@@ -1467,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",
@@ -1681,11 +1647,14 @@ proc makePtrType(baseType: PType): PType =
addSonSkipIntLit(result, baseType)
proc makeAddr(n: PNode): PNode =
result = newTree(nkHiddenAddr, n)
result.typ = makePtrType(n.typ)
if n.kind == nkHiddenAddr:
result = n
else:
result = newTree(nkHiddenAddr, n)
result.typ = makePtrType(n.typ)
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
e.sons[1] = makeAddr(e[1])
genCall(p, e, d)
return
@@ -1714,7 +1683,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
gcUsage(p.config, e)
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
binaryStmtAddr(p, e, d, "setLengthStrV2")
else:
var a, b, call: TLoc
@@ -1759,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)])
@@ -1792,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:
@@ -1928,7 +1897,7 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
if srcTyp.kind in {tyPtr, tyPointer} and etyp.kind in IntegralTypes:
putIntoDest(p, d, e, "(($1) (ptrdiff_t) ($2))" %
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
elif p.config.selectedGc == gcDestructors and etyp.kind in {tySequence, tyString}:
elif p.config.selectedGC == gcDestructors and etyp.kind in {tySequence, tyString}:
putIntoDest(p, d, e, "(*($1*) (&$2))" %
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.storage)
else:
@@ -2056,25 +2025,26 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
resetLoc(p, a)
proc genDestroy(p: BProc; n: PNode) =
if optNimV2 in p.config.globalOptions:
let t = n[1].typ.skipTypes(abstractInst)
if p.config.selectedGC == gcDestructors:
let arg = n[1].skipAddr
let t = arg.typ.skipTypes(abstractInst)
case t.kind
of tyString:
var a: TLoc
initLocExpr(p, n[1].skipAddr, a)
linefmt(p, cpsStmts, "if ($1.len && $1.p->allocator) {$n" &
initLocExpr(p, arg, a)
linefmt(p, cpsStmts, "if ($1.p && $1.p->allocator) {$n" &
" $1.p->allocator->dealloc($1.p->allocator, $1.p, $1.p->cap + 1 + sizeof(NI) + sizeof(void*)); }$n",
[rdLoc(a)])
of tySequence:
var a: TLoc
initLocExpr(p, n[1].skipAddr, a)
linefmt(p, cpsStmts, "if ($1.len && $1.p->allocator) {$n" &
initLocExpr(p, arg, a)
linefmt(p, cpsStmts, "if ($1.p && $1.p->allocator) {$n" &
" $1.p->allocator->dealloc($1.p->allocator, $1.p, ($1.p->cap * sizeof($2)) + sizeof(NI) + sizeof(void*)); }$n",
[rdLoc(a), getTypeDesc(p.module, t.lastSon)])
else: discard "nothing to do"
else:
let t = n[1].typ.skipTypes(abstractVar)
if t.destructor != nil and t.destructor.magic != mDestroy:
if t.destructor != nil and t.destructor.ast[bodyPos].len != 0:
internalError(p.config, n.info, "destructor turned out to be not trivial")
discard "ignore calls to the default destructor"
@@ -2113,7 +2083,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)
@@ -2161,7 +2131,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
genAssignment(p, dest, call, {})
of mAppendStrStr: genStrAppend(p, e, d)
of mAppendSeqElem:
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
e.sons[1] = makeAddr(e[1])
genCall(p, e, d)
else:
@@ -2195,6 +2165,22 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if not p.module.compileToCpp:
p.module.includeHeader("<stdalign.h>")
putIntoDest(p, d, e, "((NI)alignof($1))" % [getTypeDesc(p.module, t)])
of mOffsetOf:
var dotExpr: PNode
block findDotExpr:
if e[1].kind == nkDotExpr:
dotExpr = e[1]
elif e[1].kind == nkCheckedFieldExpr:
dotExpr = e[1][0]
else:
internalError(p.config, e.info, "unknown ast")
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
let member =
if t.kind == tyTuple:
"Field" & rope(dotExpr[1].sym.position)
else:
rope(dotExpr[1].sym.name.s)
putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [getTypeDesc(p.module, t), member])
of mChr: genSomeCast(p, e, d)
of mOrd: genOrd(p, e, d)
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
@@ -2255,8 +2241,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mNLen..mNError, mSlurp..mQuoteAst:
localError(p.config, e.info, strutils.`%`(errXMustBeCompileTime, e.sons[0].sym.name.s))
of mSpawn:
let n = lowerings.wrapProcForSpawn(p.module.g.graph, p.module.module, e, e.typ, nil, nil)
expr(p, n, d)
when defined(leanCompiler):
quit "compiler built without support for the 'spawn' statement"
else:
let n = spawn.wrapProcForSpawn(p.module.g.graph, p.module.module, e, e.typ, nil, nil)
expr(p, n, d)
of mParallel:
when defined(leanCompiler):
quit "compiler built without support for the 'parallel' statement"
@@ -2276,7 +2265,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
@@ -2334,7 +2323,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)
@@ -2376,7 +2365,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)
@@ -2546,6 +2535,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})
@@ -2696,9 +2688,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
(sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
(prc.kind == skMethod):
# we have not only the header:
if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags:
genProc(p.module, prc)
# Generate proc even if empty body, bugfix #11651.
genProc(p.module, prc)
of nkParForStmt: genParForStmt(p, n)
of nkState: genState(p, n)
of nkGotoState:
@@ -2718,9 +2709,14 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
of tyBool: result = rope"NIM_FALSE"
of tyEnum, tyChar, tyInt..tyInt64, tyUInt..tyUInt64: result = rope"0"
of tyFloat..tyFloat128: result = rope"0.0"
of tyCString, tyString, tyVar, tyLent, tyPointer, tyPtr, tySequence, tyUntyped,
of tyCString, tyVar, tyLent, tyPointer, tyPtr, tyUntyped,
tyTyped, tyTypeDesc, tyStatic, tyRef, tyNil:
result = rope"NIM_NIL"
of tyString, tySequence:
if p.config.selectedGC == gcDestructors:
result = rope"{0, NIM_NIL}"
else:
result = rope"NIM_NIL"
of tyProc:
if t.callConv != ccClosure:
result = rope"NIM_NIL"
@@ -2744,14 +2740,15 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
else:
globalError(p.config, info, "cannot create null element for: " & $t.kind)
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, result: var Rope; count: var int) =
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode,
result: var Rope; count: var int) =
case obj.kind
of nkRecList:
for it in obj.sons:
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 ", "
@@ -2770,7 +2767,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, result: var Rope; cou
else:
localError(p.config, cons.info, "cannot create null element for: " & $obj)
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode, result: var Rope; count: var int) =
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode,
result: var Rope; count: var int) =
var base = t.sons[0]
let oldRes = result
if not p.module.compileToCpp: result.add "{"
@@ -2783,7 +2781,7 @@ proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode, result: var Ro
inc count
getNullValueAux(p, t, obj, cons, result, count)
# do not emit '{}' as that is not valid C:
if oldcount == count: result = oldres
if oldcount == count: result = oldRes
elif not p.module.compileToCpp: result.add "}"
proc genConstObjConstr(p: BProc; n: PNode): Rope =
@@ -2798,7 +2796,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])])
@@ -2857,7 +2855,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
of nkBracket, nkPar, nkTupleConstr, nkClosure:
var t = skipTypes(n.typ, abstractInstOwned)
if t.kind == tySequence:
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
result = genConstSeqV2(p, n, n.typ)
else:
result = genConstSeq(p, n, n.typ)
@@ -2881,7 +2879,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
of nkObjConstr:
result = genConstObjConstr(p, n)
of nkStrLit..nkTripleStrLit:
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
result = genStringLiteralV2Const(p.module, n)
else:
var d: TLoc

View File

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

View File

@@ -11,8 +11,8 @@
## is needed for incremental compilation.
import
ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
intsets, platform, llstream, tables, sighashes, modulegraphs, pathutils
ast, ropes, options, strutils, nimlexbase, cgendata, rodutils,
intsets, llstream, tables, modulegraphs, pathutils
# Careful! Section marks need to contain a tabulator so that they cannot
# be part of C string literals.

View File

@@ -15,7 +15,7 @@ const
stringCaseThreshold = 8
# above X strings a hash-switch for strings is generated
proc getTraverseProc(p: BProc, v: Psym): Rope =
proc getTraverseProc(p: BProc, v: PSym): Rope =
if p.config.selectedGC in {gcMarkAndSweep, gcDestructors, gcV2, gcRefc} and
optNimV2 notin p.config.globalOptions and
containsGarbageCollectedRef(v.loc.t):
@@ -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
@@ -690,7 +691,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
lineCg(p, cpsStmts, "#raiseExceptionEx((#Exception*)$1, $2, $3, $4, $5);$n",
[e, makeCString(typ.sym.name.s),
makeCString(if p.prc != nil: p.prc.name.s else: p.module.module.name.s),
makeCString(toFileName(p.config, t.info)), toLinenumber(t.info)])
quotedFilename(p.config, t.info), toLinenumber(t.info)])
if optNimV2 in p.config.globalOptions:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [e])
else:
@@ -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", [])
@@ -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)])
@@ -1266,11 +1243,13 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs))
initLoc(a, locNone, le, OnUnknown)
a.flags.incl(lfEnforceDeref)
a.flags.incl(lfPrepareForMutation)
expr(p, le, a)
a.flags.excl(lfPrepareForMutation)
if fastAsgn: incl(a.flags, lfNoDeepCopy)
assert(a.t != nil)
genLineDir(p, ri)
loadInto(p, e.sons[0], ri, a)
loadInto(p, le, ri, a)
else:
genLineDir(p, e)
asgnFieldDiscriminant(p, e)

View File

@@ -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])

View File

@@ -61,7 +61,7 @@ proc mangleParamName(m: BModule; s: PSym): Rope =
var res = s.name.s.mangle
# Take into account if HCR is on because of the following scenario:
# if a module gets imported and it has some more importc symbols in it,
# some param names might recieve the "_0" suffix to distinguish from what
# some param names might receive the "_0" suffix to distinguish from what
# is newly available. That might lead to changes in the C code in nimcache
# that contain only a parameter name change, but that is enough to mandate
# recompilation of that source file and thus a new shared object will be
@@ -155,6 +155,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tyNone, tyTyped: result = ctVoid
of tyBool: result = ctBool
of tyChar: result = ctChar
of tyNil: result = ctPtr
of tySet: result = mapSetType(conf, typ)
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctArray
of tyObject, tyTuple: result = ctStruct
@@ -286,6 +287,7 @@ proc fillResult(conf: ConfigRef; param: PNode) =
proc typeNameOrLiteral(m: BModule; t: PType, literal: string): Rope =
if t.sym != nil and sfImportc in t.sym.flags and t.sym.magic == mNone:
useHeader(m, t.sym)
result = t.sym.loc.r
else:
result = rope(literal)
@@ -329,6 +331,9 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
addAbiCheck(m, typ, result)
proc pushType(m: BModule, typ: PType) =
for i in 0 .. high(m.typeStack):
# pointer equality is good enough here:
if m.typeStack[i] == typ: return
add(m.typeStack, typ)
proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
@@ -384,14 +389,53 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
result = getTypeForward(m, t, hashType(t))
pushType(m, t)
of tySequence:
let sig = hashType(t)
if m.config.selectedGC == gcDestructors:
result = getTypeDescAux(m, t, check)
if skipTypes(etB.sons[0], typedescInst).kind == tyEmpty:
internalError(m.config, "cannot map the empty seq type to a C type")
result = cacheGetType(m.forwTypeCache, sig)
if result == nil:
result = getTypeName(m, t, sig)
if not isImportedType(t):
m.forwTypeCache[sig] = result
addForwardStructFormat(m, rope"struct", result)
let payload = result & "_Content"
addForwardStructFormat(m, rope"struct", payload)
if cacheGetType(m.typeCache, sig) == nil:
m.typeCache[sig] = result
#echo "adding ", sig, " ", typeToString(t), " ", m.module.name.s
appcg(m, m.s[cfsTypes],
"struct $1 {$N" &
" NI len; $1_Content* p;$N" &
"};$N", [result])
else:
result = getTypeForward(m, t, hashType(t)) & seqStar(m)
pushType(m, t)
result = getTypeForward(m, t, sig) & seqStar(m)
pushType(m, t)
else:
result = getTypeDescAux(m, t, check)
proc getSeqPayloadType(m: BModule; t: PType): Rope =
var check = initIntSet()
result = getTypeDescWeak(m, t, check) & "_Content"
#result = getTypeForward(m, t, hashType(t)) & "_Content"
proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
let sig = hashType(t)
let result = cacheGetType(m.typeCache, sig)
if result == nil:
discard getTypeDescAux(m, t, check)
else:
# little hack for now to prevent multiple definitions of the same
# Seq_Content:
appcg(m, m.s[cfsTypes], """$N
$3ifndef $2_Content_PP
$3define $2_Content_PP
struct $2_Content { NI cap;#AllocatorObj* allocator;$1 data[SEQ_DECL_SIZE];};
$3endif$N
""", [getTypeDescAux(m, t.skipTypes(abstractInst).sons[0], check), result, rope"#"])
proc paramStorageLoc(param: PSym): TStorageLoc =
if param.typ.skipTypes({tyVar, tyLent, tyTypeDesc}).kind notin {
tyArray, tyOpenArray, tyVarargs}:
@@ -407,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
@@ -427,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:
@@ -435,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, ", ")
@@ -468,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")
@@ -476,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])
@@ -513,7 +557,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
if fieldType.kind == tyUncheckedArray:
addf(result, "$1 $2[SEQ_DECL_SIZE];$n",
[getTypeDescAux(m, fieldType.elemType, check), sname])
elif fieldType.kind == tySequence and m.config.selectedGC != gcDestructors:
elif fieldType.kind == tySequence:
# we need to use a weak dependency here for trecursive_table.
addf(result, "$1 $2;$n", [getTypeDescWeak(m, field.loc.t, check), sname])
elif field.bitsize != 0:
@@ -591,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")
@@ -627,15 +671,6 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
result = if result.kind == tyGenericInst: result.sons[1]
else: result.elemType
proc getSeqPayloadType(m: BModule; t: PType): Rope =
result = getTypeForward(m, t, hashType(t)) & "_Content"
when false:
var check = initIntSet()
# XXX remove this duplication:
appcg(m, m.s[cfsSeqTypes],
"struct $2_Content { NI cap; void* allocator; $1 data[SEQ_DECL_SIZE]; };$n",
[getTypeDescAux(m, t.sons[0], check), result])
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
# returns only the type's name
var t = origTyp.skipTypes(irrelevantForBackend-{tyOwned})
@@ -675,11 +710,15 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
result = name & star
m.typeCache[sig] = result
of tySequence:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
result = name & seqStar(m) & star
m.typeCache[sig] = result
pushType(m, et)
if m.config.selectedGC == gcDestructors:
result = getTypeDescWeak(m, et, check) & star
m.typeCache[sig] = result
else:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
result = name & seqStar(m) & star
m.typeCache[sig] = result
pushType(m, et)
else:
# else we have a strong dependency :-(
result = getTypeDescAux(m, et, check) & star
@@ -731,29 +770,25 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
"void* ClE_0;$n} $1;$n",
[result, rettype, desc])
of tySequence:
# we cannot use getTypeForward here because then t would be associated
# with the name of the struct, not with the pointer to the struct:
result = cacheGetType(m.forwTypeCache, sig)
if result == nil:
result = getTypeName(m, origTyp, sig)
if m.config.selectedGC == gcDestructors:
result = getTypeDescWeak(m, t, check)
else:
# we cannot use getTypeForward here because then t would be associated
# with the name of the struct, not with the pointer to the struct:
result = cacheGetType(m.forwTypeCache, sig)
if result == nil:
result = getTypeName(m, origTyp, sig)
if not isImportedType(t):
addForwardStructFormat(m, structOrUnion(t), result)
m.forwTypeCache[sig] = result
assert(cacheGetType(m.typeCache, sig) == nil)
m.typeCache[sig] = result & seqStar(m)
if not isImportedType(t):
addForwardStructFormat(m, structOrUnion(t), result)
m.forwTypeCache[sig] = result
assert(cacheGetType(m.typeCache, sig) == nil)
m.typeCache[sig] = result & seqStar(m)
if not isImportedType(t):
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
const
cppSeq = "struct $2 : #TGenericSeq {$n"
cSeq = "struct $2 {$n" &
" #TGenericSeq Sup;$n"
if m.config.selectedGC == gcDestructors:
appcg(m, m.s[cfsTypes],
"typedef struct{ NI cap;#AllocatorObj* allocator;$1 data[SEQ_DECL_SIZE];}$2_Content;$n" &
"struct $2 {$n" &
" NI len; $2_Content* p;$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
else:
if skipTypes(t.sons[0], typedescInst).kind != tyEmpty:
const
cppSeq = "struct $2 : #TGenericSeq {$n"
cSeq = "struct $2 {$n" &
" #TGenericSeq Sup;$n"
if m.compileToCpp:
appcg(m, m.s[cfsSeqTypes],
cppSeq & " $1 data[SEQ_DECL_SIZE];$n" &
@@ -762,11 +797,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
appcg(m, m.s[cfsSeqTypes],
cSeq & " $1 data[SEQ_DECL_SIZE];$n" &
"};$n", [getTypeDescAux(m, t.sons[0], check), result])
elif m.config.selectedGC == gcDestructors:
internalError(m.config, "cannot map the empty seq type to a C type")
else:
result = rope("TGenericSeq")
add(result, seqStar(m))
else:
result = rope("TGenericSeq")
add(result, seqStar(m))
of tyUncheckedArray:
result = getTypeName(m, origTyp, sig)
m.typeCache[sig] = result
@@ -774,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
@@ -830,21 +863,8 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
m.typeCache[sig] = typedefName
result = typedefName
else:
when false:
if t.sym != nil and t.sym.name.s == "KeyValuePair":
if t == origTyp:
echo "wtf: came here"
writeStackTrace()
quit 1
result = cacheGetType(m.forwTypeCache, sig)
if result == nil:
when false:
if t.sym != nil and t.sym.name.s == "KeyValuePair":
# or {sfImportc, sfExportc} * t.sym.flags == {}:
if t.loc.r != nil:
echo t.kind, " ", hashType t
echo origTyp.kind, " ", sig
assert t.loc.r == nil
result = getTypeName(m, origTyp, sig)
m.forwTypeCache[sig] = result
if not isImportedType(t):
@@ -903,8 +923,13 @@ proc getClosureType(m: BModule, t: PType, kind: TClosureTypeKind): Rope =
proc finishTypeDescriptions(m: BModule) =
var i = 0
var check = initIntSet()
while i < len(m.typeStack):
discard getTypeDesc(m, m.typeStack[i])
let t = m.typeStack[i]
if m.config.selectedGC == gcDestructors and t.skipTypes(abstractInst).kind == tySequence:
seqV2ContentType(m, t, check)
else:
discard getTypeDescAux(m, t, check)
inc(i)
template cgDeclFrmt*(s: PSym): string =
@@ -933,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:
@@ -955,7 +980,7 @@ proc getNimNode(m: BModule): Rope =
result = "$1[$2]" % [m.typeNodesName, rope(m.typeNodes)]
inc(m.typeNodes)
proc TINameForHcr(m: BModule, name: Rope): Rope =
proc tiNameForHcr(m: BModule, name: Rope): Rope =
return if m.hcrOn: "(*".rope & name & ")" else: name
proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
@@ -967,7 +992,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
else:
nimtypeKind = ord(typ.kind)
let nameHcr = TINameForHcr(m, name)
let nameHcr = tiNameForHcr(m, name)
var size: Rope
if tfIncompleteStruct in typ.flags: size = rope"void*"
@@ -989,7 +1014,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
if typename == "ref object" and origType.skipTypes(skipPtrs).sym != nil:
typename = "anon ref object from " & m.config$origType.skipTypes(skipPtrs).sym.info
addf(m.s[cfsTypeInit3], "$1.name = $2;$n",
[nameHcr, makeCstring typename])
[nameHcr, makeCString typename])
discard cgsym(m, "nimTypeRoot")
addf(m.s[cfsTypeInit3], "$1.nextType = nimTypeRoot; nimTypeRoot=&$1;$n",
[nameHcr])
@@ -1004,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):
@@ -1024,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)
@@ -1041,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:
@@ -1072,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)
@@ -1119,7 +1146,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo
var tmp = getNimNode(m)
if not isImportedType(typ):
genObjectFields(m, typ, origType, typ.n, tmp, info)
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [TINameForHcr(m, name), tmp])
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [tiNameForHcr(m, name), tmp])
var t = typ.sons[0]
while t != nil:
t = t.skipTypes(skipPtrs)
@@ -1129,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))
@@ -1147,7 +1174,7 @@ proc genTupleInfo(m: BModule, typ, origType: PType, name: Rope; info: TLineInfo)
else:
addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2;$n",
[expr, rope(length)])
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [TINameForHcr(m, name), expr])
addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [tiNameForHcr(m, name), expr])
proc genEnumInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
# Type information for enumerations is quite heavy, so we do some
@@ -1155,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
@@ -1186,17 +1213,17 @@ proc genEnumInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
add(m.s[cfsTypeInit3], specialCases)
addf(m.s[cfsTypeInit3],
"$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4.node = &$1;$n",
[getNimNode(m), rope(length), nodePtrs, TINameForHcr(m, name)])
[getNimNode(m), rope(length), nodePtrs, tiNameForHcr(m, name)])
if hasHoles:
# 1 << 2 is {ntfEnumHole}
addf(m.s[cfsTypeInit3], "$1.flags = 1<<2;$n", [TINameForHcr(m, name)])
addf(m.s[cfsTypeInit3], "$1.flags = 1<<2;$n", [tiNameForHcr(m, name)])
proc genSetInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
assert(typ.sons[0] != nil)
genTypeInfoAux(m, typ, typ, name, info)
var tmp = getNimNode(m)
addf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 0;$n" & "$3.node = &$1;$n",
[tmp, rope(firstOrd(m.config, typ)), TINameForHcr(m, name)])
[tmp, rope(firstOrd(m.config, typ)), tiNameForHcr(m, name)])
proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfo(m, typ.sons[1], info), info)
@@ -1327,12 +1354,12 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
if m.config.selectedGC != gcDestructors:
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [TINameForHcr(m, result), markerProc])
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
of tyRef:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [TINameForHcr(m, result), markerProc])
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [tiNameForHcr(m, result), markerProc])
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
of tyArray: genArrayInfo(m, t, result, info)
of tySet: genSetInfo(m, t, result, info)

View File

@@ -10,7 +10,7 @@
# This module declares some helpers for the C code generator.
import
ast, astalgo, ropes, hashes, strutils, types, msgs, wordrecg,
ast, hashes, strutils, msgs, wordrecg,
platform, trees, options
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =

View File

@@ -11,13 +11,13 @@
import
ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets,
nversion, nimsets, msgs, std / sha1, bitsets, idents, types,
nversion, nimsets, msgs, bitsets, idents, types,
ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth,
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
rodutils, renderer, cgendata, ccgmerge, aliases,
lowerings, tables, sets, ndi, lineinfos, pathutils, transf, enumtostr
when not defined(leanCompiler):
import semparallel
import spawn, semparallel
import strutils except `%` # collides with ropes.`%`
@@ -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,14 +264,8 @@ 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
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIDX:
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",
[line, quotedFilename(p.config, t.info)])
@@ -296,13 +293,13 @@ proc lenField(p: BProc): Rope =
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
proc lenExpr(p: BProc; a: TLoc): Rope =
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
result = rdLoc(a) & ".len"
else:
result = "($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)]
proc dataField(p: BProc): Rope =
if p.config.selectedGc == gcDestructors:
if p.config.selectedGC == gcDestructors:
result = rope".p->data"
else:
result = rope"->data"
@@ -380,10 +377,10 @@ proc isComplexValueType(t: PType): bool {.inline.} =
(t.kind == tyProc and t.callConv == ccClosure)
proc resetLoc(p: BProc, loc: var TLoc) =
let containsGcRef = p.config.selectedGc != gcDestructors and containsGarbageCollectedRef(loc.t)
let containsGcRef = p.config.selectedGC != gcDestructors and containsGarbageCollectedRef(loc.t)
let typ = skipTypes(loc.t, abstractVarRange)
if isImportedCppType(typ): return
if p.config.selectedGc == gcDestructors and typ.kind in {tyString, tySequence}:
if p.config.selectedGC == gcDestructors and typ.kind in {tyString, tySequence}:
assert rdLoc(loc) != nil
linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
elif not isComplexValueType(typ):
@@ -414,7 +411,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
let typ = loc.t
if p.config.selectedGc == gcDestructors and skipTypes(typ, abstractInst).kind in {tyString, tySequence}:
if p.config.selectedGC == gcDestructors and skipTypes(typ, abstractInst).kind in {tyString, tySequence}:
linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
elif not isComplexValueType(typ):
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
@@ -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)
@@ -780,8 +756,8 @@ proc cgsym(m: BModule, name: string): Rope =
# we're picky here for the system module too:
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)
if m.hcrOn and sym != nil and sym.kind in {skProc..skIterator}:
result.addActualSuffixForHCR(m.module, sym)
proc generateHeaders(m: BModule) =
add(m.s[cfsHeaders], "\L#include \"nimbase.h\"\L")
@@ -1014,23 +990,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 +1040,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)
@@ -1105,7 +1088,8 @@ proc genProcNoForward(m: BModule, prc: PSym) =
# a check for ``m.declaredThings``.
if not containsOrIncl(m.declaredThings, prc.id):
#if prc.loc.k == locNone:
# mangle the inline proc based on the module where it is defined - not on the first module that uses it
# mangle the inline proc based on the module where it is defined -
# not on the first module that uses it
fillProcLoc(findPendingModule(m, prc), prc.ast[namePos])
#elif {sfExportc, sfImportc} * prc.flags == {}:
# # reset name to restore consistency in case of hashing collisions:
@@ -1272,7 +1256,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
@@ -1309,7 +1293,6 @@ proc genMainProc(m: BModule) =
PreMainBody = "$N" &
"void PreMainInner(void) {$N" &
"$2" &
"$3" &
"}$N$N" &
PosixCmdLine &
"void PreMain(void) {$N" &
@@ -1399,17 +1382,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} != {}:
@@ -1474,20 +1451,20 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
datInit = m.getDatInitName
if m.hcrOn:
var hcr_module_meta = "$nN_LIB_PRIVATE const char* hcr_module_list[] = {$n" % []
var hcrModuleMeta = "$nN_LIB_PRIVATE const char* hcr_module_list[] = {$n" % []
let systemModulePath = getModuleDllPath(m, g.modules[g.graph.config.m.systemFileIdx.int].module)
let mainModulePath = getModuleDllPath(m, m.module)
if sfMainModule in m.module.flags:
addf(hcr_module_meta, "\t$1,$n", [systemModulePath])
addf(hcrModuleMeta, "\t$1,$n", [systemModulePath])
g.graph.importDeps.withValue(FileIndex(m.module.position), deps):
for curr in deps[]:
addf(hcr_module_meta, "\t$1,$n", [getModuleDllPath(m, g.modules[curr.int].module)])
addf(hcr_module_meta, "\t\"\"};$n", [])
addf(hcr_module_meta, "$nN_LIB_EXPORT N_NIMCALL(void**, HcrGetImportedModules)() { return (void**)hcr_module_list; }$n", [])
addf(hcr_module_meta, "$nN_LIB_EXPORT N_NIMCALL(char*, HcrGetSigHash)() { return \"$1\"; }$n$n",
addf(hcrModuleMeta, "\t$1,$n", [getModuleDllPath(m, g.modules[curr.int].module)])
addf(hcrModuleMeta, "\t\"\"};$n", [])
addf(hcrModuleMeta, "$nN_LIB_EXPORT N_NIMCALL(void**, HcrGetImportedModules)() { return (void**)hcr_module_list; }$n", [])
addf(hcrModuleMeta, "$nN_LIB_EXPORT N_NIMCALL(char*, HcrGetSigHash)() { return \"$1\"; }$n$n",
[($sigHash(m.module)).rope])
if sfMainModule in m.module.flags:
add(g.mainModProcs, hcr_module_meta)
add(g.mainModProcs, hcrModuleMeta)
addf(g.mainModProcs, "static void* hcr_handle;$N", [])
addf(g.mainModProcs, "N_LIB_EXPORT N_NIMCALL(void, $1)(void);$N", [init])
addf(g.mainModProcs, "N_LIB_EXPORT N_NIMCALL(void, $1)(void);$N", [datInit])
@@ -1511,7 +1488,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
add(g.mainDatInit, "\t*cmd_count = cmdCount;\n")
add(g.mainDatInit, "\t*cmd_line = cmdLine;\n")
else:
add(m.s[cfsInitProc], hcr_module_meta)
add(m.s[cfsInitProc], hcrModuleMeta)
return
if m.s[cfsDatInitProc].len > 0:
@@ -1538,7 +1515,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
@@ -1582,7 +1559,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)
@@ -1770,18 +1747,14 @@ 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)
let ndiName = if optCDebug in g.config.globalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi")
let ndiName = if optCDebug in g.config.globalOptions: changeFileExt(completeCfilePath(g.config, filename), "ndi")
else: AbsoluteFile""
open(result.ndi, ndiName, g.config)
proc nullify[T](arr: var T) =
for i in low(arr)..high(arr):
arr[i] = Rope(nil)
proc rawNewModule(g: BModuleList; module: PSym; conf: ConfigRef): BModule =
result = rawNewModule(g, module, AbsoluteFile toFullPath(conf, module.position.FileIndex))
@@ -1805,7 +1778,7 @@ proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile
else: graph.config.projectFull
g.generatedHeader = rawNewModule(g, module,
changeFileExt(completeCFilePath(graph.config, f), hExt))
changeFileExt(completeCfilePath(graph.config, f), hExt))
incl g.generatedHeader.flags, isHeaderFile
proc writeHeader(m: BModule) =
@@ -1838,9 +1811,9 @@ proc writeHeader(m: BModule) =
proc getCFile(m: BModule): AbsoluteFile =
let ext =
if m.compileToCpp: ".nim.cpp"
elif m.config.cmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".nim.m"
elif m.config.cmd == cmdCompileToOC or sfCompileToObjc in m.module.flags: ".nim.m"
else: ".nim.c"
result = changeFileExt(completeCFilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
result = changeFileExt(completeCfilePath(m.config, withPackageName(m.config, m.cfilename)), ext)
when false:
proc myOpenCached(graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext =
@@ -1872,21 +1845,25 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
result = n
if b == nil: return
var m = BModule(b)
if passes.skipCodegen(m.config, n): return
if passes.skipCodegen(m.config, n) or
not moduleHasChanged(m.g.graph, m.module):
return
m.initProc.options = initProcOptions(m)
#softRnl = if optLineDir in m.config.options: noRnl else: rnl
# XXX replicate this logic!
let transformed_n = transformStmt(m.g.graph, m.module, n)
let transformedN = transformStmt(m.g.graph, m.module, n)
if m.hcrOn:
addHcrInitGuards(m.initProc, transformed_n, m.inHcrInitGuard)
addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard)
else:
genStmts(m.initProc, transformed_n)
genStmts(m.initProc, transformedN)
proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
result = true
if optForceFullMake notin m.config.globalOptions:
if not equalsFile(code, cfile.cname):
if m.config.symbolFiles == readOnlySf: #isDefined(m.config, "nimdiff"):
if not moduleHasChanged(m.g.graph, m.module):
result = false
elif not equalsFile(code, cfile.cname):
if false:
#m.config.symbolFiles == readOnlySf: #isDefined(m.config, "nimdiff"):
if fileExists(cfile.cname):
copyFile(cfile.cname.string, cfile.cname.string & ".backup")
echo "diff ", cfile.cname.string, ".backup ", cfile.cname.string
@@ -1894,12 +1871,15 @@ proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
echo "new file ", cfile.cname.string
if not writeRope(code, cfile.cname):
rawMessage(m.config, errCannotOpenFile, cfile.cname.string)
return
if fileExists(cfile.obj) and os.fileNewer(cfile.obj.string, cfile.cname.string):
result = true
elif fileExists(cfile.obj) and os.fileNewer(cfile.obj.string, cfile.cname.string):
result = false
else:
result = true
else:
if not writeRope(code, cfile.cname):
rawMessage(m.config, errCannotOpenFile, cfile.cname.string)
result = true
# We need 2 different logics here: pending modules (including
# 'nim__dat') may require file merging for the combination of dead code
@@ -1911,18 +1891,19 @@ proc writeModule(m: BModule, pending: bool) =
let cfile = getCFile(m)
if true or optForceFullMake in m.config.globalOptions:
genInitCode(m)
finishTypeDescriptions(m)
if sfMainModule in m.module.flags:
# generate main file:
genMainProc(m)
add(m.s[cfsProcHeaders], m.g.mainModProcs)
generateThreadVarsSize(m)
if moduleHasChanged(m.g.graph, m.module):
genInitCode(m)
finishTypeDescriptions(m)
if sfMainModule in m.module.flags:
# generate main file:
genMainProc(m)
add(m.s[cfsProcHeaders], m.g.mainModProcs)
generateThreadVarsSize(m)
var cf = Cfile(nimname: m.module.name.s, cname: cfile,
obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {})
obj: completeCfilePath(m.config, toObjFile(m.config, cfile)), flags: {})
var code = genModule(m, cf)
if code != nil:
if code != nil or m.config.symbolFiles != disabledSf:
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.compileCCode($code)
@@ -1932,7 +1913,7 @@ proc writeModule(m: BModule, pending: bool) =
addFileToCompile(m.config, cf)
elif pending and mergeRequired(m) and sfMainModule notin m.module.flags:
let cf = Cfile(nimname: m.module.name.s, cname: cfile,
obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {})
obj: completeCfilePath(m.config, toObjFile(m.config, cfile)), flags: {})
mergeFiles(cfile, m)
genInitCode(m)
finishTypeDescriptions(m)
@@ -1946,7 +1927,7 @@ proc writeModule(m: BModule, pending: bool) =
# ``system.c`` but then compilation fails due to an error. This means
# that ``system.o`` is missing, so we need to call the C compiler for it:
var cf = Cfile(nimname: m.module.name.s, cname: cfile,
obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {})
obj: completeCfilePath(m.config, toObjFile(m.config, cfile)), flags: {})
if not fileExists(cf.obj): cf.flags = {CfileFlag.Cached}
addFileToCompile(m.config, cf)
close(m.ndi)
@@ -1954,7 +1935,7 @@ proc writeModule(m: BModule, pending: bool) =
proc updateCachedModule(m: BModule) =
let cfile = getCFile(m)
var cf = Cfile(nimname: m.module.name.s, cname: cfile,
obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {})
obj: completeCfilePath(m.config, toObjFile(m.config, cfile)), flags: {})
if mergeRequired(m) and sfMainModule notin m.module.flags:
mergeFiles(cfile, m)
@@ -1979,48 +1960,44 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
for destructorCall in graph.globalDestructors:
n.add destructorCall
if passes.skipCodegen(m.config, n): return
# if the module is cached, we don't regenerate the main proc
# nor the dispatchers? But if the dispatchers changed?
# XXX emit the dispatchers into its own .c file?
if n != nil:
m.initProc.options = initProcOptions(m)
genStmts(m.initProc, n)
if moduleHasChanged(graph, m.module):
# if the module is cached, we don't regenerate the main proc
# nor the dispatchers? But if the dispatchers changed?
# XXX emit the dispatchers into its own .c file?
if n != nil:
m.initProc.options = initProcOptions(m)
genStmts(m.initProc, n)
if m.hcrOn:
# make sure this is pulled in (meaning hcrGetGlobal() is called for it during init)
discard cgsym(m, "programResult")
if m.inHcrInitGuard:
endBlock(m.initProc)
if sfMainModule in m.module.flags:
if m.hcrOn:
# pull ("define" since they are inline when HCR is on) these functions in the main file
# so it can load the HCR runtime and later pass the library handle to the HCR runtime which
# will in turn pass it to the other modules it initializes so they can initialize the
# register/get procs so they don't have to have the definitions of these functions as well
discard cgsym(m, "nimLoadLibrary")
discard cgsym(m, "nimLoadLibraryError")
discard cgsym(m, "nimGetProcAddr")
discard cgsym(m, "procAddrError")
discard cgsym(m, "rawWrite")
# make sure this is pulled in (meaning hcrGetGlobal() is called for it during init)
discard cgsym(m, "programResult")
if m.inHcrInitGuard:
endBlock(m.initProc)
# raise dependencies on behalf of genMainProc
if m.config.target.targetOS != osStandalone and m.config.selectedGC != gcNone:
discard cgsym(m, "initStackBottomWith")
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
discard cgsym(m, "initThreadVarsEmulation")
if sfMainModule in m.module.flags:
if m.hcrOn:
# pull ("define" since they are inline when HCR is on) these functions in the main file
# so it can load the HCR runtime and later pass the library handle to the HCR runtime which
# will in turn pass it to the other modules it initializes so they can initialize the
# register/get procs so they don't have to have the definitions of these functions as well
discard cgsym(m, "nimLoadLibrary")
discard cgsym(m, "nimLoadLibraryError")
discard cgsym(m, "nimGetProcAddr")
discard cgsym(m, "procAddrError")
discard cgsym(m, "rawWrite")
if m.g.breakpoints != nil:
discard cgsym(m, "dbgRegisterBreakpoint")
if optEndb in m.config.options:
discard cgsym(m, "dbgRegisterFilename")
# raise dependencies on behalf of genMainProc
if m.config.target.targetOS != osStandalone and m.config.selectedGC != gcNone:
discard cgsym(m, "initStackBottomWith")
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
discard cgsym(m, "initThreadVarsEmulation")
if m.g.forwardedProcs.len == 0:
incl m.flags, objHasKidsValid
let disp = generateMethodDispatchers(graph)
for x in disp: genProcAux(m, x.sym)
if m.g.forwardedProcs.len == 0:
incl m.flags, objHasKidsValid
let disp = generateMethodDispatchers(graph)
for x in disp: genProcAux(m, x.sym)
m.g.modules_closed.add m
m.g.modulesClosed.add m
proc genForwardedProcs(g: BModuleList) =
# Forward declared proc:s lack bodies when first encountered, so they're given

View File

@@ -10,7 +10,7 @@
## This module contains the data structures for the C code generation phase.
import
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
ast, ropes, options, intsets,
tables, ndi, lineinfos, pathutils, modulegraphs
type
@@ -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
@@ -100,7 +100,7 @@ type
TypeCache* = Table[SigHash, Rope]
TypeCacheWithOwner* = Table[SigHash, tuple[str: Rope, owner: PSym]]
Codegenflag* = enum
CodegenFlag* = enum
preventStackTrace, # true if stack traces need to be prevented
usesThreadVars, # true if the module uses a thread var
frameDeclared, # hack for ROD support so that we don't declare
@@ -114,11 +114,9 @@ type
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Rope
mapping*: Rope # the generated mapping file (if requested)
modules*: seq[BModule] # list of all compiled modules
modules_closed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
generatedHeader*: BModule
breakPointId*: int
breakpoints*: Rope # later the breakpoints are inserted into the main proc
typeInfoMarker*: TypeCacheWithOwner
config*: ConfigRef
graph*: ModuleGraph
@@ -137,7 +135,7 @@ type
TCGen = object of PPassContext # represents a C source file
s*: TCFileSections # sections of the C file
flags*: set[Codegenflag]
flags*: set[CodegenFlag]
module*: PSym
filename*: AbsoluteFile
cfilename*: AbsoluteFile # filename of the module (including path,
@@ -152,7 +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
@@ -196,6 +194,6 @@ proc newModuleList*(g: ModuleGraph): BModuleList =
config: g.config, graph: g, nimtvDeclared: initIntSet())
iterator cgenModules*(g: BModuleList): BModule =
for m in g.modules_closed:
for m in g.modulesClosed:
# iterate modules in the order they were closed
yield m

View File

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

View File

@@ -90,9 +90,6 @@
# :unrollFinally = true
# goto nearestFinally (or -1 if not exists)
#
# Every finally block calls closureIterEndFinally() upon its successful
# completion.
#
# Example:
#
# try:
@@ -126,13 +123,14 @@
# if :curExc.isNil:
# return :tmpResult
# else:
# closureIterSetupExc(nil)
# raise
# state = -1 # Goto next state. In this case we just exit
# break :stateLoop
import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, idents,
renderer, types, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
ast, msgs, idents,
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
type
Ctx = object
@@ -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:
@@ -854,156 +854,155 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode =
result = n
case n.kind:
of nkSkip:
discard
case n.kind
of nkSkip: discard
of nkStmtList, nkStmtListExpr:
result = addGotoOut(result, gotoOut)
for i in 0 ..< n.len:
if n[i].hasYields:
# Create a new split
let go = newNodeI(nkGotoState, n[i].info)
n[i] = ctx.transformClosureIteratorBody(n[i], go)
of nkStmtList, nkStmtListExpr:
result = addGotoOut(result, gotoOut)
for i in 0 ..< n.len:
if n[i].hasYields:
# Create a new split
let go = newNodeI(nkGotoState, n[i].info)
n[i] = ctx.transformClosureIteratorBody(n[i], go)
let s = newNodeI(nkStmtList, n[i + 1].info)
for j in i + 1 ..< n.len:
s.add(n[j])
let s = newNodeI(nkStmtList, n[i + 1].info)
for j in i + 1 ..< n.len:
s.add(n[j])
n.sons.setLen(i + 1)
discard ctx.newState(s, go)
if ctx.transformClosureIteratorBody(s, gotoOut) != s:
internalError(ctx.g.config, "transformClosureIteratorBody != s")
break
n.sons.setLen(i + 1)
discard ctx.newState(s, go)
if ctx.transformClosureIteratorBody(s, gotoOut) != s:
internalError(ctx.g.config, "transformClosureIteratorBody != s")
break
of nkYieldStmt:
result = newNodeI(nkStmtList, n.info)
result.add(n)
result.add(gotoOut)
of nkYieldStmt:
result = newNodeI(nkStmtList, n.info)
result.add(n)
result.add(gotoOut)
of nkElse, nkElseExpr:
result[0] = addGotoOut(result[0], gotoOut)
result[0] = ctx.transformClosureIteratorBody(result[0], gotoOut)
of nkElse, nkElseExpr:
result[0] = addGotoOut(result[0], gotoOut)
result[0] = ctx.transformClosureIteratorBody(result[0], gotoOut)
of nkElifBranch, nkElifExpr, nkOfBranch:
result[^1] = addGotoOut(result[^1], gotoOut)
result[^1] = ctx.transformClosureIteratorBody(result[^1], gotoOut)
of nkIfStmt, nkCaseStmt:
for i in 0 ..< n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
if n[^1].kind != nkElse:
# We don't have an else branch, but every possible branch has to end with
# gotoOut, so add else here.
let elseBranch = newTree(nkElse, gotoOut)
n.add(elseBranch)
of nkWhileStmt:
# while e:
# s
# ->
# BEGIN_STATE:
# if e:
# s
# goto BEGIN_STATE
# else:
# goto OUT
result = newNodeI(nkGotoState, n.info)
let s = newNodeI(nkStmtList, n.info)
discard ctx.newState(s, result)
let ifNode = newNodeI(nkIfStmt, n.info)
let elifBranch = newNodeI(nkElifBranch, n.info)
elifBranch.add(n[0])
var body = addGotoOut(n[1], result)
body = ctx.transformBreaksAndContinuesInWhile(body, result, gotoOut)
body = ctx.transformClosureIteratorBody(body, result)
elifBranch.add(body)
ifNode.add(elifBranch)
of nkElifBranch, nkElifExpr, nkOfBranch:
result[^1] = addGotoOut(result[^1], gotoOut)
result[^1] = ctx.transformClosureIteratorBody(result[^1], gotoOut)
of nkIfStmt, nkCaseStmt:
for i in 0 ..< n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
if n[^1].kind != nkElse:
# We don't have an else branch, but every possible branch has to end with
# gotoOut, so add else here.
let elseBranch = newTree(nkElse, gotoOut)
ifNode.add(elseBranch)
s.add(ifNode)
n.add(elseBranch)
of nkBlockStmt:
result[1] = addGotoOut(result[1], gotoOut)
result[1] = ctx.transformBreaksInBlock(result[1], result[0], gotoOut)
result[1] = ctx.transformClosureIteratorBody(result[1], gotoOut)
of nkWhileStmt:
# while e:
# s
# ->
# BEGIN_STATE:
# if e:
# s
# goto BEGIN_STATE
# else:
# goto OUT
of nkTryStmt, nkHiddenTryStmt:
# See explanation above about how this works
ctx.hasExceptions = true
result = newNodeI(nkGotoState, n.info)
result = newNodeI(nkGotoState, n.info)
var tryBody = toStmtList(n[0])
var exceptBody = ctx.collectExceptState(n)
var finallyBody = newTree(nkStmtList, getFinallyNode(ctx, n))
finallyBody = ctx.transformReturnsInTry(finallyBody)
finallyBody.add(ctx.newEndFinallyNode(finallyBody.info))
let s = newNodeI(nkStmtList, n.info)
discard ctx.newState(s, result)
let ifNode = newNodeI(nkIfStmt, n.info)
let elifBranch = newNodeI(nkElifBranch, n.info)
elifBranch.add(n[0])
# The following index calculation is based on the knowledge how state
# indexes are assigned
let tryIdx = ctx.states.len
var exceptIdx, finallyIdx: int
if exceptBody.kind != nkEmpty:
exceptIdx = -(tryIdx + 1)
finallyIdx = tryIdx + 2
else:
exceptIdx = tryIdx + 1
finallyIdx = tryIdx + 1
var body = addGotoOut(n[1], result)
let outToFinally = newNodeI(nkGotoState, finallyBody.info)
body = ctx.transformBreaksAndContinuesInWhile(body, result, gotoOut)
body = ctx.transformClosureIteratorBody(body, result)
block: # Create initial states.
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
let realTryIdx = ctx.newState(tryBody, result)
assert(realTryIdx == tryIdx)
elifBranch.add(body)
ifNode.add(elifBranch)
if exceptBody.kind != nkEmpty:
ctx.curExcHandlingState = finallyIdx
let realExceptIdx = ctx.newState(exceptBody, nil)
assert(realExceptIdx == -exceptIdx)
let elseBranch = newTree(nkElse, gotoOut)
ifNode.add(elseBranch)
s.add(ifNode)
ctx.curExcHandlingState = oldExcHandlingState
let realFinallyIdx = ctx.newState(finallyBody, outToFinally)
assert(realFinallyIdx == finallyIdx)
of nkBlockStmt:
result[1] = addGotoOut(result[1], gotoOut)
result[1] = ctx.transformBreaksInBlock(result[1], result[0], gotoOut)
result[1] = ctx.transformClosureIteratorBody(result[1], gotoOut)
block: # Subdivide the states
let oldNearestFinally = ctx.nearestFinally
ctx.nearestFinally = finallyIdx
of nkTryStmt, nkHiddenTryStmt:
# See explanation above about how this works
ctx.hasExceptions = true
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
if ctx.transformReturnsInTry(tryBody) != tryBody:
internalError(ctx.g.config, "transformReturnsInTry != tryBody")
if ctx.transformClosureIteratorBody(tryBody, outToFinally) != tryBody:
internalError(ctx.g.config, "transformClosureIteratorBody != tryBody")
ctx.curExcHandlingState = finallyIdx
ctx.addElseToExcept(exceptBody)
if ctx.transformReturnsInTry(exceptBody) != exceptBody:
internalError(ctx.g.config, "transformReturnsInTry != exceptBody")
if ctx.transformClosureIteratorBody(exceptBody, outToFinally) != exceptBody:
internalError(ctx.g.config, "transformClosureIteratorBody != exceptBody")
ctx.curExcHandlingState = oldExcHandlingState
ctx.nearestFinally = oldNearestFinally
if ctx.transformClosureIteratorBody(finallyBody, gotoOut) != finallyBody:
internalError(ctx.g.config, "transformClosureIteratorBody != finallyBody")
of nkGotoState, nkForStmt:
internalError(ctx.g.config, "closure iter " & $n.kind)
result = newNodeI(nkGotoState, n.info)
var tryBody = toStmtList(n[0])
var exceptBody = ctx.collectExceptState(n)
var finallyBody = newTree(nkStmtList, getFinallyNode(ctx, n))
finallyBody = ctx.transformReturnsInTry(finallyBody)
finallyBody.add(ctx.newEndFinallyNode(finallyBody.info))
# The following index calculation is based on the knowledge how state
# indexes are assigned
let tryIdx = ctx.states.len
var exceptIdx, finallyIdx: int
if exceptBody.kind != nkEmpty:
exceptIdx = -(tryIdx + 1)
finallyIdx = tryIdx + 2
else:
for i in 0 ..< n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
exceptIdx = tryIdx + 1
finallyIdx = tryIdx + 1
let outToFinally = newNodeI(nkGotoState, finallyBody.info)
block: # Create initial states.
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
let realTryIdx = ctx.newState(tryBody, result)
assert(realTryIdx == tryIdx)
if exceptBody.kind != nkEmpty:
ctx.curExcHandlingState = finallyIdx
let realExceptIdx = ctx.newState(exceptBody, nil)
assert(realExceptIdx == -exceptIdx)
ctx.curExcHandlingState = oldExcHandlingState
let realFinallyIdx = ctx.newState(finallyBody, outToFinally)
assert(realFinallyIdx == finallyIdx)
block: # Subdivide the states
let oldNearestFinally = ctx.nearestFinally
ctx.nearestFinally = finallyIdx
let oldExcHandlingState = ctx.curExcHandlingState
ctx.curExcHandlingState = exceptIdx
if ctx.transformReturnsInTry(tryBody) != tryBody:
internalError(ctx.g.config, "transformReturnsInTry != tryBody")
if ctx.transformClosureIteratorBody(tryBody, outToFinally) != tryBody:
internalError(ctx.g.config, "transformClosureIteratorBody != tryBody")
ctx.curExcHandlingState = finallyIdx
ctx.addElseToExcept(exceptBody)
if ctx.transformReturnsInTry(exceptBody) != exceptBody:
internalError(ctx.g.config, "transformReturnsInTry != exceptBody")
if ctx.transformClosureIteratorBody(exceptBody, outToFinally) != exceptBody:
internalError(ctx.g.config, "transformClosureIteratorBody != exceptBody")
ctx.curExcHandlingState = oldExcHandlingState
ctx.nearestFinally = oldNearestFinally
if ctx.transformClosureIteratorBody(finallyBody, gotoOut) != finallyBody:
internalError(ctx.g.config, "transformClosureIteratorBody != finallyBody")
of nkGotoState, nkForStmt:
internalError(ctx.g.config, "closure iter " & $n.kind)
else:
for i in 0 ..< n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
proc stateFromGotoState(n: PNode): int =
assert(n.kind == nkGotoState)
@@ -1149,7 +1148,6 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
# :state = exceptionTable[:state]
block:
# exceptionTable[:state]
let getNextState = newTree(nkBracketExpr,
ctx.createExceptionTable(),
@@ -1164,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)
@@ -1176,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
@@ -1188,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,
@@ -1289,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)
@@ -1312,7 +1310,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# Optimize empty states away
ctx.deleteEmptyStates()
# Make new body by concating the list of states
# Make new body by concatenating the list of states
result = newNodeI(nkStmtList, n.info)
for s in ctx.states:
assert(s.len == 2)

View File

@@ -13,6 +13,8 @@ import
options, idents, nimconf, scriptconfig, extccomp, commands, msgs,
lineinfos, modulegraphs, condsyms, os, pathutils
from strutils import normalize
type
NimProg* = ref object
suggestMode*: bool
@@ -72,7 +74,11 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
runNimScriptIfExists(scriptFile)
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile == conf.projectFull:
return false
if conf.command == "":
conf.command = "e"
return false
elif conf.command.normalize == "e":
return false
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile)
@@ -81,7 +87,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
discard
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars(conf)
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":

View File

@@ -17,6 +17,7 @@ template bootSwitch(name, expr, userString) =
const name = if expr: " " & userString else: ""
bootSwitch(usedRelease, defined(release), "-d:release")
bootSwitch(usedDanger, defined(danger), "-d:danger")
bootSwitch(usedGnuReadline, defined(useLinenoise), "-d:useLinenoise")
bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
@@ -26,9 +27,11 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
import
os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos,
wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos,
pathutils, strtabs
from incremental import nimIncremental
# but some have deps to imported modules. Yay.
bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
bootSwitch(usedNativeStacktrace,
@@ -47,15 +50,16 @@ const
"Compiled at $4\n" &
"Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
proc genFeatureDesc[T: enum](t: typedesc[T]): string {.compileTime.} =
var x = ""
for f in low(T)..high(T):
if x.len > 0: x.add "|"
x.add $f
x
const
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
FeatureDesc = block:
var x = ""
for f in low(Feature)..high(Feature):
if x.len > 0: x.add "|"
x.add $f
x
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % FeatureDesc
AdvancedUsage = slurp"../doc/advopt.txt".replace(" //", " ") % [genFeatureDesc(Feature), genFeatureDesc(LegacyFeature)]
proc getCommandLineDesc(conf: ConfigRef): string =
result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name,
@@ -96,7 +100,7 @@ proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
when gitHash.len == 40:
msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
msgWriteln(conf, "active boot switches:" & usedRelease &
msgWriteln(conf, "active boot switches:" & usedRelease & usedDanger &
usedTinyC & usedGnuReadline & usedNativeStacktrace &
usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
{msgStdout})
@@ -262,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
@@ -275,8 +279,9 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "fieldchecks": result = contains(conf.options, optFieldCheck)
of "rangechecks": result = contains(conf.options, optRangeCheck)
of "boundchecks": result = contains(conf.options, optBoundsCheck)
of "refchecks": result = contains(conf.options, optRefCheck)
of "overflowchecks": result = contains(conf.options, optOverflowCheck)
of "movechecks": result = contains(conf.options, optMoveCheck)
of "stylechecks": result = contains(conf.options, optStyleCheck)
of "linedir": result = contains(conf.options, optLineDir)
of "assertions", "a": result = contains(conf.options, optAssert)
of "run", "r": result = contains(conf.globalOptions, optRun)
@@ -432,30 +437,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)
@@ -468,24 +474,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")
@@ -529,8 +529,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "fieldchecks": processOnOffSwitch(conf, {optFieldCheck}, arg, pass, info)
of "rangechecks": processOnOffSwitch(conf, {optRangeCheck}, arg, pass, info)
of "boundchecks": processOnOffSwitch(conf, {optBoundsCheck}, arg, pass, info)
of "refchecks": processOnOffSwitch(conf, {optRefCheck}, arg, pass, info)
of "overflowchecks": processOnOffSwitch(conf, {optOverflowCheck}, arg, pass, info)
of "movechecks": processOnOffSwitch(conf, {optMoveCheck}, arg, pass, info)
of "stylechecks": processOnOffSwitch(conf, {optStyleCheck}, arg, pass, info)
of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
of "deadcodeelim": discard # deprecated, dead code elim always on
@@ -666,7 +667,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
helpOnError(conf, pass)
of "symbolfiles": discard "ignore for backwards compat"
of "incremental":
when not defined(nimIncremental):
when not nimIncremental:
localError(conf, info, "the compiler was not built with " &
"incremental compilation features; bootstrap with " &
"-d:nimIncremental to enable")
@@ -739,6 +740,11 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf.features.incl parseEnum[Feature](arg)
except ValueError:
localError(conf, info, "unknown experimental feature")
of "legacy":
try:
conf.legacyFeatures.incl parseEnum[LegacyFeature](arg)
except ValueError:
localError(conf, info, "unknown obsolete feature")
of "nocppexceptions":
expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optNoCppExceptions)
@@ -777,13 +783,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
@@ -806,7 +821,7 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
argsCount: var int; config: ConfigRef): bool =
if argsCount == 0:
# nim filename.nims is the same as "nim e filename.nims":
if p.key.endswith(".nims"):
if p.key.endsWith(".nims"):
config.command = "e"
incl(config.globalOptions, optWasNimscript)
config.projectName = unixToNativePath(p.key)

View File

@@ -10,7 +10,7 @@
# This module handles the conditional symbols.
import
strtabs, platform, strutils, idents
strtabs
from options import Feature
from lineinfos import HintsToStr, WarningsToStr
@@ -86,6 +86,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasSignatureHashInMacro")
defineSymbol("nimHasDefault")
defineSymbol("nimMacrosSizealignof")
defineSymbol("nimNoZeroExtendMagic")
defineSymbol("nimMacrosGetNodeId")
for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f)
@@ -93,3 +95,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasWarning" & s)
for s in HintsToStr:
defineSymbol("nimHasHint" & s)
defineSymbol("nimFixedOwned")
defineSymbol("nimHasStyleChecks")
defineSymbol("nimToOpenArrayCString")
defineSymbol("nimHasUsed")

View File

@@ -10,8 +10,7 @@
# This module implements a dependency file generator.
import
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
pathutils
options, ast, ropes, idents, passes, modulepaths, pathutils
from modulegraphs import ModuleGraph, PPassContext
@@ -35,14 +34,14 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
let b = Backend(g.graph.backend)
case n.kind
of nkImportStmt:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
var imported = getModuleName(g.config, n.sons[i])
addDependencyAux(b, g.module.name.s, imported)
of nkFromStmt, nkImportExceptStmt:
var imported = getModuleName(g.config, n.sons[0])
addDependencyAux(b, g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
for i in 0 ..< sonsLen(n): discard addDotDependency(c, n.sons[i])
for i in 0 ..< len(n): discard addDotDependency(c, n.sons[i])
else:
discard

View File

@@ -29,7 +29,7 @@
## "A GraphFree Approach to DataFlow Analysis" by Markus Mohnen.
## https://link.springer.com/content/pdf/10.1007/3-540-45937-5_6.pdf
import ast, astalgo, types, intsets, tables, msgs, options, lineinfos, renderer
import ast, types, intsets, lineinfos, renderer
from patterns import sameTrees
@@ -119,10 +119,10 @@ use(x)
Generates:
L0: fork L1
L0: fork lab1
join L0 # patched.
goto Louter
L1:
lab1:
def x
join L0
Louter:
@@ -265,14 +265,14 @@ proc genLabel(c: Con): TPosition =
proc jmpBack(c: var Con, n: PNode, p = TPosition(0)) =
let dist = p.int - c.code.len
doAssert(-0x7fff < dist and dist < 0x7fff)
doAssert(low(int) div 2 + 1 < dist and dist < high(int) div 2)
c.code.add Instr(n: n, kind: goto, dest: dist)
proc patch(c: var Con, p: TPosition) =
# patch with current index
let p = p.int
let diff = c.code.len - p
doAssert(-0x7fff < diff and diff < 0x7fff)
doAssert(low(int) div 2 + 1 < diff and diff < high(int) div 2)
c.code[p].dest = diff
proc popBlock(c: var Con; oldLen: int) =
@@ -354,24 +354,24 @@ when true:
else:
proc genWhile(c: var Con; n: PNode) =
# L1:
# lab1:
# cond, tmp
# fork tmp, L2
# fork tmp, lab2
# body
# jmp L1
# L2:
# jmp lab1
# lab2:
let oldForksLen = c.forks.len
let L1 = c.genLabel
let lab1 = c.genLabel
withBlock(nil):
if isTrue(n.sons[0]):
c.gen(n.sons[1])
c.jmpBack(n, L1)
c.jmpBack(n, lab1)
else:
c.gen(n.sons[0])
let L2 = c.forkI(n)
let lab2 = c.forkI(n)
c.gen(n.sons[1])
c.jmpBack(n, L1)
c.patch(L2)
c.jmpBack(n, lab1)
c.patch(lab2)
setLen(c.forks, oldForksLen)
proc genBlock(c: var Con; n: PNode) =
@@ -383,23 +383,23 @@ proc genJoins(c: var Con; n: PNode) =
proc genBreak(c: var Con; n: PNode) =
genJoins(c, n)
let L1 = c.gotoI(n)
let lab1 = c.gotoI(n)
if n.sons[0].kind == nkSym:
#echo cast[int](n.sons[0].sym)
for i in countdown(c.blocks.len-1, 0):
if c.blocks[i].label == n.sons[0].sym:
c.blocks[i].fixups.add L1
c.blocks[i].fixups.add lab1
return
#globalError(n.info, "VM problem: cannot find 'break' target")
else:
c.blocks[c.blocks.high].fixups.add L1
c.blocks[c.blocks.high].fixups.add lab1
template forkT(n, body) =
let oldLen = c.forks.len
let L1 = c.forkI(n)
let lab1 = c.forkI(n)
body
c.patch(L1)
c.joinI(L1, n)
c.patch(lab1)
c.joinI(lab1, n)
setLen(c.forks, oldLen)
proc genIf(c: var Con, n: PNode) =
@@ -415,15 +415,15 @@ proc genIf(c: var Con, n: PNode) =
D
cond
fork L1
fork lab1
A
goto Lend
L1:
lab1:
condB
fork L2
fork lab2
B
goto Lend2
L2:
lab2:
condC
fork L3
C
@@ -457,23 +457,23 @@ proc genIf(c: var Con, n: PNode) =
proc genAndOr(c: var Con; n: PNode) =
# asgn dest, a
# fork L1
# fork lab1
# asgn dest, b
# L1:
# lab1:
# join F1
c.gen(n.sons[1])
forkT(n):
c.gen(n.sons[2])
proc genCase(c: var Con; n: PNode) =
# if (!expr1) goto L1;
# if (!expr1) goto lab1;
# thenPart
# goto LEnd
# L1:
# if (!expr2) goto L2;
# lab1:
# if (!expr2) goto lab2;
# thenPart2
# goto LEnd
# L2:
# lab2:
# elsePart
# Lend:
let isExhaustive = skipTypes(n.sons[0].typ,
@@ -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,20 +607,15 @@ 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
proc instrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind in {def, use}
proc useInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == use
if ins.sym != nil and loc.kind == nkSym:
result = ins.sym == loc.sym
else:
@@ -633,25 +628,33 @@ proc instrTargets*(ins: Instr; loc: PNode): bool =
# use x; question does it affect 'x.f'? Yes.
result = aliases(ins.n, loc) or aliases(loc, ins.n)
proc defInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == def
if ins.sym != nil and loc.kind == nkSym:
result = ins.sym == loc.sym
else:
result = ins.n == loc or sameTrees(ins.n, loc)
if not result:
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
result = aliases(ins.n, loc)
proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
var n = orig
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv:
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr, nkBracketExpr:
n = n[0]
of nkHiddenDeref, nkDerefExpr:
# We "own" sinkparam[].loc but not ourVar[].location as it is a nasty
# pointer indirection.
n = n[0]
return n.kind == nkSym and n.sym.owner == owner and (isSinkParam(n.sym) or
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned, tyVar})
of nkBracketExpr:
let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
n = x
else:
break
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
else:
break
# XXX Allow closure deref operations here if we know
@@ -700,9 +703,9 @@ proc genCall(c: var Con; n: PNode) =
# every call can potentially raise:
if c.inTryStmt > 0 and canRaise(n[0]):
# we generate the instruction sequence:
# fork L1
# fork lab1
# goto exceptionHandler (except or finally)
# L1:
# lab1:
# join F1
let endGoto = c.forkI(n)
c.tryStmtFixups.add c.gotoI(n)
@@ -766,7 +769,7 @@ proc gen(c: var Con; n: PNode) =
of nkBreakStmt: genBreak(c, n)
of nkTryStmt, nkHiddenTryStmt: genTry(c, n)
of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange,
nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr:
nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr, nkYieldStmt:
for x in n: gen(c, x)
of nkPragmaBlock: gen(c, n.lastSon)
of nkDiscardStmt, nkObjDownConv, nkObjUpConv: gen(c, n.sons[0])

View File

@@ -15,8 +15,8 @@ import
ast, strutils, strtabs, options, msgs, os, ropes, idents,
wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast,
packages/docutils/rst, packages/docutils/rstgen,
packages/docutils/highlite, json, xmltree, cgi, trees, types,
typesrenderer, astalgo, modulepaths, lineinfos, sequtils, intsets,
json, xmltree, cgi, trees, types,
typesrenderer, astalgo, lineinfos, intsets,
pathutils, trees
const
@@ -406,6 +406,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 +416,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 +425,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
@@ -680,7 +683,9 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
path = path[cwd.len+1 .. ^1].replace('\\', '/')
let gitUrl = getConfigVar(d.conf, "git.url")
if gitUrl.len > 0:
let defaultBranch = if NimPatch mod 2 == 1: "devel" else: "master"
let defaultBranch =
if NimPatch mod 2 == 1: "devel"
else: "version-$1-$2" % [$NimMajor, $NimMinor]
let commit = getConfigVar(d.conf, "git.commit", defaultBranch)
let develBranch = getConfigVar(d.conf, "git.devel", "devel")
dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc,
@@ -867,13 +872,13 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
when useEffectSystem: documentRaises(d.cache, n)
genItem(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':
genItem(d, n.sons[i], n.sons[i].sons[0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
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]):
@@ -921,13 +926,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:
@@ -964,13 +969,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:

View File

@@ -11,8 +11,7 @@
# semantic checking.
import
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
pathutils
options, ast, msgs, idents, passes, docgen, lineinfos, pathutils
from modulegraphs import ModuleGraph, PPassContext

View File

@@ -138,13 +138,13 @@ proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer)
proc getField(conf: ConfigRef, n: PNode; position: int): PSym =
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
result = getField(conf, n.sons[i], position)
if result != nil: return
of nkRecCase:
result = getField(conf, n.sons[0], position)
if result != nil: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
case n.sons[i].kind
of nkOfBranch, nkElse:
result = getField(conf, lastSon(n.sons[i]), position)
@@ -158,7 +158,7 @@ proc packObject(conf: ConfigRef, x: PNode, typ: PType, res: pointer) =
internalAssert conf, x.kind in {nkObjConstr, nkPar, nkTupleConstr}
# compute the field's offsets:
discard getSize(conf, typ)
for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
for i in ord(x.kind == nkObjConstr) ..< len(x):
var it = x.sons[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
@@ -245,7 +245,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode
proc unpackObjectAdd(conf: ConfigRef, x: pointer, n, result: PNode) =
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
unpackObjectAdd(conf, x, n.sons[i], result)
of nkRecCase:
globalError(conf, result.info, "case objects cannot be unpacked")
@@ -275,7 +275,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
globalError(conf, n.info, "cannot map value from FFI")
if typ.n.isNil:
globalError(conf, n.info, "cannot unpack unnamed tuple")
for i in ord(n.kind == nkObjConstr) ..< sonsLen(n):
for i in ord(n.kind == nkObjConstr) ..< len(n):
var it = n.sons[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
@@ -289,7 +289,7 @@ proc unpackArray(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
if n.isNil:
result = newNode(nkBracket)
result.typ = typ
newSeq(result.sons, lengthOrd(conf, typ).int)
newSeq(result.sons, lengthOrd(conf, typ).toInt)
else:
result = n
if result.kind != nkBracket:

View File

@@ -10,8 +10,7 @@
## Template evaluation engine. Now hygienic.
import
strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
lineinfos
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents
type
TemplCtx = object
@@ -21,6 +20,7 @@ type
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
# new symbol
config: ConfigRef
ic: IdentCache
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
result = copyNode(a)
@@ -38,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):
@@ -53,7 +53,11 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
#if x.kind == skParam and x.owner.kind == skModule:
# internalAssert c.config, false
idTablePut(c.mapping, s, x)
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
if sfGenSym in s.flags and optNimV019 notin c.config.globalOptions:
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
if c.instLines: actual.info else: templ.info)
else:
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
else:
result.add copyNode(c, templ, actual)
of nkNone..nkIdent, nkType..nkNilLit: # atom
@@ -64,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:
@@ -78,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
@@ -131,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]
@@ -161,7 +165,9 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
result.typ = res.typ
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
conf: ConfigRef; fromHlo=false): PNode =
conf: ConfigRef;
ic: IdentCache;
fromHlo=false): PNode =
inc(conf.evalTemplateCounter)
if conf.evalTemplateCounter > evalTemplateLimit:
globalError(conf, n.info, errTemplateInstantiationTooNested)
@@ -173,6 +179,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.owner = tmpl
ctx.genSymOwner = genSymOwner
ctx.config = conf
ctx.ic = ic
initIdTable(ctx.mapping)
let body = tmpl.getBody

View File

@@ -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)
@@ -416,7 +416,7 @@ proc setCC*(conf: ConfigRef; ccname: string; info: TLineInfo) =
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, ccList])
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
conf.linkOptions = ""
conf.ccompilerpath = getConfigVar(conf, conf.cCompiler, ".path")
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
for i in low(CC) .. high(CC): undefSymbol(conf.symbols, CC[i].name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
@@ -443,10 +443,10 @@ proc initVars*(conf: ConfigRef) =
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
addCompileOption(conf, getConfigVar(conf, conf.cCompiler, ".options.always"))
#addLinkOption(getConfigVar(cCompiler, ".options.linker"))
if len(conf.ccompilerpath) == 0:
conf.ccompilerpath = getConfigVar(conf, conf.cCompiler, ".path")
if len(conf.cCompilerPath) == 0:
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
proc completeCFilePath*(conf: ConfigRef; cfile: AbsoluteFile,
proc completeCfilePath*(conf: ConfigRef; cfile: AbsoluteFile,
createSubDir: bool = true): AbsoluteFile =
result = completeGeneratedFilePath(conf, cfile, createSubDir)
@@ -591,7 +591,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): str
for includeDir in items(conf.cIncludes):
includeCmd.add(join([CC[c].includeCmd, includeDir.quoteShell]))
compilePattern = joinPath(conf.ccompilerpath, exe)
compilePattern = joinPath(conf.cCompilerPath, exe)
else:
includeCmd = ""
compilePattern = getCompilerExe(conf, c, cfile.cname)
@@ -606,7 +606,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): str
if not cfile.flags.contains(CfileFlag.External) or noAbsolutePaths(conf):
toObjFile(conf, cf).string
else:
completeCFilePath(conf, toObjFile(conf, cf)).string
completeCfilePath(conf, toObjFile(conf, cf)).string
elif noAbsolutePaths(conf):
extractFilename(cfile.obj.string)
else:
@@ -666,11 +666,11 @@ proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
var c = Cfile(nimname: splitFile(filename).name, cname: filename,
obj: toObjFile(conf, completeCFilePath(conf, filename, false)),
obj: toObjFile(conf, completeCfilePath(conf, filename, false)),
flags: {CfileFlag.External})
addExternalFileToCompile(conf, c)
proc compileCFiles(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var TStringSeq,
proc compileCFiles(conf: ConfigRef; list: CfileList, script: var Rope, cmds: var TStringSeq,
prettyCmds: var TStringSeq) =
var currIdx = 0
for it in list:
@@ -704,7 +704,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
# bug #6452: We must not use ``quoteShell`` here for ``linkerExe``
if needsExeExt(conf): linkerExe = addFileExt(linkerExe, "exe")
if noAbsolutePaths(conf): result = linkerExe
else: result = joinPath(conf.cCompilerpath, linkerExe)
else: result = joinPath(conf.cCompilerPath, linkerExe)
let buildgui = if optGenGuiApp in conf.globalOptions and conf.target.targetOS == osWindows:
CC[conf.cCompiler].buildGui
else:
@@ -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.
#
@@ -856,7 +856,7 @@ proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
finally:
removeFile(linkerArgs)
proc getObjFilePath(conf: ConfigRef, f: CFile): string =
proc getObjFilePath(conf: ConfigRef, f: Cfile): string =
if noAbsolutePaths(conf): f.obj.extractFilename
else: f.obj.string
@@ -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,19 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
pastStart = true
lit "\L"
proc nimfiles(conf: ConfigRef; f: File) =
var i = 0
for it in conf.m.fileInfos:
if isAbsolute(it.fullPath.string):
if i > 0: lit "],\L"
lit "["
str it.fullPath.string
lit ", "
str $secureHashFile(it.fullPath.string)
inc i
lit "]\L"
var buf = newStringOfCap(50)
let jsonFile = conf.getNimcacheDir / RelativeFile(conf.projectName & ".json")
@@ -1009,9 +1024,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\"nimfiles\":[\L"
nimfiles(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("nimfiles") 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 nimfilesPairs = data["nimfiles"]
doAssert nimfilesPairs.kind == JArray
for p in nimfilesPairs:
doAssert p.kind == JArray
# >= 2 for forwards compatibility with potential later .json files:
doAssert p.len >= 2
let nimFilename = p[0].getStr
let oldHashValue = p[1].getStr
let newHashValue = $secureHashFile(nimFilename)
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 +1080,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):
@@ -1041,7 +1095,7 @@ proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
echo getCurrentException().getStackTrace()
quit "error evaluating JSON file: " & jsonFile.string
proc genMappingFiles(conf: ConfigRef; list: CFileList): Rope =
proc genMappingFiles(conf: ConfigRef; list: CfileList): Rope =
for it in list:
addf(result, "--file:r\"$1\"$N", [rope(it.cname.string)])

View File

@@ -10,8 +10,8 @@
# This module implements Nim's standard template filter.
import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
renderer, filters, lineinfos, pathutils
llstream, strutils, ast, msgs, options,
filters, lineinfos, pathutils
type
TParseState = enum
@@ -22,7 +22,7 @@ type
info: TLineInfo
indent, emitPar: int
x: string # the current input line
outp: PLLStream # the ouput will be parsed by pnimsyn
outp: PLLStream # the output will be parsed by pnimsyn
subsChar, nimDirective: char
emit, conc, toStr: string
curly, bracket, par: int

View File

@@ -10,7 +10,7 @@
# This module implements Nim's simple filters and helpers for filters.
import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
llstream, idents, strutils, ast, msgs, options,
renderer, pathutils
proc invalidPragma(conf: ConfigRef; n: PNode) =
@@ -20,7 +20,7 @@ proc invalidPragma(conf: ConfigRef; n: PNode) =
proc getArg(conf: ConfigRef; n: PNode, name: string, pos: int): PNode =
result = nil
if n.kind in {nkEmpty..nkNilLit}: return
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if n.sons[i].kind == nkExprEqExpr:
if n.sons[i].sons[0].kind != nkIdent: invalidPragma(conf, n)
if cmpIgnoreStyle(n.sons[i].sons[0].ident.s, name) == 0:

View File

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

View File

@@ -10,7 +10,7 @@
## This module implements the 'implies' relation for guards.
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
saturate, modulegraphs, options, lineinfos
saturate, modulegraphs, options, lineinfos, int128
const
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
@@ -35,8 +35,8 @@ const
someMul = {mMulI, mMulF64}
someDiv = {mDivI, mDivF64}
someMod = {mModI}
someMax = {mMaxI, mMaxF64}
someMin = {mMinI, mMinF64}
someMax = {mMaxI}
someMin = {mMinI}
someBinaryOp = someAdd+someSub+someMul+someMax+someMin
proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit}
@@ -442,8 +442,8 @@ proc sameTree*(a, b: PNode): bool =
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
@@ -981,9 +981,10 @@ proc buildElse(n: PNode; o: Operators): PNode =
var s = newNodeIT(nkCurly, n.info, settype(n.sons[0]))
for i in 1..n.len-2:
let branch = n.sons[i]
assert branch.kind == nkOfBranch
for j in 0..branch.len-2:
s.add(branch.sons[j])
assert branch.kind != nkElse
if branch.kind == nkOfBranch:
for j in 0..branch.len-2:
s.add(branch.sons[j])
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opContains)
result.sons[1] = s

View File

@@ -14,7 +14,7 @@ proc hlo(c: PContext, n: PNode): PNode
proc evalPattern(c: PContext, n, orig: PNode): PNode =
internalAssert c.config, n.kind == nkCall and n.sons[0].kind == nkSym
# we need to ensure that the resulting AST is semchecked. However, it's
# aweful to semcheck before macro invocation, so we don't and treat
# awful to semcheck before macro invocation, so we don't and treat
# templates and macros as immediate in this context.
var rule: string
if optHints in c.config.options and hintPattern in c.config.notes:

View File

@@ -12,7 +12,7 @@
# id. This module is essential for the compiler's performance.
import
hashes, strutils, wordrecg
hashes, wordrecg
type
TIdObj* = object of RootObj

View File

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

View File

@@ -10,8 +10,8 @@
## This module implements the symbol importing mechanism.
import
intsets, strutils, os, ast, astalgo, msgs, options, idents, lookups,
semdata, passes, renderer, modulepaths, sigmatch, lineinfos
intsets, ast, astalgo, msgs, options, idents, lookups,
semdata, modulepaths, sigmatch, lineinfos, sets
proc readExceptSet*(c: PContext, n: PNode): IntSet =
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
@@ -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)
@@ -79,19 +80,19 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
else:
when false:
if s.kind == skStub: loadStub(s)
if s.kind notin ExportableSymKinds:
internalError(c.config, n.info, "importSymbol: 2")
let multiImport = s.kind notin ExportableSymKinds or s.kind in skProcKinds
# for an enumeration we have to add all identifiers
case s.kind
of skProcKinds:
if multiImport:
# for a overloadable syms add all overloaded routines
var it: TIdentIter
var e = initIdentIter(it, fromMod.tab, s.name)
while e != nil:
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
rawImportSymbol(c, e)
if s.kind in ExportableSymKinds:
rawImportSymbol(c, e, fromMod)
e = nextIdentIter(it, fromMod.tab)
else: rawImportSymbol(c, s)
else:
rawImportSymbol(c, s, fromMod)
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
@@ -103,14 +104,14 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
if s.kind notin ExportableSymKinds:
internalError(c.config, s.info, "importAllSymbols: " & $s.kind & " " & s.name.s)
if exceptSet.isNil or s.name.id notin exceptSet:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
s = nextIter(i, fromMod.tab)
proc importAllSymbols*(c: PContext, fromMod: PSym) =
var exceptSet: IntSet
importAllSymbolsExcept(c, fromMod, exceptSet)
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym) =
if n.isNil: return
case n.kind
of nkExportStmt:
@@ -120,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")
@@ -139,7 +141,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
let f = checkModuleName(c.config, n)
if f != InvalidFileIDX:
if f != InvalidFileIdx:
let L = c.graph.importStack.len
let recursion = c.graph.importStack.find(f)
c.graph.importStack.add f
@@ -185,11 +187,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 +221,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 +234,4 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
n.sons[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, readExceptSet(c, n))
#importForwarded(c, m.ast, exceptSet)
#importForwarded(c, m.ast, exceptSet, m)

View File

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

View File

@@ -134,7 +134,7 @@ to do it.
]#
import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents,
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
lineinfos, parampatterns, sighashes
@@ -150,10 +150,11 @@ type
graph: ModuleGraph
emptyNode: PNode
otherRead: PNode
inLoop: int
uninit: IntSet # set of uninit'ed vars
uninitComputed: bool
const toDebug = ""
const toDebug = "" # "server" # "serverNimAsyncContinue"
template dbg(body) =
when toDebug.len > 0:
@@ -165,12 +166,12 @@ proc isLastRead(location: PNode; c: var Con; pc, comesFrom: int): int =
while pc < c.g.len:
case c.g[pc].kind
of def:
if instrTargets(c.g[pc], location):
if defInstrTargets(c.g[pc], location):
# the path lead to a redefinition of 's' --> abandon it.
return high(int)
inc pc
of use:
if instrTargets(c.g[pc], location):
if useInstrTargets(c.g[pc], location):
c.otherRead = c.g[pc].n
return -1
inc pc
@@ -255,7 +256,7 @@ proc isLastRead(n: PNode; c: var Con): bool =
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:
@@ -310,6 +311,8 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
m.add "; try to make "
m.add renderTree(ri)
m.add " a 'sink' parameter"
m.add "; routine: "
m.add c.owner.name.s
localError(c.graph.config, ri.info, errGenerated, m)
proc makePtrType(c: Con, baseType: PType): PType =
@@ -319,7 +322,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)
@@ -337,10 +340,23 @@ proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
addrExp.add(dest)
result = newTree(nkCall, newSymNode(op), addrExp)
when false:
proc preventMoveRef(dest, ri: PNode): bool =
let lhs = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
var ri = ri
if ri.kind in nkCallKinds and ri[0].kind == nkSym and ri[0].sym.magic == mUnown:
ri = ri[1]
let rhs = ri.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = lhs.kind == tyRef and rhs.kind == tyOwned
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})
let k = if t.attachedOps[attachedSink] != nil: attachedSink
else: attachedAsgn
else: attachedAsgn
if t.attachedOps[k] != nil:
result = genOp(c, t, k, dest, ri)
else:
@@ -349,8 +365,10 @@ 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: Con; t: PType; dest, ri: PNode): PNode =
proc genCopy(c: var Con; t: PType; dest, ri: PNode): PNode =
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)
@@ -410,7 +428,7 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode =
add(v, vpart)
result.add v
result.add genWasMoved(n, c)
result.add genWasMoved(skipConv(n), c)
result.add tempAsNode
proc sinkParamIsLastReadCheck(c: var Con, s: PNode) =
@@ -419,17 +437,6 @@ 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 isSinkTypeForParam(t: PType): bool =
# a parameter like 'seq[owned T]' must not be used only once, but its
# elements must, so we detect this case here:
result = t.skipTypes({tyGenericInst, tyAlias}).kind in {tySink, tyOwned}
when false:
if isSinkType(t):
if t.skipTypes({tyGenericInst, tyAlias}).kind in {tyArray, tyVarargs, tyOpenArray, tySequence}:
result = false
else:
result = true
proc passCopyToSink(n: PNode; c: var Con): PNode =
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
let tmp = getTemp(c, n.typ, n.info)
@@ -448,6 +455,25 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
result.add newTree(nkAsgn, tmp, p(n, c))
result.add tmp
proc isDangerousSeq(t: PType): bool {.inline.} =
let t = t.skipTypes(abstractInst)
result = t.kind == tySequence and tfHasOwned notin t.sons[0].flags
proc containsConstSeq(n: PNode): bool =
if n.kind == nkBracket and n.len > 0 and n.typ != nil and isDangerousSeq(n.typ):
return true
result = false
case n.kind
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
result = containsConstSeq(n[1])
of nkObjConstr, nkClosure:
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
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
@@ -464,7 +490,12 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
result.add arg[0]
for i in 1..<arg.len:
result.add pArg(arg[i], c, i < L and isSinkTypeForParam(parameters[i]))
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkTripleStrLit}:
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 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"
result = arg
elif arg.kind == nkSym and isSinkParam(arg.sym):
@@ -472,7 +503,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
# to disable the destructor which we have not elided
sinkParamIsLastReadCheck(c, arg)
result = destructiveMoveVar(arg, c)
elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c):
elif isAnalysableFieldAccess(arg, c.owner) and isLastRead(arg, c):
# 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)
@@ -500,7 +531,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
result.add p(arg[0], c)
for i in 1..<arg.len:
var branch: PNode
if arg[i].kind == nkOfbranch:
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}:
@@ -511,8 +542,6 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
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)
else:
# an object that is not temporary but passed to a 'sink' parameter
# results in a copy.
@@ -580,7 +609,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
result.add p(ri[0], c)
for i in 1..<ri.len:
var branch: PNode
if ri[i].kind == nkOfbranch:
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}:
@@ -593,7 +622,10 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
result.add branch
of nkBracket:
# array constructor
result = genSink(c, dest.typ, dest, ri)
if ri.len > 0 and isDangerousSeq(ri.typ):
result = genCopy(c, dest.typ, 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,
@@ -611,7 +643,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
of nkTupleConstr, nkClosure:
result = genSink(c, dest.typ, dest, ri)
let ri2 = copyTree(ri)
for i in 0..<ri.len:
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:
@@ -629,7 +661,8 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
var snk = genSink(c, dest.typ, 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):
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)
snk.add ri
@@ -661,7 +694,8 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
result = genCopy(c, dest.typ, dest, ri)
result.add p(ri, c)
else:
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c):
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)
snk.add ri
@@ -721,7 +755,7 @@ proc p(n: PNode; c: var Con): PNode =
for i in 0..<n.len:
let it = n[i]
let L = it.len
let ri = it[L-1]
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)
@@ -735,6 +769,8 @@ proc p(n: PNode; c: var Con): PNode =
# 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
@@ -757,8 +793,12 @@ proc p(n: PNode; c: var Con): PNode =
else:
result = n
of nkAsgn, nkFastAsgn:
if hasDestructor(n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda, nkClosure}:
result = moveOrCopy(n[0], n[1], c)
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)
@@ -777,20 +817,31 @@ proc p(n: PNode; c: var Con): PNode =
result[1][0] = p(result[1][0], c)
of nkRaiseStmt:
if optNimV2 in c.graph.config.globalOptions and n[0].kind != nkEmpty:
let t = n[0].typ
let tmp = getTemp(c, t, n.info)
var m = genCopyNoCheck(c, t, tmp, n[0])
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)
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)

View File

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

687
compiler/int128.nim Normal file
View File

@@ -0,0 +1,687 @@
## This module is for compiler internal use only. For reliable error
## messages and range checks, the compiler needs a data type that can
## hold all from ``low(BiggestInt)`` to ``high(BiggestUInt)``, This
## type is for that purpose.
from math import trunc
type
Int128* = object
udata: array[4,uint32]
template sdata(arg: Int128, idx: int): int32 =
# udata and sdata was supposed to be in a union, but unions are
# handled incorrectly in the VM.
cast[ptr int32](arg.udata[idx].unsafeAddr)[]
# encoding least significant int first (like LittleEndian)
const
Zero* = Int128(udata: [0'u32,0,0,0])
One* = Int128(udata: [1'u32,0,0,0])
Ten* = Int128(udata: [10'u32,0,0,0])
Min = Int128(udata: [0'u32,0,0,0x80000000'u32])
Max = Int128(udata: [high(uint32),high(uint32),high(uint32),uint32(high(int32))])
NegOne* = Int128(udata: [0xffffffff'u32,0xffffffff'u32,0xffffffff'u32,0xffffffff'u32])
template low*(t: typedesc[Int128]): Int128 = Min
template high*(t: typedesc[Int128]): Int128 = Max
proc `$`*(a: Int128): string
proc toInt128*[T: SomeInteger](arg: T): Int128 =
when T is SomeUnsignedInt:
when sizeof(arg) <= 4:
result.udata[0] = uint32(arg)
else:
result.udata[0] = uint32(arg and T(0xffffffff))
result.udata[1] = uint32(arg shr 32)
else:
when sizeof(arg) <= 4:
result.sdata(0) = int32(arg)
if arg < 0: # sign extend
result.sdata(1) = -1
result.sdata(2) = -1
result.sdata(3) = -1
else:
let tmp = int64(arg)
result.udata[0] = uint32(tmp and 0xffffffff)
result.sdata(1) = int32(tmp shr 32)
if arg < 0: # sign extend
result.sdata(2) = -1
result.sdata(3) = -1
template isNegative(arg: Int128): bool =
arg.sdata(3) < 0
template isNegative(arg: int32): bool =
arg < 0
proc bitconcat(a,b: uint32): uint64 =
(uint64(a) shl 32) or uint64(b)
proc bitsplit(a: uint64): (uint32,uint32) =
(cast[uint32](a shr 32), cast[uint32](a))
proc toInt64*(arg: Int128): int64 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt64Checked*(arg: Int128; onError: int64): int64 =
if isNegative(arg):
if arg.sdata(3) != -1 or arg.sdata(2) != -1:
return onError
else:
if arg.sdata(3) != 0 or arg.sdata(2) != 0:
return onError
return cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt32*(arg: Int128): int32 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
arg.sdata(0)
proc toInt16*(arg: Int128): int16 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
int16(arg.sdata(0))
proc toInt8*(arg: Int128): int8 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
int8(arg.sdata(0))
proc toInt*(arg: Int128): int =
when sizeof(int) == 4:
cast[int](toInt32(arg))
else:
cast[int](toInt64(arg))
proc toUInt64*(arg: Int128): uint64 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
bitconcat(arg.udata[1], arg.udata[0])
proc toUInt32*(arg: Int128): uint32 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
arg.udata[0]
proc toUInt16*(arg: Int128): uint16 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
uint16(arg.udata[0])
proc toUInt8*(arg: Int128): uint8 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
uint8(arg.udata[0])
proc toUInt*(arg: Int128): uint =
when sizeof(int) == 4:
cast[uint](toInt32(arg))
else:
cast[uint](toInt64(arg))
proc castToInt64*(arg: Int128): int64 =
## Conversion to int64 without range check.
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc castToUInt64*(arg: Int128): uint64 =
## Conversion to uint64 without range check.
cast[uint64](bitconcat(arg.udata[1], arg.udata[0]))
proc addToHex(result: var string; arg: uint32) =
for i in 0 ..< 8:
let idx = (arg shr ((7-i) * 4)) and 0xf
result.add "0123456789abcdef"[idx]
proc addToHex*(result: var string; arg: Int128) =
var i = 3
while i >= 0:
result.addToHex(arg.udata[i])
i -= 1
proc toHex*(arg: Int128): string =
result.addToHex(arg)
proc inc*(a: var Int128, y: uint32 = 1) =
let input = a
a.udata[0] += y
if unlikely(a.udata[0] < y):
a.udata[1].inc
if unlikely(a.udata[1] == 0):
a.udata[2].inc
if unlikely(a.udata[2] == 0):
a.udata[3].inc
doAssert(a.sdata(3) != low(int32), "overflow")
proc cmp*(a,b: Int128): int =
let tmp1 = cmp(a.sdata(3), b.sdata(3))
if tmp1 != 0: return tmp1
let tmp2 = cmp(a.udata[2], b.udata[2])
if tmp2 != 0: return tmp2
let tmp3 = cmp(a.udata[1], b.udata[1])
if tmp3 != 0: return tmp3
let tmp4 = cmp(a.udata[0], b.udata[0])
return tmp4
proc `<`*(a,b: Int128): bool =
cmp(a,b) < 0
proc `<=`*(a,b: Int128): bool =
cmp(a,b) <= 0
proc `==`*(a,b: Int128): bool =
if a.udata[0] != b.udata[0]: return false
if a.udata[1] != b.udata[1]: return false
if a.udata[2] != b.udata[2]: return false
if a.udata[3] != b.udata[3]: return false
return true
proc inplaceBitnot(a: var Int128) =
a.udata[0] = not a.udata[0]
a.udata[1] = not a.udata[1]
a.udata[2] = not a.udata[2]
a.udata[3] = not a.udata[3]
proc bitnot*(a: Int128): Int128 =
result.udata[0] = not a.udata[0]
result.udata[1] = not a.udata[1]
result.udata[2] = not a.udata[2]
result.udata[3] = not a.udata[3]
proc bitand*(a,b: Int128): Int128 =
result.udata[0] = a.udata[0] and b.udata[0]
result.udata[1] = a.udata[1] and b.udata[1]
result.udata[2] = a.udata[2] and b.udata[2]
result.udata[3] = a.udata[3] and b.udata[3]
proc bitor*(a,b: Int128): Int128 =
result.udata[0] = a.udata[0] or b.udata[0]
result.udata[1] = a.udata[1] or b.udata[1]
result.udata[2] = a.udata[2] or b.udata[2]
result.udata[3] = a.udata[3] or b.udata[3]
proc bitxor*(a,b: Int128): Int128 =
result.udata[0] = a.udata[0] xor b.udata[0]
result.udata[1] = a.udata[1] xor b.udata[1]
result.udata[2] = a.udata[2] xor b.udata[2]
result.udata[3] = a.udata[3] xor b.udata[3]
proc `shr`*(a: Int128, b: int): Int128 =
let b = b and 127
if b < 32:
result.sdata(3) = a.sdata(3) shr b
result.udata[2] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr b)
result.udata[1] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr b)
result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr b)
elif b < 64:
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = a.sdata(3) shr (b and 31)
result.udata[1] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr (b and 31))
result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr (b and 31))
elif b < 96:
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = -1
result.sdata(1) = a.sdata(3) shr (b and 31)
result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr (b and 31))
else: # b < 128
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = -1
result.sdata(1) = -1
result.sdata(0) = a.sdata(3) shr (b and 31)
proc `shl`*(a: Int128, b: int): Int128 =
let b = b and 127
if b < 32:
result.udata[0] = a.udata[0] shl b
result.udata[1] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl b) shr 32)
result.udata[2] = cast[uint32]((bitconcat(a.udata[2], a.udata[1]) shl b) shr 32)
result.udata[3] = cast[uint32]((bitconcat(a.udata[3], a.udata[2]) shl b) shr 32)
elif b < 64:
result.udata[0] = 0
result.udata[1] = a.udata[0] shl (b and 31)
result.udata[2] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl (b and 31)) shr 32)
result.udata[3] = cast[uint32]((bitconcat(a.udata[2], a.udata[1]) shl (b and 31)) shr 32)
elif b < 96:
result.udata[0] = 0
result.udata[1] = 0
result.udata[2] = a.udata[0] shl (b and 31)
result.udata[3] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl (b and 31)) shr 32)
else:
result.udata[0] = 0
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = a.udata[0] shl (b and 31)
proc `+`*(a,b: Int128): Int128 =
let tmp0 = uint64(a.udata[0]) + uint64(b.udata[0])
result.udata[0] = cast[uint32](tmp0)
let tmp1 = uint64(a.udata[1]) + uint64(b.udata[1]) + (tmp0 shr 32)
result.udata[1] = cast[uint32](tmp1)
let tmp2 = uint64(a.udata[2]) + uint64(b.udata[2]) + (tmp1 shr 32)
result.udata[2] = cast[uint32](tmp2)
let tmp3 = uint64(a.udata[3]) + uint64(b.udata[3]) + (tmp2 shr 32)
result.udata[3] = cast[uint32](tmp3)
proc `+=`*(a: var Int128, b: Int128) =
a = a + b
proc `-`*(a: Int128): Int128 =
result = bitnot(a)
result.inc
proc `-`*(a,b: Int128): Int128 =
a + (-b)
proc `-=`*(a: var Int128, b: Int128) =
a = a - b
proc abs*(a: Int128): Int128 =
if isNegative(a):
-a
else:
a
proc abs(a: int32): int =
if a < 0: -a else: a
proc `*`(a: Int128, b: uint32): Int128 =
let tmp0 = uint64(a.udata[0]) * uint64(b)
let tmp1 = uint64(a.udata[1]) * uint64(b)
let tmp2 = uint64(a.udata[2]) * uint64(b)
let tmp3 = uint64(a.udata[3]) * uint64(b)
if unlikely(tmp3 > uint64(high(int32))):
assert(false, "overflow")
result.udata[0] = cast[uint32](tmp0)
result.udata[1] = cast[uint32](tmp1) + cast[uint32](tmp0 shr 32)
result.udata[2] = cast[uint32](tmp2) + cast[uint32](tmp1 shr 32)
result.udata[3] = cast[uint32](tmp3) + cast[uint32](tmp2 shr 32)
proc `*`*(a: Int128, b: int32): Int128 =
let isNegative = isNegative(a) xor isNegative(b)
result = a * cast[uint32](abs(b))
if b < 0:
result = -result
proc `*=`*(a: var Int128, b: int32): Int128 =
result = result * b
proc makeInt128(high,low: uint64): Int128 =
result.udata[0] = cast[uint32](low)
result.udata[1] = cast[uint32](low shr 32)
result.udata[2] = cast[uint32](high)
result.udata[3] = cast[uint32](high shr 32)
proc high64(a: Int128): uint64 =
bitconcat(a.udata[3], a.udata[2])
proc low64(a: Int128): uint64 =
bitconcat(a.udata[1], a.udata[0])
proc `*`*(lhs,rhs: Int128): Int128 =
let isNegative = isNegative(lhs) xor isNegative(rhs)
let
a = cast[uint64](lhs.udata[0])
b = cast[uint64](lhs.udata[1])
c = cast[uint64](lhs.udata[2])
d = cast[uint64](lhs.udata[3])
e = cast[uint64](rhs.udata[0])
f = cast[uint64](rhs.udata[1])
g = cast[uint64](rhs.udata[2])
h = cast[uint64](rhs.udata[3])
let a32 = cast[uint64](lhs.udata[1])
let a00 = cast[uint64](lhs.udata[0])
let b32 = cast[uint64](rhs.udata[1])
let b00 = cast[uint64](rhs.udata[0])
result = makeInt128(high64(lhs) * low64(rhs) + low64(lhs) * high64(rhs) + a32 * b32, a00 * b00)
result = result + toInt128(a32 * b00) shl 32
result = result + toInt128(a00 * b32) shl 32
if isNegative != isNegative(result):
assert(false, "overflow")
proc `*=`*(a: var Int128, b: Int128) =
a = a * b
import bitops
proc fastLog2*(a: Int128): int =
if a.udata[3] != 0:
return 96 + fastLog2(a.udata[3])
if a.udata[2] != 0:
return 64 + fastLog2(a.udata[2])
if a.udata[1] != 0:
return 32 + fastLog2(a.udata[1])
if a.udata[0] != 0:
return fastLog2(a.udata[0])
proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
assert(divisor != Zero)
let isNegativeA = isNegative(dividend)
let isNegativeB = isNegative(divisor)
var dividend = abs(dividend)
let divisor = abs(divisor)
if divisor > dividend:
result.quotient = Zero
result.remainder = dividend
return
if divisor == dividend:
result.quotient = One
result.remainder = Zero
return
var denominator = divisor
var quotient = Zero
# Left aligns the MSB of the denominator and the dividend.
let shift = fastLog2(dividend) - fastLog2(denominator)
denominator = denominator shl shift
# Uses shift-subtract algorithm to divide dividend by denominator. The
# remainder will be left in dividend.
for i in 0 .. shift:
quotient = quotient shl 1
if dividend >= denominator:
dividend = dividend - denominator
quotient = bitor(quotient, One)
denominator = denominator shr 1
if isNegativeA xor isNegativeB:
result.quotient = -quotient
else:
result.quotient = quotient
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
proc `div`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
return a
proc `mod`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
return b
proc addInt128*(result: var string; value: Int128) =
let initialSize = result.len
if value == Zero:
result.add "0"
elif value == low(Int128):
result.add "-170141183460469231731687303715884105728"
else:
let isNegative = isNegative(value)
var value = abs(value)
while value > Zero:
let (quot, rem) = divMod(value, Ten)
result.add "0123456789"[rem.toInt64]
value = quot
if isNegative:
result.add '-'
var i = initialSize
var j = high(result)
while i < j:
swap(result[i], result[j])
i += 1
j -= 1
proc `$`*(a: Int128): string =
result.addInt128(a)
proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
assert(pos < arg.len)
assert(arg[pos] in {'-','0'..'9'})
var isNegative = false
var pos = pos
if arg[pos] == '-':
isNegative = true
pos += 1
result = Zero
while pos < arg.len and arg[pos] in '0' .. '9':
result = result * Ten
result.inc(uint32(arg[pos]) - uint32('0'))
pos += 1
if isNegative:
result = -result
# fluff
proc `<`*(a: Int128, b: BiggestInt): bool =
cmp(a,toInt128(b)) < 0
proc `<`*(a: BiggestInt, b: Int128): bool =
cmp(toInt128(a), b) < 0
proc `<=`*(a: Int128, b: BiggestInt): bool =
cmp(a,toInt128(b)) <= 0
proc `<=`*(a: BiggestInt, b: Int128): bool =
cmp(toInt128(a), b) <= 0
proc `==`*(a: Int128, b: BiggestInt): bool =
a == toInt128(b)
proc `==`*(a: BiggestInt, b: Int128): bool =
toInt128(a) == b
proc `-`*(a: BiggestInt, b: Int128): Int128 =
toInt128(a) - b
proc `-`*(a: Int128, b: BiggestInt): Int128 =
a - toInt128(b)
proc `+`*(a: BiggestInt, b: Int128): Int128 =
toInt128(a) + b
proc `+`*(a: Int128, b: BiggestInt): Int128 =
a + toInt128(b)
proc toFloat64*(arg: Int128): float64 =
let isNegative = isNegative(arg)
let arg = abs(arg)
let a = float64(bitconcat(arg.udata[1], arg.udata[0]))
let b = float64(bitconcat(arg.udata[3], arg.udata[2]))
result = a + 18446744073709551616'f64 * b # a + 2^64 * b
if isNegative:
result = -result
proc ldexp(x: float64, exp: cint): float64 {.importc: "ldexp", header: "<math.h>".}
template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
proc toInt128*(arg: float64): Int128 =
let isNegative = arg < 0
assert(arg < 0x47E0000000000000'f64, "out of range")
assert(arg >= 0xC7E0000000000000'f64, "out of range")
let v0 = ldexp(abs(arg), -100)
let w0 = uint64(trunc(v0))
let v1 = ldexp(v0 - float64(w0), 50)
let w1 = uint64(trunc(v1))
let v2 = ldexp(v1 - float64(w1), 50)
let w2 = uint64(trunc(v2))
let res = bitor(toInt128(w0) shl 100, toInt128(w1) shl 50, toInt128(w2))
if isNegative:
return -res
else:
return res
proc maskUInt64*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0]
result.udata[1] = arg.udata[1]
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt32*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0]
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt16*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0] and 0xffff
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt8*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0] and 0xff
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
case numbytes
of 1:
return maskUInt8(arg)
of 2:
return maskUInt16(arg)
of 4:
return maskUInt32(arg)
of 8:
return maskUInt64(arg)
else:
assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
when isMainModule:
let (a,b) = divMod(Ten,Ten)
doAssert $One == "1"
doAssert $Ten == "10"
doAssert $Zero == "0"
let c = parseDecimalInt128("12345678989876543210123456789")
doAssert $c == "12345678989876543210123456789"
var d : array[39, Int128]
d[0] = parseDecimalInt128("1")
d[1] = parseDecimalInt128("10")
d[2] = parseDecimalInt128("100")
d[3] = parseDecimalInt128("1000")
d[4] = parseDecimalInt128("10000")
d[5] = parseDecimalInt128("100000")
d[6] = parseDecimalInt128("1000000")
d[7] = parseDecimalInt128("10000000")
d[8] = parseDecimalInt128("100000000")
d[9] = parseDecimalInt128("1000000000")
d[10] = parseDecimalInt128("10000000000")
d[11] = parseDecimalInt128("100000000000")
d[12] = parseDecimalInt128("1000000000000")
d[13] = parseDecimalInt128("10000000000000")
d[14] = parseDecimalInt128("100000000000000")
d[15] = parseDecimalInt128("1000000000000000")
d[16] = parseDecimalInt128("10000000000000000")
d[17] = parseDecimalInt128("100000000000000000")
d[18] = parseDecimalInt128("1000000000000000000")
d[19] = parseDecimalInt128("10000000000000000000")
d[20] = parseDecimalInt128("100000000000000000000")
d[21] = parseDecimalInt128("1000000000000000000000")
d[22] = parseDecimalInt128("10000000000000000000000")
d[23] = parseDecimalInt128("100000000000000000000000")
d[24] = parseDecimalInt128("1000000000000000000000000")
d[25] = parseDecimalInt128("10000000000000000000000000")
d[26] = parseDecimalInt128("100000000000000000000000000")
d[27] = parseDecimalInt128("1000000000000000000000000000")
d[28] = parseDecimalInt128("10000000000000000000000000000")
d[29] = parseDecimalInt128("100000000000000000000000000000")
d[30] = parseDecimalInt128("1000000000000000000000000000000")
d[31] = parseDecimalInt128("10000000000000000000000000000000")
d[32] = parseDecimalInt128("100000000000000000000000000000000")
d[33] = parseDecimalInt128("1000000000000000000000000000000000")
d[34] = parseDecimalInt128("10000000000000000000000000000000000")
d[35] = parseDecimalInt128("100000000000000000000000000000000000")
d[36] = parseDecimalInt128("1000000000000000000000000000000000000")
d[37] = parseDecimalInt128("10000000000000000000000000000000000000")
d[38] = parseDecimalInt128("100000000000000000000000000000000000000")
for i in 0 ..< d.len:
for j in 0 ..< d.len:
doAssert(cmp(d[i], d[j]) == cmp(i,j))
if i + j < d.len:
doAssert d[i] * d[j] == d[i+j]
if i - j >= 0:
doAssert d[i] div d[j] == d[i-j]
var sum: Int128
for it in d:
sum += it
doAssert $sum == "111111111111111111111111111111111111111"
for it in d.mitems:
it = -it
for i in 0 ..< d.len:
for j in 0 ..< d.len:
doAssert(cmp(d[i], d[j]) == -cmp(i,j))
if i + j < d.len:
doAssert d[i] * d[j] == -d[i+j]
if i - j >= 0:
doAssert d[i] div d[j] == -d[i-j]
doAssert $high(Int128) == "170141183460469231731687303715884105727"
doAssert $low(Int128) == "-170141183460469231731687303715884105728"
var ma = 100'i64
var mb = 13
# 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))

View File

@@ -29,11 +29,11 @@ implements the required case distinction.
import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
nversion, nimsets, msgs, std / sha1, bitsets, idents, types, os, tables,
times, ropes, math, passes, ccgutils, wordrecg, renderer,
ast, strutils, trees, magicsys, options,
nversion, msgs, idents, types, tables,
ropes, math, passes, ccgutils, wordrecg, renderer,
intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
pathutils, transf
transf
from modulegraphs import ModuleGraph, PPassContext
@@ -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,20 +428,6 @@ const # magic checked op; magic unchecked op;
["", ""], # BitnotI
["", ""], # UnaryPlusF64
["", ""], # UnaryMinusF64
["", ""], # AbsF64
["Ze8ToI", "Ze8ToI"], # mZe8ToI
["Ze8ToI64", "Ze8ToI64"], # mZe8ToI64
["Ze16ToI", "Ze16ToI"], # mZe16ToI
["Ze16ToI64", "Ze16ToI64"], # mZe16ToI64
["Ze32ToI64", "Ze32ToI64"], # mZe32ToI64
["ZeIToI64", "ZeIToI64"], # mZeIToI64
["toU8", "toU8"], # toU8
["toU16", "toU16"], # toU16
["toU32", "toU32"], # toU32
["", ""], # ToFloat
["", ""], # ToBiggestFloat
["", ""], # ToInt
["", ""], # ToBiggestInt
["nimCharToStr", "nimCharToStr"],
["nimBoolToStr", "nimBoolToStr"],
["cstrToNimstr", "cstrToNimstr"],
@@ -491,7 +475,7 @@ template binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
a, tmp = x.rdLoc
b, tmp2 = y.rdLoc
when "$3" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
when "$4" in frmt: (a, tmp) = maybeMakeTemp(p, n[1], x)
when "$4" in frmt: (b, tmp2) = maybeMakeTemp(p, n[2], y)
r.res = frmt % [a, b, tmp, tmp2]
r.kind = resExpr
@@ -544,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
@@ -579,23 +563,21 @@ 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("", "")
of mdivU: applyFormat("", "")
of mmodU: applyFormat("($1 % $2)", "($1 % $2)")
of mSubU: applyFormat("", "")
of mMulU: applyFormat("", "")
of mDivU: applyFormat("", "")
of mModU: applyFormat("($1 % $2)", "($1 % $2)")
of mEqI: applyFormat("($1 == $2)", "($1 == $2)")
of mLeI: applyFormat("($1 <= $2)", "($1 <= $2)")
of mLtI: applyFormat("($1 < $2)", "($1 < $2)")
of mEqF64: applyFormat("($1 == $2)", "($1 == $2)")
of mLeF64: applyFormat("($1 <= $2)", "($1 <= $2)")
of mLtF64: applyFormat("($1 < $2)", "($1 < $2)")
of mleU: applyFormat("($1 <= $2)", "($1 <= $2)")
of mltU: applyFormat("($1 < $2)", "($1 < $2)")
of mleU64: applyFormat("($1 <= $2)", "($1 <= $2)")
of mltU64: applyFormat("($1 < $2)", "($1 < $2)")
of mLeU: applyFormat("($1 <= $2)", "($1 <= $2)")
of mLtU: applyFormat("($1 < $2)", "($1 < $2)")
of mLeU64: applyFormat("($1 <= $2)", "($1 <= $2)")
of mLtU64: applyFormat("($1 < $2)", "($1 < $2)")
of mEqEnum: applyFormat("($1 == $2)", "($1 == $2)")
of mLeEnum: applyFormat("($1 <= $2)", "($1 <= $2)")
of mLtEnum: applyFormat("($1 < $2)", "($1 < $2)")
@@ -620,20 +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 mZe8ToI: applyFormat("Ze8ToI($1)", "Ze8ToI($1)")
of mZe8ToI64: applyFormat("Ze8ToI64($1)", "Ze8ToI64($1)")
of mZe16ToI: applyFormat("Ze16ToI($1)", "Ze16ToI($1)")
of mZe16ToI64: applyFormat("Ze16ToI64($1)", "Ze16ToI64($1)")
of mZe32ToI64: applyFormat("Ze32ToI64($1)", "Ze32ToI64($1)")
of mZeIToI64: applyFormat("ZeIToI64($1)", "ZeIToI64($1)")
of mtoU8: applyFormat("toU8($1)", "toU8($1)")
of mtoU16: applyFormat("toU16($1)", "toU16($1)")
of mtoU32: applyFormat("toU32($1)", "toU32($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)+\"\")")
@@ -684,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) =
@@ -749,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")
@@ -767,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
@@ -858,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])
@@ -930,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:
@@ -968,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)
@@ -987,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
@@ -1000,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
@@ -1175,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
@@ -1191,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)
@@ -1200,8 +1165,8 @@ 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]
@@ -1330,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)
@@ -1440,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
@@ -1474,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
@@ -1562,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, ", ")
@@ -1578,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
@@ -1609,9 +1578,9 @@ proc arrayTypeForElemType(typ: PType): string =
of tyInt, tyInt32: "Int32Array"
of tyInt16: "Int16Array"
of tyInt8: "Int8Array"
of tyUint, tyUint32: "Uint32Array"
of tyUint16: "Uint16Array"
of tyUint8: "Uint8Array"
of tyUInt, tyUInt32: "Uint32Array"
of tyUInt16: "Uint16Array"
of tyUInt8: "Uint8Array"
of tyFloat32: "Float32Array"
of tyFloat64, tyFloat: "Float64Array"
else: ""
@@ -1629,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:
@@ -1652,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)])
@@ -1753,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:
@@ -1765,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):
@@ -1811,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])
@@ -2058,8 +2033,14 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mParseBiggestFloat:
useMagic(p, "nimParseBiggestFloat")
genCall(p, n, r)
of mArray:
genCall(p, n, r)
of mSlice:
# arr.slice([begin[, end]]): 'end' is exclusive
var x, y, z: TCompRes
gen(p, n.sons[1], x)
gen(p, n.sons[2], y)
gen(p, n.sons[3], z)
r.res = "($1.slice($2, $3+1))" % [x.rdLoc, y.rdLoc, z.rdLoc]
r.kind = resExpr
else:
genCall(p, n, r)
#else internalError(p.config, e.info, 'genMagic: ' + magicToStr[op]);
@@ -2070,7 +2051,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:
@@ -2092,7 +2073,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:
@@ -2109,7 +2090,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]
@@ -2129,7 +2110,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
@@ -2264,7 +2245,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
if prc.typ.sons[0] != nil and sfPure notin prc.flags:
resultSym = prc.ast.sons[resultPos].sym
let mname = mangleName(p.module, resultSym)
if not isindirect(resultSym) and
if not isIndirect(resultSym) and
resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and
mapType(p, resultSym.typ) == etyBaseIndex:
resultAsgn = p.indentLine(("var $# = null;$n") % [mname])
@@ -2278,8 +2259,8 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
else:
returnStmt = "return $#;$n" % [a.res]
let transformed_body = transformBody(oldProc.module.graph, prc, cache = false)
p.nested: genStmt(p, transformed_body)
let transformedBody = transformBody(oldProc.module.graph, prc, cache = false)
p.nested: genStmt(p, transformedBody)
var def: Rope
if not prc.constraint.isNil:
@@ -2409,7 +2390,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkFloatLit..nkFloat64Lit:
let f = n.floatVal
case classify(f)
of fcNaN:
of fcNan:
r.res = rope"NaN"
of fcNegZero:
r.res = rope"-0.0"
@@ -2463,7 +2444,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)
@@ -2559,7 +2540,7 @@ proc genModule(p: PProc, n: PNode) =
add(p.body, frameCreate(p,
makeJSString("module " & p.module.module.name.s),
makeJSString(toFilename(p.config, p.module.module.info))))
let n_transformed = transformStmt(p.module.graph, p.module.module, n)
let transformedN = transformStmt(p.module.graph, p.module.module, n)
if p.config.hcrOn and n.kind == nkStmtList:
let moduleSym = p.module.module
var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" &
@@ -2567,7 +2548,7 @@ proc genModule(p: PProc, n: PNode) =
lineF(p, "var $1;$n", [moduleLoadedVar])
var inGuardedBlock = false
addHcrInitGuards(p, n_transformed, moduleLoadedVar, inGuardedBlock)
addHcrInitGuards(p, transformedN, moduleLoadedVar, inGuardedBlock)
if inGuardedBlock:
dec p.extraIndent
@@ -2575,7 +2556,7 @@ proc genModule(p: PProc, n: PNode) =
lineF(p, "$1 = true;$n", [moduleLoadedVar])
else:
genStmt(p, n_transformed)
genStmt(p, transformedN)
if optStackTrace in p.options:
add(p.body, frameDestroy(p))
@@ -2600,7 +2581,7 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
attachProc(p, prc)
var disp = generateMethodDispatchers(graph)
for i in 0..sonsLen(disp)-1:
for i in 0..len(disp)-1:
let prc = disp.sons[i].sym
if not globals.generatedSyms.containsOrIncl(prc.id):
var p = newProc(globals, m, nil, m.module.options)

View File

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

View File

@@ -10,9 +10,9 @@
# This file implements lambda lifting for the transformator.
import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs,
intsets, strutils, options, ast, astalgo, msgs,
idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos,
transf
transf, liftdestructors
discard """
The basic approach is that captured vars need to be put on the heap and
@@ -257,6 +257,8 @@ 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:
createTypeBoundOps(g, nil, env.typ, n.info)
result.add makeClosure(g, iter, env, n.info)
proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
@@ -324,6 +326,7 @@ proc asOwnedRef(c: DetectionPass; t: PType): PType =
if optNimV2 in c.graph.config.globalOptions:
assert t.kind == tyRef
result = newType(tyOwned, t.owner)
result.flags.incl tfHasOwned
result.rawAddSon t
else:
result = t
@@ -341,7 +344,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
# This seems to be generally correct but since it's a bit risky it's only
# enabled for gcDestructors.
let fieldType = if c.graph.config.selectedGc == gcDestructors:
let fieldType = if false: # c.graph.config.selectedGC == gcDestructors:
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
else:
c.getEnvTypeForOwner(dep, info)
@@ -474,7 +477,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
w = up
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt:
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
discard
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil:
@@ -490,6 +493,7 @@ type
processed: IntSet
envVars: Table[int, PNode]
inContainer: int
unownedEnvVars: Table[int, PNode] # only required for --newruntime
proc initLiftingPass(fn: PSym): LiftingPass =
result.processed = initIntSet()
@@ -514,9 +518,9 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
localError(g.config, n.info, "internal error: environment misses: " & s.name.s)
result = n
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType): PNode =
var v = newSym(skVar, getIdent(cache, envName), owner, owner.info)
incl(v.flags, sfShadowed)
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNode =
var v = newSym(skVar, getIdent(cache, envName), owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = typ
result = newSymNode(v)
when false:
@@ -528,16 +532,21 @@ proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType): PNode =
result = newSymNode(v)
proc setupEnvVar(owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode =
c: var LiftingPass; info: TLineInfo): PNode =
if owner.isIterator:
return getHiddenParam(d.graph, owner).newSymNode
result = c.envvars.getOrDefault(owner.id)
result = c.envVars.getOrDefault(owner.id)
if result.isNil:
let envVarType = d.ownerToType.getOrDefault(owner.id)
if envVarType.isNil:
localError d.graph.config, owner.info, "internal error: could not determine closure type"
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType))
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info)
c.envVars[owner.id] = result
if optNimV2 in d.graph.config.globalOptions:
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = envVarType
c.unownedEnvVars[owner.id] = newSymNode(v)
proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
let p = getHiddenParam(g, owner)
@@ -550,20 +559,34 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
result = rawIndirectAccess(result, upField, p.info)
proc rawClosureCreation(owner: PSym;
d: DetectionPass; c: var LiftingPass): PNode =
d: DetectionPass; c: var LiftingPass;
info: TLineInfo): PNode =
result = newNodeI(nkStmtList, owner.info)
var env: PNode
if owner.isIterator:
env = getHiddenParam(d.graph, owner).newSymNode
else:
env = setupEnvVar(owner, d, c)
env = setupEnvVar(owner, d, c, info)
if env.kind == nkSym:
var v = newNodeI(nkVarSection, env.info)
addVar(v, env)
result.add(v)
if optNimV2 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:
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)
# add assignment statements for captured parameters:
for i in 1..<owner.typ.n.len:
let local = owner.typ.n[i].sym
@@ -583,6 +606,18 @@ proc rawClosureCreation(owner: PSym;
# oldenv, env.info))
else:
localError(d.graph.config, env.info, "internal error: cannot create up reference")
# we are not in the sem'check phase anymore! so pass 'nil' for the PContext
# and hope for the best:
if optNimV2 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:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
let nilLit = newNodeIT(nkNilLit, info, unowned.typ)
res.add newAsgnStmt(unowned, nilLit, info)
proc closureCreationForIter(iter: PNode;
d: DetectionPass; c: var LiftingPass): PNode =
@@ -602,10 +637,12 @@ 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:
createTypeBoundOps(d.graph, nil, vnode.typ, iter.info)
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
if upField != nil:
let u = setupEnvVar(owner, d, c)
let u = setupEnvVar(owner, d, c, iter.info)
if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}):
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
u, iter.info))
@@ -615,7 +652,9 @@ proc closureCreationForIter(iter: PNode;
proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode =
let access = setupEnvVar(owner, d, c)
var access = setupEnvVar(owner, d, c, n.info)
if optNimV2 in d.graph.config.globalOptions:
access = c.unownedEnvVars[owner.id]
let obj = access.typ.skipTypes({tyOwned, tyRef})
let field = getFieldFromObj(obj, n.sym)
if field != nil:
@@ -641,7 +680,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
result = closureCreationForIter(n, d, c)
elif s.skipGenericOwner == owner:
# direct dependency, so use the outer's env variable:
result = makeClosure(d.graph, s, setupEnvVar(owner, d, c), n.info)
result = makeClosure(d.graph, s, setupEnvVar(owner, d, c, n.info), n.info)
else:
let available = getHiddenParam(d.graph, owner)
let wanted = getHiddenParam(d.graph, s).typ
@@ -671,10 +710,11 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c.inContainer = 0
var body = transformBody(d.graph, s)
body = liftCapturedVars(body, s, d, c)
if c.envvars.getOrDefault(s.id).isNil:
if c.envVars.getOrDefault(s.id).isNil:
s.transformedBody = body
else:
s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c), body)
s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c, n.info), body)
finishClosureCreation(s, d, c, n.info, s.transformedBody)
c.inContainer = oldInContainer
if s.typ.callConv == ccClosure:
@@ -718,7 +758,10 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# transform, let's not touch the LHS in order to make the lifting pass
# correct when `result` is lifted
n[0].sons[1] = liftCapturedVars(n[0].sons[1], owner, d, c)
else: assert n[0].kind == nkEmpty
else:
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
of nkTypeOfExpr:
result = n
else:
if owner.isIterator:
if nfLL in n.flags:
@@ -810,8 +853,9 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
var c = initLiftingPass(fn)
result = liftCapturedVars(body, fn, d, c)
# echo renderTree(result, {renderIds})
if c.envvars.getOrDefault(fn.id) != nil:
result = newTree(nkStmtList, rawClosureCreation(fn, d, c), result)
if c.envVars.getOrDefault(fn.id) != nil:
result = newTree(nkStmtList, rawClosureCreation(fn, d, c, body.info), result)
finishClosureCreation(fn, d, c, body.info, result)
else:
result = body
#if fn.name.s == "get2":
@@ -879,6 +923,9 @@ 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:
createTypeBoundOps(g, nil, env.typ, body.info)
elif op.kind == nkStmtListExpr:
let closure = op.lastSon
if closure.kind == nkClosure:
@@ -888,7 +935,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
var loopBody = newNodeI(nkStmtList, body.info, 3)
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(g, body.info, tyBool))
whileLoop.sons[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
whileLoop.sons[1] = loopBody
result.add whileLoop

View File

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

View File

@@ -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
@@ -146,10 +146,6 @@ type
previousToken: TLineInfo
config*: ConfigRef
when defined(nimpretty):
var
gIndentationWidth*: int
proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
result = newLineInfo(L.fileIdx, tok.line, tok.col)
when defined(nimpretty):
@@ -173,7 +169,7 @@ proc isNimIdentifier*(s: string): bool =
inc(i)
result = true
proc tokToStr*(tok: TToken): string =
proc `$`*(tok: TToken): string =
case tok.tokType
of tkIntLit..tkInt64Lit: result = $tok.iNumber
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
@@ -188,11 +184,11 @@ proc tokToStr*(tok: TToken): string =
proc prettyTok*(tok: TToken): string =
if isKeyword(tok.tokType): result = "keyword " & tok.ident.s
else: result = tokToStr(tok)
else: result = $tok
proc printTok*(conf: ConfigRef; tok: TToken) =
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
TokTypeToStr[tok.tokType] & " " & tokToStr(tok))
TokTypeToStr[tok.tokType] & " " & $tok)
proc initToken*(L: var TToken) =
L.tokType = tkInvalid
@@ -223,7 +219,7 @@ proc fillToken(L: var TToken) =
proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
cache: IdentCache; config: ConfigRef) =
openBaseLexer(lex, inputstream)
lex.fileIdx = fileidx
lex.fileIdx = fileIdx
lex.indentAhead = -1
lex.currLineIndent = 0
inc(lex.lineNumber, inputstream.lineOffset)
@@ -379,7 +375,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
result.literal = ""
result.base = base10
startpos = L.bufpos
tokenBegin(result, startPos)
tokenBegin(result, startpos)
# First stage: find out base, make verifications, build token literal string
# {'c', 'C'} is added for deprecation reasons to provide a clear error message
@@ -534,13 +530,13 @@ proc getNumber(L: var TLexer, result: var TToken) =
case result.tokType
of tkIntLit, tkInt64Lit: result.iNumber = xi
of tkInt8Lit: result.iNumber = BiggestInt(int8(toU8(int(xi))))
of tkInt16Lit: result.iNumber = BiggestInt(int16(toU16(int(xi))))
of tkInt32Lit: result.iNumber = BiggestInt(int32(toU32(int64(xi))))
of tkInt8Lit: result.iNumber = ashr(xi shl 56, 56)
of tkInt16Lit: result.iNumber = ashr(xi shl 48, 48)
of tkInt32Lit: result.iNumber = ashr(xi shl 32, 32)
of tkUIntLit, tkUInt64Lit: result.iNumber = xi
of tkUInt8Lit: result.iNumber = BiggestInt(cast[uint8](toU8(int(xi))))
of tkUInt16Lit: result.iNumber = BiggestInt(cast[uint16](toU16(int(xi))))
of tkUInt32Lit: result.iNumber = BiggestInt(cast[uint32](toU32(int64(xi))))
of tkUInt8Lit: result.iNumber = xi and 0xff
of tkUInt16Lit: result.iNumber = xi and 0xffff
of tkUInt32Lit: result.iNumber = xi and 0xffffffff
of tkFloat32Lit:
result.fNumber = (cast[PFloat32](addr(xi)))[]
# note: this code is endian neutral!
@@ -569,7 +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:
@@ -868,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
@@ -882,6 +880,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
var h: Hash = 0
var pos = L.bufpos
tokenBegin(tok, pos)
var suspicious = false
while true:
var c = L.buf[pos]
case c
@@ -892,21 +891,26 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h !& ord(c)
inc(pos)
suspicious = true
of '_':
if L.buf[pos+1] notin SymChars:
lexMessage(L, errGenerated, "invalid token: trailing underscore")
break
inc(pos)
suspicious = true
else: break
tokenEnd(tok, pos-1)
h = !$h
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
L.bufpos = pos
if (tok.ident.id < ord(tokKeywordLow) - ord(tkSymbol)) or
(tok.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
tok.tokType = tkSymbol
else:
tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
if suspicious and {optStyleHint, optStyleError} * L.config.globalOptions != {}:
lintReport(L.config, getLineInfo(L), tok.ident.s.normalize, tok.ident.s)
L.bufpos = pos
proc endOperator(L: var TLexer, tok: var TToken, pos: int,
hash: Hash) {.inline.} =
@@ -1119,7 +1123,7 @@ proc skip(L: var TLexer, tok: var TToken) =
inc(pos)
inc(tok.strongSpaceA)
of '\t':
if not L.allowTabs: lexMessagePos(L, errGenerated, pos, "tabulators are not allowed")
if not L.allowTabs: lexMessagePos(L, errGenerated, pos, "tabs are not allowed, use spaces instead")
inc(pos)
of CR, LF:
tokenEndPrevious(tok, pos)
@@ -1174,8 +1178,6 @@ proc skip(L: var TLexer, tok: var TToken) =
tok.commentOffsetB = L.offsetBase + pos - 1
tok.tokType = tkComment
tok.indent = commentIndent
if gIndentationWidth <= 0:
gIndentationWidth = tok.indent
proc rawGetTok*(L: var TLexer, tok: var TToken) =
template atTokenEnd() {.dirty.} =
@@ -1334,10 +1336,13 @@ proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
var tok: TToken
initToken(tok)
openLexer(lex, fileIdx, inputstream, cache, config)
while true:
var prevToken = tkEof
while tok.tokType != tkEof:
rawGetTok(lex, tok)
result = tok.indent
if result > 0 or tok.tokType == tkEof: break
if tok.indent > 0 and prevToken in {tkColon, tkEquals, tkType, tkConst, tkLet, tkVar, tkUsing}:
result = tok.indent
if result > 0: break
prevToken = tok.tokType
closeLexer(lex)
proc getPrecedence*(ident: PIdent): int =

View File

@@ -10,28 +10,27 @@
## This module implements lifting for type-bound operations
## (``=sink``, ``=``, ``=destroy``, ``=deepCopy``).
# included from sempass2.nim
# Todo:
# - use openArray instead of array to avoid over-specializations
import sighashes
import modulegraphs, lineinfos, idents, ast, renderer, semdata,
sighashes, lowerings, options, types, msgs, magicsys, tables
type
TLiftCtx = object
graph: ModuleGraph
g: ModuleGraph
info: TLineInfo # for construction
kind: TTypeAttachedOp
fn: PSym
asgnForType: PType
recurse: bool
c: PContext
c: PContext # c can be nil, then we are called from lambdalifting!
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo): PSym
proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo)
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo)
proc at(a, i: PNode, elemType: PType): PNode =
result = newNodeI(nkBracketExpr, a.info, 2)
@@ -41,7 +40,7 @@ proc at(a, i: PNode, elemType: PType): PNode =
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
for i in 0 ..< t.len:
let lit = lowerings.newIntLit(c.graph, x.info, i)
let lit = lowerings.newIntLit(c.g, x.info, i)
fillBody(c, t.sons[i], body, x.at(lit, t.sons[i]), y.at(lit, t.sons[i]))
proc dotField(x: PNode, f: PSym): PNode =
@@ -88,7 +87,12 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
of nkRecList:
for t in items(n): fillBodyObj(c, t, body, x, y)
else:
illFormedAstLocal(n, c.graph.config)
illFormedAstLocal(n, c.g.config)
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
if t.len > 0 and t.sons[0] != nil:
fillBodyObjT(c, skipTypes(t.sons[0], abstractPtrs), body, x, y)
fillBodyObj(c, t.n, body, x, y)
proc genAddr(g: ModuleGraph; x: PNode): PNode =
if x.kind == nkHiddenDeref:
@@ -125,20 +129,28 @@ 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.graph.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 =
if c.c != nil and typeInst != nil:
result = c.c.instTypeBoundOp(c.c, op, typeInst, c.info, attachedAsgn, 1)
else:
localError(c.g.config, c.info,
"cannot generate destructor for generic type: " & typeToString(t))
result = nil
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
field: var PSym): bool =
if optNimV2 in c.graph.config.globalOptions:
if c.g.config.selectedGC == gcDestructors:
let op = field
if field != nil and sfOverriden in field.flags:
if sfError in op.flags:
incl c.fn.flags, sfError
else:
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
#else:
# markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add newAsgnCall(c.graph, op, x, y)
body.add newAsgnCall(c.g, op, x, y)
result = true
elif tfHasAsgn in t.flags:
var op: PSym
@@ -152,38 +164,45 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
else:
op = field
if op == nil:
op = produceSym(c.c, t, c.kind, c.info)
op = produceSym(c.g, c.c, t, c.kind, c.info)
if sfError in op.flags:
incl c.fn.flags, sfError
else:
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
#else:
# markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
# We also now do generic instantiations in the destructor lifting pass:
if op.ast[genericParamsPos].kind != nkEmpty:
assert t.typeInst != nil
op = c.c.instTypeBoundOp(c.c, op, t.typeInst, c.info, attachedAsgn, 1)
op = instantiateGeneric(c, op, t, t.typeInst)
field = op
#echo "trying to use ", op.ast
#echo "for ", op.name.s, " "
#debug(t)
#return false
assert op.ast[genericParamsPos].kind == nkEmpty
body.add newAsgnCall(c.graph, op, x, y)
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.c, t, attachedDestructor, c.info)
op = produceSym(c.g, c.c, t, attachedDestructor, c.info)
doAssert op != nil
doAssert op == t.destructor
if op != nil:
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add destructorCall(c.graph, op, x)
body.add destructorCall(c.g, op, x)
elif useNoGc(c, t):
internalError(c.graph.config, c.info,
internalError(c.g.config, c.info,
"type-bound operator could not be resolved")
proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
@@ -193,14 +212,13 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
if op != nil and sfOverriden in op.flags:
if op.ast[genericParamsPos].kind != nkEmpty:
assert t.typeInst != nil
# patch generic destructor:
op = c.c.instTypeBoundOp(c.c, op, t.typeInst, c.info, attachedAsgn, 1)
op = instantiateGeneric(c, op, t, t.typeInst)
t.attachedOps[attachedDestructor] = op
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add destructorCall(c.graph, op, x)
body.add destructorCall(c.g, op, x)
result = true
#result = addDestructorCall(c, t, body, x)
of attachedAsgn:
@@ -210,7 +228,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
of attachedDeepCopy:
let op = t.attachedOps[attachedDeepCopy]
if op != nil:
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add newDeepCopyCall(op, x, y)
result = true
@@ -227,13 +245,13 @@ proc addVar(father, v, value: PNode) =
addSon(father, vpart)
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
var temp = newSym(skTemp, getIdent(c.graph.cache, lowerings.genPrefix), c.fn, c.info)
temp.typ = getSysType(c.graph, body.info, tyInt)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
temp.typ = getSysType(c.g, body.info, tyInt)
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, c.info)
result = newSymNode(temp)
v.addVar(result, lowerings.newIntLit(c.graph, body.info, first))
v.addVar(result, lowerings.newIntLit(c.g, body.info, first))
body.add v
proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
@@ -243,9 +261,9 @@ proc genBuiltin(g: ModuleGraph; magic: TMagic; name: string; i: PNode): PNode =
proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
result = newNodeI(nkWhileStmt, c.info, 2)
let cmp = genBuiltin(c.graph, mLtI, "<", i)
cmp.add genLen(c.graph, dest)
cmp.typ = getSysType(c.graph, c.info, tyBool)
let cmp = genBuiltin(c.g, mLtI, "<", i)
cmp.add genLen(c.g, dest)
cmp.typ = getSysType(c.g, c.info, tyBool)
result.sons[0] = cmp
result.sons[1] = newNodeI(nkStmtList, c.info)
@@ -253,8 +271,8 @@ proc genIf(c: var TLiftCtx; cond, action: PNode): PNode =
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action))
proc addIncStmt(c: var TLiftCtx; body, i: PNode) =
let incCall = genBuiltin(c.graph, mInc, "inc", i)
incCall.add lowerings.newIntLit(c.graph, c.info, 1)
let incCall = genBuiltin(c.g, mInc, "inc", i)
incCall.add lowerings.newIntLit(c.g, c.info, 1)
body.add incCall
proc newSeqCall(g: ModuleGraph; x, y: PNode): PNode =
@@ -271,18 +289,18 @@ proc setLenStrCall(g: ModuleGraph; x, y: PNode): PNode =
result.add lenCall
proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
let lenCall = genBuiltin(c.graph, mLengthSeq, "len", y)
lenCall.typ = getSysType(c.graph, x.info, tyInt)
var op = getSysMagic(c.graph, x.info, "setLen", mSetLengthSeq)
op = c.c.instTypeBoundOp(c.c, op, t, c.info, attachedAsgn, 1)
let lenCall = genBuiltin(c.g, mLengthSeq, "len", y)
lenCall.typ = getSysType(c.g, x.info, tyInt)
var op = getSysMagic(c.g, x.info, "setLen", mSetLengthSeq)
op = instantiateGeneric(c, op, t, t)
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.graph.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),
y.at(i, elemType))
y.at(i, elemType))
addIncStmt(c, whileLoop.sons[1], i)
body.add whileLoop
@@ -297,63 +315,69 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add setLenSeqCall(c, t, x, y)
forallElements(c, t, body, x, y)
of attachedSink:
let moveCall = genBuiltin(c.graph, mMove, "move", x)
let moveCall = genBuiltin(c.g, mMove, "move", x)
moveCall.add y
doAssert t.destructor != nil
moveCall.add destructorCall(c.graph, t.destructor, x)
moveCall.add destructorCall(c.g, t.destructor, x)
body.add moveCall
of attachedDestructor:
# destroy all elements:
forallElements(c, t, body, x, y)
body.add genBuiltin(c.graph, mDestroy, "destroy", x)
body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
createTypeBoundOps(c.c, t, body.info)
createTypeBoundOps(c.g, c.c, t, body.info)
case c.kind
of attachedAsgn, attachedDeepCopy:
doAssert t.assignment != nil
body.add newAsgnCall(c.graph, t.assignment, x, y)
body.add newAsgnCall(c.g, t.assignment, x, y)
of attachedSink:
# we always inline the move for better performance:
let moveCall = genBuiltin(c.graph, mMove, "move", x)
let moveCall = genBuiltin(c.g, mMove, "move", x)
moveCall.add y
doAssert t.destructor != nil
moveCall.add destructorCall(c.graph, t.destructor, x)
moveCall.add destructorCall(c.g, t.destructor, x)
body.add moveCall
# alternatively we could do this:
when false:
doAssert t.asink != nil
body.add newAsgnCall(c.graph, t.asink, x, y)
body.add newAsgnCall(c.g, t.asink, x, y)
of attachedDestructor:
doAssert t.destructor != nil
body.add destructorCall(c.graph, t.destructor, x)
body.add destructorCall(c.g, t.destructor, x)
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
of attachedAsgn, attachedDeepCopy:
body.add callCodegenProc(c.graph, "nimAsgnStrV2", c.info, genAddr(c.graph, x), y)
body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c.g, x), y)
of attachedSink:
let moveCall = genBuiltin(c.graph, mMove, "move", x)
let moveCall = genBuiltin(c.g, mMove, "move", x)
moveCall.add y
doAssert t.destructor != nil
moveCall.add destructorCall(c.graph, t.destructor, x)
moveCall.add destructorCall(c.g, t.destructor, x)
body.add moveCall
of attachedDestructor:
body.add genBuiltin(c.graph, mDestroy, "destroy", x)
body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
of attachedSink:
# we 'nil' y out afterwards so we *need* to take over its reference
# count value:
body.add genIf(c, x, callCodegenProc(c.graph, "nimDecWeakRef", c.info, x))
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
body.add newAsgnStmt(x, y)
of attachedAsgn:
body.add genIf(c, y, callCodegenProc(c.graph, "nimIncWeakRef", c.info, y))
body.add genIf(c, x, callCodegenProc(c.graph, "nimDecWeakRef", c.info, x))
body.add genIf(c, y, callCodegenProc(c.g, "nimIncWeakRef", c.info, y))
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, x, callCodegenProc(c.graph, "nimDecWeakRef", c.info, x))
# it's better to prepend the destruction of weak refs in order to
# prevent wrong "dangling refs exist" problems:
let des = genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
if body.len == 0:
body.add des
else:
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
@@ -361,14 +385,14 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let elemType = t.lastSon
#fillBody(c, elemType, actions, genDeref(x), genDeref(y))
#var disposeCall = genBuiltin(c.graph, mDispose, "dispose", x)
#var disposeCall = genBuiltin(c.g, mDispose, "dispose", x)
if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.graph, "nimRawDispose", c.info, x)
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
else:
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.graph, "nimDestroyAndDispose", c.info, x)
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
case c.kind
of attachedSink, attachedAsgn:
@@ -384,35 +408,40 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# 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.graph, "deepCopy", mDeepCopy))
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
call.sons[1] = y
body.add newAsgnStmt(x, call)
elif optNimV2 in c.graph.config.globalOptions:
let xx = genBuiltin(c.graph, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.graph, c.info, tyPointer)
elif optNimV2 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)
case c.kind
of attachedSink:
# we 'nil' y out afterwards so we *need* to take over its reference
# count value:
body.add genIf(c, xx, callCodegenProc(c.graph, "nimDecWeakRef", c.info, xx))
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
body.add newAsgnStmt(x, y)
of attachedAsgn:
let yy = genBuiltin(c.graph, mAccessEnv, "accessEnv", y)
yy.typ = getSysType(c.graph, c.info, tyPointer)
body.add genIf(c, yy, callCodegenProc(c.graph, "nimIncWeakRef", c.info, yy))
body.add genIf(c, xx, callCodegenProc(c.graph, "nimDecWeakRef", c.info, xx))
let yy = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
yy.typ = getSysType(c.g, c.info, tyPointer)
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncWeakRef", c.info, yy))
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, xx, callCodegenProc(c.graph, "nimDecWeakRef", c.info, xx))
let des = genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
if body.len == 0:
body.add des
else:
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let xx = genBuiltin(c.graph, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.graph, c.info, tyPointer)
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.g, c.info, tyPointer)
var actions = newNodeI(nkStmtList, c.info)
let elemType = t.lastSon
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
actions.add callCodegenProc(c.graph, "nimDestroyAndDispose", c.info, xx)
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
case c.kind
of attachedSink, attachedAsgn:
body.add genIf(c, xx, actions)
@@ -428,7 +457,8 @@ 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.graph.config.globalOptions:
if optNimV2 in c.g.config.globalOptions and
optRefCheck in c.g.config.options:
weakrefOp(c, t, body, x, y)
else:
defaultOp(c, t, body, x, y)
@@ -439,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.graph.config.globalOptions:
if optNimV2 in c.g.config.globalOptions:
case base.kind
of tyRef:
ownedRefOp(c, base, body, x, y)
@@ -458,13 +488,13 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tySequence:
if useNoGc(c, t):
useSeqOrStrOp(c, t, body, x, y)
elif c.graph.config.selectedGC == gcDestructors:
elif c.g.config.selectedGC == gcDestructors:
# note that tfHasAsgn is propagated so we need the check on
# 'selectedGC' here to determine if we have the new runtime.
discard considerUserDefinedOp(c, t, body, x, y)
elif tfHasAsgn in t.flags:
if c.kind != attachedDestructor:
body.add newSeqCall(c.graph, x, y)
body.add newSeqCall(c.g, x, y)
forallElements(c, t, body, x, y)
else:
defaultOp(c, t, body, x, y)
@@ -477,19 +507,23 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
defaultOp(c, t, body, x, y)
of tyObject:
if not considerUserDefinedOp(c, t, body, x, y):
fillBodyObj(c, t.n, body, x, y)
fillBodyObjT(c, t, body, x, y)
of tyDistinct:
if not considerUserDefinedOp(c, t, body, x, y):
fillBody(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
of tyTuple:
fillBodyTup(c, t, body, x, y)
of tyVarargs, tyOpenArray:
localError(c.graph.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,
tyTypeDesc, tyGenericInvocation, tyForward:
#internalError(c.graph.config, c.info, "assignment requested for type: " & typeToString(t))
#internalError(c.g.config, c.info, "assignment requested for type: " & typeToString(t))
discard
of tyVar, tyLent:
if c.kind != attachedDestructor:
@@ -498,25 +532,24 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
tyGenericInst, tyStatic, tyAlias, tySink:
fillBody(c, lastSon(t), body, x, y)
proc produceSymDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
assert typ.kind == tyDistinct
let baseType = typ[0]
if baseType.attachedOps[kind] == nil:
discard produceSym(c, baseType, kind, info)
discard produceSym(g, c, baseType, kind, info)
typ.attachedOps[kind] = baseType.attachedOps[kind]
result = typ.attachedOps[kind]
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo): PSym =
if typ.kind == tyDistinct:
return produceSymDistinctType(c, typ, kind, info)
return produceSymDistinctType(g, c, typ, kind, info)
var a: TLiftCtx
a.info = info
a.graph = c.graph
a.g = g
a.kind = kind
a.c = c
let g = c.graph
let body = newNodeI(nkStmtList, info)
let procname = getIdent(g.cache, AttachedOpToStr[kind])
@@ -538,7 +571,7 @@ proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
typ.attachedOps[kind] = result
var tk: TTypeKind
if optNimV2 in c.graph.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
@@ -562,33 +595,39 @@ proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
discard "now a nop"
proc patchBody(c: PContext; n: PNode; info: TLineInfo) =
proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) =
if n.kind in nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
let t = n[1].typ.skipTypes(abstractVar)
if t.destructor == nil:
discard produceSym(c, t, attachedDestructor, info)
discard produceSym(g, c, t, attachedDestructor, info)
if t.destructor != nil:
if t.destructor.ast[genericParamsPos].kind != nkEmpty:
internalError(c.graph.config, info, "resolved destructor is generic")
internalError(g.config, info, "resolved destructor is generic")
if t.destructor.magic == mDestroy:
internalError(c.graph.config, info, "patching mDestroy with mDestroy?")
internalError(g.config, info, "patching mDestroy with mDestroy?")
n.sons[0] = newSymNode(t.destructor)
for x in n: patchBody(c, x, info)
for x in n: patchBody(g, c, x, info)
template inst(field, t) =
if field.ast != nil and field.ast[genericParamsPos].kind != nkEmpty:
if t.typeInst != nil:
field = c.instTypeBoundOp(c, field, t.typeInst, info, attachedAsgn, 1)
var a: TLiftCtx
a.info = info
a.g = g
a.kind = k
a.c = c
field = instantiateGeneric(a, field, t, t.typeInst)
if field.ast != nil:
patchBody(c, field.ast, info)
patchBody(g, c, field.ast, info)
else:
localError(c.graph.config, info, "unresolved generic parameter")
localError(g.config, info, "unresolved generic parameter")
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
## In the semantic pass this is called in strategic places
## to ensure we lift assignment, destructors and moves properly.
## The later 'injectdestructors' pass depends on it.
@@ -596,13 +635,13 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
incl orig.flags, tfCheckedForDestructor
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned, CoDistinct})
var canon = c.graph.canonTypes.getOrDefault(h)
var canon = g.canonTypes.getOrDefault(h)
var overwrite = false
if canon == nil:
let typ = orig.skipTypes({tyGenericInst, tyAlias})
c.graph.canonTypes[h] = typ
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:
@@ -615,7 +654,7 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
# we generate the destructor first so that other operators can depend on it:
for k in attachedDestructor..attachedSink:
if canon.attachedOps[k] == nil:
discard produceSym(c, canon, k, info)
discard produceSym(g, c, canon, k, info)
else:
inst(canon.attachedOps[k], canon)

View File

@@ -10,7 +10,7 @@
## This module implements the '.liftLocals' pragma.
import
intsets, strutils, options, ast, astalgo, msgs,
strutils, options, ast, msgs,
idents, renderer, types, lowerings, lineinfos
from pragmas import getPragmaVal

View File

@@ -13,7 +13,7 @@
import ropes, tables, pathutils
const
explanationsBaseUrl* = "https://nim-lang.org/docs/manual"
explanationsBaseUrl* = "https://nim-lang.org/docs"
type
TMsgKind* = enum
@@ -33,12 +33,14 @@ type
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnUnusedImportX,
warnEachIdentIsTuple,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnCaseTransition, warnUser,
hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintLineTooLong, hintXDeclaredButNotUsed,
hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
@@ -78,6 +80,7 @@ const
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
warnWriteToForeignHeap: "write to foreign heap",
warnUnsafeCode: "unsafe code: '$1'",
warnUnusedImportX: "imported and not used: '$1'",
warnEachIdentIsTuple: "each identifier is a tuple",
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
warnProveField: "cannot prove that field '$1' is accessible",
@@ -108,7 +111,7 @@ const
hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'",
hintConditionAlwaysFalse: "condition is always false: '$1'",
hintName: "name should be: '$1'",
hintName: "$1",
hintPattern: "$1",
hintExecuting: "$1",
hintLinking: "",
@@ -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",
@@ -193,7 +197,7 @@ type
# used for better error messages and
# embedding the original source in the
# generated code
dirtyfile*: AbsoluteFile # the file that is actually read into memory
dirtyFile*: AbsoluteFile # the file that is actually read into memory
# and parsed; usually "" but is used
# for 'nimsuggest'
hash*: string # the checksum of the file
@@ -229,19 +233,21 @@ proc raiseRecoverableError*(msg: string) {.noinline.} =
raise newException(ERecoverableError, msg)
const
InvalidFileIDX* = FileIndex(-1)
InvalidFileIdx* = FileIndex(-1)
proc unknownLineInfo*(): TLineInfo =
result.line = uint16(0)
result.col = int16(-1)
result.fileIndex = InvalidFileIDX
result.fileIndex = InvalidFileIdx
type
Severity* {.pure.} = enum ## VS Code only supports these three
Hint, Warning, Error
const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
const
trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
commandLineIdx* = FileIndex(-3)
type
MsgConfig* = object ## does not need to be stored in the incremental cache

View File

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

View File

@@ -10,7 +10,7 @@
## Low-level streams for high performance.
import
strutils, pathutils
pathutils
# support '-d:useGnuReadline' for backwards compatibility:
when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)):
@@ -97,7 +97,7 @@ proc continueLine(line: string, inTripleString: bool): bool {.inline.} =
proc countTriples(s: string): int =
var i = 0
while i < s.len:
while i+2 < s.len:
if s[i] == '"' and s[i+1] == '"' and s[i+2] == '"':
inc result
inc i, 2

View File

@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, idents, semdata, types, msgs, options,
renderer, wordrecg, idgen, nimfix/prettybase, lineinfos, strutils
renderer, nimfix/prettybase, lineinfos, strutils
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)
@@ -233,7 +233,7 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addInterfaceDeclAux(c, sym)
when defined(nimfix):
# when we cannot find the identifier, retry with a changed identifer:
# when we cannot find the identifier, retry with a changed identifier:
proc altSpelling(x: PIdent): PIdent =
case x.s[0]
of 'A'..'Z': result = getIdent(toLowerAscii(x.s[0]) & x.s.substr(1))
@@ -430,7 +430,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimOtherModule:
result = nextIdentIter(o.it, o.m.tab).skipAlias(n, c.config)
of oimSymChoice:
if o.symChoiceIndex < sonsLen(n):
if o.symChoiceIndex < len(n):
result = n.sons[o.symChoiceIndex].sym
incl(o.inSymChoice, result.id)
inc o.symChoiceIndex

View File

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

View File

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

View File

@@ -10,7 +10,7 @@
# Built-in types and compilerprocs are registered here.
import
ast, astalgo, hashes, msgs, platform, nversion, times, idents,
ast, astalgo, msgs, platform, idents,
modulegraphs, lineinfos
export createMagic

View File

@@ -13,22 +13,17 @@ when not defined(nimcore):
{.error: "nimcore MUST be defined for Nim's core tooling".}
import
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
os, condsyms, times,
wordrecg, sem, semdata, idents, passes, extccomp,
llstream, strutils, ast, lexer, syntaxes, options, msgs,
condsyms, times,
sem, idents, passes, extccomp,
cgen, json, nversion,
platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
parser, modules, ccgutils, sigmatch, ropes,
platform, nimconf, passaux, depends, vm, idgen,
modules,
modulegraphs, tables, rod, lineinfos, pathutils
when not defined(leanCompiler):
import jsgen, docgen, docgen2
from magicsys import resetSysTypes
proc codegenPass(g: ModuleGraph) =
registerPass g, cgenPass
proc semanticPasses(g: ModuleGraph) =
registerPass g, verbosePass
registerPass g, semPass
@@ -87,6 +82,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
@@ -148,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)
@@ -343,8 +337,11 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdInteractive
commandInteractive(graph)
of "e":
incl conf.globalOptions, optWasNimscript
commandEval(graph, mainCommandArg(conf))
if not fileExists(conf.projectFull):
rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string)
elif not conf.projectFull.string.endsWith(".nims"):
rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string)
# main NimScript logic handled in cmdlinehelper.nim.
of "nop", "help":
# prevent the "success" message:
conf.cmd = cmdDump

View File

@@ -29,7 +29,7 @@ import ast, intsets, tables, options, lineinfos, hashes, idents,
incremental, btrees, md5
type
SigHash* = distinct Md5Digest
SigHash* = distinct MD5Digest
ModuleGraph* = ref object
modules*: seq[PSym] ## indexed by int32 fileIdx
@@ -64,7 +64,7 @@ type
importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.}
includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.}
recordStmt*: proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.}
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API
cacheCounters*: Table[string, BiggestInt]
cacheTables*: Table[string, BTree[string, PNode]]
passes*: seq[TPass]
@@ -98,7 +98,7 @@ const
proc toBase64a(s: cstring, len: int): string =
## encodes `s` into base64 representation.
result = newStringOfCap(((len + 2) div 3) * 4)
result.add '_'
result.add "__"
var i = 0
while i < len - 2:
let a = ord(s[i])
@@ -215,7 +215,7 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false)
if g.suggestMode:
g.deps.incl m.position.dependsOn(dep.int)
# we compute the transitive closure later when quering the graph lazily.
# we compute the transitive closure later when querying the graph lazily.
# this improves efficiency quite a lot:
#invalidTransitiveClosure = true

View File

@@ -8,7 +8,7 @@
#
import ast, renderer, strutils, msgs, options, idents, os, lineinfos,
pathutils, nimblecmd
pathutils
when false:
const
@@ -162,6 +162,6 @@ proc checkModuleName*(conf: ConfigRef; n: PNode; doLocalError=true): FileIndex =
if doLocalError:
let m = if modulename.len > 0: modulename else: $n
localError(conf, n.info, "cannot open file: " & m)
result = InvalidFileIDX
result = InvalidFileIdx
else:
result = fileInfoIdx(conf, fullPath)

View File

@@ -10,8 +10,8 @@
## Implements the module handling, including the caching of modules.
import
ast, astalgo, magicsys, std / sha1, msgs, cgendata, sigmatch, options,
idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
ast, astalgo, magicsys, msgs, options,
idents, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
lineinfos, pathutils, tables
proc resetSystemArtifacts*(g: ModuleGraph) =
@@ -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)
@@ -77,8 +76,6 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
if result == nil:
result = newModule(graph, fileIdx)
result.flags = result.flags + flags
if sfMainModule in result.flags:
graph.config.mainPackageId = result.owner.id
result.id = id
registerModule(graph, result)
else:
@@ -133,12 +130,12 @@ proc wantMainModule*(conf: ConfigRef) =
"command expects a filename")
conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIDX) =
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
connectCallbacks(graph)
let conf = graph.config
wantMainModule(conf)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIDX: conf.projectMainIdx else: projectFileIdx
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})

View File

@@ -8,7 +8,7 @@
#
import
options, strutils, os, tables, ropes, platform, terminal, macros,
options, strutils, os, tables, ropes, terminal, macros,
lineinfos, pathutils
proc toCChar*(c: char; result: var string) =
@@ -40,9 +40,8 @@ proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
#shallow(result.fullPath)
result.projPath = projPath
#shallow(result.projPath)
let fileName = fullPath.extractFilename
result.shortName = fileName.changeFileExt("")
result.quotedName = fileName.makeCString
result.shortName = fullPath.extractFilename
result.quotedName = result.shortName.makeCString
result.quotedFullName = fullPath.string.makeCString
result.lines = @[]
when defined(nimpretty):
@@ -96,14 +95,20 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
result.fileIndex = fileInfoIdx
result.line = uint16(line)
result.col = int16(col)
if line < int high(uint16):
result.line = uint16(line)
else:
result.line = high(uint16)
if col < int high(int16):
result.col = int16(col)
else:
result.col = -1
proc newLineInfo*(conf: ConfigRef; filename: AbsoluteFile, line, col: int): TLineInfo {.inline.} =
result = newLineInfo(fileInfoIdx(conf, filename), line, col)
proc concat(strings: openarray[string]): string =
proc concat(strings: openArray[string]): string =
var totalLen = 0
for s in strings: totalLen += s.len
result = newStringOfCap totalLen
@@ -155,18 +160,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:
if optListFullPaths in conf.globalOptions:
conf.m.fileInfos[fileIdx.int32].fullPath.string
else:
conf.m.fileInfos[fileIdx.int32].projPath.string
conf.m.fileInfos[fileIdx.int32].shortName
proc toProjPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil:
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
else: conf.m.fileInfos[fileIdx.int32].projPath.string
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil: result = "???"
else: result = conf.m.fileInfos[fileIdx.int32].fullPath.string
if fileIdx.int32 < 0 or conf == nil:
result = (if fileIdx == commandLineIdx: commandLineDesc else: "???")
else:
result = conf.m.fileInfos[fileIdx.int32].fullPath.string
proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: AbsoluteFile) =
assert fileIdx.int32 >= 0
@@ -183,7 +195,7 @@ proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile =
if fileIdx.int32 < 0:
result = AbsoluteFile"???"
result = AbsoluteFile(if fileIdx == commandLineIdx: commandLineDesc else: "???")
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isEmpty:
result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else:
@@ -192,22 +204,28 @@ proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile
template toFilename*(conf: ConfigRef; info: TLineInfo): string =
toFilename(conf, info.fileIndex)
template toProjPath*(conf: ConfigRef; info: TLineInfo): string =
toProjPath(conf, info.fileIndex)
template toFullPath*(conf: ConfigRef; info: TLineInfo): string =
toFullPath(conf, info.fileIndex)
template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string =
string toFullPathConsiderDirty(conf, info.fileIndex)
proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
if info.fileIndex.int32 < 0:
result = "???"
return
let absPath = conf.m.fileInfos[info.fileIndex.int32].fullPath.string
if optListFullPaths in conf.globalOptions:
result = absPath
else:
let relPath = conf.m.fileInfos[info.fileIndex.int32].projPath.string
result = if relPath.count("..") > 2: absPath else: relPath
proc toMsgFilename*(conf: ConfigRef; info: FileIndex): string =
let
absPath = toFullPath(conf, info)
relPath = toProjPath(conf, info)
result = if (optListFullPaths in conf.globalOptions) or
(relPath.len > absPath.len) or
(relPath.count("..") > 2):
absPath
else:
relPath
template toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
toMsgFilename(conf, info.fileIndex)
proc toLinenumber*(info: TLineInfo): int {.inline.} =
result = int info.line
@@ -215,12 +233,9 @@ proc toLinenumber*(info: TLineInfo): int {.inline.} =
proc toColumn*(info: TLineInfo): int {.inline.} =
result = info.col
proc toFileLine*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
result = toFilename(conf, info) & ":" & $info.line
proc toFileLineCol*(conf: ConfigRef; info: TLineInfo): string {.inline.} =
# consider calling `helpers.lineInfoToString` instead
result = toFilename(conf, info) & "(" & $info.line & ", " &
result = toMsgFilename(conf, info) & "(" & $info.line & ", " &
$(info.col + ColOffset) & ")"
proc `$`*(conf: ConfigRef; info: TLineInfo): string = toFileLineCol(conf, info)
@@ -452,7 +467,8 @@ proc sourceLine*(conf: ConfigRef; i: TLineInfo): string =
proc writeSurroundingSrc(conf: ConfigRef; info: TLineInfo) =
const indent = " "
msgWriteln(conf, indent & $sourceLine(conf, info))
msgWriteln(conf, indent & spaces(info.col) & '^')
if info.col >= 0:
msgWriteln(conf, indent & spaces(info.col) & '^')
proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): string =
let title = case msg
@@ -532,7 +548,7 @@ proc localError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
proc localError*(conf: ConfigRef; info: TLineInfo, arg: string) =
liMessage(conf, info, errGenerated, arg, doNothing)
proc localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openarray[string]) =
proc localError*(conf: ConfigRef; info: TLineInfo, format: string, params: openArray[string]) =
localError(conf, info, format % params)
proc message*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
@@ -556,8 +572,9 @@ template internalAssert*(conf: ConfigRef, e: bool) =
if not e: internalError(conf, $instantiationInfo())
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
assert i.fileIndex.int32 >= 0
if optExcessiveStackTrace in conf.globalOptions:
if i.fileIndex.int32 < 0:
result = makeCString "???"
elif optExcessiveStackTrace in conf.globalOptions:
result = conf.m.fileInfos[i.fileIndex.int32].quotedFullName
else:
result = conf.m.fileInfos[i.fileIndex.int32].quotedName
@@ -577,3 +594,10 @@ proc listHints*(conf: ConfigRef) =
if hint in conf.notes: "x" else: " ",
lineinfos.HintsToStr[ord(hint) - ord(hintMin)]
])
proc lintReport*(conf: ConfigRef; info: TLineInfo, beau, got: string) =
let m = "'$2' should be: '$1'" % [beau, got]
if optStyleError in conf.globalOptions:
localError(conf, info, m)
else:
message(conf, info, hintName, m)

View File

@@ -7,6 +7,8 @@ define:nimcore
#define:nimIncremental
#import:"$projectpath/testability"
#define:staticSqlite
@if windows:
cincludes: "$lib/wrappers/libffi/common"
@end
@@ -14,6 +16,10 @@ define:nimcore
define:useStdoutAsStdmsg
define:nimOldCaseObjects
@if nimHasStyleChecks:
styleCheck:error
@end
#define:useNodeIds
#gc:markAndSweep

View File

@@ -19,9 +19,9 @@ when defined(i386) and defined(windows) and defined(vcc):
{.link: "../icons/nim-i386-windows-vcc.res".}
import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt,
scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper,
commands, options, msgs,
extccomp, strutils, os, main, parseopt,
idents, lineinfos, cmdlinehelper,
pathutils
include nodejs
@@ -47,13 +47,21 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
parseopt.next(p)
case p.kind
of cmdEnd: break
of cmdLongoption, cmdShortOption:
of cmdLongOption, cmdShortOption:
config.commandLine.add " "
config.commandLine.add p.key
if p.val.len > 0:
config.commandLine.add ':'
config.commandLine.add p.val
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
if processArgument(pass, p, argsCount, config): break
if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and

View File

@@ -10,7 +10,7 @@
# This module handles the reading of the config file.
import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
llstream, commands, os, strutils, msgs, lexer,
options, idents, wordrecg, strtabs, lineinfos, pathutils
# ---------------- configuration file parser -----------------------------
@@ -123,31 +123,31 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
of wEnd: doEnd(L, tok, condStack)
of wWrite:
ppGetTok(L, tok)
msgs.msgWriteln(config, strtabs.`%`(tokToStr(tok), config.configVars,
msgs.msgWriteln(config, strtabs.`%`($tok, config.configVars,
{useEnvironment, useKey}))
ppGetTok(L, tok)
else:
case tok.ident.s.normalize
of "putenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
var key = $tok
ppGetTok(L, tok)
os.putEnv(key, tokToStr(tok))
os.putEnv(key, $tok)
ppGetTok(L, tok)
of "prependenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
var key = $tok
ppGetTok(L, tok)
os.putEnv(key, tokToStr(tok) & os.getEnv(key))
os.putEnv(key, $tok & os.getEnv(key))
ppGetTok(L, tok)
of "appendenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
var key = $tok
ppGetTok(L, tok)
os.putEnv(key, os.getEnv(key) & tokToStr(tok))
os.putEnv(key, os.getEnv(key) & $tok)
ppGetTok(L, tok)
else:
lexMessage(L, errGenerated, "invalid directive: '$1'" % tokToStr(tok))
lexMessage(L, errGenerated, "invalid directive: '$1'" % $tok)
proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
ppGetTok(L, tok)
@@ -156,7 +156,7 @@ proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var s
proc checkSymbol(L: TLexer, tok: TToken) =
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
lexMessage(L, errGenerated, "expected identifier, but got: " & tokToStr(tok))
lexMessage(L, errGenerated, "expected identifier, but got: " & $tok)
proc parseAssignment(L: var TLexer, tok: var TToken;
config: ConfigRef; condStack: var seq[bool]) =
@@ -164,21 +164,21 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
confTok(L, tok, config, condStack) # skip unnecessary prefix
var info = getLineInfo(L, tok) # save for later in case of an error
checkSymbol(L, tok)
var s = tokToStr(tok)
var s = $tok
confTok(L, tok, config, condStack) # skip symbol
var val = ""
while tok.tokType == tkDot:
add(s, '.')
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(s, tokToStr(tok))
add(s, $tok)
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketLe:
# BUGFIX: val, not s!
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(val, '[')
add(val, tokToStr(tok))
add(val, $tok)
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketRi: confTok(L, tok, config, condStack)
else: lexMessage(L, errGenerated, "expected closing ']'")
@@ -188,12 +188,12 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
if len(val) > 0: add(val, ':')
confTok(L, tok, config, condStack) # skip ':' or '=' or '%'
checkSymbol(L, tok)
add(val, tokToStr(tok))
add(val, $tok)
confTok(L, tok, config, condStack) # skip symbol
while tok.ident != nil and tok.ident.s == "&":
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(val, tokToStr(tok))
add(val, $tok)
confTok(L, tok, config, condStack)
if percent:
processSwitch(s, strtabs.`%`(val, config.configVars,

View File

@@ -46,7 +46,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
s = nextIdentIter(it, i.mainModule.tab)
proc selectRoutine*(i: Interpreter; name: string): PSym =
## Selects a declared rountine (proc/func/etc) from the main module.
## Selects a declared routine (proc/func/etc) from the main module.
## The routine needs to have the export marker ``*``. The only matching
## routine is returned and ``nil`` if it is overloaded.
result = selectUniqueSymbol(i, name, {skTemplate, skMacro, skFunc,

View File

@@ -98,7 +98,7 @@ proc handleCmdLine(config: ConfigRef) =
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig, config) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "", config)
mainCommand()

View File

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

View File

@@ -10,15 +10,14 @@
# this unit handles Nim sets; it implements symbolic sets
import
ast, astalgo, trees, nversion, lineinfos, platform, bitsets, types, renderer,
options
ast, astalgo, lineinfos, bitsets, types, options
proc inSet*(s: PNode, elem: PNode): bool =
assert s.kind == nkCurly
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]):
@@ -48,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]):
@@ -60,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])
while j <= getOrdValue(s.sons[i].sons[1]):
bitSetIncl(b, j - first)
j = getOrdValue(s.sons[i].sons[0], first)
while j <= getOrdValue(s.sons[i].sons[1], first):
bitSetIncl(b, toInt64(j - first))
inc(j)
else:
bitSetIncl(b, getOrdValue(s.sons[i]) - first)
bitSetIncl(b, toInt64(getOrdValue(s.sons[i]) - first))
proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
var
@@ -78,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
@@ -91,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)
@@ -99,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)
@@ -150,7 +149,7 @@ proc setHasRange*(s: PNode): bool =
assert s.kind == nkCurly
if s.kind != nkCurly:
return false
for i in 0 ..< sonsLen(s):
for i in 0 ..< len(s):
if s.sons[i].kind == nkRange:
return true
result = false

View File

@@ -1,9 +1,7 @@
import os
proc findNodeJs*(): string =
proc findNodeJs*(): string {.inline.} =
## Find NodeJS executable and return it as a string.
result = findExe("nodejs")
if result == "":
result = findExe("node")
if result == "":
result = findExe("iojs")

View File

@@ -15,6 +15,6 @@ const
VersionAsString* = system.NimVersion
RodFileVersion* = "1223" # modify this if the rod-format changes!
NimCompilerApiVersion* = 3 ## Check for the existance of this before accessing it
NimCompilerApiVersion* = 3 ## Check for the existence of this before accessing it
## as older versions of the compiler API do not
## declare this.

View File

@@ -8,7 +8,7 @@
#
import
os, strutils, strtabs, osproc, sets, lineinfos, platform,
os, strutils, strtabs, sets, lineinfos, platform,
prefixmatches, pathutils
from terminal import isatty
@@ -25,12 +25,11 @@ type # please make sure we have under 32 options
# (improves code efficiency a lot!)
TOption* = enum # **keep binary compatible**
optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
optOverflowCheck, optNilCheck,
optNaNCheck, optInfCheck, optMoveCheck,
optOverflowCheck, optNilCheck, optRefCheck,
optNaNCheck, optInfCheck, optStyleCheck,
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
@@ -78,12 +77,13 @@ type # please make sure we have under 32 options
optWholeProject # for 'doc2': output any dependency
optDocInternal # generate documentation for non-exported symbols
optMixedMode # true if some module triggered C++ codegen
optListFullPaths # use full paths in toMsgFilename, toFilename
optListFullPaths # use full paths in toMsgFilename
optNoNimblePath
optHotCodeReloading
optDynlibOverrideAll
optNimV2
optMultiMethods
optNimV019
TGlobalOptions* = set[TGlobalOption]
@@ -110,7 +110,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
@@ -135,6 +135,12 @@ type
## which itself requires `nimble install libffi`, see #10150
## Note: this feature can't be localized with {.push.}
LegacyFeature* = enum
allowSemcheckedAstModification,
## Allows to modify a NimNode where the type has already been
## flagged with nfSem. If you actually do this, it will cause
## bugs.
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf
@@ -149,7 +155,7 @@ type
Cfile* = object
nimname*: string
cname*, obj*: AbsoluteFile
flags*: set[CFileFlag]
flags*: set[CfileFlag]
CfileList* = seq[Cfile]
Suggest* = ref object
@@ -196,6 +202,7 @@ type
cppDefines*: HashSet[string] # (*)
headerFile*: string
features*: set[Feature]
legacyFeatures*: set[LegacyFeature]
arguments*: string ## the arguments to be passed to the program that
## should be run
ideCmd*: IdeCmd
@@ -229,6 +236,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
@@ -246,7 +254,7 @@ type
compileOptionsCmd*: seq[string]
linkOptions*: string # (*)
compileOptions*: string # (*)
ccompilerpath*: string
cCompilerPath*: string
toCompile*: CfileList # (*)
suggestionResultHook*: proc (result: Suggest) {.closure.}
suggestVersion*: int
@@ -270,12 +278,12 @@ const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, par
const
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck,
optMoveCheck}
optStyleCheck, optRefCheck}
DefaultOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
optBoundsCheck, optOverflowCheck, optAssert, optWarns,
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
optHints, optStackTrace, optLineTrace,
optTrMacros, optNilCheck, optMoveCheck}
optTrMacros, optNilCheck, optStyleCheck}
DefaultGlobalOptions* = {optThreadAnalysis,
optExcessiveStackTrace, optListFullPaths}
@@ -314,7 +322,7 @@ proc newConfigRef*(): ConfigRef =
m: initMsgConfig(),
evalExpr: "",
cppDefines: initHashSet[string](),
headerFile: "", features: {}, foreignPackageNotes: {hintProcessing, warnUnknownMagic,
headerFile: "", features: {}, legacyFeatures: {}, foreignPackageNotes: {hintProcessing, warnUnknownMagic,
hintQuitCalled, hintExecuting},
notes: NotesVerbosity[1], mainPackageNotes: NotesVerbosity[1],
configVars: newStringTable(modeStyleInsensitive),
@@ -335,6 +343,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
@@ -388,7 +397,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}
@@ -398,8 +407,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":
result = conf.target.targetOS in {osMacosx, osIos}
of "sunos": result = conf.target.targetOS == osSolaris
of "nintendoswitch":
result = conf.target.targetOS == osNintendoSwitch
@@ -462,12 +473,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.
@@ -498,7 +513,7 @@ proc setDefaultLibpath*(conf: ConfigRef) =
# Find out if $nim/../../lib/system.nim exists.
let parentNimLibPath = realNimPath.parentDir.parentDir / "lib"
if not fileExists(conf.libpath.string / "system.nim") and
fileExists(parentNimlibPath / "system.nim"):
fileExists(parentNimLibPath / "system.nim"):
conf.libpath = AbsoluteDir parentNimLibPath
proc canonicalizePath*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
@@ -590,7 +605,7 @@ proc rawFindFile2(conf: ConfigRef; f: RelativeFile): AbsoluteFile =
result = it / f
if fileExists(result):
# bring to front
for j in countDown(i,1):
for j in countdown(i, 1):
swap(conf.lazyPaths[j], conf.lazyPaths[j-1])
return canonicalizePath(conf, result)
@@ -709,3 +724,13 @@ proc `$`*(c: IdeCmd): string =
of ideOutline: "outline"
of ideKnown: "known"
of ideMsg: "msg"
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.
if conf != nil and conf.target.targetCPU == cpuI386:
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
if conf.target.targetOS != osWindows:
# on i386 for all known POSIX systems, 64bits ints are aligned
# to 4bytes (except with -malign-double)
return 4
return 8

View File

@@ -39,22 +39,17 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
if parents <= 0: break
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
# foo/../bar becomes foo7_7bar
result = relativeTo(path, conf.projectPath, '/').string.multiReplace(
{"/": "7", "..": "_", "7": "77", "_": "__", ":": "8", "8": "88"})
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
result = "@m" & relativeTo(path, conf.projectPath, '/').string.multiReplace({"/": "@s", "#": "@h", "@": "@@", ":": "@c"})
proc demanglePackageName*(path: string): string =
result = path.multiReplace(
{"88": "8", "8": ":", "77": "7", "__": "_", "_7": "../", "7": "/"})
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
proc withPackageName*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
let x = getPackageName(conf, path.string)
if x.len == 0:
result = path
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
result = p / RelativeFile(fakePackageName(conf, path))
result = p / RelativeFile(fakePackageName(conf, path))

View File

@@ -10,7 +10,7 @@
## This module implements the pattern matching features for term rewriting
## macro support.
import strutils, ast, astalgo, types, msgs, idents, renderer, wordrecg, trees,
import strutils, ast, types, msgs, idents, renderer, wordrecg, trees,
options
# we precompile the pattern here for efficiency into some internal
@@ -218,20 +218,22 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
of nkSym:
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
else: {skVar, skResult, skTemp}
if n.sym.kind in kinds:
if n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}:
result = arLValue
elif isUnsafeAddr and n.sym.kind == skParam:
result = arLValue
elif n.sym.kind in kinds:
if owner != nil and owner == n.sym.owner and
sfGlobal notin n.sym.flags:
result = arLocalLValue
else:
result = arLValue
elif n.sym.kind == skParam and n.sym.typ.kind == tyVar:
result = arLValue
elif n.sym.kind == skType:
let t = n.sym.typ.skipTypes({tyTypeDesc})
if t.kind == tyVar: result = arStrange
of nkDotExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}:
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue
elif isUnsafeAddr and t.kind == tyLent:
result = arLValue
@@ -242,7 +244,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
result = arDiscriminant
of nkBracketExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}:
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue
elif isUnsafeAddr and t.kind == tyLent:
result = arLValue

View File

@@ -27,7 +27,7 @@ when isMainModule:
outp.close
import
llstream, lexer, idents, strutils, ast, astalgo, msgs, options, lineinfos,
llstream, lexer, idents, strutils, ast, msgs, options, lineinfos,
pathutils
when defined(nimpretty):
@@ -147,10 +147,17 @@ template withInd(p, body: untyped) =
body
p.currInd = oldInd
template newlineWasSplitting(p: var TParser) =
when defined(nimpretty):
layouter.newlineWasSplitting(p.em)
template realInd(p): bool = p.tok.indent > p.currInd
template sameInd(p): bool = p.tok.indent == p.currInd
template sameOrNoInd(p): bool = p.tok.indent == p.currInd or p.tok.indent < 0
proc validInd(p: var TParser): bool {.inline.} =
result = p.tok.indent < 0 or p.tok.indent > p.currInd
proc rawSkipComment(p: var TParser, node: PNode) =
if p.tok.tokType == tkComment:
if node != nil:
@@ -339,17 +346,17 @@ proc parseSymbol(p: var TParser, mode = smNormal): PNode =
parMessage(p, errIdentifierExpected, p.tok)
break
of tkOpr, tkDot, tkDotDot, tkEquals, tkParLe..tkParDotRi:
let lineinfo = parLineinfo(p)
let lineinfo = parLineInfo(p)
var accm = ""
while p.tok.tokType in {tkOpr, tkDot, tkDotDot, tkEquals,
tkParLe..tkParDotRi}:
accm.add(tokToStr(p.tok))
accm.add($p.tok)
getTok(p)
let node = newNodeI(nkIdent, lineinfo)
node.ident = p.lex.cache.getIdent(accm)
result.add(node)
of tokKeywordLow..tokKeywordHigh, tkSymbol, tkIntLit..tkCharLit:
result.add(newIdentNodeP(p.lex.cache.getIdent(tokToStr(p.tok)), p))
result.add(newIdentNodeP(p.lex.cache.getIdent($p.tok), p))
getTok(p)
else:
parMessage(p, errIdentifierExpected, p.tok)
@@ -367,6 +374,7 @@ proc colonOrEquals(p: var TParser, a: PNode): PNode =
if p.tok.tokType == tkColon:
result = newNodeP(nkExprColonExpr, p)
getTok(p)
newlineWasSplitting(p)
#optInd(p, result)
addSon(result, a)
addSon(result, parseExpr(p))
@@ -702,7 +710,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,
@@ -903,6 +911,9 @@ proc parsePragma(p: var TParser): PNode =
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
result = newNodeP(nkPragma, p)
inc p.inPragma
when defined(nimpretty):
inc p.em.doIndentMore
inc p.em.keepIndents
getTok(p)
optInd(p, result)
while p.tok.tokType notin {tkCurlyDotRi, tkCurlyRi, tkEof}:
@@ -921,6 +932,9 @@ proc parsePragma(p: var TParser): PNode =
else:
parMessage(p, "expected '.}'")
dec p.inPragma
when defined(nimpretty):
dec p.em.doIndentMore
dec p.em.keepIndents
proc identVis(p: var TParser; allowDot=false): PNode =
#| identVis = symbol opr? # postfix position
@@ -967,7 +981,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
while true:
case p.tok.tokType
of tkSymbol, tkAccent:
if withPragma in flags: a = identWithPragma(p, allowDot=withdot in flags)
if withPragma in flags: a = identWithPragma(p, allowDot=withDot in flags)
else: a = parseSymbol(p)
if a.kind == nkEmpty: return
else: break
@@ -1076,7 +1090,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
getTok(p)
optInd(p, result)
result.sons[0] = parseTypeDesc(p)
elif not retColon and not hasParle:
elif not retColon and not hasParLe:
# Mark as "not there" in order to mark for deprecation in the semantic pass:
result = p.emptyNode
when defined(nimpretty):
@@ -1189,6 +1203,13 @@ proc parseFor(p: var TParser): PNode =
colcom(p, result)
addSon(result, parseStmt(p))
template nimprettyDontTouch(body) =
when defined(nimpretty):
inc p.em.keepIndents
body
when defined(nimpretty):
dec p.em.keepIndents
proc parseExpr(p: var TParser): PNode =
#| expr = (blockExpr
#| | ifExpr
@@ -1198,12 +1219,26 @@ proc parseExpr(p: var TParser): PNode =
#| | tryExpr)
#| / simpleExpr
case p.tok.tokType:
of tkBlock: result = parseBlock(p)
of tkIf: result = parseIfExpr(p, nkIfExpr)
of tkFor: result = parseFor(p)
of tkWhen: result = parseIfExpr(p, nkWhenExpr)
of tkCase: result = parseCase(p)
of tkTry: result = parseTry(p, isExpr=true)
of tkBlock:
nimprettyDontTouch:
result = parseBlock(p)
of tkIf:
nimprettyDontTouch:
result = parseIfExpr(p, nkIfExpr)
of tkFor:
nimprettyDontTouch:
result = parseFor(p)
of tkWhen:
nimprettyDontTouch:
result = parseIfExpr(p, nkWhenExpr)
of tkCase:
# Currently we think nimpretty is good enough with case expressions,
# so it is allowed to touch them:
#nimprettyDontTouch:
result = parseCase(p)
of tkTry:
nimprettyDontTouch:
result = parseTry(p, isExpr=true)
else: result = simpleExpr(p)
proc parseEnum(p: var TParser): PNode
@@ -1289,6 +1324,7 @@ proc binaryNot(p: var TParser; a: PNode): PNode =
proc parseTypeDesc(p: var TParser): PNode =
#| typeDesc = simpleExpr ('not' expr)?
newlineWasSplitting(p)
result = simpleExpr(p, pmTypeDesc)
result = binaryNot(p, result)
@@ -1504,6 +1540,7 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
elif p.tok.indent >= 0 and p.tok.indent <= p.currInd or not isExprStart(p):
# NL terminates:
addSon(result, p.emptyNode)
# nimpretty here!
else:
var e = parseExpr(p)
e = postExprBlocks(p, e)
@@ -1716,9 +1753,6 @@ proc parsePattern(p: var TParser): PNode =
result = parseStmt(p)
eat(p, tkCurlyRi)
proc validInd(p: var TParser): bool =
result = p.tok.indent < 0 or p.tok.indent > p.currInd
proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
#| indAndComment = (IND{>} COMMENT)? | COMMENT?
#| routine = optInd identVis pattern? genericParamList?
@@ -1803,7 +1837,7 @@ proc parseEnum(p: var TParser): PNode =
symPragma = newNodeP(nkPragmaExpr, p)
addSon(symPragma, a)
addSon(symPragma, pragma)
# nimpretty support here
if p.tok.indent >= 0 and p.tok.indent <= p.currInd:
add(result, symPragma)
break
@@ -2213,6 +2247,7 @@ proc parseStmt(p: var TParser): PNode =
#| stmt = (IND{>} complexOrSimpleStmt^+(IND{=} / ';') DED)
#| / simpleStmt ^+ ';'
if p.tok.indent > p.currInd:
# nimpretty support here
result = newNodeP(nkStmtList, p)
withInd(p):
while true:
@@ -2289,6 +2324,7 @@ proc parseTopLevelStmt(p: var TParser): PNode =
result = p.emptyNode
# progress guaranteed
while true:
# nimpretty support here
if p.tok.indent != 0:
if p.firstTok and p.tok.indent < 0: discard
elif p.tok.tokType != tkSemiColon:

View File

@@ -10,7 +10,7 @@
## implements some little helper passes
import
strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos
ast, passes, idents, msgs, options, idgen, lineinfos
from modulegraphs import ModuleGraph, PPassContext
@@ -30,6 +30,6 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode =
# system.nim deactivates all hints, for verbosity:3 we want the processing
# messages nonetheless, so we activate them again unconditionally:
incl(v.config.notes, hintProcessing)
message(v.config, n.info, hintProcessing, $idgen.gFrontendId)
message(v.config, n.info, hintProcessing, $idgen.gFrontEndId)
const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)

View File

@@ -11,9 +11,9 @@
## `TPass` interface.
import
strutils, options, ast, astalgo, llstream, msgs, platform, os,
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
nimsets, syntaxes, times, idgen, modulegraphs, reorder, rod,
options, ast, llstream, msgs,
idents,
syntaxes, idgen, modulegraphs, reorder, rod,
lineinfos, pathutils
type
@@ -90,14 +90,13 @@ proc processTopLevelStmt(graph: ModuleGraph, n: PNode, a: var TPassContextArray)
proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
let fullPath = findModule(conf, module, relativeTo)
if fullPath.isEmpty:
result = InvalidFileIDX
result = InvalidFileIdx
else:
result = fileInfoIdx(conf, fullPath)
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
@@ -113,6 +112,19 @@ const
nkMacroDef, nkConverterDef, nkIteratorDef, nkFuncDef, nkPragma,
nkExportStmt, nkExportExceptStmt, nkFromStmt, nkImportStmt, nkImportExceptStmt}
proc prepareConfigNotes(graph: ModuleGraph; module: PSym) =
if sfMainModule in module.flags:
graph.config.mainPackageId = module.owner.id
# don't be verbose unless the module belongs to the main package:
if module.owner.id == graph.config.mainPackageId:
graph.config.notes = graph.config.mainPackageNotes
else:
if graph.config.mainPackageNotes == {}: graph.config.mainPackageNotes = graph.config.notes
graph.config.notes = graph.config.foreignPackageNotes
proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
result = module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange")
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {.discardable.} =
if graph.stopCompile(): return true
var
@@ -120,6 +132,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
a: TPassContextArray
s: PLLStream
fileIdx = module.fileIdx
prepareConfigNotes(graph, module)
if module.id < 0:
# new module caching mechanism:
for i in 0 ..< graph.passes.len:

View File

@@ -10,7 +10,7 @@
## Path handling utilities for Nim. Strictly typed code in order
## to avoid the never ending time sink in getting path handling right.
import os, strutils, pathnorm
import os, pathnorm
type
AbsoluteFile* = distinct string

View File

@@ -11,8 +11,7 @@
## macro support.
import
ast, astalgo, types, semdata, sigmatch, msgs, idents, aliases, parampatterns,
trees
ast, types, semdata, sigmatch, idents, aliases, parampatterns, trees
type
TPatternContext = object
@@ -59,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
@@ -113,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:
@@ -175,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
@@ -251,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
@@ -296,7 +295,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
# constraint not fulfilled:
if not ok: return nil
markUsed(c.config, n.info, s, c.graph.usageSym)
markUsed(c, n.info, s)
if ctx.subMatch:
assert m.len == 3
m.sons[1] = result

View File

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

View File

@@ -9,9 +9,7 @@
## Plugin to transform an inline iterator into a data structure.
import ".." / [ast, astalgo,
magicsys, lookups, semdata,
lambdalifting, msgs]
import ".." / [ast, lookups, semdata, lambdalifting, msgs]
proc iterToProcImpl*(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info)

View File

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

View File

@@ -12,64 +12,66 @@
import
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees,
types, lookups, lineinfos, pathutils
types, lookups, lineinfos, pathutils, linter
const
FirstCallConv* = wNimcall
LastCallConv* = wNoconv
const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
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,
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, wVarargs, wCompileTime, wMerge,
wBorrow, wImportCompilerProc, wThread,
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wConstructor, wExportNims, wUsed, wLiftLocals, wStacktrace, wLinetrace}
converterPragmas* = procPragmas
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
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}
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNosideeffect}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wMovechecks, wAssertions,
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,
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,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental, wThis}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
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,
wInjectStmt, wExperimental, wThis, wUsed}
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wNoSideEffect, wSideEffect, wNoreturn, wDynlib, wHeader,
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, wCursor}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
wThread, wRaises, wLocks, wTags, wGcSafe}
forVarPragmas* = {wInject, wGensym}
allRoutinePragmas* = methodPragmas + iteratorPragmas + lambdaPragmas
@@ -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)
@@ -161,7 +164,7 @@ proc processImportObjC(c: PContext; s: PSym, extname: string, info: TLineInfo) =
incl(s.flags, sfNamedParamCall)
excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToObjC)
incl(m.flags, sfCompileToObjc)
proc newEmptyStrNode(c: PContext; n: PNode): PNode {.noinline.} =
result = newNodeIT(nkStrLit, n.info, getSysType(c.graph, n.info, tyString))
@@ -331,21 +334,21 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
of wChecks: ChecksOptions
of wObjChecks: {optObjCheck}
of wFieldChecks: {optFieldCheck}
of wRangechecks: {optRangeCheck}
of wBoundchecks: {optBoundsCheck}
of wOverflowchecks: {optOverflowCheck}
of wNilchecks: {optNilCheck}
of wFloatchecks: {optNaNCheck, optInfCheck}
of wRangeChecks: {optRangeCheck}
of wBoundChecks: {optBoundsCheck}
of wOverflowChecks: {optOverflowCheck}
of wNilChecks: {optNilCheck}
of wFloatChecks: {optNaNCheck, optInfCheck}
of wNanChecks: {optNaNCheck}
of wInfChecks: {optInfCheck}
of wMovechecks: {optMoveCheck}
of wStyleChecks: {optStyleCheck}
of wAssertions: {optAssert}
of wWarnings: {optWarns}
of wHints: {optHints}
of wLinedir: {optLineDir}
of wStacktrace: {optStackTrace}
of wLinetrace: {optLineTrace}
of wDebugger: {optEndb}
of wLineDir: {optLineDir}
of wStackTrace: {optStackTrace}
of wLineTrace: {optLineTrace}
of wDebugger: {optNone}
of wProfiler: {optProfiler, optMemTracker}
of wMemTracker: {optMemTracker}
of wByRef: {optByRef}
@@ -423,7 +426,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
x.notes = c.config.notes
x.features = c.features
c.optionStack.add(x)
for i in start ..< sonsLen(n):
for i in start ..< len(n):
if not tryProcessOption(c, n.sons[i], c.config.options):
# simply store it somewhere:
if x.otherPragmas.isNil:
@@ -434,6 +437,8 @@ proc processPush(c: PContext, n: PNode, start: int) =
# If stacktrace is disabled globally we should not enable it
if optStackTrace notin c.optionStack[0].options:
c.config.options.excl(optStackTrace)
when defined(debugOptions):
echo c.config $ n.info, " PUSH config is now ", c.config.options
proc processPop(c: PContext, n: PNode) =
if c.optionStack.len <= 1:
@@ -443,6 +448,8 @@ proc processPop(c: PContext, n: PNode) =
c.config.notes = c.optionStack[^1].notes
c.features = c.optionStack[^1].features
c.optionStack.setLen(c.optionStack.len - 1)
when defined(debugOptions):
echo c.config $ n.info, " POP config is now ", c.config.options
proc processDefine(c: PContext, n: PNode) =
if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
@@ -491,7 +498,7 @@ proc processCompile(c: PContext, n: PNode) =
let dest = getStrLit(c, it, 1)
var found = parentDir(toFullPath(c.config, n.info)) / s
for f in os.walkFiles(found):
let obj = completeCFilePath(c.config, AbsoluteFile(dest % extractFilename(f)))
let obj = completeCfilePath(c.config, AbsoluteFile(dest % extractFilename(f)))
docompile(c, it, AbsoluteFile f, obj)
else:
let s = expectStrLit(c, n)
@@ -501,7 +508,7 @@ proc processCompile(c: PContext, n: PNode) =
else:
found = findFile(c.config, s)
if found.isEmpty: found = AbsoluteFile s
let obj = toObjFile(c.config, completeCFilePath(c.config, found, false))
let obj = toObjFile(c.config, completeCfilePath(c.config, found, false))
docompile(c, it, found, obj)
proc processLink(c: PContext, n: PNode) =
@@ -509,15 +516,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:
@@ -610,9 +608,9 @@ proc pragmaLine(c: PContext, n: PNode) =
proc processPragma(c: PContext, n: PNode, i: int) =
let it = n[i]
if it.kind notin nkPragmaCallKinds and it.len == 2: invalidPragma(c, n)
elif it[0].kind != nkIdent: invalidPragma(c, n)
elif it[1].kind != nkIdent: invalidPragma(c, n)
if it.kind notin nkPragmaCallKinds and it.safeLen == 2: invalidPragma(c, n)
elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent:
invalidPragma(c, n)
var userPragma = newSym(skTemplate, it[1].ident, nil, it.info, c.config.options)
userPragma.ast = newNode(nkPragma, n.info, n.sons[i+1..^1])
@@ -722,7 +720,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:
@@ -750,7 +748,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:
@@ -762,21 +761,31 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
let ident = considerQuotedIdent(c, key)
var userPragma = strTableGet(c.userPragmas, ident)
if userPragma != nil:
if {optStyleHint, optStyleError} * c.config.globalOptions != {}:
styleCheckUse(c.config, key.info, userPragma)
# number of pragmas increase/decrease with user pragma expansion
inc c.instCounter
if c.instCounter > 100:
globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s)
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
else:
let k = whichKeyword(ident)
if k in validPragmas:
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")
@@ -794,6 +803,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:
@@ -807,12 +825,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:
@@ -839,7 +857,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)
@@ -858,12 +876,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
incl(sym.loc.flags, lfNoDecl)
# implies nodecl, because otherwise header would not make sense
if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
of wNosideeffect:
of wNoSideEffect:
noVal(c, it)
if sym != nil:
incl(sym.flags, sfNoSideEffect)
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
of wSideeffect:
of wSideEffect:
noVal(c, it)
incl(sym.flags, sfSideEffect)
of wNoreturn:
@@ -874,6 +892,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if sym.typ[0] != nil:
localError(c.config, sym.ast[paramsPos][0].info,
".noreturn with return type not allowed")
of wNoDestroy:
noVal(c, it)
incl(sym.flags, sfGeneratedOp)
of wDynlib:
processDynLib(c, it, sym)
of wCompilerProc, wCore:
@@ -959,7 +980,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
@@ -984,8 +1005,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
@@ -1003,12 +1022,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
noVal(c, it)
if sym != nil: incl(sym.flags, sfNoInit)
of wCodegenDecl: processCodegenDecl(c, it, sym)
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wOptimization, wMovechecks, wCallconv, wDebugger, wProfiler,
wFloatchecks, wNanChecks, wInfChecks, wPatterns, wTrMacros:
of wChecks, wObjChecks, wFieldChecks, wRangeChecks, wBoundChecks,
wOverflowChecks, wNilChecks, wAssertions, wWarnings, wHints,
wLineDir, wOptimization, wStyleChecks, wCallconv, wDebugger, wProfiler,
wFloatChecks, wNanChecks, wInfChecks, wPatterns, wTrMacros:
processOption(c, it, c.config.options)
of wStacktrace, wLinetrace:
of wStackTrace, wLineTrace:
if sym.kind in {skProc, skMethod, skConverter}:
processOption(c, it, sym.options)
else:
@@ -1130,7 +1149,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:
@@ -1160,7 +1179,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)
@@ -1185,14 +1204,16 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
return false
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
isStatement: bool) =
if n == nil: return
var i = 0
while i < n.len:
if singlePragma(c, sym, n, i, validPragmas, false): break
if singlePragma(c, sym, n, i, validPragmas, false, isStatement): break
inc i
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
isStatement: bool) =
if n == nil: return
pragmaRec(c, sym, n, validPragmas)
pragmaRec(c, sym, n, validPragmas, isStatement)
implicitPragmas(c, sym, n, validPragmas)

View File

@@ -14,8 +14,8 @@ import
ast, astalgo, msgs, semdata, types, trees, strutils
proc equalGenericParams(procA, procB: PNode): bool =
if sonsLen(procA) != sonsLen(procB): return false
for i in 0 ..< sonsLen(procA):
if len(procA) != len(procB): return false
for i in 0 ..< len(procA):
if procA.sons[i].kind != nkSym:
return false
if procB.sons[i].kind != nkSym:
@@ -29,7 +29,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
result = true
proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym =
# Searchs for a forward declaration or a "twin" symbol of fn
# Searches for a forward declaration or a "twin" symbol of fn
# in the symbol table. If the parameter lists are exactly
# the same the sym in the symbol table is returned, else nil.
var it: TIdentIter
@@ -72,8 +72,8 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
of paramsEqual:
if (sfExported notin result.flags) and (sfExported in fn.flags):
let message = ("public implementation '$1' has non-public " &
"forward declaration in $2") %
[getProcHeader(c.config, result), c.config$result.info]
"forward declaration at $2") %
[getProcHeader(c.config, result, getDeclarationPath = false), c.config$result.info]
localError(c.config, fn.info, message)
return
of paramsIncompatible:
@@ -95,9 +95,9 @@ proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym =
when false:
proc paramsFitBorrow(child, parent: PNode): bool =
var length = sonsLen(child)
var length = len(child)
result = false
if length == sonsLen(parent):
if length == len(parent):
for i in 1 ..< length:
var m = child.sons[i].sym
var n = parent.sons[i].sym
@@ -108,7 +108,7 @@ when false:
result = true
proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
var it: TIdentIter
for scope in walkScopes(startScope):

View File

@@ -9,6 +9,11 @@
# This module implements the renderer of the standard Nim representation.
when defined(nimHasUsed):
# 'import renderer' is so useful for debugging
# that Nim shouldn't produce a warning for that:
{.used.}
import
lexer, options, idents, strutils, ast, msgs, lineinfos
@@ -64,14 +69,11 @@ proc renderDefinitionName*(s: PSym, noQuotes = false): string =
else:
result = '`' & x & '`'
when not defined(nimpretty):
const
IndentWidth = 2
longIndentWid = IndentWidth * 2
else:
template IndentWidth: untyped = lexer.gIndentationWidth
template longIndentWid: untyped = IndentWidth() * 2
const
IndentWidth = 2
longIndentWid = IndentWidth * 2
when defined(nimpretty):
proc minmaxLine(n: PNode): (int, int) =
case n.kind
of nkTripleStrLit:
@@ -333,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):
@@ -394,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))
@@ -405,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
@@ -435,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
@@ -447,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))
@@ -456,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
@@ -490,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:
@@ -555,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) =
@@ -564,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
@@ -599,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)
@@ -617,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
@@ -662,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)
@@ -711,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
@@ -729,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)
@@ -743,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])
@@ -843,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:
@@ -898,16 +904,19 @@ proc accentedName(g: var TSrcGen, n: PNode) =
gsub(g, n)
proc infixArgument(g: var TSrcGen, n: PNode, i: int) =
if i >= n.len: return
if i < 1 and i > 2: return
var needsParenthesis = false
let n_next = n[i].skipHiddenNodes
if n_next.kind == nkInfix:
if n_next[0].kind in {nkSym, nkIdent} and n[0].kind in {nkSym, nkIdent}:
let nextId = if n_next[0].kind == nkSym: n_next[0].sym.name else: n_next[0].ident
let nNext = n[i].skipHiddenNodes
if nNext.kind == nkInfix:
if nNext[0].kind in {nkSym, nkIdent} and n[0].kind in {nkSym, nkIdent}:
let nextId = if nNext[0].kind == nkSym: nNext[0].sym.name else: nNext[0].ident
let nnId = if n[0].kind == nkSym: n[0].sym.name else: n[0].ident
if getPrecedence(nextId) < getPrecedence(nnId):
needsParenthesis = true
if i == 1:
if getPrecedence(nextId) < getPrecedence(nnId):
needsParenthesis = true
elif i == 2:
if getPrecedence(nextId) <= getPrecedence(nnId):
needsParenthesis = true
if needsParenthesis:
put(g, tkParLe, "(")
gsub(g, n, i)
@@ -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)
@@ -1144,10 +1153,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
elif n[0].kind == nkSym: n[0].sym.name
elif n[0].kind in {nkOpenSymChoice, nkClosedSymChoice}: n[0][0].sym.name
else: nil
let n_next = skipHiddenNodes(n[1])
if n_next.kind == nkPrefix or (opr != nil and renderer.isKeyword(opr)):
let nNext = skipHiddenNodes(n[1])
if nNext.kind == nkPrefix or (opr != nil and renderer.isKeyword(opr)):
put(g, tkSpaces, Space)
if n_next.kind == nkInfix:
if nNext.kind == nkInfix:
put(g, tkParLe, "(")
gsub(g, n.sons[1])
put(g, tkParRi, ")")
@@ -1191,19 +1200,19 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
if n.len > 0: gsub(g, n.sons[0])
put(g, tkParRi, ")")
of nkRefTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkRef, "ref")
gsub(g, n.sons[0])
else:
put(g, tkRef, "ref")
of nkPtrTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkPtr, "ptr")
gsub(g, n.sons[0])
else:
put(g, tkPtr, "ptr")
of nkVarTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkVar, "var")
gsub(g, n.sons[0])
else:
@@ -1234,7 +1243,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkEquals, "=")
gsub(g, n.sons[2])
of nkObjectTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkObject, "object")
gsub(g, n.sons[0])
gsub(g, n.sons[1])
@@ -1244,7 +1253,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkObject, "object")
of nkRecList:
indentNL(g)
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
optNL(g)
gsub(g, n.sons[i], c)
gcoms(g)
@@ -1254,14 +1263,14 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
putWithSpace(g, tkOf, "of")
gsub(g, n, 0)
of nkProcTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkProc, "proc")
gsub(g, n, 0)
gsub(g, n, 1)
else:
put(g, tkProc, "proc")
of nkIteratorTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkIterator, "iterator")
gsub(g, n, 0)
gsub(g, n, 1)
@@ -1274,7 +1283,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n.sons[0])
put(g, tkBracketRi, "]")
of nkEnumTy:
if sonsLen(n) > 0:
if len(n) > 0:
putWithSpace(g, tkEnum, "enum")
gsub(g, n.sons[0])
gcoms(g)
@@ -1332,7 +1341,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
incl(a.flags, rfInConstExpr)
gsection(g, n, a, tkConst, "const")
of nkVarSection, nkLetSection, nkUsingStmt:
var L = sonsLen(n)
var L = len(n)
if L == 0: return
if n.kind == nkVarSection: putWithSpace(g, tkVar, "var")
elif n.kind == nkLetSection: putWithSpace(g, tkLet, "let")
@@ -1543,7 +1552,7 @@ proc renderModule*(n: PNode, infile, outfile: string,
g: TSrcGen
initSrcGen(g, renderFlags, conf)
g.fid = fid
for i in 0 ..< sonsLen(n):
for i in 0 ..< len(n):
gsub(g, n.sons[i])
optNL(g)
case n.sons[i].kind
@@ -1576,3 +1585,15 @@ proc getTokSym*(r: TSrcGen): PSym =
result = r.tokens[r.idx-1].sym
else:
result = nil
proc quoteExpr*(a: string): string {.inline.} =
## can be used for quoting expressions in error msgs.
"'" & a & "'"
proc genFieldError*(field: PSym, disc: PSym): string =
## this needs to be in a module accessible by jsgen, ccgexprs, and vm to
## provide this error msg FieldError; msgs would be better but it does not
## import ast
result = field.name.s.quoteExpr & " is not accessible using discriminant " &
disc.name.s.quoteExpr & " of type " &
disc.owner.name.s.quoteExpr

View File

@@ -1,7 +1,7 @@
import
intsets, ast, idents, algorithm, renderer, parser, os, strutils,
sequtils, msgs, modulegraphs, syntaxes, options, modulepaths, tables,
intsets, ast, idents, algorithm, renderer, os, strutils,
msgs, modulegraphs, syntaxes, options, modulepaths,
lineinfos
type
@@ -151,10 +151,10 @@ proc expandIncludes(graph: ModuleGraph, module: PSym, n: PNode,
if a.kind == nkIncludeStmt:
for i in 0..<a.len:
var f = checkModuleName(graph.config, a.sons[i])
if f != InvalidFileIDX:
if f != InvalidFileIdx:
if containsOrIncl(includedFiles, f.int):
localError(graph.config, a.info, "recursive dependency: '$1'" %
toFilename(graph.config, f))
toMsgFilename(graph.config, f))
else:
let nn = includeModule(graph, module, f)
let nnn = expandIncludes(graph, module, nn, modulePath,

View File

@@ -9,7 +9,7 @@
## This module implements the canonalization for the various caching mechanisms.
import ast, idgen, lineinfos, msgs, incremental, modulegraphs, pathutils
import ast, idgen, lineinfos, incremental, modulegraphs, pathutils
when not nimIncremental:
template setupModuleCache*(g: ModuleGraph) = discard

View File

@@ -9,7 +9,7 @@
## This module implements the new compilation cache.
import strutils, os, intsets, tables, ropes, db_sqlite, msgs, options, types,
import strutils, intsets, tables, ropes, db_sqlite, msgs, options,
renderer, rodutils, idents, astalgo, btrees, magicsys, cgmeth, extccomp,
btrees, trees, condsyms, nversion, pathutils
@@ -17,7 +17,6 @@ import strutils, os, intsets, tables, ropes, db_sqlite, msgs, options, types,
## - Dependency computation should use *signature* hashes in order to
## avoid recompiling dependent modules.
## - Patch the rest of the compiler to do lazy loading of proc bodies.
## - Patch the C codegen to cache proc bodies and maybe types.
template db(): DbConn = g.incr.db
@@ -72,9 +71,12 @@ proc getModuleId(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): in
# not changed, so use the cached AST:
doAssert(result != 0)
var cycleCheck = initIntSet()
if not needsRecompile(g, fileIdx, fullpath, cycleCheck) and not g.incr.configChanged:
echo "cached successfully! ", string fullpath
return -result
if not needsRecompile(g, fileIdx, fullpath, cycleCheck):
if not g.incr.configChanged or g.config.symbolFiles == readOnlySf:
#echo "cached successfully! ", string fullpath
return -result
elif g.config.symbolFiles == readOnlySf:
internalError(g.config, "file needs to be recompiled: " & (string fullpath))
db.exec(sql"update modules set fullHash = ? where id = ?", currentFullhash, module[0])
db.exec(sql"delete from deps where module = ?", module[0])
db.exec(sql"delete from types where module = ?", module[0])
@@ -154,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, ')')
@@ -221,22 +223,16 @@ 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.destructor != nil and t.destructor.id != 0:
if t.paddingAtEnd != 0:
add(result, '\15')
encodeVInt(t.destructor.id, result)
pushSym(w, t.destructor)
if t.deepCopy != nil:
encodeVInt(t.paddingAtEnd, result)
for a in t.attachedOps:
add(result, '\16')
encodeVInt(t.deepcopy.id, result)
pushSym(w, t.deepcopy)
if t.assignment != nil:
add(result, '\17')
encodeVInt(t.assignment.id, result)
pushSym(w, t.assignment)
if t.sink != nil:
add(result, '\18')
encodeVInt(t.sink.id, result)
pushSym(w, t.sink)
if a == nil:
encodeVInt(-1, result)
else:
encodeVInt(a.id, result)
pushSym(w, a)
for i, s in items(t.methods):
add(result, '\19')
encodeVInt(i, result)
@@ -248,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:
@@ -305,7 +301,7 @@ proc encodeSym(g: ModuleGraph, s: PSym, result: var string) =
pushSym(w, s.owner)
if s.flags != {}:
result.add('$')
encodeVInt(cast[int32](s.flags), result)
encodeVBiggestInt(cast[int64](s.flags), result)
if s.magic != mNone:
result.add('@')
encodeVInt(ord(s.magic), result)
@@ -429,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 -----------------------------------
@@ -642,16 +636,15 @@ proc loadType(g; id: int; info: TLineInfo): PType =
if b.s[b.pos] == '\15':
inc(b.pos)
result.destructor = loadSym(g, decodeVInt(b.s, b.pos), info)
if b.s[b.pos] == '\16':
inc(b.pos)
result.deepCopy = loadSym(g, decodeVInt(b.s, b.pos), info)
if b.s[b.pos] == '\17':
inc(b.pos)
result.assignment = loadSym(g, decodeVInt(b.s, b.pos), info)
if b.s[b.pos] == '\18':
inc(b.pos)
result.sink = loadSym(g, decodeVInt(b.s, b.pos), info)
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)
let id = decodeVInt(b.s, b.pos)
if id >= 0:
result.attachedOps[a] = loadSym(g, id, info)
while b.s[b.pos] == '\19':
inc(b.pos)
let x = decodeVInt(b.s, b.pos)
@@ -739,7 +732,7 @@ proc loadSymFromBlob(g; b; info: TLineInfo): PSym =
result.owner = loadSym(g, decodeVInt(b.s, b.pos), result.info)
if b.s[b.pos] == '$':
inc(b.pos)
result.flags = cast[TSymFlags](int32(decodeVInt(b.s, b.pos)))
result.flags = cast[TSymFlags](decodeVBiggestInt(b.s, b.pos))
if b.s[b.pos] == '@':
inc(b.pos)
result.magic = TMagic(decodeVInt(b.s, b.pos))
@@ -772,6 +765,7 @@ proc loadSymFromBlob(g; b; info: TLineInfo): PSym =
if b.s[b.pos] == '\24':
inc b.pos
result.transformedBody = decodeNode(g, b, result.info)
#result.transformedBody = nil
of skModule, skPackage:
decodeInstantiations(g, b, result.info, result.usedGenerics)
of skLet, skVar, skField, skForVar:
@@ -785,7 +779,7 @@ proc loadSymFromBlob(g; b; info: TLineInfo): PSym =
if b.s[b.pos] == '(':
#if result.kind in routineKinds:
# result.ast = decodeNodeLazyBody(b, result.info, result)
# result.ast = nil
#else:
result.ast = decodeNode(g, b, result.info)
if sfCompilerProc in result.flags:
@@ -846,7 +840,7 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) =
of "error": localError(g.config, n.info, errUser, n[1].strVal)
of "compile":
internalAssert g.config, n.len == 3 and n[2].kind == nkStrLit
let cname = AbsoluteFile n[1].strVal,
let cname = AbsoluteFile n[1].strVal
var cf = Cfile(nimname: splitFile(cname).name, cname: cname,
obj: AbsoluteFile n[2].strVal,
flags: {CfileFlag.External})
@@ -902,6 +896,10 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) =
internalAssert g.config, imported.id < 0
of nkStmtList, nkStmtListExpr:
for x in n: replay(g, module, x)
of nkExportStmt:
for x in n:
doAssert x.kind == nkSym
strTableAdd(module.tab, x.sym)
else: discard "nothing to do for this node"
proc loadNode*(g: ModuleGraph; module: PSym): PNode =

View File

@@ -35,7 +35,7 @@ proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf",
proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
case classify(f)
of fcNaN:
of fcNan:
result = "NAN"
of fcNegZero:
result = "-0.0" & literalPostfix
@@ -46,14 +46,9 @@ proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
of fcNegInf:
result = "-INF"
else:
when defined(nimNoArrayToCstringConversion):
result = newString(81)
let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
setLen(result, n)
else:
var buf: array[0..80, char]
discard c_snprintf(buf.cstring, buf.len.uint, "%#.16e%s", f, literalPostfix.cstring)
result = $buf.cstring
result = newString(81)
let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
setLen(result, n)
proc encodeStr*(s: string, result: var string) =
for i in 0 ..< len(s):

View File

@@ -11,9 +11,10 @@
## language.
import
ast, modules, idents, passes, passaux, condsyms,
options, nimconf, sem, semdata, llstream, vm, vmdef, commands, msgs,
os, times, osproc, wordrecg, strtabs, modulegraphs, lineinfos, pathutils
ast, modules, idents, passes, condsyms,
options, sem, llstream, vm, vmdef, commands, msgs,
os, times, osproc, wordrecg, strtabs, modulegraphs,
lineinfos, pathutils
# we support 'cmpIgnoreStyle' natively for efficiency:
from strutils import cmpIgnoreStyle, contains
@@ -61,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)
@@ -75,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))
@@ -96,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:
@@ -161,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) =
@@ -184,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 optNimV2
conf.selectedGC = gcUnselected
var m = graph.makeModule(scriptName)
incl(m.flags, sfMainModule)
graph.vm = setupVM(m, cache, scriptName.string, graph)
@@ -191,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 optNimV2 in oldGlobalOptions:
conf.globalOptions.incl optNimV2
defineSymbol(conf.symbols, "nimv2")
if conf.selectedGC == gcUnselected:
conf.selectedGC = oldSelectedGC
# ensure we load 'system.nim' again for the real non-config stuff!
resetSystemArtifacts(graph)
# do not remove the defined symbols

View File

@@ -10,13 +10,13 @@
# This module implements the semantic checking pass.
import
ast, strutils, hashes, options, lexer, astalgo, trees, treetab,
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
magicsys, parser, nversion, nimsets, semfold, modulepaths, importer,
ast, strutils, options, astalgo, trees,
wordrecg, ropes, msgs, idents, renderer, types, platform, math,
magicsys, nversion, nimsets, semfold, modulepaths, importer,
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
lowerings, pluginsupport, plugins/active, rod, lineinfos, strtabs
lowerings, plugins/active, rod, lineinfos, strtabs, int128
from modulegraphs import ModuleGraph, PPassContext, onUse, onDef, onDefResolveForward
@@ -24,7 +24,7 @@ when defined(nimfix):
import nimfix/prettybase
when not defined(leanCompiler):
import semparallel
import spawn, semparallel
# implementation
@@ -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)
@@ -523,12 +527,6 @@ proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
if sfSystemModule in module.flags:
graph.systemModule = module
c.topLevelScope = openScope(c)
# don't be verbose unless the module belongs to the main package:
if module.owner.id == graph.config.mainPackageId:
graph.config.notes = graph.config.mainPackageNotes
else:
if graph.config.mainPackageNotes == {}: graph.config.mainPackageNotes = graph.config.notes
graph.config.notes = graph.config.foreignPackageNotes
result = c
proc isImportSystemStmt(g: ModuleGraph; n: PNode): bool =
@@ -577,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
@@ -618,12 +616,18 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
#if c.config.cmd == cmdIdeTools: findSuggest(c, n)
rod.storeNode(c.graph, c.module, result)
proc reportUnusedModules(c: PContext) =
for i in 0..high(c.unusedImports):
if sfUsed notin c.unusedImports[i][0].flags:
message(c.config, c.unusedImports[i][1], warnUnusedImportX, c.unusedImports[i][0].name.s)
proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
var c = PContext(context)
if c.config.cmd == cmdIdeTools and not c.suggestionsMade:
suggestSentinel(c)
closeScope(c) # close module's scope
rawCloseScope(c) # imported symbols; don't check for unused ones!
reportUnusedModules(c)
result = newNode(nkStmtList)
if n != nil:
internalError(c.config, n.info, "n is not nil") #result := n;

View File

@@ -107,7 +107,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
elif errorsEnabled or z.diagnosticsEnabled:
errors.add(CandidateError(
sym: sym,
unmatchedVarParam: int z.mutabilityProblem,
firstMismatch: z.firstMismatch,
diagnostics: z.diagnostics))
else:
@@ -173,14 +172,16 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
var filterOnlyFirst = false
if optShowAllMismatches notin c.config.globalOptions:
for err in errors:
if err.firstMismatch > 1:
if err.firstMismatch.arg > 1:
filterOnlyFirst = true
break
var maybeWrongSpace = false
var candidates = ""
var skipped = 0
for err in errors:
if filterOnlyFirst and err.firstMismatch == 1:
if filterOnlyFirst and err.firstMismatch.arg == 1:
inc skipped
continue
if err.sym.kind in routineKinds and err.sym.ast != nil:
@@ -189,39 +190,47 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
else:
add(candidates, getProcHeader(c.config, err.sym, prefer))
add(candidates, "\n")
if err.firstMismatch != 0 and n.len > 1:
let cond = n.len > 2
if cond:
candidates.add(" first type mismatch at position: " & $abs(err.firstMismatch))
if err.firstMismatch >= 0: candidates.add("\n required type: ")
else: candidates.add("\n unknown named parameter: " & $n[-err.firstMismatch][0])
var wanted, got: PType = nil
if err.firstMismatch < 0:
discard
elif err.firstMismatch < err.sym.typ.len:
wanted = err.sym.typ.sons[err.firstMismatch]
if cond: candidates.add typeToString(wanted)
else:
if cond: candidates.add "none"
if err.firstMismatch > 0 and err.firstMismatch < n.len:
if cond:
candidates.add "\n but expression '"
candidates.add renderTree(n[err.firstMismatch])
let nArg = if err.firstMismatch.arg < n.len: n[err.firstMismatch.arg] else: nil
let nameParam = if err.firstMismatch.formal != nil: err.firstMismatch.formal.name.s else: ""
if n.len > 1:
candidates.add(" first type mismatch at position: " & $err.firstMismatch.arg)
# candidates.add "\n reason: " & $err.firstMismatch.kind # for debugging
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:
doAssert nArg != nil
var wanted = err.firstMismatch.formal.typ
doAssert err.firstMismatch.formal != nil
candidates.add("\n required type for " & nameParam & ": ")
candidates.add typeToString(wanted)
candidates.add "\n but expression '"
if err.firstMismatch.kind == kVarNeeded:
candidates.add renderNotLValue(nArg)
candidates.add "' is immutable, not 'var'"
else:
candidates.add renderTree(nArg)
candidates.add "' is of type: "
got = n[err.firstMismatch].typ
if cond: candidates.add typeToString(got)
if wanted != nil and got != nil:
effectProblem(wanted, got, candidates)
if cond: candidates.add "\n"
if err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
candidates.add(" for a 'var' type a variable needs to be passed, but '" &
renderNotLValue(n[err.unmatchedVarParam]) &
"' is immutable\n")
var got = nArg.typ
candidates.add typeToString(got)
doAssert wanted != nil
if got != nil: effectProblem(wanted, got, candidates)
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
@@ -260,7 +269,7 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
while symx != nil:
if symx.kind in routineKinds:
errors.add(CandidateError(sym: symx,
unmatchedVarParam: 0, firstMismatch: 0,
firstMismatch: MismatchInfo(),
diagnostics: @[],
enabled: false))
symx = nextOverloadIter(o, c, headSymbol)
@@ -396,7 +405,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
elif c.config.errorCounter == 0:
# don't cascade errors
var args = "("
for i in 1 ..< sonsLen(n):
for i in 1 ..< len(n):
if i > 1: add(args, ", ")
add(args, typeToString(n.sons[i].typ))
add(args, ")")
@@ -474,7 +483,7 @@ proc semResolvedCall(c: PContext, x: TCandidate,
assert x.state == csMatch
var finalCallee = x.calleeSym
let info = getCallLineInfo(n)
markUsed(c.config, info, finalCallee, c.graph.usageSym)
markUsed(c, info, finalCallee)
onUse(info, finalCallee)
assert finalCallee.ast != nil
if x.hasFauxMatch:
@@ -568,7 +577,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
# binding has to stay 'nil' for this to work!
initCandidate(c, m, s, nil)
for i in 1..sonsLen(n)-1:
for i in 1..len(n)-1:
let formal = s.ast.sons[genericParamsPos].sons[i-1].typ
var arg = n[i].typ
# try transforming the argument into a static one before feeding it into
@@ -584,16 +593,16 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
var newInst = generateInstance(c, s, m.bindings, n.info)
newInst.typ.flags.excl tfUnresolved
let info = getCallLineInfo(n)
markUsed(c.config, info, s, c.graph.usageSym)
markUsed(c, info, s)
onUse(info, s)
result = newSymNode(newInst, info)
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
assert n.kind == nkBracketExpr
for i in 1..sonsLen(n)-1:
for i in 1..len(n)-1:
let e = semExpr(c, n.sons[i])
if e.typ == nil:
localError(c.config, e.info, "expression has no type")
n.sons[i].typ = errorType(c)
else:
n.sons[i].typ = e.typ.skipTypes({tyTypeDesc})
var s = s
@@ -631,7 +640,7 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
result = explicitGenericInstError(c, n)
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
# New approach: generate fn(x, y, z) where x, y, z have the proper types
# and use the overloading resolution mechanism:

View File

@@ -10,11 +10,8 @@
## This module contains the data structures for the semantic checking phase.
import
strutils, intsets, options, lexer, ast, astalgo, trees, treetab,
wordrecg,
ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
magicsys, nversion, nimsets, parser, times, passes, vmdef,
modulegraphs, lineinfos
intsets, options, ast, astalgo, msgs, idents, renderer,
magicsys, vmdef, modulegraphs, lineinfos, sets
type
TOptionEntry* = object # entries to put on a stack for pragma parsing
@@ -74,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
@@ -139,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
@@ -368,7 +368,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 =
@@ -392,8 +392,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
@@ -410,10 +410,10 @@ proc illFormedAstLocal*(n: PNode; conf: ConfigRef) =
localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) =
if sonsLen(n) != length: illFormedAst(n, conf)
if len(n) != length: illFormedAst(n, conf)
proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) =
if sonsLen(n) < length: illFormedAst(n, conf)
if len(n) < length: illFormedAst(n, conf)
proc isTopLevel*(c: PContext): bool {.inline.} =
result = c.currentScope.depthLevel <= 2

View File

@@ -25,12 +25,12 @@ const
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode =
let info = getCallLineInfo(n)
markUsed(c.config, info, s, c.graph.usageSym)
markUsed(c, info, s)
onUse(info, s)
# Note: This is n.info on purpose. It prevents template from creating an info
# context when called from an another template
pushInfoContext(c.config, n.info, s.detailedInfo)
result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in flags)
result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, efFromHlo in flags)
if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
popInfoContext(c.config)
@@ -149,10 +149,10 @@ 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
(classify(src.floatVal) in {fcNan, fcNegInf, fcInf} or
src.floatVal.int64 notin firstOrd(c.config, targetTyp)..lastOrd(c.config, targetTyp)):
result = convNotInRange
elif targetBaseTyp.kind in tyFloat..tyFloat64:
@@ -160,7 +160,7 @@ proc checkConvertible(c: PContext, targetTyp: PType, src: PNode): TConvStatus =
not floatRangeCheck(src.floatVal, targetTyp):
result = convNotInRange
elif src.kind in nkCharLit..nkUInt64Lit and
not floatRangeCheck(src.intval.float, targetTyp):
not floatRangeCheck(src.intVal.float, targetTyp):
result = convNotInRange
else:
# we use d, s here to speed up that operation a bit:
@@ -220,8 +220,12 @@ proc maybeLiftType(t: var PType, c: PContext, info: TLineInfo) =
closeScope(c)
if lifted != nil: t = lifted
proc isOwnedSym(c: PContext; n: PNode): bool =
let s = qualifiedLookUp(c, n, {})
result = s != nil and sfSystemModule in s.owner.flags and s.name.s == "owned"
proc semConv(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2:
if len(n) != 2:
localError(c.config, n.info, "a type conversion takes exactly one argument")
return n
@@ -247,7 +251,7 @@ proc semConv(c: PContext, n: PNode): PNode =
maybeLiftType(targetType, c, n[0].info)
if targetType.kind in {tySink, tyLent, tyOwned}:
if targetType.kind in {tySink, tyLent} or isOwnedSym(c, n[0]):
let baseType = semTypeNode(c, n.sons[1], nil).skipTypes({tyTypeDesc})
let t = newTypeS(targetType.kind, c)
if targetType.kind == tyOwned:
@@ -297,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
@@ -327,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})
@@ -337,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:
@@ -365,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}
@@ -404,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)
@@ -448,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)
@@ -466,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")
@@ -495,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]
@@ -509,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):
@@ -561,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:
@@ -660,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}:
@@ -676,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])
@@ -844,9 +867,10 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
analyseIfAddressTakenInCall(c, result)
if callee.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
if result.typ != nil and
not (result.typ.kind == tySequence and result.typ.sons[0].kind == tyEmpty):
liftTypeBoundOps(c, result.typ, n.info)
when false:
if result.typ != nil and
not (result.typ.kind == tySequence and result.typ.sons[0].kind == tyEmpty):
liftTypeBoundOps(c, result.typ, n.info)
#result = patchResolvedTypeBoundOp(c, result)
if c.matchedConcept == nil:
result = evalAtCompileTime(c, result)
@@ -863,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
@@ -882,7 +906,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
semOpAux(c, n)
var t: PType = nil
if n.sons[0].typ != nil:
t = skipTypes(n.sons[0].typ, abstractInst+{tyOwned}-{tyTypeDesc})
t = skipTypes(n.sons[0].typ, abstractInst+{tyOwned}-{tyTypeDesc, tyDistinct})
if t != nil and t.kind == tyProc:
# This is a proc variable, apply normal overload resolution
let m = resolveIndirectCall(c, n, nOrig, t)
@@ -894,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))
@@ -982,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:
@@ -992,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)
@@ -1085,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
@@ -1117,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:
@@ -1127,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 ...
@@ -1157,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
@@ -1175,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
@@ -1197,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))
@@ -1210,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)
@@ -1237,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
@@ -1301,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:
@@ -1336,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
@@ -1350,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)
@@ -1399,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)
@@ -1426,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
@@ -1457,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:
@@ -1536,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)
@@ -1600,7 +1625,7 @@ proc borrowCheck(c: PContext, n, le, ri: PNode) =
template resultTypeIsInferrable(typ: PType): untyped =
typ.isMetaType and typ.kind != tyTypeDesc
proc goodLineInfo(arg: PNode): TLineinfo =
proc goodLineInfo(arg: PNode): TLineInfo =
if arg.kind == nkStmtListExpr and arg.len > 0:
goodLineInfo(arg[^1])
else:
@@ -1689,8 +1714,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
borrowCheck(c, n, lhs, rhs)
n.sons[1] = fitNode(c, le, rhs, goodLineInfo(n[1]))
liftTypeBoundOps(c, lhs.typ, lhs.info)
#liftTypeBoundOps(c, n.sons[0].typ, n.sons[0].info)
when false: liftTypeBoundOps(c, lhs.typ, lhs.info)
fixAbstractType(c, n)
asgnToResultVar(c, n, n.sons[0], n.sons[1])
@@ -1757,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
@@ -1872,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]
@@ -1882,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):
@@ -1907,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:
@@ -1923,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:
@@ -1996,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)])
@@ -2007,8 +2037,11 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
let oldErrorCount = c.config.errorCounter
let oldErrorMax = c.config.errorMax
let oldCompilesId = c.compilesContextId
inc c.compilesContextIdGenerator
c.compilesContextId = c.compilesContextIdGenerator
# if this is a nested 'when compiles', do not increase the ID so that
# generic instantiations can still be cached for this level.
if c.compilesContextId == 0:
inc c.compilesContextIdGenerator
c.compilesContextId = c.compilesContextIdGenerator
# do not halt after first error:
c.config.errorMax = high(int)
@@ -2050,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)
@@ -2085,7 +2118,7 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
# since it's an instantiation, we unmark it as a compilerproc. Otherwise
# codegen would fail:
if sfCompilerProc in result.flags:
result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC}
result.flags = result.flags - {sfCompilerProc, sfExportc, sfImportc}
result.loc.r = nil
proc setMs(n: PNode, s: PSym): PNode =
@@ -2094,50 +2127,55 @@ 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})
#restoreOldStyleType(n.sons[1])
n.typ = getSysType(c.graph, n.info, tyInt)
let size = getSize(c.config, n[1].typ)
if size >= 0:
result = newIntNode(nkIntLit, size)
result.info = n.info
result.typ = n.typ
else:
result = n
result = foldSizeOf(c.config, n, n)
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
# this is a hotspot in the compiler!
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,23 +2185,30 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result.sons[1] = semStmt(c, x, {})
dec c.inParallelStmt
of mSpawn:
result = setMs(n, s)
for i in 1 ..< n.len:
result.sons[i] = semExpr(c, n.sons[i])
let typ = result[^1].typ
if not typ.isEmptyType:
if spawnResult(typ, c.inParallelStmt > 0) == srFlowVar:
result.typ = createFlowVar(c, typ, n.info)
else:
result.typ = typ
result.add instantiateCreateFlowVarCall(c, typ, n.info).newSymNode
markUsed(c, n.info, s)
when defined(leanCompiler):
localError(c.config, n.info, "compiler was built without 'spawn' support")
result = n
else:
result.add c.graph.emptyNode
result = setMs(n, s)
for i in 1 ..< n.len:
result.sons[i] = semExpr(c, n.sons[i])
let typ = result[^1].typ
if not typ.isEmptyType:
if spawnResult(typ, c.inParallelStmt > 0) == srFlowVar:
result.typ = createFlowVar(c, typ, n.info)
else:
result.typ = typ
result.add instantiateCreateFlowVarCall(c, typ, n.info).newSymNode
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)
@@ -2180,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`
@@ -2196,7 +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)
@@ -2225,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:
@@ -2263,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])
@@ -2292,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]):
@@ -2311,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])
@@ -2333,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:
@@ -2359,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],
@@ -2387,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
@@ -2429,10 +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, n.info, exported)
proc semExport(c: PContext, n: PNode): PNode =
result = newNodeI(nkExportStmt, n.info)
@@ -2452,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 =
@@ -2706,7 +2755,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkUsingStmt: result = semUsing(c, n)
of nkAsmStmt: result = semAsm(c, n)
of nkYieldStmt: result = semYield(c, n)
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas, true)
of nkIteratorDef: result = semIterator(c, n)
of nkProcDef: result = semProc(c, n)
of nkFuncDef: result = semFunc(c, n)

View File

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

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